open-zwave-1.5/000077500000000000000000000000001264474202400134575ustar00rootroot00000000000000open-zwave-1.5/.gitignore000066400000000000000000000015021264474202400154450ustar00rootroot00000000000000.dep/ .lib/ MinOZW cpp/src/vers.cpp libopenzwave.a libopenzwave.pc libopenzwave.so* libopenzwave.so *.obj /cpp/build/windows/vs2010/Debug/*.log /cpp/build/windows/vs2010/Debug/OpenZWave.tlog/*.tlog /cpp/build/windows/vs2010/Debug/OpenZWave.tlog/*.lastbuildstate *.idb *.pdb *.log *.tlog /dotnet/build/vs2010/Debug/app.res Debug /dotnet/examples/OZWForm/src/OZWForm.csproj /dotnet/examples/OZWForm/src/OZWForm.sdf /dotnet/examples/OZWForm/src/OZWForm.sln /dotnet/examples/OZWForm/src/OZWForm.v12.suo *.cache *.res *.lib *.dll *.metagen *.exp *.exe OZWForm.exe.config OZWForm.vshost.exe.config OZWForm.vshost.exe.manifest *.resources /dotnet/examples/OZWForm/src/bin/x86/Release/OZW_Log.txt /dotnet/examples/OZWForm/src/bin/x86/Release /dotnet/examples/OZWForm/src/obj/x86/Release .gitignore /cpp/build/windows/winversion.cpp .distfilesopen-zwave-1.5/ChangeLog000066400000000000000000000554551264474202400152470ustar00rootroot00000000000000Version 1.5 - Rename zwcfg_*.xml to zwcache_*.xml to reflect its not a config file, but a cache. (Justin) Version 1.4 - Released 10th Jan, 2016 Version 1.3 - Added support for Merten Plug-in Roller Shutter Module (Marco) - Fixed Issue 383 - Update Remotec ZXT-120 Config file thanks to yy.bendavid & gizmocuz (Alex) - Fixed Issue 392 - Add Qubino ZMNHJA2 Config file thanks to nicoserveur (Alex) - Fixed Issue 394 - Add 2GIG CT100 USA version device thanks to mldkfa (Alex) - Fixed Issue 387 - Add Zipato RFID Config file thanks to jeanfrancois.auger (Alex) - Fixed Issue 391 - Update zwave.key keyfob config thanks to gizmocuz (Alex) - Fixed Issue 397 - Update remotec ZXT-120 config thanks to gizmocuz (Alex) - Fixed Issue 396 - Add Z-Wave.me RaZberry thanks to steph10200 (Alex) - Fixed Issue 398 - Add Z-Wave.me USB Stick thanks to ugo.viti (Alex) - Fixed Issue 389 - Add Evolve LRM-AS/LSM-15 Config file thanks to Gwmullin (Alex) - Fixed Issue 386 - Add Duwi and Z-Wave.Me Config files thanks to pim.vanderhaven (Alex) - Fixed Issue 401 - Add Toon/Quby devices (Alex) - Added new manufacturers and new devices (Alex) - Add Wenzhou TSP01 Config file thanks to Jan (Alex) - Standardize some of the Logging Messages so its easier to parse (Justin) - Implemented Issue 325 - Add a GetChangeVerfied method to the Manager and Value classes to determine if a Value is checked upon refresh from a device (Justin) - Fixed issue 350 - FreeBSD Makefile updates and a few patches (Justin) - Fixed issue 395 - Clear the ListItems Vector before populating with new values (Justin) - Fixed issue 402 - Clean vers.cpp when we issue a make clean (Justin) - Fixed issue 405 - Add new ID's for Fibaro FGD211 and FGS221 (Justin) - Fixed issue 406 - Add Remotec ZFM-80 (Justin) - Fixed issue 410 - Add Vision ZP3102 (Justin) - Fixed issue 412 - Updated Zipato RGB Bulb Config (Justin) - Fixed Issue 343 - Add Exceptions instead of Exit for some fatal errors Also, add Exceptions if any of the GetValue or SetValue calls in the Manager class are passed invalid ValueID's (Justin) - Fixed duplicate Vision devices and added a missing id for ZP3102 (Alex) - Fixed Issue 417 - Add Z-Wave.Me ZME_UZB1 USB Stick thanks to Ugo (Alex) - Add new Aeon Repeater device (Alex) - Fixed a crash in the LogFile Class when the destructor was called (Justin) - Fix Issue 426 - Upon restarts of OZW, we restarted the entire discovery process again (Justin) - Fix a off by 1 issue with the Security CC that was causing the Assoication Set Failures on Secured Devices. (Justin) - Added Aeon Labs Smart Energy Switch V2 that supports the Security CC but doesn't support the Basic CC - Related to issue 427 (Justin) - Fixed issue 420 - Dotnet Patch from scopollif. (Justin) - Fixed issue 415 - add 2Gig CT101 Thermostat (Justin) - Started Implementing the Central Scene CC - With a good start by tmartinez69009 - We still need to figure out the Capabilities decode - Issue 367 (Justin) - Fixed issue 425 - Bail out of Decrypting Packets if they are too short (Justin) - Fixed Fibaro FGD211 device config, removed automatic association for group 1&2 (Alex) - Updated Z-Wave.Me device list thanks to Willem (Alex) - Fixed Issue 431 - Update Fibaro fgrgbwm441 config thanks to Piotr (Alex) - Fixed Issue 433 - Update Fibaro fgwpe config thanks to Piotr (Alex) - Fixed Issue 439 - Update Fibaro FGMS001 config thanks to Jug (Alex) - Fixed Issue 434 - Update Fibaro fgbs001 config thanks to Piotr (Alex) - Fixed Issue 436 - Update Fibaro fgd211 config thanks to Piotr (Alex) - Fixed Issue 437 - Update Qubino ZMNHDA2 config thanks to Piotr (Alex) - Added Aeon Siren Gen5 device thanks to Alle (Alex) - Added GE 12724 3-Way Dimmer Switch device thanks to Dax (Alex) - Added additional Fibaro FGBS001 device id thanks to Stef (Alex) - Added ConnectHome CH-201 device thanks to Tehnoinstyle (Alex) - Detect if the Controller Supports SUC - If not, Dont try to become a SUC when starting up (Justin) - Add Sigma Designs UZB Z-Wave USB Adapter (Justin) - Make sure LogLevels parsed are within range (Justin) - Fix IntervalBetweenPolls always being false regardless of Options.xml setting. (Justin) - Make sure we refresh all UserCodes upto the first available slot unless RefreshAllUserCodes is true in Options.xml (Justin) - Added Qubino ZMNHIA2 device thanks to Paul (Alex) - Fixed Issue 444 - Added Aeon Aeon Labs Micro Smart Energy Dimmer thanks to yy (Alex) - Fixed Issue 430 - Spelling Mistake (Justin) - Add Support for CommandClasses that are marked as Controlling (versus Controlled) to be able to still query the Device for Data. This is needed for the CentralScene CC which is implemented as Controlling on most devices (Justin) - CentralScene CC should be able to query for number of Scene's supported. Needs further testing with other devices (only BeNext at the moment is tested) (Justin) - When refreshing the ConfigParams on a device, place the messages in the MsgQueue_Query queue rather tha the MsgQueue_Send queue. This should help the "responsiveness" of OZW during startup if a user sends a message and there is a big backlog in the Send Queue (Justin) - Fixed issue 452 - Fix the ValueID for Door_Lock index to report correct status. (Justin) - Fixed issue 448 - Dont request Basic Get if we have a mapped Class during startup (Justin) - Added Everspring HAN02 device thanks to lookwhatthecat (Alex) - Fixed issue 453 - Don't crash if we skip notifications due to invalid ValueID's (Justin) - Fixed issue 456 - Added NorthQ NQ-9021 device thanks to manu (Alex) - Fixed issue 455 - Fixed Fibaro FGD211 device config thanks to Wouter (Alex) - Fixed Popp 123580 Plug-in Dimmer device config thanks to Tom (Alex) - Fixed issue 457 - Added zwave.me KFOB-S device thanks to Tony (Alex) - Updated BeNext TagReader device config thanks to Rob (Alex) - Added Philio PST02-1B device thanks to Thaui (Alex) - Updated BeNext TagReader device config (Alex) - Fixed issue 449 - Update Wenzhou TZ67 device config thanks to bas (Alex) - Fixed issue 367 - Implement CentralScene with lots of testing by TMartinez (Justin) - Update our Mutex's to use Scoped Locks instead. This saves us from having to track Lock/Unlocks. Implemented for the m_nodeMutex in the DriverClass. We should also port the Polling and Send Mutex's as well. This fixes issue 451 (Justin) - Fixed issue 459 - Alarm Class Version 2 (Justin) - Fix DoorLockLogging Class not saving the Max Number of records (Justin) - Fixed issue 470 - Qubino ZMNHDA2 device update thanks to kvervloesem (Alex) - Fixed Issue 462 - Fix Builds on FreeBSD - From Stromnet (Justin) - Added Vision Z-Wave USB Stick device thanks to GizMoCuz (Alex) - Fixed issue 469 - Added Fibaro Smoke Detector FGSD-002 thanks to tmartine (Alex) - Fix LogImpl crash if no filename was configured (pull req 488) (Stromnet) - Update Fibaro Smoke Sensor device, interview process wouldn't complete (Alex) - Fixed issue 464 - Added/Updated Polycontrol keypad/doorlock devices thanks to santal (Alex) - Fixed issue 495 - Added Fibaro FGD211 device thanks to nechry (Alex) - Fixed issue 496 - Added Aeon-Labs Z-Stick Gen5 thanks to nechry (Alex) - Don't kill Notifications for ValueAdded and ValueRemoved as they might not exist right then (Justin) - Pull Request #516 - Add Philio PST02-1C thanks to Ugoviti (Justin) - Pull Request #517 - Add Aeon Labs Gen5 thanks to Ugoviti (Justin) - Pull Request #515 - Add Widom USB104 Universal Relay Switch thanks to Ugoviti (Justin) - Pull Request #508 - Update Fibaro FGFS101 Association Groups thanks to Nechry (Justin) - Pull Request #504 - CRC16Encap CC Support from xs4 (Justin) - Pull Request #522 - Dragon Tech In wall dimmer from Stevejbauer (Justin) - Fix Issue #523 - Add Wenzhou Door/Window Sensor from whiteduck22 (Justin) - Pull Request #534 - Add Aeon Labs Recessed Door Sensor Gen5 from xxv (Justin) - Pull Request #532 - Fix Aeon Labs DoorWindow Sensor Config from Nechry (Justin) - Pull Request #529 - Updated Config for the Zipato MiniKeyPad from Nechry (Justin) - Pull Request #528 and #527 - Add Aeon Labs Key Fob Gen5 Config from Nechry (Justin) - Add new ID's for BeNext Energy Switch from Rob (Justin) - Depreciate the ControllerCommand method in the Manager class and replace with direct function calls (Justin) - Pull Request #538 and #541 - Add SwiidInter to manufacturer_specific from Nechry (Justin) - Pull Request #545 - Add Philio PST02-A 4 in 1 MultiSensor from Nechry (Justin) - Pull Request #565 - Add MultiInstanceAssociation CommandClass from xs4 (Justin) - Pull Request #546 - Update Philio PST02-A Config from Nechry (Justin) - Pull Request #547 & #549 - New Config File for Philio PST02-B from Nechry (Justin) - Pull Request #548 - Update Config file for Philio PST02-C from Nechry (Justin) - Pull Request #550 - Config File for Vision zd2102 from Ugoviti (Justin) - Fix a crash when dumping the Queue to the Log, reported by Gizmocuz (Justin) - Pull Request #555 - Update the dotNet wrapper and OZWForm to use the new Manager Methods that replace the BeginControllerCommand Method. From JKlessens (Justin) - Pull Request #564 - Add Cooper Configs from Stevejbauer (Justin) - Pull Request #561 - Add Version String Method from Ikkemaniac (Justin) - Pull Request #562 - Fix Windows Build Event with wrong directory from douglasbeck (Justin) - Pull Request #567 and Issue 566 - Add Fibaro FGS221 from Nechry and DanielLast (Justin) - Pull Request #574 - Add Fibaro FGS212 Config from Nechry (Justin) - Pull Request #576 - Fix up Qubino ZMNHBA2 Help from DavZero (Justin) - Pull Request #578 - Add NodOn SmartPlug, Swiid SwiidPlug and update ZME_064435 Config fron Nechry (Justin) - Pull Request #580 - Add zwave.me Razberry ZWave+ adapter from Nechry (Justin) - Pull Request #581 - Update Zipato Minikeypad from Nechry (Justin) - Fixed issue #352 - Security Rewrite (Justin) - Fixed issue #467 - Fixed Aeon Labs Multisensor Gen5 (Justin) - Fixed issue #471 - Fixed Vision ZD2102 (Justin) - Fixed issue #472 - Fixed Aeon Labs Siren Gen5 (Justin) - Fixed issue #473 - Fixed Philio PST02-1C Slim Multisensor (Justin) - Fixed issue #540 - Depreciate the BeginControllerCommand Method for dedicated methods in the Manager Class - Applications should update their code to use the new API instead. (Justin) - Pull Request #587 - Add Zwave.me ZME_WALLC-S Secure Wall Controller from xs4 (Justin) - Fixed issue #586 - Compile Error on newer GCC's (Justin) - Fixed issue #568 - Compile Error on new OSX (Justin) - Update the device_classes.xml with the latest known mappings (Justin) - Enable NWI when adding nodes if HighPower is also enabled (Justin) - Pull Request #596 - Aeotec Z-Stick Gen5 and GE 12722 on/Off Relay from SpudGunMan (Justin) - Pull Request #595 - Aeotec Smart Switch Gen5 Config Updates from Gert Boer and Nechry (Justin) - Pull Request #594 - Aeotec Minimote Config Updates from Nechry (Justin) - Update Aeon Labs to Aeotec as thats their Retail name (Justin) - Pull Request #598 - Update Config Files for Fibaro FGS212 and FGS222 from Nechry (Justin) - If we recieve a cleartext message for a Secured CommandClass, drop the message (Configurable - Set EnforceSecureReception to false in options.xml) (Justin) - Add Aeotec LED Bulb, MultiSensor 6 and SmartSwitch 6 Configs (Justin) - Add Aeotec DSC24 identification and Everspring AD147 identification + config - Add Schlage BE469NXCEN TouchScreen DeadBolt from Rushidesai (Justin) - Pull Request #622 - Aeotec Micro Smart Energy Switch from Ugoviti (Justin) - Issue #628 - Update Everspring SP814 Config file from iarmstrong (Justin) - Issue #621 - Add Apache License for the cpp/build/sh2ju.sh script from Alteholz (Justin) - Issue #585 - Possible fix for Node 0/255 when adding new nodes. (Justin) - Issue #626 & #381 - Fix Segfault when trying to get a Empty/unpopulated ValueList (when we get a ValueAdded Notificiation) - Issue #637 - Change Color Channels ValueID from Config to System Genre (Justin) - Issue #635 and #636 - Add widom energy driven switch from RobyBob64 (Justin) - Issue #632 - Add Horstmann SES 301 Temp Sensor from ado464 (Justin) - Pull Request #639 - Update ZME_06433 with bugfixes and new options from cyr123 (Justin) - Pull Request #640 - Add FGD212 Dimmer 2 Config from xs4 (Justin) - Pull Request #641 - Update ZMNHBA2 Config from xs4 (Justin) - Add Aeotec Smart Dimmer 6 Config (Justin) - Pull Request #649 - Add Everspring st812-Flood Detector from Warp95 (Justin) - Pull Request #648 - Added configuration file for Merten 50x5xx Roller Shutter Module from Sascha (Justin) - Pull Request #641 - A Large set of Config File updates from the Jeedom team (Justin) - Issue #656 - Update ZME064435 and ZME05470 with Scene Activation Command Class from CompaTech (Justin) - Pull Request #655 - Update BeNext Devices from ewgast (Justin) - Issue #658 - Reset a Message SendAttempts value when moving to the Wakeup Queue, otherwise it gets dropped when we attempt to send it when the device wakes up as it exceeds the retry count. (Justin) - Issue #416 and Pull Request #506 - ValueShort and ValueSchedule were using wrong Value Storage enums. Enhance Value::VerifyRefreshedValue to handle almsot all types (Except Schedule) (Justin) - Issue #501 - Fix ThermostatFanMode when checking for Valid Modes (Justin) - Pull Request #659 - Added configuration file for D-Link Corp and DCH-Z110 Door/Window 3in1 sensor from psixilambda (Justin) - Issue #446 - Fix Visual Studio 2015 breakage. (Justin) - Pull Request #664 - Add ZMHAD1 Qubino support from Wackoracoon (Justin) - Pull Request #665 - Add ZMNHBD2 Flush 2 Relay from emdioh (Justin) - Pull Request #668 - Add some new variables to pkg-config from Ekarak (Justin) - Add a ozw_config file as a replacement for pkg-config and update pkgconfig install dirs (Justin) - Pull Request #670 - Typo: Changes "Temerature" to "Temperature" from cslarsen (Justin) - Added Aeotec DoorBell and Dry Contact Sensor (Justin) - Issue #672 - Infinate Loop when refreshing ZWPlus Command Class (Justin) - Issue #674 - Fix crash on Central Scene Message (Justin) - Issue #671 - Updated Zwave.me ZME_WALLC-S Config file from rgroothuis (Justin) - Pull Request #676 - Fix Windows Build Version and a few enhancements to the dotNet wrapper from bufferUnderrun (Justin) - OOhhhh. Pretty Colors (Justin) - Pull Request #677 - Update for Linear Dimmers PD300Z-2 and WD500Z-1 from vexofp (Justin) - Added Aeotec DoorBell and Dry Contact Sensors config files (Justin) - Issue #679 - Add Thermofloor TF 016 Terhmostat from Cog (Justin) - Pull Request #686 - Add Australian Z-Stick Gen5 from phil-nelson (Justin) - Pull Request #693 - Notification::GetAsString needs to be Const from Ekarak (Justin) - Merge a few fixes from Gizmocuz for VisualStudio Warnings (Justin) - Update of Deb files from Lucas Nussbaum (Justin) - Pull Request #700 - Updated Linear switch configs and added Enerwave ZWN-SC7 config from Vexofp (Justin) - Pull Request #696 - Config for HomeSeer HSM200, add config parameters for schlage touchscreen deadbolts from gwmullin (Justin) - Issue #698 - Add config file for Vision CP3102 from Erik-NA (Justin) - Issue #692 - Add Wenzhou TZ68 config file from gsolem (Justin) - DotNet Wrapper fix for GetAllScenese from Bas Prins (Justin) - Issue #688 - Qubino ZMNHDD1 Z-Wave Plus flush dimmer from bbqkees (Justin) - Issue #701 - FreeBSD Fixes from stromnet (Justin) - Issue #703 - Updated Config file for Benext DoorSensor from gizmocus (Justin) - Issue #702 - Config file for Qubino ZMNHND1 Flush Relay from hanscbecker (Justin) - Pull Request #705 - config files for fortrezz MIMOlite from gwmullin (Justin) - Pull Request #706 - config files for Qubino ZMNHCDx from guillaumezin (Justin) - Pull Request #711 - config files for POPP Wall Plug Switch Schuko from hellqvist (Justin) - Add additional codes for Fibaro FGRM222 Roller Shutter from proohu01 (Justin) - Add ZME_064381 IP44 Plug-in Switch config from Geoff Coupe (Justin) - Pull Request #712 - New Manager::GetValueListValues function to get the indexes of a List from out4b (Justin) - Pull Request #710 - Added config files for Eurotronic Comet thermostatic radiator valve (Justin) - Issue #714 - Z-Wave.Me ZME_KFOB-C 4 Button Key Fob config files from pbda (Justin) - Issue #715 - Add Sensative Strips-MAZW config file from michapr (Justin) - Issue #716 - Aeotec MultiSensor 6 config updates from michapr (Justin) - Pull Request #720 - Added support for Merten Plug-in Roller Shutter Module from Marco (Justin) - Pull Request #721 - Create POP009303.xml from armaesiea (Justin) - Pull Request #724 - Update config/fibaro/fgd212.xml from MHediund (Justin) - Pull Request #727 - Update DotNet Wrapper from bufferUnderrun (Justin) - Pull Request #728 - Fix FreeBSD compile from durin42 (Justin) - Store Manufacturer ID, Type and Product ID as shorts instead of strings. (Justin) - Change QueryStage_Probe1 to QueryStage_CacheLoad to reflect this is where we start when loading a device from Cache (Justin) - Issue #729 - Add Qubino Flush Dimmer ZMNHJD1 from Stephane guillard (Justin) Version 1.2 - Released on 15/10/14 Version 1.1 - Fixed Command Class Recieved Message Counter when we are handling a MultiInstanceMessageEncap Message (Justin) - Fixed Issue 310 - Unbalanced Lock/Release in Manager::IsNodeFailed and Manager::GetNodeQueryStage (Justin) - For Sleeping Devices - Do Not automatically add WakeUp Class to these devices if they advertise themselves as FrequentListening. This matches the Logic in the QueryStage functions where we skip querying the Device for Wakeup Configuration if its set as FLiRS. Needs some testing (Justin) - Options.xml file can now live in both the System Config Path (/etc/openzwave for example) or the Local Application Path. Local Options.xml will override any System Options.xml (Justin) - Updated the Include Paths so we only have to specify the top level src directory for GCC, and the rest of the headers are specified as subdirs. Based on work started by Svente Karisson (Justin) - A few fixes for Windows Calls and various casts required to eliminate warnings (Svente Karisson) - Add a Error String if we fail to parse our Options.xml files (Justin) - Added a Complete Door Lock Command Class (Justin) - Change the Logic in the UserCode Command Class to only retrive UserCodes upto the first available slot (Justin) - Add a ValueButton to the UserCode class to refresh all UserCodes (Justin) - Fixed Issue 301 - Updated Aeon Recessed Door Sensor (Justin) - Fixed Issue 302 - New ID for Aeon Labs Door/Window Sensor (Justin) - Fixed Issue 306 & 304 - Updated Fibaro FGMS Config File (Justin) - Fixed Issue 308 - Add Zenzhou TZ65D Dual Wall Dimmer (Justin) - Fixed Issue 309 - Add Config File for ZWave.Me Flush Mountable Switch (Justin) - Fixed Issue 311 - Add Vision Siren (Justin) - Fixed Issue 314 - Updated Fibaro RGBW Config File (Justin) - Fixed Issue 318 - Updated Fibaro Wall Plug Config File (Justin) - Fixed Issue 321 - Updated Fibaro FGRM222 Config File (Justin) - Fixed Issue 324 - New Config file for Aeon Labs MiniMote (Justin) - Added ZWave.Me iTemp Config file thanks to Willem Burgers (Justin) - Added new id for Aeon Labs Micro Smart Engergy Illuminator G2 thanks to jmeyer (Justin) - Fixed Issue 329 - Update Fibaro FGD211 Config File (Alex) - Fixed Issue 330 - Update Fibaro FGS211 Config File (Alex) - Fixed Issue 331 - Update Fibaro RGBWM441 Config File (Alex) - Add new id for GE Duplex Receptacle (Alex) - Add 18 new ids for Vision devices (Alex) - Add Device Qees RETO Plug-in Switch Plus Config File (Alex) - Implement DoorLockLogging Command Class (Justin) - Implement Security Command Class (Justin) - Add a additional ID for Vision ZM1701 Deadbolt without Handle (Justin) - Add a ID and Config file for Assa Abloy Real Living Cap-Touch Deadbolt (Justin) - Implement the TimeParameters Command Class (Justin) - Fix up AssumeAwake Option for the Wakeup Class (Justin) - Update BeNext Tag Reader Config File (Alex) - Fixed Issue 335 - Update zwave.me KeyFob Config File (Alex) - Fixed Issue 336 - Update Aeon Labs DoorSensor Config File (Alex) - Fixed Issue 337 - Update Aeon Labs Multi Sensor Config File (Alex) - Fixed Issue 338 - Update Aeon Labs Multi Sensor Config File (Alex) - Fixed Issue 339 - Update Fibaro Door Opening Sensor Config File (Alex) - Fixed Issue 340 - Add Remotec ZRC-100 Remote Control (Alex) - Fixed Issue 301 - Add Philio PAN04-1 Relay Insert (Alex) - Fixed Issue 341 - Corrected directory/filename errors in manufacturer xml (Alex) - Fixed Issue 342 - Added 4 Qubino devices thanks to jeanfrancois (Alex) - Fixed Issue 345 - Added new ids for Fibaro FGK101 and FGBS001 (Alex) - Fixed Issue 351 - Added new ids for Vision VS6301 and updated Product Name (Justin) - Fixed Issue 348 - Typo in Config Index Number for zwave.me ZME_06436 (Justin) - Fix Several Warnings/Initilizers etc (Justin) - Fixed Issue 357 - Fixed Qubino manufacturer id from 345 (dec) to 159 (hex) (Alex) - Fixed Issue 356 - New ID for Fibaro FGMS001 (Alex) - Do Not Open and Close the Log file on each message. Close it during the Destructor (Justin) - Race Condition in the RemoveDriver call and Notifications. Add a new Notification about the Driver being removed, and by default turn off NodeRemoved/ValueRemoved Notifications from being sent if the Driver is being unloaded. WARNING: If you call any manager functions that require the Driver after recieving this message, there is a high probability your application will crash with a SegV (Justin) - Fixed Issue 361 - Update Qubino ZMNHDA2 Config File, proper endpoint mapping (Alex) - Fixed Issue 359 - Update Qubino ZMNHBA2 Config File, fixed invalid group 4 (Alex) - Fixed Issue 360 - Add Config File for Popp 123658 (Alex) - Fixed Issue 364 - Update Schlagelink iTemp Config File, removed invalid char (Alex) - Fixed Issue 365 - Add Config File for Popp 123601 Plug-in Switch thanks to tony.b.hansson (Alex) - Fixed Issue 366 - Add Config File for Popp 123580 Plug-in Dimmer thanks to tony.b.hansson (Alex) - Fixed Issue 363 - Added new id for Schlagelink iTemp thanks to steph10200 (Alex) - Fixed Issue 370 - Fixed Config File for zwave.me 06433 thanks to geilername (Alex) - Fixed Issue 368 - Bounds Checking on our String Arrays (Justin) - Fixed Issue 362 - Fix Mapping between ValueGenre Names and Enum's. This might require you to delete your zwcfg_*.xml file if you encounter problems (Justin) - Fixed Issue 371 - Double ReleaseNodes on Invalid Node in GetNodeStatistics (Justin) - Fixed Issue 372 - Mutex Unlocking in the Driver::isPolled method (Justin) - Remove tinyxml.h include from our headers so we don't have to distribute the TinyXML header files (Justin) - Remove the hidapi.h include from our headers so we don't have to distribute the hidapi header files (Justin) - Fixed Issue 375 - Add Ecolink Garage Door Sensor - (Justin) open-zwave-1.5/INSTALL000066400000000000000000000050551264474202400145150ustar00rootroot00000000000000Minimal Install Guide for OpenZWave! For Unix's (including Mac, bsd's etc) ================= execute Make in the Top Level Directory make Libraries to link to (Static and Dynamic) will be in top level directory as well (but you can change that as detailed below with LIBDIR) To Install: make install Some Options you can set: "BUILD=(release|debug)" - Build a Release or Debug Version of the Library (Release is default) "PREFIX=(path)" - Prefix to install the shared library into - Defaults to /usr/local "LIBDIR=/tmp" - Path to place the libraries into after complication. A poor mans "make install" for simple Applications. To use the options, specify them on the commandline when executing make eg: "BUILD=debug PREFIX=/opt/local make" What Gets installed: When make install is called the following happens: * Documentation: if you have DoxyGen, API documentation is installed into (PREFIX)/share/doc/openzwave-(version)/ * Shared Libary (libopenzwave.so.*): The Shared Library is installed into either (prefix)/lib64 (on 64 bit platforms) or (prefix)/lib/ on 32 bit platforms) * Header Files: Installed into (prefix)/include/openzwave/ * pkg-config file: Installed into (prefix)/lib(64)/pkgconfig/libopenzwave.pc * Config files and Device Databases (manufacturer_specific.xml et al) Installed into (prefix)/etc/openzwave/ * MinOZW example program: Installed into (prefix)/bin/ directory The Static Version of the library is never installed, but will be created in top build directory after a successfull make. Windows Versions ================ Visual Studio Solution Files and Mingw32 Makefiles are present in cpp/build/windows/. Select the correct Visual Studio or Mingw32 directory depending on the versions you have. (Note, if building DLL's on Windows (currently a option in the vs2010 solution) - You have to ensure you application is compiled with exactly the same compiler options and versions as OpenZWave - Otherwise strange things might happen) For the .NET dll, the solution files exist in the dotnet/build/ directory Sample Programs =============== For all platforms, there is a simple example program that will print out events as they happen on your ZWave network. This sample is called MinOZW and you can find the source in the cpp/examples directory. By default, these examples are built during the Make Install Stage. If you want compile them separately, you can use the "make examples" target. For the .NET wrapper, there is a OZWForm application in dotnet/examples/OZWForm/. Please read the README file in that directory for further instructions open-zwave-1.5/Makefile000066400000000000000000000032261264474202400151220ustar00rootroot00000000000000# # Makefile for OpenzWave Mac OS X applications # Greg Satz # GNU make only # requires libudev-dev .SUFFIXES: .d .cpp .o .a .PHONY: default clean install top_srcdir := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) top_builddir ?= $(CURDIR) export top_builddir PREFIX ?= /usr/local export PREFIX all: CPPFLAGS=$(CPPFLAGS) $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) 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) clean: $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) $(MAKECMDGOALS) $(MAKE) -C $(top_srcdir)/cpp/examples/MinOZW/ -$(MAKEFLAGS) $(MAKECMDGOALS) cpp/src/vers.cpp: CPPFLAGS=$(CPPFLAGS) $(MAKE) -C $(top_srcdir)/cpp/build/ -$(MAKEFLAGS) cpp/src/vers.cpp check: xmltest include $(top_srcdir)/cpp/build/support.mk ifeq ($(XMLLINT),) xmltest: $(XMLLINT) $(error xmllint command not found.) else xmltest: $(XMLLINT) @$(XMLLINT) --noout --schema $(top_srcdir)/config/device_classes.xsd $(top_srcdir)/config/device_classes.xml @$(XMLLINT) --noout --schema $(top_srcdir)/config/options.xsd $(top_srcdir)/config/options.xml @$(XMLLINT) --noout --schema $(top_srcdir)/config/manufacturer_specific.xsd $(top_srcdir)/config/manufacturer_specific.xml @$(XMLLINT) --noout --schema $(top_srcdir)/config/device_configuration.xsd $(top_srcdir)/config/*/*.xml endif dist-update: @echo "Updating List of Distribition Files" @$(GIT) ls-files > .distfiles @$(top_srcdir)/makedist DIST_FORMATS ?= gzip include $(top_srcdir)/distfiles.mk include $(top_srcdir)/dist.mk open-zwave-1.5/README.md000066400000000000000000000126501264474202400147420ustar00rootroot00000000000000Open-ZWave Library ================== 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. 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 ## 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. ## 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 your 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 think you have found a bug, please see the next section. 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 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. ## 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. ## Contributing to OZW We are happy to accept Pull Requests via GitHub. A few things to follow when preparing a Pull Request. 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. ## Final Words As mentioned above, Open-ZWave is developed by mainly reverse engineering the protocol as well as consulting various public information on the Internet. We have not used any of the Sigma SDK’s or documentation and thus often it will take us a while to support new features of Z-Wave. We have had very preliminary discussions with both the Z-Wave Alliance and Sigma previously but we do not have any "official" endorsement from either of them (though that is a goal for the developers). We do believe that OZW has benefited the Z-Wave ecosystem though, and have received feedback that we are well known by various Z-Wave Vendors. That being said, although our license (LGPL) permits commercial applications (provided your follow the rules) we strong recommend you consult a lawyer prior to implementing OZW support into your application. Of course, for Open Source applications, as long as you abide by our License (LGPL) we would love to welcome you the OZW community! And for those that are wondering, you cannot use OZW to create Z-Wave Nodes. This is not the goal of the library, and we believe that if we started implementing a software stack that allowed users to start creating Z-Wave Nodes, Sigma designs would not be so happy about our existence. Hence please avoid discussing this topic on our mailing list . open-zwave-1.5/config/000077500000000000000000000000001264474202400147245ustar00rootroot00000000000000open-zwave-1.5/config/2gig/000077500000000000000000000000001264474202400155545ustar00rootroot00000000000000open-zwave-1.5/config/2gig/ct100.xml000066400000000000000000000003251264474202400171250ustar00rootroot00000000000000 open-zwave-1.5/config/2gig/ct101.xml000066400000000000000000000003251264474202400171260ustar00rootroot00000000000000 open-zwave-1.5/config/2gig/ct30.xml000066400000000000000000000003251264474202400170470ustar00rootroot00000000000000 open-zwave-1.5/config/BeNext/000077500000000000000000000000001264474202400161115ustar00rootroot00000000000000open-zwave-1.5/config/BeNext/1poleswitch.xml000066400000000000000000000027621264474202400211040ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). The mode in which a different Z-Wave message is sent. The time that a user has to activate the double button pressed scene, if time is passed then the single pressed button scene is notified. (value * 10 ms) A signed integer to determine the offset of the temperature. open-zwave-1.5/config/BeNext/2poleswitch.xml000066400000000000000000000027621264474202400211050ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). The mode in which a different Z-Wave message is sent. The time that a user has to activate the double button pressed scene, if time is passed then the single pressed button scene is notified. (value * 10 ms) A signed integer to determine the offset of the temperature. open-zwave-1.5/config/BeNext/AlarmSound.xml000066400000000000000000000075521264474202400207110ustar00rootroot00000000000000 Set all configuration values to default values (factory settings) Enables an internal routine that periodically checks the Z-Wave device in assocication group 2 Configure the time that the AlarmSound sends a new frame when previous frame was send successful Configure the time that the AlarmSound sends a few frame when previous frame was send not successful A (signed) offset to calibrate the onboard temperature sensor A (signed) offset to calibrate the onboard temperature sensor The index of the sound mode when a switch binary/basic set frame is received The index of the sound mode when the AlarmSound will start when it is unplugged The index of the sound mode when the AlarmSound will play when it is unable to reach the device in association group 2 Params 10 until 27 are the values to configure the sound and light thtat are played when index 1 is selected Params 28 until 45 are the values to configure the sound and light thtat are played when index 2 is selected Params 46 until 63 are the values to configure the sound and light thtat are played when index 3 is selected Params 64 until 81 are the values to configure the sound and light thtat are played when index 4 is selected Params 82 until 99 are the values to configure the sound and light thtat are played when index 5 is selected Params 100 until 117 are the values to configure the sound and light thtat are played when index 6 is selected open-zwave-1.5/config/BeNext/BuiltinDimmer.xml000066400000000000000000000121511264474202400213770ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). The way how the button reacts when press/released The way the Built-in Dimmer reacts when light is turned on/off with button This parameter is used to enable the dimming option of the product. When disabled the dimming and fading routine are disabled. The maximum powerload in watts when light is turned on, when measured higher then this value the Inline Dimmer is automatically turned off. The speed of dimming when activated (manual and RF). Dim speed is 1% per value (* 10 ms) The speed of fading up when activated (manual and RF). Fade speed is 1% per value (* 10 ms) The time window to repress button to start dimming. Toggle time is value (* 10ms) A percentage that an energy value must be different compared to a previous sent value before an unsolicited meter report is sent. Minimum value = 10% Maximum value = 100% A watt value that an energy value must be different compared to a previous sent value before an unsolicited meter report is sent. Minimum value = 5 watt Maximum value = 255 watt A time value that has to be passed compared to a previous sent value before a unsolicited meter report is sent. Minimum value = 10 seconds Maximum value = 255 seconds What to do with lamp status when power applied. If 0x00: Always switch light off when power applied. If > 0x00: Switch lamp on/off depending on last known lampstatus before power was disconnected. The speed of fading up when activated (manual and RF). Fade speed is 1% per value (* 10 ms) open-zwave-1.5/config/BeNext/DoorSensor.xml000066400000000000000000000057731264474202400207440ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). Configure what the external contact sends when triggered. (Default: 0) Is not used but can still be set and requested. Is not used but can still be set and requested. To configure the operating mode. (Default: 1) A signed integer to determine the offset of the temperature. (Default: 0) Debounce time when the external contact is opened. (Default: 0) Debounce time when the external contact is opened. (Default 0) A delay from the wake up time to give the external contact a chance to change his status. (Default 0, value * 100 ms, 0 - 25,5 seconds) open-zwave-1.5/config/BeNext/EnergySwitch.xml000066400000000000000000000026161264474202400212530ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). The state in what the switch is when power is supplied. When the relay is switched it can't be switched again until the configured time has passed. Show the led state compared to the relay state. open-zwave-1.5/config/BeNext/HeatingControl.xml000066400000000000000000000055651264474202400215660ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). The interval that data is requested (and therefore updated) from the thermostat and boiler. Value in seconds. The value that the room temperature must differ (compared to his previous send value) before an unsolicited room temperature report is send to the associated node. Value in 0.1 °C. The value that the temperature setpoint must differ (compared to his previous send value) before an unsolicited temperature setpoint report is send to the associated node. Value in 0.1 °C . TConfigure if the unsolicited reports are send with the CRC-16 encapsulation. Not that the receiving node should support this encapsulation to parse the Z-Wave frame! Type of 'special' thermostat: NOTE: when remeha Celcia 20 support is set then any other thermostat can not be set (!) NOTE2: when Remeha Celcia 20 gives 'Fout 203' send cfg value again Enable/Disable thermostat schedule inside the heatingcontroller. open-zwave-1.5/config/BeNext/Molite.xml000066400000000000000000000040531264474202400200660ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). The time used in mode 2 to turn the sensor off. This Time will start running as soon as detection is seen. The switch off time will start running as soon as mode timeout is done. Motion sensor is turned on and when movement is detected again the mode timeout (cfg param 1) will start running all over again. When switch off time is done a basic off message is sent to the associated node. Sensitivity value between 0 and 127 (values above 127 will be reported as the set value but will be handled in SW as 127). The mode that is entered after detection. If mode is 0 or higher then 3, that value will be reported after a get but will be handled in SW as mode 2. open-zwave-1.5/config/BeNext/PluginDimmer.xml000066400000000000000000000105711264474202400212330ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). The way the Built-in Dimmer reacts when light is turned on/off with button This parameter is used to enable the dimming option of the product. When disabled the dimming and fading routine are disabled. The maximum powerload in watts when light is turned on, when measured higher then this value the Inline Dimmer is automatically turned off. The speed of dimming when activated (manual and RF). Dim speed is 1% per value (* 10 ms) The speed of fading up when activated (manual and RF). Fade speed is 1% per value (* 10 ms) A percentage that an energy value must be different compared to a previous sent value before an unsolicited meter report is sent. Minimum value = 10% Maximum value = 100% A watt value that an energy value must be different compared to a previous sent value before an unsolicited meter report is sent. Minimum value = 5 watt Maximum value = 255 watt A time value that has to be passed compared to a previous sent value before a unsolicited meter report is sent. Minimum value = 10 seconds Maximum value = 255 seconds What to do with lamp status when power applied. If 0x00: Always switch light off when power applied. If > 0x00: Switch lamp on/off depending on last known lampstatus before power was disconnected. The speed of fading up when activated (manual and RF). Fade speed is 1% per value (* 10 ms) open-zwave-1.5/config/BeNext/SceneController.xml000066400000000000000000000020171264474202400217340ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). The time that a user has to activate the double button pressed scene, if time is passed then the single pressed button scene is notified. open-zwave-1.5/config/BeNext/TagReader.xml000066400000000000000000000042351264474202400204750ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). To configure the time the beep is automatically turned off in seconds. To configure the timeout to wait for a WAKEUP_NO_MORE_INFORMATION before the error beep is automatically sound. The error beeps are fixed 8 beeps shortly after each other. To configure the number of beeps per second. Every beep is fixed about 10ms. To configure the operating mode. If any mode other then 3, that value will be reported after a get but will be handled in SW as mode 1. The time (*10 ms) that the RFID circuit is started after home or away is pressed (default 100 = 100*10ms=1s) open-zwave-1.5/config/POP009303.xml000066400000000000000000000154721264474202400165740ustar00rootroot00000000000000 In separate mode button 1 works with Group A, button 3 with Group 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 Wall Controller wakes up and there is no controller nearby, several unsuccessful communication attempts will drain battery. If the Wall Controller wakes up and there is no controller nearby, several unsuccessful communication attempts will drain battery. open-zwave-1.5/config/act/000077500000000000000000000000001264474202400154735ustar00rootroot00000000000000open-zwave-1.5/config/act/lfm20.xml000066400000000000000000000002221264474202400171310ustar00rootroot00000000000000 open-zwave-1.5/config/act/zdm230.xml000066400000000000000000000135411264474202400172400ustar00rootroot00000000000000 Dimmers controlled by this switch will start dimming from their current level. Disable transmitting commands to Z-Wave devices that are in Group 4 without disassociating those devices from the group. In night-light mode the LED on the switch will turn ON when the switch is turned OFF. Change the top of the switch to OFF and the bottom of the switch to ON. Note: If you invert the switches and also install the product upside down, remember the load will now be controlled by the right, not the left switch. This dimmer will start dimming from its current level. When you press and hold the bottom of the ZDM230 switch once, the Z-Wave devices that are associated into Group 1 are sent the Dim command. If this parameter is set to "Yes" the devices in Group 1 will not go to the same level as the ZDM230. 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. Units in Group 4 only track when the dimmer is being turned ON and OFF and not while dimming. The ZDM230 can operate shade control devices via its group 2. The ZDM230 can operate shade control devices via its group 3. The ZDM230 will flicker its LED when it is transmitting to any of its 4 groups. This flickering can be set to not flicker at all, to flicker the entire time it is transmitting, or to flicker for only 1 second when it begins transmitting. Poll Group 2 Interval Poll Group 2 open-zwave-1.5/config/act/zdw103.xml000066400000000000000000000104471264474202400172530ustar00rootroot00000000000000 Dimmers controlled by this switch will start dimming from their current level. In night-light mode the LED on the switch will turn ON when the switch is turned OFF. Change the top of the switch to OFF and the bottom of the switch to ON. This dimmer will start dimming from its current level. 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. The ZDW103 can operate shade control devices via its group 2. The ZDW103 can operate shade control devices via its group 3. The ZDW103 will flicker its LED when it is transmitting to any of its 4 groups. This flickering can be set to not flicker at all, to flicker the entire time it is transmitting, or to flicker for only 1 second when it begins transmitting. open-zwave-1.5/config/act/zdw232.xml000066400000000000000000000165271264474202400172630ustar00rootroot00000000000000 The ZDW232 can send Dim commands to Z-Wave enabled dimmers. The Dim command has a start level embedded in it. A dimmer receiving this command will start dimming from that start level. However, the command also has a bit that indicates whether the dimmer should ignore the start level. If the bit is set to 1, the dimmer will ignore the start level and instead start dimming from its current level. If this bit is set to 0, the dimmer will not ignore the start level. You may wish to disable transmitting commands to Z-Wave devices that are in Group 4 without "un-associating" those devices from the group. Setting parameter 2 to the value of 1 will stop the ZDW232 from transmitting to devices that are "associated" into Group 4. It is possible that you may only want the units in Group 4 to track when the dimmer is being turned ON and OFF and not when dimming. In night-light mode the LED on the switch will turn ON when the switch is turned OFF. To change the top of the switch to OFF and the bottom of the switch to ON, set parameter 4 to 1. The ZDW232 can be set to ignore the start level that is part of the dim command, regardless of whether the command is telling the dimmer to ignore the start level or not ignore the start level embedded in the command (see Parameter 1). Setting parameter 5 to a value of 1 (factory default) will cause the ZDW232 to ignore the start level and to dim or brighten from its current level. Setting the value to 0 will cause the ZDW232 to dim or brighten from the level in the command. When you press and hold the bottom of the ZDW232 switch once, the Z-Wave devices that areassociated into Group 1 are sent the Dim command. If parameter 6 is set to 0, after you release the switch, the ZDW232 will command devices in that group to go to the same level of the ZDW232. If parameter 6 is set to a value of 1 (factory default) the devices in Group 1 will not go to the same level of the ZDW232. 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. After the ZDW232 is commanded to stop dimming, it will then command the Z-Wave devices in Group 4 to the ZDW232's new level. To prevent the ZDW232 from commanding the Z-Wave devices in Group 4 during this particular occurrence, set Parameter 13 to the value of 1. The ZDW232 can operate shade control devices via its group 2 if this configuration parameter is set to 1. The ZDW232 can operate shade control devices via its group 3 if this configuration parameter is set to 1. The ZDW232 will flicker its LED when it is transmitting to any of its 4 groups. This flickering can be set to not flicker at all, to flicker the entire time it is transmitting, or to flicker for only 1 second when it begins transmitting. Poll Group 2 Interval Poll Group 2 open-zwave-1.5/config/act/zir010.xml000066400000000000000000000060411264474202400172430ustar00rootroot00000000000000 The ZIR010 can be configured to operate in 1 of 3 modes. Those modes are: Lighting Mode (factory default) Alarm Mode Sensor Mode To change the mode of operation: For Lighting Mode: Send a value of 0 to Configuration Parameter #17. For Alarm Mode: Send a value of 1 to Configuration Parameter #17. For Sensor Mode: Send a value of 2 to Configuration Parameter # 17. Information reproduced from: http://www.pepper1.net/zwavedb/uploads/resources/bdf086a9388325a2fb8b8aa298e24e512faec65d.pdf The configuration parameter that can be used to adjust the amount of delay before the OFF or IDLE command is transmitted is Configuration Parameter # 18. This parameter can be configured with the value of 0 through 255. Where 0 means no delay and 255 means 255 minutes of delay. Default appears to be 1 min. Information reproduced from: http://www.pepper1.net/zwavedb/uploads/resources/bdf086a9388325a2fb8b8aa298e24e512faec65d.pdf The ZIR010 can be disabled from sending commands unsolicited without removing associated devices by setting Configuration Parameter # 19 to 0 (when asked for number of bytes, select 1). Setting it back to 1 will re-enable the ZIR010. Information reproduced from: http://www.pepper1.net/zwavedb/uploads/resources/bdf086a9388325a2fb8b8aa298e24e512faec65d.pdf The time the ZIR010 stays awake can be adjusted from 15 seconds to 45 seconds by sending a value of 15 to 45 to the ZIR010 using Configuration Parameter # 22 (when asked for the number of bytes, select 1). This awake time period starts over every time the ZIR010 receives a command or request. Defaults to 30 seconds. Information reproduced from: http://www.pepper1.net/zwavedb/uploads/resources/bdf086a9388325a2fb8b8aa298e24e512faec65d.pdf open-zwave-1.5/config/act/zrp110.xml000066400000000000000000000004241264474202400172520ustar00rootroot00000000000000 open-zwave-1.5/config/act/zrw103.xml000066400000000000000000000033561264474202400172720ustar00rootroot00000000000000 Dimmers controlled by this switch will start dimming from their current level. In night-light mode the LED on the switch will turn ON when the switch is turned OFF. Change the top of the switch to OFF and the bottom of the switch to ON. The ZRW103 will flicker its LED when it is transmitting to any of its 4 groups. This flickering can be set to not flicker at all, to flicker the entire time it is transmitting, or to flicker for only 1 second when it begins transmitting. open-zwave-1.5/config/aeotec/000077500000000000000000000000001264474202400161645ustar00rootroot00000000000000open-zwave-1.5/config/aeotec/alms.xml000066400000000000000000000071461264474202400176520ustar00rootroot00000000000000 Stay awake for 10 minutes after batteries are inserted How long should the device associated to multi sensor keep state On before sending it Off command (if the value is bigger than 255, the value would be rounded to next integer in minutes) Enable Motion Sensor Which commands to send when PIR motion sensor triggered Reset to default parameters number 101-103. Any value other then 0 will initiate this reset. Which reports need to send automatically in timing intervals for group 1. Bitsets: 0 -> Battery report, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity Which reports need to send automatically in timing intervals for group 2. Bitsets: 0 -> Battery report, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity Which reports need to send automatically in timing intervals for group 3. Bitsets: 0 -> Battery report, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity Reset to default parameters number 111-113. Any value other then 0 will initiate this reset. The interval of sending report group 1. 1 to 2678400 seconds The interval of sending report group 2. 1 to 2678400 seconds The interval of sending report group 3. 1 to 2678400 seconds Reset to factory defaults. open-zwave-1.5/config/aeotec/doorbell_gen5.xml000066400000000000000000000123001264474202400214220ustar00rootroot00000000000000 Set the repetitions for playing doorbell ringtone. Value=1 to 255, the range of repetition is 1 to 100. Note: If the time of playing doorbell ringtone is more than 20s, the volume of ringtone will reduce to silence no matter how many repetitions of doorbell ringtone are set. Set the default doorbell ringtone. Value=1-100, Specify the ringtone as default. Select a ringtone to play. Value=0, stop playing. Value=1-100, play the specified ringtone. Value=255, play the default ringtone. Value=other, ignore. Playback Control Set the volume of ringtone. Define functions of "Button -" and "Button+". Button - is previous, Button+ is next. Define functions of "Button -" and "Button+" when short pressing and long pressing it. Get Wireless Button Battery Status Defines the automated status notification of an associated device when status changes Defines the automated status notification of an associated device when the wireless button battery level changes Pair the Wireless Button with Doorbell. Value=0x55555555, Start the Wireless Button pairing mode and the blue Led will blink slowly, short press the Wireless Button once, if the blue Led change to be solid, which means the pairing is successful. Otherwise, repeat the steps. It will automatically exit the pairing mode after 8s if there is no pressing action of the Wireless Button. Note: You can send this configuration Get CC to ask the pairing result: If configuration report value=0x00000000, which means the pairing is failed. If configuration report value =0xFFFFFFFF, which means the pairing is successful. Enable/disable Configuration Locked Reset to the default configuration. open-zwave-1.5/config/aeotec/doorwindow.xml000066400000000000000000000042611264474202400211040ustar00rootroot00000000000000 Default setting: Open: FF, Close: 00 Default setting: Disable Default setting: Open: FF, Close: 00 Which reports need to send automatically in timing intervals for group 1. Bitsets: 0->Battery report, 4->Sensor Binary, 8->Basic Set, Default setting: 0x00000100 (Basic Set) Ideal Setting for OZW is 17 (Sensor Binary and Battery Report) Device Tag Reset to factory defaults. open-zwave-1.5/config/aeotec/drycontactsensor.xml000066400000000000000000000056421264474202400223210ustar00rootroot00000000000000 Which value of the Sensor Binary Report will be sent when the Sensor is triggered On. Enable/disable wake up 10 minutes when re-power on the Sensor. Which value of the Basic Report will be sent when the Sensor is triggered On. Set the low battery value. Set the interval time of battery report. Value=0, disable the battery report for a interval time. Value=1 to 0x7FFFFFFF, the interval time of battery report is set. Note: 1, if the value is less than 10, the time unit is second. If the value is more than 10, the time unit is 4 minutes, which means if the value is more than 10 and less than 240, the interval time is 4 minutes. If the value is more than 240 and less than 480, the interval is 8 minutes. 2, if the current battery report falls below the low battery value (configurable parameter 39), it will send battery report=0xFF. Defines the type of report sent. Value 1 (msb) Reserved Value 2 Reserved Value 3 bits 7-1 reserved bits 0 - Basic Report Value 4 (lsb) bits 7-4 reserved bit 3 Sensor Binary bit 2-0 reserved Reset to the default configuration. open-zwave-1.5/config/aeotec/dsd31.xml000066400000000000000000000050001264474202400176170ustar00rootroot00000000000000 Select the Siren Sound and Volume Enable to send notifications to associated devices (Group 1) when the state of Siren changed Partner ID Enable/disable Lock Configuration Reset to the default configuration. open-zwave-1.5/config/aeotec/hdss_gen5.xml000066400000000000000000000143141264474202400205700ustar00rootroot00000000000000 Current Overload Protection. Load will be closed when the Current more than 39.5A and the time more than 5 seconds LED status after power on Enables automatic notifications to associated devices whenever there is a state change. Enable/disable Wattage threshold and percent. The minimum change in wattage for a report to be sent. Minimum change in percent of wattage to send a report. Set report types for groups 1, 2 and 3 to default. Reverts to 0 after set. Defines the type of report sent for reporting group 1. 2 is multisensor report. 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 MRC (KWH) bit 2 MRC (watt) bit 1 MSRC (Current) bit 0 MRC (Voltage) The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. Defines the type of report sent for reporting group 2. 2 is multisensor report. 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 MRC (KWH) bit 2 MRC (watt) bit 1 MSRC (Current) bit 0 MRC (Voltage) The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. Defines the type of report sent for reporting group 3. 2 is multisensor report. 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 MRC (KWH) bit 2 MRC (watt) bit 1 MSRC (Current) bit 0 MRC (Voltage) The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. 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. Lock/ unlock all configuration parameters Reset to the default configuration. open-zwave-1.5/config/aeotec/hem.xml000066400000000000000000000214531264474202400174640ustar00rootroot00000000000000 Voltage to calculate wattage from amperage. US=120. EU,ANZ=240. Automatic report only when power is changed. Threshold change in wattage to induce a automatic report (whole HEM). Threshold change in wattage to induce a automatic report (Clamp 1). Threshold change in wattage to induce a automatic report (Clamp 2). Threshold change in wattage to induce a automatic report (Clamp 3). Percentage change in wattage to induce a automatic report (whole HEM). Percentage change in wattage to induce a automatic report (Clamp 1). Percentage change in wattage to induce a automatic report (Clamp 2). Percentage change in wattage to induce a automatic report (Clamp 3). Accumulate energy when Battery Powered. This byte denotes whether the product is using batteries (value = 0) or using USB power (value = 1). Reset to default parameters number 101-103. Any value other then 0 will initiate this reset. Which reports need to send in group1. Format is as follows: Byte 1 (msb): Reserved Byte 2: Reserved Byte 3: Bit 7: reserved Bit 6: reserved Bit 5: Auto Send Meter Report (for kWh) at the group time interval (Clamp 3) Bit 4: Auto Send Meter Report (for kWh) at the group time interval (Clamp 2) Bit 3: Auto Send Meter Report (for kWh) at the group time interval (Clamp 1) Bit 2: Auto Send Meter Report (for watts) at the group time interval (Clamp 3) Bit 1: Auto Send Meter Report (for watts) at the group time interval (Clamp 2) Bit 0: Auto Send Meter Report (for watts) at the group time interval (Clamp 1) Byte 4 (lsb): Bit 7: reserved Bit 6: reserved Bit 5: reserved Bit 4: reserved Bit 3: Auto Send Meter Report (for kWh) at the group time interval (whole HEM) Bit 2: Auto Send Meter Report (for watts) at the group time interval (whole HEM) Bit 1: Auto Send Multilevel Sensor Report (for watts) at the group time interval (whole HEM) Bit 0: Auto Send Battery Report at the group time interval (whole HEM) Which reports need to send in group2. Format is as follows: Byte 1 (msb): Reserved Byte 2: Reserved Byte 3: Bit 7: reserved Bit 6: reserved Bit 5: Auto Send Meter Report (for kWh) at the group time interval (Clamp 3) Bit 4: Auto Send Meter Report (for kWh) at the group time interval (Clamp 2) Bit 3: Auto Send Meter Report (for kWh) at the group time interval (Clamp 1) Bit 2: Auto Send Meter Report (for watts) at the group time interval (Clamp 3) Bit 1: Auto Send Meter Report (for watts) at the group time interval (Clamp 2) Bit 0: Auto Send Meter Report (for watts) at the group time interval (Clamp 1) Byte 4 (lsb): Bit 7: reserved Bit 6: reserved Bit 5: reserved Bit 4: reserved Bit 3: Auto Send Meter Report (for kWh) at the group time interval (whole HEM) Bit 2: Auto Send Meter Report (for watts) at the group time interval (whole HEM) Bit 1: Auto Send Multilevel Sensor Report (for watts) at the group time interval (whole HEM) Bit 0: Auto Send Battery Report at the group time interval (whole HEM) Which reports need to send in group3. Format is as follows: Byte 1 (msb): Reserved Byte 2: Reserved Byte 3: Bit 7: reserved Bit 6: reserved Bit 5: Auto Send Meter Report (for kWh) at the group time interval (Clamp 3) Bit 4: Auto Send Meter Report (for kWh) at the group time interval (Clamp 2) Bit 3: Auto Send Meter Report (for kWh) at the group time interval (Clamp 1) Bit 2: Auto Send Meter Report (for watts) at the group time interval (Clamp 3) Bit 1: Auto Send Meter Report (for watts) at the group time interval (Clamp 2) Bit 0: Auto Send Meter Report (for watts) at the group time interval (Clamp 1) Byte 4 (lsb): Bit 7: reserved Bit 6: reserved Bit 5: reserved Bit 4: reserved Bit 3: Auto Send Meter Report (for kWh) at the group time interval (whole HEM) Bit 2: Auto Send Meter Report (for watts) at the group time interval (whole HEM) Bit 1: Auto Send Multilevel Sensor Report (for watts) at the group time interval (whole HEM) Bit 0: Auto Send Battery Report at the group time interval (whole HEM) Reset to default parameters number 111-113. Any value other then 0 will initiate this reset. The interval of sending report group 1. The interval of sending report group 2. The interval of sending report group 3. Re-calibrate (will destroy factory calibration). CONTACT AEON LABS before using. Device tag. Reset to the default configuration. open-zwave-1.5/config/aeotec/hemg2.xml000066400000000000000000000204221264474202400177100ustar00rootroot00000000000000 If the reverse clamping pliers, negative power is detected. Automatic report only when power is changed. Threshold change in wattage to induce a automatic report (whole HEM). Threshold change in wattage to induce a automatic report (Clamp 1). Threshold change in wattage to induce a automatic report (Clamp 2). Threshold change in wattage to induce a automatic report (Clamp 3). Percentage change in wattage to induce a automatic report (whole HEM). Percentage change in wattage to induce a automatic report (Clamp 1). Percentage change in wattage to induce a automatic report (Clamp 2). Percentage change in wattage to induce a automatic report (Clamp 3). Reset to default parameters number 101-103. Any value other then 0 will initiate this reset. Which reports need to send in group1. Format is as follows: Byte 1 (msb): Reserved Byte 2: Reserved Byte 3: Bit 7: reserved Bit 6: reserved Bit 5: Auto Send Meter Report (for kWh) at the group time interval (Clamp 3) Bit 4: Auto Send Meter Report (for kWh) at the group time interval (Clamp 2) Bit 3: Auto Send Meter Report (for kWh) at the group time interval (Clamp 1) Bit 2: Auto Send Meter Report (for watts) at the group time interval (Clamp 3) Bit 1: Auto Send Meter Report (for watts) at the group time interval (Clamp 2) Bit 0: Auto Send Meter Report (for watts) at the group time interval (Clamp 1) Byte 4 (lsb): Bit 7: reserved Bit 6: reserved Bit 5: reserved Bit 4: reserved Bit 3: Auto Send Meter Report (for kWh) at the group time interval (whole HEM) Bit 2: Auto Send Meter Report (for watts) at the group time interval (whole HEM) Bit 1: Auto Send Multilevel Sensor Report (for watts) at the group time interval (whole HEM) Bit 0: Auto Send Battery Report at the group time interval (whole HEM) Which reports need to send in group2. Format is as follows: Byte 1 (msb): Reserved Byte 2: Reserved Byte 3: Bit 7: reserved Bit 6: reserved Bit 5: Auto Send Meter Report (for kWh) at the group time interval (Clamp 3) Bit 4: Auto Send Meter Report (for kWh) at the group time interval (Clamp 2) Bit 3: Auto Send Meter Report (for kWh) at the group time interval (Clamp 1) Bit 2: Auto Send Meter Report (for watts) at the group time interval (Clamp 3) Bit 1: Auto Send Meter Report (for watts) at the group time interval (Clamp 2) Bit 0: Auto Send Meter Report (for watts) at the group time interval (Clamp 1) Byte 4 (lsb): Bit 7: reserved Bit 6: reserved Bit 5: reserved Bit 4: reserved Bit 3: Auto Send Meter Report (for kWh) at the group time interval (whole HEM) Bit 2: Auto Send Meter Report (for watts) at the group time interval (whole HEM) Bit 1: Auto Send Multilevel Sensor Report (for watts) at the group time interval (whole HEM) Bit 0: Auto Send Battery Report at the group time interval (whole HEM) Which reports need to send in group3. Format is as follows: Byte 1 (msb): Reserved Byte 2: Reserved Byte 3: Bit 7: reserved Bit 6: reserved Bit 5: Auto Send Meter Report (for kWh) at the group time interval (Clamp 3) Bit 4: Auto Send Meter Report (for kWh) at the group time interval (Clamp 2) Bit 3: Auto Send Meter Report (for kWh) at the group time interval (Clamp 1) Bit 2: Auto Send Meter Report (for watts) at the group time interval (Clamp 3) Bit 1: Auto Send Meter Report (for watts) at the group time interval (Clamp 2) Bit 0: Auto Send Meter Report (for watts) at the group time interval (Clamp 1) Byte 4 (lsb): Bit 7: reserved Bit 6: reserved Bit 5: reserved Bit 4: reserved Bit 3: Auto Send Meter Report (for kWh) at the group time interval (whole HEM) Bit 2: Auto Send Meter Report (for watts) at the group time interval (whole HEM) Bit 1: Auto Send Multilevel Sensor Report (for watts) at the group time interval (whole HEM) Bit 0: Auto Send Battery Report at the group time interval (whole HEM) Reset to default parameters number 111-113. Any value other then 0 will initiate this reset. The interval of sending report group 1. The interval of sending report group 2. The interval of sending report group 3. Device tag. Reset to the default configuration. open-zwave-1.5/config/aeotec/keyfob.xml000066400000000000000000000135211264474202400201670ustar00rootroot00000000000000 open-zwave-1.5/config/aeotec/keyfob2.xml000066400000000000000000000022631264474202400202520ustar00rootroot00000000000000 Enable selective Group Mode or Scene Mode when the Key Fob is in Use mode Reset configuration set up to default setting open-zwave-1.5/config/aeotec/ledbulb.xml000066400000000000000000000063271264474202400203270ustar00rootroot00000000000000 Enable/disable to send out a report when the color is changed Enable/disable the function of using External Switch to turn on/off the bulb Enable/disable the function of using External Switch to changes the bulb color Reboot/save/exit Colorful mode Colorful mode configuration (See table) Color index configuration when the bulb is in Multi color mode (See table) Enable to send notifications to associated devices (Lifeline) when the state of LED Bulb is changed Lock/ unlock all configuration parameters Reset to the default configuration open-zwave-1.5/config/aeotec/minimote.xml000066400000000000000000000105221264474202400205270ustar00rootroot00000000000000 Default Mode – The button on the Minimote uses the factory default functions for operation instead of any special functionality related to the below modes. Scene Mode – The button on the Minimote executes a scene from data received for Parameters Numbers 0-239 related to the button being pressed. Add Mode – The button on the Minimote is able to include/add devices into the Z-Wave network. Remove Mode – The button on the Minimote is able to remove devices from the Z-Wave network. Association Mode – The button on the Minimote is able to associate one device to another. Learn Mode – 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. Enable selective Group Mode or Scene Mode when Button is in Use. NOTE: Minimote firmware 1.17 or higher is required, firmware 1.19 is highly recommended. open-zwave-1.5/config/aeotec/msesv2.xml000066400000000000000000000160001264474202400201220ustar00rootroot00000000000000 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. Current Overload Protection. Load will be closed when 3 the Current more than 2.7A and the time more than 2 minutes Enables automatic notifications to associated devices whenever there is a state change. Enable/disable Wattage threshold and percent. The minimum change in wattage for a report to be sent. Minimum change in percent of wattage to send a report. Set report types for groups 1, 2 and 3 to default. Reverts to 0 after set. Defines the type of report sent for reporting group 1. 2 is multisensor report. 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 MRC (KWH) bit 2 MRC (watt) bit 1 MSRC (Current) bit 0 MRC (Voltage) The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. Defines the type of report sent for reporting group 2. 2 is multisensor report. 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 MRC (KWH) bit 2 MRC (watt) bit 1 MSRC (Current) bit 0 MRC (Voltage) The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. Defines the type of report sent for reporting group 3. 2 is multisensor report. 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 MRC (KWH) bit 2 MRC (watt) bit 1 MSRC (Current) bit 0 MRC (Voltage) The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. 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. Turn external button mode Device tag. Reset to the default configuration. open-zwave-1.5/config/aeotec/multisensor6.xml000066400000000000000000000203451264474202400213640ustar00rootroot00000000000000 Stay awake for 10 minutes after batteries are inserted How long should the device associated to multi sensor keep state On before sending it Off command (if the value is bigger than 255, the value would be rounded to next integer in minutes) Enable Motion Sensor Which commands to send when PIR motion sensor triggered OZW Ideal Value is Binary Sensor Report Configure low battery value Value=10 to 50. Enable/disable the selective reporting only when measurements reach a certain threshold or percentage set in the threshold settings. This is used to reduce network traffic. Threshold change in temperature to induce an automatic report. Note: 1. When the unit is Celsius, threshold=Value. 2. When the unit is Fahrenheit, threshold=Value*1.8. The accuracy is 0.1. 3. The high byte is the part of integer, the low byte is the fractional part. Threshold change in humidity to induce an automatic report. Note: The accuracy is 0.1. The high byte is the part of integer, the low byte is the fractional part. Threshold change in luminance to induce an automatic report. Threshold change in battery level to induce an automatic report. Note: The accuracy is 0.1. The high byte is the part of integer, the low byte is the fractional part. Threshold change in ultraviolet to induce an automatic report. Enable/disable to send the alarm report of low temperature(Less than 15 Degress C) Reset The Reporting Group Configuration (101 to 103) to default Which reports need to send automatically in timing intervals for group 1. Bitsets: 0 -> Battery report, 4 -> Ultraviolet, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity Which reports need to send automatically in timing intervals for group 2. Bitsets: 0 -> Battery report, 4 -> Ultraviolet, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity Which reports need to send automatically in timing intervals for group 3. Bitsets: 0 -> Battery report, 4 -> Ultraviolet, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity Reset The Reporting Group Interval Configuration (111 to 113) to default The interval of sending report group 1. 1 to 2678400 seconds The interval of sending report group 2. 1 to 2678400 seconds The interval of sending report group 3. 1 to 2678400 seconds The calibration value = standard value ‐ measure value. E.g. If measure value =25.3°C and the standard value = 23.2°C, so the calibration value= 23.2°C ‐ 25.3°C= ‐2.1°C (0xFFEB). If the measure value =30.1°C and the standard value = 33.2°C, so the calibration value= 33.2°C ‐ 30.1°C=3.1°C (0x001F). The calibration value = standard value ‐ measure value. E.g. If measure value =80RH and the standard value = 75RH, so the calibration value= 75RH – 80RH= ‐5RH (0xFFFB). If the measure value =85RH and the standard value = 90RH, so the calibration value= 90RH – 85RH=5RH (0x0005). The calibration value = standard value ‐ measure value. E.g. If measure value =800Lux and the standard value = 750Lux, so the calibration value= 750 – 800= ‐50 (0xFFCE). If the measure value =850Lux and the standard value = 900Lux, so the calibration value= 900 – 850=50 (0x0032). The calibration value = standard value ‐ measure value. E.g. If measure value =9 and the standard value = 8, so the calibration value= 8 – 9= ‐1 (0xFE). If the measure value =7 and the standard value = 9, so the calibration value= 9 – 7=2 (0x02). Enable/disable Lock Configuration Reset to factory defaults. open-zwave-1.5/config/aeotec/multisensor_gen5.xml000066400000000000000000000127651264474202400222230ustar00rootroot00000000000000 Stay awake for 10 minutes after batteries are inserted How long should the device associated to multi sensor keep state On before sending it Off command (if the value is bigger than 255, the value would be rounded to next integer in minutes) Enable Motion Sensor Which commands to send when PIR motion sensor triggered OZW Ideal Value is Binary Sensor Report Enable/disable the selective reporting only when measurements reach a certain threshold or percentage set in the threshold settings. This is used to reduce network traffic. Threshold change in temperature to induce an automatic report. Note: 1. When the unit is Celsius, threshold=Value. 2. When the unit is Fahrenheit, threshold=Value*1.8. The accuracy is 0.1. 3. The high byte is the part of integer, the low byte is the fractional part. Threshold change in humidity to induce an automatic report. Note: The accuracy is 0.1. The high byte is the part of integer, the low byte is the fractional part. Threshold change in luminance to induce an automatic report. Threshold change in battery level to induce an automatic report. Note: The accuracy is 0.1. The high byte is the part of integer, the low byte is the fractional part. Enable/disable to send the alarm report of low temperature(Less than 15 Degress C) Which reports need to send automatically in timing intervals for group 1. Bitsets: 0 -> Battery report, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity Which reports need to send automatically in timing intervals for group 2. Bitsets: 0 -> Battery report, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity Which reports need to send automatically in timing intervals for group 3. Bitsets: 0 -> Battery report, 5 -> Temperature, 6 -> Humidity, 7 -> Luminosity The interval of sending report group 1. 1 to 2678400 seconds The interval of sending report group 2. 1 to 2678400 seconds The interval of sending report group 3. 1 to 2678400 seconds Enable/disable Lock Configuration Reset to factory defaults. open-zwave-1.5/config/aeotec/panicbtn.xml000066400000000000000000000022751264474202400205120ustar00rootroot00000000000000 Enable selective Group Mode or Scene Mode when the Panic Button is in Use mode Reset configuration set up to default setting open-zwave-1.5/config/aeotec/recessed_doorsensor.xml000066400000000000000000000064031264474202400227630ustar00rootroot00000000000000 0, Open: FF, Close: 00; 1, Open: 00, Close: FF; Default setting: 0 0, Open: FF, Close: 00; 1, Open: 00, Close: FF; Default setting: 0 0, Disable, 1, Enable; Default setting: 0 This parameter is available when the low battery checking function is activated or the device was waked up by other actions (i.e. the z-wave button trigger, magnet switch trigger and the Wake Up Interval Set timeout trigger). The Recessed Door Sensor will check the battery power when it was wake up as other ways. For example: the z-wave button trigger, magnet switch trigger and the Wake Up Interval Set timeout trigger. Default setting: 86640 Bitsets: 4 -> Sensor Binary 8 -> Basic Set Default setting: 0x00000100 (Basic Set) Device Tag Reset to factory defaults. open-zwave-1.5/config/aeotec/recessed_doorsensor_gen5.xml000066400000000000000000000070311264474202400236770ustar00rootroot00000000000000 Which value of the Sensor Binary Report will be sent when the magnet switch to open/close. Which value of the Basic Set will be sent when the magnet switch to open/close. Enable/disable the function of low battery checking, when the current voltage is less than the warning voltage, it will send the Battery Low Warning Report. This parameter is available when the low battery checking function is activated or the device was waked up by other actions (i.e. the z-wave button trigger, magnet switch trigger and the Wake Up Interval Set timeout trigger). The Recessed Door Sensor will check the battery power when it was wake up as other ways. For example: the z-wave button trigger, magnet switch trigger and the Wake Up Interval Set timeout trigger. Default setting: 86640 To set which command will be sent to the associated nodes when the magnet switch is triggered. Bitsets: 4 -> Sensor Binary 8 -> Basic Set Default setting: 0x100 (Basic Set) OZW Ideal Setting: 0x10 (Sensor Binary Report) Lock/ unlock all configuration parameters Device Tag Reset to factory defaults. open-zwave-1.5/config/aeotec/sd6.xml000066400000000000000000000175001264474202400174050ustar00rootroot00000000000000 Load will be closed when the Current overruns (US 15.5A, Others 16.2) for more than 2 minutes Configure the output load status after re-power on. Defines the automated status notification of an associated device when status changes Configure what the LED Ring displays during operations Configure the RGB Value when in Night Light Mode. Byte 1: Red Color Byte 2: Green Color Byte 3: Blue Color Configure the brightness level of RGB LED (0%-100%) when it is in Energy Mode/momentary indicate mode. Byte 1: Red Color Byte 2: Green Color Byte 3: Blue Color Enable/disable Wattage threshold and percent. 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. 2 is multisensor report. 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 KWH bit 2 Watt bit 1 Current bit 0 Voltage Defines the type of report sent for reporting group 1. 2 is multisensor report. 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 KWH bit 2 Watt bit 1 Current bit 0 Voltage Defines the type of report sent for reporting group 1. 2 is multisensor report. 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 KWH bit 2 Watt 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. Partner ID Enable/disable Configuration Locked Device tag. Reset to the default configuration. open-zwave-1.5/config/aeotec/ses.xml000066400000000000000000000137121264474202400175040ustar00rootroot00000000000000 Defines the contents of Multilevel Sensor Report after Multilevel Sensor Get received. 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. Enable/disable Wattage threshold and percent. The minimum change in wattage for a report to be sent. Minimum change in percent of wattage to send a report. Set report types for groups 1, 2 and 3 to default. Reverts to 0 after set. Defines the type of report sent for reporting group 1. 2 is multisensor report. 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 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. Defines the type of report sent for reporting group 2. 2 is multisensor report. 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 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. Defines the type of report sent for reporting group 3. 2 is multisensor report. 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 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. 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. Device tag. Reset to the default configuration. open-zwave-1.5/config/aeotec/ses2.xml000066400000000000000000000174701264474202400175730ustar00rootroot00000000000000 Configuration Value 1: 1‐255 Configuration Value 1 is to Specify the time that Smart Switch need blink, The unit is Second; Configuration Value 2: 1‐255 Configuration Value 2 is to Specify the Cycle of on/off, the unit of it is 0.1 second. Load will be closed when the Current overruns (EU 16.2A) for more than 2 minutes Configure the output load status after re-power on. Defines the automated status notification of an associated device when status changes Enable/disable Wattage threshold and percent. 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. 2 is multisensor report. 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 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. Defines the type of report sent for reporting group 2. 2 is multisensor report. 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 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. Defines the type of report sent for reporting group 3. 2 is multisensor report. 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 MRC(KWH) bit 2 MRC(watt) bit 1 MSRC bit 0 reserved The MRC(KWH) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(KWh) automatically. The MRC(Watt) flag signals that Report Group 1 send(1) or don't send(0) Meter Report Command(wattage) automatically. The MSRC flag signals that Report Group 1 send(1) or don't send(0) Multilevel Sensor Report Command(wattage) automatically. 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. Partner ID Enable/disable Configuration Locked Device tag. Reset to the default configuration. open-zwave-1.5/config/aeotec/ss6.xml000066400000000000000000000163371264474202400174330ustar00rootroot00000000000000 Load will be closed when the Current overruns (US 15.5A, Others 16.2) for more than 2 minutes Configure the output load status after re-power on. Configure the RGB Led Color for Testing Defines the automated status notification of an associated device when status changes Configure the RGB Value when in Night Light Mode. Byte 1: Red Color Byte 2: Green Color Byte 3: Blue Color Configure the brightness level of RGB LED (0%-100%) when it is in Energy Mode/momentary indicate mode. Byte 1: Red Color Byte 2: Green Color Byte 3: Blue Color Enable/disable Wattage threshold and percent. 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. 2 is multisensor report. 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 KWH bit 2 Watt bit 1 Current bit 0 Voltage Defines the type of report sent for reporting group 1. 2 is multisensor report. 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 KWH bit 2 Watt bit 1 Current bit 0 Voltage Defines the type of report sent for reporting group 1. 2 is multisensor report. 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 KWH bit 2 Watt 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. Partner ID Enable/disable Configuration Locked Device tag. Reset to the default configuration. open-zwave-1.5/config/aeotec/watersensor.xml000066400000000000000000000037731264474202400212740ustar00rootroot00000000000000 Toggle the sensor binary report value when the Water Sensor is Triggered Enable wake up 10 minutes when the power is switched on. Toggle the basic set value when the Water Sensor is Triggered To set which command will be sent to the associated nodes when the Water Sensor is triggered. Bitsets: 1 -> Battery 4 -> Sensor Binary 8 -> Basic Set 12 -> Alarm Default setting: 0x100 (Basic Set) OZW Ideal Setting: 0x1011 (Battery, Sensor Binary Report, Alarm) Reset to factory defaults. open-zwave-1.5/config/aeotec/zstickgen5.xml000066400000000000000000000035561264474202400210050ustar00rootroot00000000000000 When the USB power supply, the LED indicator light configuration 1~10, other= ignore. A total of 10 levels, level 1 as the weak output power, and so on, 10 for most output power level Lock/ unlock all configuration parameters Reset to the default configuration open-zwave-1.5/config/assa_abloy/000077500000000000000000000000001264474202400170415ustar00rootroot00000000000000open-zwave-1.5/config/assa_abloy/RealLivingCapTouch.xml000066400000000000000000000010331264474202400232430ustar00rootroot00000000000000 open-zwave-1.5/config/cooper/000077500000000000000000000000001264474202400162135ustar00rootroot00000000000000open-zwave-1.5/config/cooper/RF9505-T.xml000066400000000000000000000044661264474202400200020ustar00rootroot00000000000000 The amount of time in seconds the switch will turn on for when panic mode is trigered. The configuration value is a signed single byte number. This value may represent a value with no units or may represent a value such as time. 0 to 127 (decimal) represents 0 to 127 seconds of time. -128 to -1 (negative decimal numbers) represents 128 to 255 seconds as calculated by this formula. Config value = desired time in seconds (or desired value) -256 For an example of 172 seconds: config value = 172 - 256 = -84 (decimal) or 0xAC (hex) The amount of time in seconds the switch will turn off for when panic mode is triggered. The configuration value is a signed single byte number. This value may represent a value with no units or may represent a value such as time. 0 to 127 (decimal) represents 0 to 127 seconds of time. -128 to -1 (negative decimal numbers) represents 128 to 255 seconds as calculated by this formula. Config value = desired time in seconds (or desired value) -256 For an example of 172 seconds: config value = 172 - 256 = -84 (decimal) or 0xAC (hex) Power up state of the device Enables this device to participate in panic mode open-zwave-1.5/config/cooper/RF9540-N.xml000066400000000000000000000115751264474202400177720ustar00rootroot00000000000000 The configuration value is a signed single byte number. This value may represent a value with no units or may represent a value such as time. 0 to 127 (decimal) represents 0 to 127 seconds of time. -128 to -1 (negative decimal numbers) represents 128 to 255 seconds as calculated by this formula. Config value = desired time in seconds (or desired value) -256 For an example of 172 seconds: config value = 172 - 256 = -84 (decimal) or 0xAC (hex) The amount of time in seconds the switch will turn on for when panic mode is trigered. The configuration value is a signed single byte number. This value may represent a value with no units or may represent a value such as time. 0 to 127 (decimal) represents 0 to 127 seconds of time. -128 to -1 (negative decimal numbers) represents 128 to 255 seconds as calculated by this formula. Config value = desired time in seconds (or desired value) -256 For an example of 172 seconds: config value = 172 - 256 = -84 (decimal) or 0xAC (hex) The amount of time in seconds the switch will turn off for when panic mode is triggered. The configuration value is a signed single byte number. This value may represent a value with no units or may represent a value such as time. 0 to 127 (decimal) represents 0 to 127 seconds of time. -128 to -1 (negative decimal numbers) represents 128 to 255 seconds as calculated by this formula. Config value = desired time in seconds (or desired value) -256 For an example of 172 seconds: config value = 172 - 256 = -84 (decimal) or 0xAC (hex) Setting this to anything other than 0 will cause the value to be transmitted to devices in the association group when the switch is triggered. A setting other than 0 will likely result in undesired operation Power up state of the device Enables this switch to participate in panic mode The amount of time in seconds the switch will take to reach the desired dim level. The configuration value is a signed single byte number. This value may represent a value with no units or may represent a value such as time. 0 to 127 (decimal) represents 0 to 127 seconds of time. -128 to -1 (negative decimal numbers) represents 128 to 255 seconds as calculated by this formula. Config value = desired time in seconds (or desired value) -256 For an example of 172 seconds: config value = 172 - 256 = -84 (decimal) or 0xAC (hex) Ensures that LED / CFL bulbs turn on when the preset dim level is low. Enabling this feature may cause the lights brightness to momentarily be bright when the switch is turned on before reducing in brightness to desired level The minimum dim level the switch will allow. The minimum level must always be at least 13 below the maximum level. The maximum dim level the switch will allow. The maximum level must always be at least 13 above the minimum level. open-zwave-1.5/config/danfoss/000077500000000000000000000000001264474202400163615ustar00rootroot00000000000000open-zwave-1.5/config/danfoss/living.xml000066400000000000000000000003521264474202400203730ustar00rootroot00000000000000 open-zwave-1.5/config/danfoss/z.xml000066400000000000000000000005121264474202400173520ustar00rootroot00000000000000 open-zwave-1.5/config/device_classes.xml000066400000000000000000000460071264474202400204310ustar00rootroot00000000000000 open-zwave-1.5/config/device_classes.xsd000066400000000000000000000054371264474202400204310ustar00rootroot00000000000000 open-zwave-1.5/config/device_configuration.xsd000066400000000000000000000256431264474202400216440ustar00rootroot00000000000000 open-zwave-1.5/config/dlink/000077500000000000000000000000001264474202400160255ustar00rootroot00000000000000open-zwave-1.5/config/dlink/dch-z110.xml000066400000000000000000000156701264474202400200070ustar00rootroot00000000000000 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. Setting the illummination threshold to turn on the light. When the event triggered and the environment illumination lower then the threshold, the device will turn on the light. 0 means turn off illumination detected function and never turn on the light. 1 means darkest. 99 means brightest. 100 means turn off illumination detected function. And always turn on the light. * Notice * in none test mode, only the value in 1 to 99 will enable the illumination detected function and update the illumination value. Bit 0: Reserved Bit 1: Reserved Bit 2: Disable the door/window function (1: Disable, 0: Enable). Bit 3: Setting the temperature scale. 0: Fahrenheit, 1:Celsius. Bit 4: Disable the illumination report after event triggered (1: Disable, 0: Enable). Bit 5: Disable the temperature report after event triggered (1: Disable, 0: Enable). Multi-Sensor Function switch. Using bit to control. Bit 0: Disable magnetic integrate illumination to turn ON the lighting nodes in the association group 2 (1: Disable, 0: Enable). Bit 1: Reserved always 1 Bit 2: Reserved always 1 Bit 3: Reserved Bit 4: Disable delay 5 seconds to turn off the light, when door/window closed. Bit 5: Disable auto turn off the light, after door/window opened to turn on the light. Notice: If bit2 is zero, this setting is useless. Notice: If the configuration No.9 is zero, this setting is useless. Bit 6: Enable temperature monitoring. When this bit enabled the temperature changed 3 degree Fahrenheit. It will report. And also temp above 140 it will report every 64 seconds. Customer function switch, using bit control. Bit 0: Reserve. Bit 1: Enable sending motion OFF report. Note: Depends on the Bit4, 0: Report Notification CC, Type: 0x07, Event: 0xFE 1: Sensor Binary Report, Type: 0x0C, Value: 0x00. Bit 2: Enable PIR super sensitivity mode. Bit 3: Enable don't send out BASIC OFF after door closed. Bit 4: Notification Type, 0: Using Notification Report. 1: Using Sensor Binary Report. Bit 5: Disable Multi CC in auto report. Bit 6: Disable to report battery state when the device triggered. Bit 7: Reserve. 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 the door/window state. 0 means turn off auto report door/window state. The default value is 12. The tick time can setting by the configuration No.20. The interval time for auto report the illumination. 0 means turn off auto report illumination. The default value is 12. The tick time can setting by the configuration No.20. The interval time for auto report the temperature. 0 means turn off auto report temperature. 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. The temperature differential to report. 0 means turn off this function. The unit is Fahrenheit. Enable this function the device will detect every minutes. And when the temperature is over 140 degree Fahrenheit, it will continue report. Enable this functionality will cause some issue please see the detail in the "Temperature Report" section. The illumination differential to report.0 means turn off this function. The unit is percentage. Enable this function the device will detect every minutes. Enable this functionality will cause some issue please see the detail in the "Illumination Report" section. open-zwave-1.5/config/dragontech/000077500000000000000000000000001264474202400170425ustar00rootroot00000000000000open-zwave-1.5/config/dragontech/wd-100.xml000066400000000000000000000023571264474202400205030ustar00rootroot00000000000000 The orientation of the ON/OFF on the rocker switch can be inverted by changing the configuration item from 0 to 1 indicates the number of levels the lighting will change when the timer runs out indicates the time duration of each level. The resolution is 10 miliseconds. for example, a default value of 3 means the timer runs out every 30 milliseconds. open-zwave-1.5/config/duwi/000077500000000000000000000000001264474202400156745ustar00rootroot00000000000000open-zwave-1.5/config/duwi/ZWES1000.xml000066400000000000000000000005431264474202400175110ustar00rootroot00000000000000 open-zwave-1.5/config/duwi/ZWESJ300.xml000066400000000000000000000013701264474202400175440ustar00rootroot00000000000000 Continuous operation. 0x01-0x7F: 1-127 seconds in 1-second steps. 0x80-0xFE: 130-1390 seconds (0xFE) in 10 second-steps. 0xFF: 120 seconds (default; open-zwave-1.5/config/enerwave/000077500000000000000000000000001264474202400165405ustar00rootroot00000000000000open-zwave-1.5/config/enerwave/zwn-sc7.xml000066400000000000000000000003521264474202400205720ustar00rootroot00000000000000 open-zwave-1.5/config/eurotronic/000077500000000000000000000000001264474202400171155ustar00rootroot00000000000000open-zwave-1.5/config/eurotronic/eur_cometz.xml000066400000000000000000000021301264474202400220070ustar00rootroot00000000000000 open-zwave-1.5/config/eurotronic/eur_stellaz.xml000066400000000000000000000024471264474202400221770ustar00rootroot00000000000000 open-zwave-1.5/config/everspring/000077500000000000000000000000001264474202400171105ustar00rootroot00000000000000open-zwave-1.5/config/everspring/ad146.xml000066400000000000000000000030031264474202400204450ustar00rootroot00000000000000 0 is off. 1 to 99 sets output level at specified value. 255 sets output level at last memorized level Delaying time to report to Group 1 Remember the last status: 0 (do not remember) | 1 (remember) 0: Single Pole Double Throw (1: Toggle switch) Output mode setting: 0 (dimming) | 1 (on/off) open-zwave-1.5/config/everspring/ad147.xml000066400000000000000000000025631264474202400204600ustar00rootroot00000000000000 0 is off. 1 to 99 sets output level at specified value. 255 sets output level at last memorized level Delaying time to report to Group 1 Remember the last status: 0 (do not remember) | 1 (remember) Output mode setting: 0 (dimming) | 1 (on/off) open-zwave-1.5/config/everspring/an145.xml000066400000000000000000000007011264474202400204600ustar00rootroot00000000000000 open-zwave-1.5/config/everspring/an158.xml000066400000000000000000000025421264474202400204710ustar00rootroot00000000000000 This is the time the switching status needs to remain unchanged after a change to cause the device to send out a status message. 0 is Disabled. Enable or Disable Send Basic Command to Group 2 when the local button press changes the switching state. The device will report its meter value within the interval set. Set to 0 will disable the autoreporting function. open-zwave-1.5/config/everspring/an179.xml000066400000000000000000000025711264474202400204760ustar00rootroot00000000000000 Basic Set Command value The delaying time to report to Group 1 Remember the last status on plug 0: Single Pole Double Throw (1: Toggle switch) open-zwave-1.5/config/everspring/an180.xml000066400000000000000000000022411264474202400204600ustar00rootroot00000000000000 Basic Set Command value The delaying time to report to Group 1 Remember the last status on plug open-zwave-1.5/config/everspring/hsp02.xml000066400000000000000000000040401264474202400205640ustar00rootroot00000000000000 When Basic Set Command is sent where contains a value, 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 modeule shall be. The Detecting function can be Disabled of Enabled. 1 Means lowest sensitivity and 10 means highest. Adjust the interval of being re-triggered afer the detector has been triggered in seconds. Sets minimum Lux Level of ambient illumination neccesary for Motion Detector to trigger. The duration determines how long before the module sends an Off after being triggered. open-zwave-1.5/config/everspring/se812.xml000066400000000000000000000006771264474202400205060ustar00rootroot00000000000000 open-zwave-1.5/config/everspring/sf812.xml000066400000000000000000000010001264474202400204640ustar00rootroot00000000000000 open-zwave-1.5/config/everspring/sm103.xml000066400000000000000000000025351264474202400205020ustar00rootroot00000000000000 Defines the level in the event sent when the sensor is triggered. Default is 99 (full brightness for a Z-Wave dimmer). 100-127 will set device on to the last value it was when turned off. On Time sets the number of seconds the sensor stays alerted before the off event is sent. Enable/Disable power saving mode. 0 enables. open-zwave-1.5/config/everspring/sp103.xml000066400000000000000000000041631264474202400205040ustar00rootroot00000000000000 Phase Level of ON Command The Configuration parameter that can be used to adjust the phase level of ON command is transmitted is Configuration Parameter # 1. This parameter can be configured with the value of 0 through 127. Value 0: Set Device OFF(0x00) Value 1-99: Set Device On (1-99) Value 100-127: Set Device On to the last phase (0xFF) Note: 0xFF means the device will be on to the last phase before the device was turned off. Information reproduced from: http://www.techstyleuk.co.uk/index_files/sp103_manual.pdf Enabling/Disabling Power Saving Function (for testing) When no movement has been detected for 10 seconds, the SP103 will enter the power saving mode. It can be disabled or enabled power saving function by setting Configuration Parameter # 3. This parameter can be configured with the value of 0 through 127, where 0 means power saving being enabled and others mean power saving being disabled. PS : As long as the batteries have been refitted, the Detector will enable the power saving function automatically. Information reproduced from: http://www.techstyleuk.co.uk/index_files/sp103_manual.pdf open-zwave-1.5/config/everspring/sp814.xml000066400000000000000000000040371264474202400205150ustar00rootroot00000000000000 When Basic Set Command is sent where contains a value, 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 modeule shall be. The Detecting function can be Disabled of Enabled. 1 Means lowest sensitivity and 10 means highest. Adjust the interval of being re-triggered afer the detector has been triggered in seconds. Sets minimum Lux Level of ambient illumination neccesary for Motion Detector to trigger. The duration determines how long before the module sends an Off after being triggered. open-zwave-1.5/config/everspring/st812.xml000066400000000000000000000014201264474202400205100ustar00rootroot00000000000000 Defines the level in the Basic Set event sent to group 2 when the sensor is triggered. Default is 99 (full brightness for a Z-Wave dimmer). 0 disables. open-zwave-1.5/config/everspring/st814.xml000066400000000000000000000045051264474202400205210ustar00rootroot00000000000000 Defines the level in the Basic Set event sent to group 2 when the sensor is triggered. Default is 99 (full brightness for a Z-Wave dimmer). 0 disables. Temperature level to trigger when a ON command is sent out. 99 will clear the value. Temperature level to trigger when an OFF command is sent out. 99 will clear the value. Humidity level to trigger when a ON command is sent out. 99 will clear the value. Humidity level to trigger when a OFF command is sent out. 99 will clear the value. Sets the auto report time interval. 0 disables. Sets the auto report temperature trigger interval. 0 disables. Sets the auto report humidity trigger interval. 0 disables. open-zwave-1.5/config/everspring/st815.xml000066400000000000000000000035731264474202400205260ustar00rootroot00000000000000 Defines the level in the Basic Set event sent to group 2 when the sensor is triggered. Default is 99 (full brightness for a Z-Wave dimmer). 0 disables. Lux level to trigger when a ON command is sent out. 0 will clear the value. Lux level to trigger when an OFF command is sent out. 0 will clear the value. Set Lux timer trigger to send an OFF command. 0 will clear the value. Sets the auto report time interval. 0 disables. Sets the auto report Lux interval. 0 disabled. open-zwave-1.5/config/everspring/tse03.xml000066400000000000000000000010431264474202400205660ustar00rootroot00000000000000 open-zwave-1.5/config/everspringct/000077500000000000000000000000001264474202400174375ustar00rootroot00000000000000open-zwave-1.5/config/everspringct/hsm02.xml000066400000000000000000000076201264474202400211170ustar00rootroot00000000000000 When Basic Set Command is sent where contains a value, 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. The Configuration parameter that can be used to adjust the amount of delay before the OFF command is transmitted as Configuration Parameter #2. This parameter can be configured with the value of 0 through 127, where 0 means send OFF command immediately and 127 means 127 seconds of delay Magnets to be opened/closed Once the power has been applied, Alarm Report Command will be sent to Nodes in Grouping 1 to confirm the power applied status for HSM02. When HSM02 automatically wakes up, it will check the battery usage. When low battery is detected, Alarm Report Command will be sent to Nodes in Grouping 1, afterward, LED will light up for 1 sec to remind user when HSM02 is triggered due to open or close incidents. Grouping 1, afterward, LED will light up for 1 sec to remind user when HSM02 is triggered due to open or close incidents. The users can also enquire the battery status of the unit by sending BATTERY_GET command via Z-Wave Controller. Once the unit receives the command, it will return BATTERY_REPORT command. The unit will send Battery_Level = 255 (0xFF) command to the Z-Wave Controller to inform that the unit is in low battery status. open-zwave-1.5/config/evolve/000077500000000000000000000000001264474202400162245ustar00rootroot00000000000000open-zwave-1.5/config/evolve/lrm-as.xml000066400000000000000000000017421264474202400201450ustar00rootroot00000000000000 By default, the LED on the LRM-AS will turn OFF when the load attached is turned ON. To make the LED turn ON when the load attached is turned ON, set parameter to a value of 0. To change the top of the switch to OFF and the bottom of the switch to ON, set parameter to 1. Set this parameter to 0 to disable load sense. Set this parameter to 1 to enable load sense open-zwave-1.5/config/evolve/lsm-15.xml000066400000000000000000000014001264474202400177570ustar00rootroot00000000000000 By default, the LED on the LSM-15 will turn OFF when the load attached is turned ON. To make the LED turn ON when the load attached is turned ON, set parameter to a value of 0. To change the top of the switch to OFF and the bottom of the switch to ON, set parameter to 1. open-zwave-1.5/config/evolve/ltm-5.xml000066400000000000000000000040621264474202400177060ustar00rootroot00000000000000 Dimmers controlled by this switch will start dimming from their current level. In night-light mode the LED on the switch will turn ON when the switch is turned OFF. Change the top of the switch to OFF and the bottom of the switch to ON. This dimmer will start dimming from its current level. Flicker LED while transmitting. How often to poll to keep synchronized with group. Poll only the first node in Group 1. open-zwave-1.5/config/fibaro/000077500000000000000000000000001264474202400161665ustar00rootroot00000000000000open-zwave-1.5/config/fibaro/fgbs001.xml000066400000000000000000000233751264474202400200640ustar00rootroot00000000000000 Input I alarm cancellation delay. Additional delay after an alarm from input IN1 has ceased. The parameter allows you to specify additional time, after which the input no. 1 alarm is cancelled once its violation has ceased. Default 0. Input II alarm cancellation delay. Additional delay after an alarm from input IN1 has ceased. The parameter allows you to specify additional time, after which the input no. 1 alarm is cancelled once its violation has ceased. Default 0. Type of input no. 1, what the input 1 will report if no contact is made. Default 1. Type of input no. 2, what the input 2 will report if no contact is made. Default 1. Type of transmitted control frame for association group 1, activated via input IN1. The parameter allows to specify the type of alarm frame or to force transmission of control commands (BASIC_SET). Default 255 - BASIC SET. Type of transmitted control frame for association group 2, activated via input IN1. The parameter allows to specify the type of alarm frame or to force transmission of control commands (BASIC_SET). Default 255 - BASIC SET. Value of the parameter specifying the forced level of dimming / opening sun blinds when comes "switch on" / "open" command to devices from association group no. 1. In the case of alarm frames the alarm priority is specified. Possible parameter settings: (1 – 99) and 255. Value of 255 makes it possible to activate the device when using the Dimmer module it means activating the device and setting it to the previous stored condition, e.g. when Dimmer is set to 30%, then deactivated, and then reactivated using command 255, it will automatically be set to the previous condition, i.e. 30%. Default 255. Value of the parameter specifying the forced level of dimming / opening sun blinds when comes "switch on" / "open" command to devices from association group no. 2. In the case of alarm frames the alarm priority is specified. Possible parameter settings: (1 – 99) and 255. Value of 255 makes it possible to activate the device when using the Dimmer module it means activating the device and setting it to the previous stored condition, e.g. when Dimmer is set to 30%, then deactivated, and then reactivated using command 255, it will automatically be set to the previous condition, i.e. 30%. Default 255. Deactivating transmission of the frame cancelling the alarm or the control frame deactivating the device (Basic). It allows for disabling the deactivation function or the alarm cancellation function for devices associated with the appropriate input of the Fibaro Sensor. NOTE: Information concerning alarm violation or activation commands for devices from association groups are always sent. Default 0. ATTENTION: Information alarm triggered or command enabled for devices with associative groups are always sent. NOTE: Value "Group 1 not sent, Group 2 not sent" is only available in version 2.1 and up Interval between successive readings of temperature from all sensors connected to the device in seconds. Possible parameter settings: (1 – 255). Default 20. ATTENTION: taking temperature readings from the sensor does not result in sending a temperature condition report to the central hub. Interval between forcing to send report concerning the temperature conditions. The forced report is sent immediately after the next reading of temperature from the sensor, irrespective of the settings of parameter no. 12. Value 0 = Deactivates the function. Default 200. ATTENTION: Frequent sending of temperature condition reports is reasonable when the sensor is located somewhere where can occure rapid changes of ambient temperature. In other cases it is recommended to leave the parameter set to the default value. Insensitiveness to temperature changes. This is the maximum acceptable difference between the last reported temperature and the current temperature taken from the sensor. If the temperatures differ by the set value or more, then a report with the current temperature value is sent to the device assigned to association group no. 3. Intervals between taking readings from sensors are specified by parameter no. 10. Possible parameter settings:0 – 255 [0oC to 16oC] [0 oF – 28.8oF] In order to set the appropriate value of the parameter, the following formula should be used: x = delta T x 16 - for Celsius x = delta T x 80 / 9 - for Fahrenheit x – parameter value delta T – maximum acceptable temperature gradient in Celsius or Fahrenheit If the value is set to 0, then information about the temperature will be sent every time, immediately once the readings have been taken from the sensor. Default 8. Transmitting the alarm or control frame in "broadcast" mode (i.e. to all devices within range), information sent in this mode is not repeated by the mesh network. Default 0. ATTENTION: If the broadcast mode of information transmission is activated for a given channel, then transmission of information in singlecast mode to devices assigned to the association group of this channel is deactivated. Enable/Disable scene functionality. The device offers the possibility of sending commands compatible with Command class scene activation. Information is sent to devices assigned to association group no. 3. Default 0. open-zwave-1.5/config/fibaro/fgd211.xml000066400000000000000000000211351264474202400176760ustar00rootroot00000000000000 Activate/Deactive ALL ON/OFF. Default 255. Activate/Deactivate association sending for group 1 - Note: Parameter 15 must set to 1 to work properly. Default 0. Key no.2 is not represented by any physical device except of devices on association list. This functionality prevents of lack of reaction on pressing key no.2 through polling devices from association list one by one and checking their actual statuses. Default 1. Options for changing parameter 1-99. Default 1. Options for changing parameter 1-255 (10ms - 2,5s). Default 5. Options for changing parameter 1-255 (10ms - 2,5s) - 0: this value disables the smooth change in light intensity. Default 1. ATTENTION: value 0 is required for inductive and capacitive devices unsuitable for dimming (e.g. fluorescent lamps, motors, etc...) Options for changing parameter 1-99. Default 1. Options for changing parameter 2-99. Default 99. Options for changing parameter 1-98. Default 2. Binary inputs type configuration. Default 0. Double-click set lighting at 100%. Default 1. Saving state before power faillure. Default 1. The function of 3-way switch provides the option to double key no. 1. The dimmer may control two bi-stable push-buttons or an infinite number of mono-stable push-buttons. Default 0. The dimmer communicate the level to the associated devices. Default 0. This function allow user to change [On-Off] bi-stable keys (parameter no. 14). Default 0. This function will enable decreasing the minimum level of the Dimmer by extending the control impulse.[100 - 170]. By changing the minimum level, the user may completely dim LED bulbs. Not all LED bulbs available on the market have the dimmming option. WARNING: Wrong setting of the function may cause incorrect operation of the Dimmer. INFO: THIS PARAMETER IS NOT AVAILABLE IN DEVICE FGD211 v2.1-2.3 Alarm of any type (general alarm, water flooding alarm, smoke alarm: CO, CO2, temperature alarm). Default 3. Amount of time the device keeps on flashing after receipt of Alarm Frame (1ms-65535ms). Default 600. Available settings: from 1 to 99 Parameters value changes depending on the dimming level. The device offers the possibility of sending commands compatible with Command class scene activation. Information is sent to devices assigned to association group no. 3. Controllers such as Home Center 2 are able to interpret such commands and based on these commands they activate scenes, to which specific scene IDs have been assigned. The user may expand the functionality of the button connected to inputs S1 and S2 by distinguishing the actions of keys connected to those inputs. For example: double click would activate the scene goodnight and triple click would activate the scene morning. Default 0. open-zwave-1.5/config/fibaro/fgd212.xml000066400000000000000000000526621264474202400177100ustar00rootroot00000000000000 Parameter is set automatically during the calibration process. Options for changing parameter 1-98. Default 1. Parameter is set automatically during the calibration process. Options for changing parameter 2-99. Default 99. Virtual value set as a percentage level between parameters MIN (1%) and MAX. (99%). The Dimmer will set to this value after first switch on. It is required for warming up and switching dimmable compact fluorescent lamps and certain types of light sources. Options for changing parameter 1-99. Default 1. 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. Available settings: 0-255 (0s - 25,5s) Available settings: 1-99 Default: 1 Available settings: 0-255 (0s - 2,55s) Default setting: 1 Available settings: 1-99 Default: 1 Available settings: 0-255 (0s - 2,55s) Default setting: 1 Saving state before power faillure. Default 1. Available settings: 0 - Function disabled; 1-32767 - time to turn off measured in seconds (1s - 9,1h) Default setting: 0 Activate/Deactive ALL ON/OFF. Default 255. Changing value of this parameter will force the calibration process. This parameter determines operating mode of the Dimmer (automatic/manual settings). Function based on the sudden power variation of a specific value, interpreted as a LOAD ERROR. Available settings: 0 - function disabled; 1-99 - percentage value of power variation, compared to standard power consumption, measured during the calibration procedure (to be interpreted as load error/burnt out bulb) Default setting: 30 Time of delay (in seconds) for power variation detection, interpreted as a LOAD ERROR or OVERLOAD detection (too much power connected to the Dimmer). Available settings: 0 - detection of a burnt out bulb disabled; 1-255 - delay time in seconds; Default setting: 5 If the parameter is active, switching on the Dimmer (S1 single click) will always set this brightness level. Available settings: 0 - function disabled; 1-99 - percentage level of brightness; Default setting: 0 Binary inputs type configuration. Default 0. The value sent to associated devices on single click. Double-click set lighting at 100%. Default 1. Parameter determines, which actions will not result in sending frames to association groups. Parameter values may be combined, e.g. 1+2=3 means that associations on switching on or off the Dimmer (single click) will not be sent. Available settings: 0-31 0 - all actions send to association groups; 1 - do not send when switching on the Dimmer (single click); 2 - do not send when switching off the Dimmer (single click); 4 - do not send when changing dimming level (holding and releasing); 8 - do not send on double click; 16 - send 0xFF value on double click; Default setting: 0 Parameter determines, which actions will not result in sending frames to association groups. Parameter values may be combined, e.g. 1+2=3 means that associations on switching on or off the Dimmer (single click) will not be sent. Available settings: 0-31 0 - all actions send to association groups; 1 - do not send when switching on the Dimmer (single click); 2 - do not send when switching off the Dimmer (single click); 4 - do not send when changing dimming level (holding and releasing); 8 - do not send on double click; 16 - send 0xFF value on double click; Default setting: 0 Switch no. 2 controls the Dimmer additionally (in 3-way switch mode). Function disabled for parameter 20 set to 2 (roller blind switch) 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. Parameter values may be combined, e.g. 1+2=3 means that 2nd & 3rd group are sent as secure. Available settings: 0-15 0 - all groups (II-V) sent as non-secure; 1 - 2nd group sent as secure; 2 - 3rd group sent as secure; 4 - 4th group sent as secure; 8 - 5th group sent as secure; 15 - all groups (II-V) sent as secure; Default setting: 15 SCENE ID depends on the switch type configurations. Default 0. Forced auto-calibration will set this parameter’s value to 2. Load control mode recognized during auto-calibration. Load control mode recognized during auto-calibration. Dimmability of the load 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. Behaviour of the Dimmer after OVERCURRENT or SURGE Reaching the defined value will result in turning off the load. Additional apparent power limit of 350VA is active by default. Available settings: 0 - functionality disabled; 1-350 - 1W-350W; Default setting: 250 Response to General Purpose Alarm; Default 3. Response to Water Flooding Alarm; Default 2. Response to Smoke, CO or CO2 Alarm; Default 3. Response to Temperature Alarm; Default 1. Alarm state may be cancelled earlier, as a result of pressing the switches or sending the Z-Wave command frame. OVERLOAD alarm report (load power consumption too high) LOAD ERROR alarm report (no load, load failure, burnt out bulb) OVERCURRENT alarm report (short circuit, burnt out bulb causing overcurrent) SURGE alarm report (Dimmer output overvoltage) OVERHEAT (critical temperature) and VOLTAGE DROP (low voltage) alarm report The parameter defines the power level change that will result in a new power report being sent. The value is a percentage of the previous report. Available settings: 0 - power reports disabled; 1-100 (1-100%) - power report threshold; Default setting: 10 (10%) Parameter 52 defines a time period between consecutive reports. Timer is reset and counted from zero after each report. Available settings: 0 - periodic reports disabled; 1-32767 (1-32767 seconds); Default setting: 3600 (3600s) Energy level change which will result in sending a new energy report. Available settings: 0 - energy reports disabled; 1-255 (0,01 - 2,55 kWh) - report triggering threshold; Default setting: 10 (0,1 kWh) The Dimmer may include active power and energy consumed by itself in reports sent to the main controller. This parameter defines how to calculate active power. This parameter is useful in a case of 2-wire connection with light sources other than resistive. The parameter is set to 0 after forced auto-calibration. This parameter determines the approximate value of the power that will be reported by the device at its maximum brightness level. This parameter works only when parameter 58 has a value other than 0. Available settings: 0-500 (0-500W) - power consumed by the load at the maximum brightness level. Default setting: 0 open-zwave-1.5/config/fibaro/fgfs101.xml000066400000000000000000000225071264474202400200650ustar00rootroot00000000000000 Flood alarm cancellation delay. Additional delay after a flood alarm has ceased. The parameter allows you to specify additional time, after which the flood alarm is cancelled once its violation has ceased. Acoustic and visual signals in case of flooding. Type of alarm frame for association group 1, activated by flood sensor. The parameter allows to specify the type of alarm frame or to force transmission of control commands (BASIC_SET) Value of the parameter specifying the forced level of dimming / opening sun blinds when comes "switch on" / "open" command to devices from association group no. 1. In the case of alarm frames the alarm priority is specified. Possible parameter settings: (1 – 99) and 255. Value of 255 makes it possible to activate the device when using the Dimmer module it means activating the device and setting it to the previous stored condition, e.g. when Dimmer is set to 30%, then deactivated, and then reactivated using command 255, it will automatically be set to the previous condition, i.e. 30%. Deactivating transmission of the frame cancelling the alarm or the control frame deactivating the device (Basic). It allows for disabling the deactivation function or the alarm cancellation function for devices associated with the appropriate input of the Fibaro Sensor. NOTE: Information concerning alarm violation or activation commands for devices from association groups are always sent. Interval between successive readings of temperature from all sensors connected to the device in seconds. Note: taking temperature readings from the sensor does not result in sending a temperature condition report to the central hub. Insensitiveness to temperature changes. This is the maximum acceptable difference between the last reported temperature and the current temperature taken from the sensor. If the temperatures differ by the set value or more, then a report with the current temperature value is sent to the device assigned to association group no. 3. Intervals between taking readings from sensors are specified by parameter no. 10. Possible parameter settings:1 – 1000 [each 0.01oC] [0.01oC – 10.00oC]. Transmitting the alarm or control frame in "broadcast" mode (i.e. to all devices within range), information sent in this mode is not repeated by the mesh network. NOTE: If the broadcast mode of information transmission is activated for a given channel, then transmission of information in singlecast mode to devices assigned to the association group of this channel is deactivated. The parameter stores a temperature value, below which LED indicator blinks with a colour determined by Parameter 61 settings. By default the LED indicator blinks blue. Possible parameter settings:-10000 – 10000 [each 0.01oC] [-100oC – 100oC]. The parameter stores a temperature value, above which LED indicator blinks with a colour determined by Parameter 62 settings. By default the LED indicator blinks red. Possible parameter settings:-10000 – 10000 [each 0.01oC] [-100oC – 100oC]. The parameter stores RGB colour value. The parameter stores RGB colour value. Parameter determines LED indicator's operation. Set to 0 turns the indicator off, saving battery life. Parameter stores a temperature value to be added to or deducted from the current temperature measured by the internal temperature sensor in order to compensate the difference between air temperature and the temperature at floor level. Possible parameter settings:-10000 – 10000 [each 0.01oC] [-100oC – 100oC]. The device is able to turn on alarms resulting from sensors vibrations, e.g. when the sensor is moved, or the TMP button is released. Group 2 association alarms are not cancelled. Parameter determines a time period after which alarm will become 'quiet' - still active but the device will go into battery saving mode. Visual or acoustic alarm will be reactivated after time period specified in Parameter 76. When alarm status ceases, alarm will be turned off immediately. Value of 0 means visual and acoustic alarms are active indefinitely. In battery power mode the device will never go to sleep which may shorten battery life significantly. Parameter determines a time period after which an alarm frame will be retransmitted. Value of 0 cancels an alarm frame retransmission. Allows for turning off the internal flood sensor. Tamper and internal temperature sensors will remain active. open-zwave-1.5/config/fibaro/fgk001.xml000066400000000000000000000162541264474202400177100ustar00rootroot00000000000000 Input I alarm cancellation delay. Additional delay after an alarm from input IN1 has ceased. The parameter allows you to specify additional time, after which the input no. 1 alarm is cancelled once its violation has ceased. Status change signalled by LED. Default setting: LED turned On Type of input no. 1, what the input 1 will report if no contact is made Type of transmitted control frame for association group 1, activated via input IN1. The parameter allows to specify the type of alarm frame or to force transmission of control commands (BASIC_SET) Value of the parameter specifying the forced level of dimming / opening sun blinds when comes "switch on" / "open" command to devices from association group no. 1. In the case of alarm frames the alarm priority is specified. Possible parameter settings: (1 - 99) and 255. Value of 255 makes it possible to activate the device when using the Dimmer module it means activating the device and setting it to the previous stored condition, e.g. when Dimmer is set to 30%, then deactivated, and then reactivated using command 255, it will automatically be set to the previous condition, i.e. 30%. Deactivating transmission of the frame cancelling the alarm or the control frame deactivating the device (Basic). It allows for disabling the deactivation function or the alarm cancellation function for devices associated with the appropriate input of the Fibaro Sensor. NOTE: Information concerning alarm violation or activation commands for devices from association groups are always sent. Interval between successive readings of temperature from all sensors connected to the device in seconds. Note: taking temperature readings from the sensor does not result in sending a temperature condition report to the central hub. Interval between forcing to send report concerning the temperature conditions. The forced report is sent immediately after the next reading of temperature from the sensor, irrespective of the settings of parameter no. 12. Value 0 = Deactivates the function. Note: Frequent sending of temperature condition reports is reasonable when the sensor is located somewhere where can occure rapid changes of ambient temperature. In other cases it is recommended to leave the parameter set to the default value. Insensitiveness to temperature changes. This is the maximum acceptable difference between the last reported temperature and the current temperature taken from the sensor. If the temperatures differ by the set value or more, then a report with the current temperature value is sent to the device assigned to association group no. 3. Intervals between taking readings from sensors are specified by parameter no. 10. Possible parameter settings:0 - 255 [0oC to 16oC] [0 oF - 28.8oF] In order to set the appropriate value of the parameter, the following formula should be used: x = delta T x 16 - for Celsius x = delta T x 80 / 9 - for Fahrenheit x - parameter value delta T - maximum acceptable temperature gradient in Celsius or Fahrenheit If the value is set to 0, then information about the temperature will be sent every time, immediately once the readings have been taken from the sensor. Transmitting the alarm or control frame in "broadcast" mode (i.e. to all devices within range), information sent in this mode is not repeated by the mesh network. NOTE: If the broadcast mode of information transmission is activated for a given channel, then transmission of information in singlecast mode to devices assigned to the association group of this channel is deactivated. Enable/Disable scene functionality. The device offers the possibility of sending commands compatible with Command class scene activation. Information is sent to devices assigned to association group no. 3. open-zwave-1.5/config/fibaro/fgms.xml000066400000000000000000000400441264474202400176460ustar00rootroot00000000000000 The lower the value, the more sensitive the PIR sensor. Available settings: 8 - 255 Default setting: 10 Period of time through which the PIR sensor is "blind" (insensitive) to motion. After this time period the PIR sensor will be again able to detect motion. The longer the insensitivity period, the longer the battery life. If the sensor is required to detect motion quickly, the time period may be shortened. The time of insensitivity should be shorter that the time period set in parameter 6. Available settings: 0 - 15 Formula to calculate the time: time [s] = 0.5 x (value + 1) Default setting: 15 (8 seconds) Sets the number of moves required for the PIR sensor to report motion. The lower the value, the less sensitive the PIR sensor. It's not recommended to modify this parameter settings. Available settings: 0 - 3 Formula to calculate the number of pulses: pulses = (value + 1) Default setting: 1 (2 pulses) Period of time during which the number of moves set in parameter 3 must be detected in order for the PIR sensor to report motion. The higher the value, the more sensitive the PIR sensor. It's not recommended to modify this parameter setting. Available settings: 0 - 3 Formula to calculate the time: time [s] = 4 x (value + 1) Default setting: 2 (12 seconds) Motion alarm will be cancelled in the main controller and the associated devices after the period of time set in this parameter. Any motion detected during the cancellation delay time countdown will result in the countdown being restarted. In case of small values, below 10 seconds, the value of parameter 2 must be modified (PIR sensor's "Blind Time"). Available settings: 1 - 65535 Default setting: 30 (30 seconds) The parameter determines the part of day in which the PIR sensor will be active. 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) The 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) The parameter determines the command frames sent in 1-st association group, assigned to PIR sensor. Values of BASIC ON and BASIC OFF command frames may be modified by dedicated parameters. Default setting: 0 (ON and OFF) The value of 255 allows to turn ON a device. In case of the Dimmer, the value of 255 means turning ON at the last memorized state, e.g. the Dimmer turned ON at 30% and turned OFF using the value of 255, and then turned OFF, will be turned ON at 30%, i.e. the last memorized state. Available settings: 0 - 255 Default setting: 255 The command frame sent at the moment of motion alarm cancellation, after the cancellation delay time, specified in parameter 6, has passed. The value of 0 allows to turn a device OFF while the value of 255 allows to turn ON a device. In case of the Dimmer, the value of 255 means turning ON at the last memorized state, e.g. the Dimmer turned ON at 30% and turned OFF using the value of 255, and then turned OFF, will be turned ON at 30%, i.e. the last memorized state. Available settings: 0 - 255 Default setting: 0 The parameter determines the changes in forces acting on the Fibaro Motion Sensor resulting in tamper alarm being reported - g-force acceleration. Available settings: 0 - 122 (0.08 - 2g; multiply by 0.016g; 0 = tamper inactive) Default setting: 15 (0.224g) Time period after which a tamper alarm will be cancelled. Another tampering detected during the countdown to cancellation will not extend the delay. Available settings: 1 - 65535 Default setting: 30 (seconds) The parameter determines the behaviour of tamper and how it reports. Tamper: Tamper alarm is reported in Sensor Alarm command class. Cancellation: Cancellation is reported in Sensor Alarm command class after the time period set in parameter 22 (Tamper Alarm Cancellation Delay). Orientation: Sensor's orientation in space is reported in Fibaro Command Class after the time period set in parameter 22. Vibration: The maximum level of vibrations recorded in the time period set in parameter 22 is reported. Reports stop being sent when the vibrations cease. The reports are sent in Sensor Alarm command class. Value displayed in the "value" field (0 - 100) depends on the vibrations force. Reports to the association groups are sent using Sensor Alarm command class. Default setting: 0 (Tamper) The parameter determines whether the tamper alarm frame will or will not be sent in broadcast mode. Alarm frames sent in broadcast mode may be received by all of the devices within communication range (if they accept such frames). Default setting: 0 The parameter determines the change in light intensity level resulting in illumination report being sent to the main controller. Available settings: 0 - 65535 (1 - 65535 lux; 0 = reports are not sent) Default setting: 200 (200 lux) Time interval between consecutive illumination reports. The reports are sent even if there are no changes in the light intensity. Available settings: 0 - 65535 (1 - 65535 seconds; 0 = reports are not sent) Default setting: 0 (no reports) NOTE Frequent reports will shorten the battery life. Parameter value under 5 may result in blocking the temperature reports. The parameter determines the change in level of temperature resulting in 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) The parameter determines 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. Available settings: 0 - 65535 (1 - 65535 seconds; 0 = temperature will not be measured) Default setting: 900 (900 seconds) NOTE Frequent reports will shorten the battery life. Parameter value under 5 may result in blocking the illumination reports. The parameter determines how often the temperature reports will be sent to the main controller. Available settings: 0 - 65535 (1 - 65535 seconds; 0 = 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 The parameter determines the way in which LED behaves after motion has been detected. Values 1 and from 3 to 9 = single long blink at the moment of reporting motion. No other motion will be indicated until alarm is cancelled. Values from 10 to 18 = single long blink at the moment of reporting motion and one short blink each time the motion is detected again. Values from 19 to 26 = single long blink at the moment of reporting motion and two short blinks each time the motion is detected again. Default setting: 10 (flashlight) The parameter determines the brightness of LED when indicating motion. Available settings: 0 - 100 (1 - 100%; 0 = brightness determined by the ambient lighting - see parameters 82 and 83) Default setting: 50 The parameter is relevant only when the parameter 81 is set to 0. Available settings: 0 to parameter 83 value Default setting: 100 (100 lux) The parameter is relevant only when the parameter 81 is set to 0. Available settings: parameter 82 value to 65535 Default setting: 1000 (1000 lux) NOTE The value of the parameter 83 must be higher than the value of the parameter 82. This parameter is relevant only when parameter 80 has been properly configured. Available settings: 0 to parameter 87 value (degrees Celsius) Default setting: 18 (18C) This parameter is relevant only when parameter 80 has been properly configured. Available settings: parameter 86 value to 255 (degrees Celsius) Default setting: 28 (28C) Indicating mode resembles a police car (white, red and blue). Default setting: 1 (on) open-zwave-1.5/config/fibaro/fgr221.xml000066400000000000000000000115241264474202400177160ustar00rootroot00000000000000 Binary inputs type configuration Options for changing parameter 1-99, default 16 Only valid for the 1.9 version of FGR221. The device offers the possibility of sending commands compatible with Command class scene activation. Information is sent to devices assigned to association group no. 3. Controllers such as Home Center 2 are able to interpret such commands and based on these commands they activate scenes, to which specific scene IDs have been assigned. The user may expand the functionality of the button connected to inputs S1 and S2 by distinguishing the actions of keys connected to those inputs. For example: double click would activate the scene goodnight and triple click would activate the scene morning. open-zwave-1.5/config/fibaro/fgrgbwm441.xml000066400000000000000000000243011264474202400205740ustar00rootroot00000000000000 Activate/Deactive ALL ON/OFF Choose which command classes are sent to associated devices. Choose the behaviour of transitions between different levels. Size of the step for each change in level during the transition. Time between each step in a transition between levels. Setting this to zero means an instantaneous change. 0 - immediate change; 1->63: 20ms->126ms (value*20ms); 65->127: 1s->63s (value-64)*1s; 129->191: 10s->630s (value-128)*10s; 193->255: 1min->63min (value-192)*1min. Default setting: 67 (3s) Maximum brightness level for the dimmer Minimum brightness level for the dimmer This is too complex to describe here, since this value is built up from 4-bits for each of the 4 channels. Refer to the table in the product manual. Default value is 4369 (1111 in hex). Option double click (lighting set at 100%). 0 - Double click disabled, 1 - Double click enabled. Default setting 1 Saving state before power faillure Alarm of any type (general alarm, water flooding alarm, smoke alarm: CO, CO2, temperature alarm). Default setting 0 (Inactive) Program number selected from the 10 available. In ALARM PROGRAM mode (see parameter 30), this defines the time in seconds the program lasts (1s->65534s) Specify which command class is used to report output status changes Parameter defines a value by which input voltage must change in order to be reported to the main controller. New value is calculated based on last reported value: Default setting: 5 (0.5V). Range: 1->100 - (0.1V->10V). Sent if last reported value differs from the current value. Reports will also be sent in case of polling. Default setting: 30 (30s). Range: 1->65534 (1s->65534s) - interval between reports. Zero means reports are only sent in the case of polling, or at turning OFF the device Interval between energy consumption reports (in kWh). New reported energy consumption value is calculated based on last reported value. 1->254 (0.01kWh->2.54kWh). Zero means changes in consumed energy will not be reported, except in case of polling. Set whether to remember the previous RGB mix after the brightness has fallen to zero (black) First predefined program to use when device is set to work in RGB/RGBW mode (parameter 14) Behaviour when an input is triple-clicked open-zwave-1.5/config/fibaro/fgrm222.xml000066400000000000000000000256761264474202400201110ustar00rootroot00000000000000 Once the Local Protection is activated, the module stops responding to S1 and S2 push buttons. SCENE ID and association commands will not be sent as well. The only exception is the B-button. Menu and Z-Wave network inclusion, after the B-button or S1 push button triple click, are still active. Once the RF Protection is activated, the module stops responding to command frames setting the blind position. It's still possible however to configure the device (advanced configuration parameters, protection modes) and checking it's current state through polling (position, power, energy). Parameters value shoud be set to 1 if the module operates in Venetian Blind mode. Defauld setting: 0 Default settng: 1 In Venetian Blind mode (parameter 10 set to 2) the parameter determines time of full turn of the lamellas. In Gate Mode (parameter 10 set to 3 or 4) the parameter defines the COUNTDOWN time, i.e. the time period after which an open gate starts closing. In any other operating mode the parameter value is irrelevant. Value of 0 means the gate will not close automatically Available settings: 0-65535 (0 - 655,35s) Default setting: 150 (1,5 s) In Venetian Blind Mode (parameter 10 set to 2) the parameter influences lamellas positioning in various situations. In any other operating mode the parameter value is irrelevant. Default settng: 1 The parameter settings are relevant for Roller Blind Mode and Venetian Blind Mode (parameter 10 set to 0, 1, 2). In Roller Blind Mode or Venetian Blind mode (parameter 10 set to 0, 1, 2) the parameter determines when the Roller Shutter relays are turned off after reaching a limit switch. In Gate Mode (parameter 10 set to 3 or 4) the parameter determines a time period after which a gate will start closing after a S2 contact has been disconnected. In this mode, time to turn off the Roller Shutter relays after reaching a limit switch is set to 3 seconds and cannot be modified. Value of 0 means the gate will note close automatically. Available settings: 0 - 255 (0,1-25,5s). Default setting: 10 (1s). Power threshold to be interpreted as reaching a limit switch. Available settings: 0 - 255 (1-255 W) The value of 0 means reaching a limit switch will not be detected Default setting: 10 (10W). Time period for the motor to continue operation. Available settings: 0 - 65535 (0 - 65535s) The value of 0 means the function is disabled. Default setting: 240 (240s. - 4 minutes) By modifying the parameters setting from 0 to 1 a Roller Shutter enters the calibration mode. The parameter relevant only if a Roller Shutter is set to work in positioning mode (parameter 10 set to 1, 2 or 4). Default setting: 2-Close blind Default setting: 0-No reaction Default setting: 1-Open blind Default setting: 1-Open blind In Venetian Blind Mode (parameter 10 set to 2), the parameter determines how the lamellas will react upon alarm detection. In any other modes, the parameter value is not relevant. Default setting: 1 Set lamellas to their extreme position Power level change that will result in new power value report being sent. The parameter defines a change that needs to occur in order to trigger the report. The value is a percentage of the previous report. Power report threshold available settings: 1-100 (1-100%). Value of 0 means the reports are turned off. Default setting: 10 (10%). The parameter defines a time period between consecutive reports. Available settings: 1-65534 (1-65534 seconds) Value of 0 means the reports are turned off. Default setting: 3600 (3600 seconds / 60 minutes). Energy level change which will result in new energy value report being sent. The parameter defines a change that needs to occur in order to trigger the report. Energy threshold available settings: 1-254 (0,01 - 2,54kWh). Value of 0 means the reports are turned off. Default setting 10 (0,1kWh). A Roller Shutter may include power and energy used by itself in reports sent to the main controller Default setting: 0-Self-measurement inactive Parameter determines whether scenes or associations are activated by the switch keys. Default setting: 0-Associations activation open-zwave-1.5/config/fibaro/fgs211.xml000066400000000000000000000143231264474202400177160ustar00rootroot00000000000000 Activate/Deactive ALL ON/OFF Auto off relay after specified time, with the possibility of manual override - immediate Off after button push. Default value: 0 Manual override disabled Automatic turning off relay 1 after set time, (0-255) in 10ms increments for FW1.0 to FW2.0, (0-65535) in 100 ms increment for FW2.1+ Activate/Deactivate association sending for group 1 - Also see param #15 In case of bi-stable switches, define their behaviour (toggle or follow) Binary inputs type configuration Enable/Disable opoeration of dimmer or roller shutter devices associated to group 1. Available only when using mono-stable inputs (buttons) - Hold button 1 or double-tap for operation Saving state before power faillure Amount of time (ms) the device keeps on flashing after receipt of Alarm Frame open-zwave-1.5/config/fibaro/fgs212.xml000066400000000000000000000143311264474202400177160ustar00rootroot00000000000000 Activate/Deactive ALL ON/OFF Auto off relay after specified time, with the possibility of manual override - immediate Off after button push. Default value: 0 Manual override disabled Time period for auto off, in miliseconds (0,1 s – 6553,5 s) 0 - Auto off disabled Default value: 0 Activate/Deactivate association sending for group 1 - Also see param #15 In case of bi-stable switches, define their behaviour (toggle or follow) Binary inputs type configuration Enable/Disable opoeration of dimmer or roller shutter devices associated to group 1. Available only when using mono-stable inputs (buttons) - Hold button 1 or double-tap for operation Saving state before power faillure Amount of time (ms) the device keeps on flashing after receipt of Alarm Frame open-zwave-1.5/config/fibaro/fgs221.xml000066400000000000000000000222741264474202400177230ustar00rootroot00000000000000 Activate/Deactive ALL ON/OFF Auto off relay after specified time, with the possibility of manual override - immediate Off after button push. Default value: 0 Manual override disabled Automatic turning off relay 1 after set time, (0-255) in 10ms increments for FW1.0 to FW2.0, (0-65535) in 100 ms increment for FW2.1+ Automatic turning off relay 2 after set time, (0-255) in 10ms increments for FW1.0 to FW2.0, (0-65535) in 100 ms increment for FW2.1+ Activate/Deactivate association sending for group 1 - Also see param #16 Key no.2 is not represented by any physical device except of devices on association list. This functionality prevents of lack of reaction on pressing key no.2 through polling devices from association list one by one and checking their actual statuses. In case of bi-stable switches, define their behaviour (toggle or follow) Binary inputs type configuration Enable/Disable opoeration of dimmer or roller shutter devices associated to group 1. Available only when using mono-stable inputs (buttons) - Hold button 1 or double-tap for operation Saving state before power faillure Amount of time (ms) the device keeps on flashing after receipt of Alarm Frame open-zwave-1.5/config/fibaro/fgs222.xml000066400000000000000000000223441264474202400177220ustar00rootroot00000000000000 Activate/Deactive ALL ON/OFF Auto off relay after specified time, with the possibility of manual override - immediate Off after button push. Default value: 0 Manual override disabled Time period for auto off, in miliseconds (0,1 s – 6553,5 s) 0 - Auto off disabled Default value: 0 Time period for auto off, in miliseconds (0,1 s – 6553,5 s) 0 - Auto off disabled Default value: 0 Activate/Deactivate association sending for group 1 - Also see param #16 Key no.2 is not represented by any physical device except of devices on association list. This functionality prevents of lack of reaction on pressing key no.2 through polling devices from association list one by one and checking their actual statuses. In case of bi-stable switches, define their behaviour (toggle or follow) Binary inputs type configuration Enable/Disable opoeration of dimmer or roller shutter devices associated to group 1. Available only when using mono-stable inputs (buttons) - Hold button 1 or double-tap for operation Saving state before power faillure Amount of time (ms) the device keeps on flashing after receipt of Alarm Frame open-zwave-1.5/config/fibaro/fgsd002.xml000066400000000000000000000155011264474202400200570ustar00rootroot00000000000000 There are 3 levels of sensitivity to smoke presence. Level 1 means the highest sensitivity. Rising the parameter value lowers the sensitivity to smoke presence. This parameter allows to activate excess temperature and/or enclosure opening notifications sent to the main controller. This parameter allows to activate visual indications but does not apply to major alarms, such as FIRE, TROUBLE and LOW BATTERY ALARM. This parameter allows to activate sound signals but does not apply to major alarms, such as FIRE, TROUBLE and LOW BATTERY ALARM. This parameter defines which frames will be sent in the 2-nd Association Group (FIRE ALARM). BASIC ON frame is sent in case of smoke presence detection and FIRE ALARM triggering. Available settings: (1 - 99) or 255. Default setting: 255 BASIC OFF frame is sent in case of FIRE ALARM cancellation. Available settings: (1 - 99) or 255. Default setting: 255 A value other than 0 means that alarms are being sent in broadcast mode, i.e. to all devices within a Fibaro Smoke Sensor's range. Time interval between consecutive temperature reports. Report is sent when new temperature value is different from the one previously reported - according to the set hysteresis (parameter 21). Available settings: 0,1-8640 (multiply by 10 seconds) [10s-24h]. Default setting: 1 (10s) The temperature report will only be sent if there is a difference in temperature value from the previous value reported, defined in this parameter (hysteresis). Available settings: 1 – 100 (in 0,1°C steps). Default setting: 10 (1°C) Temperature value measured by the built-in temperature sensor above which the excess temperature notification is sent. Available settings: 1 – 100. Default setting: 55 (55°C) Time interval of signaling (visual indication/sound) excess temperature level. Available settings: 1 – 8640 (multiply by 10 seconds) [10s-24h]. Default setting: 1 (10s) Time interval of signaling (visual indication/sound) lack of Z-Wave range. Available settings: 1 – 8640 (multiply by 10 seconds) [10s-24h]. Default setting: 180 (30min) open-zwave-1.5/config/fibaro/fgss101.xml000066400000000000000000000232141264474202400200760ustar00rootroot00000000000000 The time between when the smoke disappears and the Fibaro Smoke Sensor stops sending the alarm signal. Available settings: 0 – 17280, 65535 (5s multiplier) [5s-24h]. 0: no delay, immediate cancellation, 65535: alarm cancellation inactive - Smoke Sensor will keep indicating smoke alarm after the smoke will have disappeared. The smoke alarm can be only ceased manually, by entering 2nd menu level (see section XIII). Default setting: 0 Allows for deactivating the LED indicator and the acoustic alarm, in case of detecting an alarm of any type. This doesn’t affect the communication with the Z-Wave network controller, i.e. the sensor will keep sending alarms, reports and all information to the associated devices. Modifying this parameter settings helps extending the battery life. Type of alarm frame for association group 1, activated by smoke sensor. The parameter allows to specify the type of alarm frame or to force transmission of control commands (BASIC_SET) The value of 255 allows for turning on a device. In case of Dimmer, the value of 255 means turning on the device with the last memorized state. E.g. Dimmer set to 30% and then turned off, and next turned on using the 255 command, will turn on with the last remembered status, i.e. 30%. In case of alarm frames, alarm priority is defined. Available settings: (1 - 99) or 255. Default setting: 255 Time interval between consecutive temperature reports. The parameter is relevant for the battery powering mode only. Longer time interval means less frequent communication and thus a longer battery life. Report is sent when new temperatue value is different from the one previously reported. Temperature reports can be also sent as a result of polling. Available settings: 1 – 17280, 0 (multiply by 5 seconds) [5s-24h]. 0 – reports inactive. Default setting: 0 (Reports inactive) The temperature report will only be sent if there is a difference in temperature value from the previous value reported, defined in this parameter (hysteresis). Temparature reports can be also sent as a result of polling. Available settings: 0 – 100 (in 0,1C steps). 0 – temperature change reporting inactive. Default setting: 20 (2C) Transmitting the alarm or control frame in "broadcast" mode (i.e. to all devices within range), information sent in this mode is not repeated by the mesh network. NOTE: If the broadcast mode of information transmission is activated for a given channel, then transmission of information in singlecast mode to devices assigned to the association group of this channel is deactivated. Parameter stores a temperature value to be added to or deducted from the current temperature measured by internal temperature sensor in order to compensate the difference between air temperature and temperature measured at the ceiling level. Available settings: -1000 -/+ 1000 (in 0,1C steps). Default setting: 0 (0C) Time period between the consecutive Z-Wave network range tests. In battery powering mode, Z-Wave network range test is carried out at the wake up interval. The value of 0 turns off the Z-Wave range test, regardless of the powering mode chosen. Available settings: 0 – 144 (10min multiplier) [10min-24h]. 0 – Z-Wave network range test inactive. Default setting: 1 (10min) Temperature value, measured by the built-in temperature sensor, above which the temperature alarm is sent. Available settings: 0,2 - 100. 0 – temperature alarm inactive. 2 - 100 – (2 - 100C). Default setting: 54 (54C) There are 3 levels of sensitivity to smoke presence. Level 1 means the highest sensitivity. This parameter allows for specifying the moment in which the Black Box starts recording data. After the specified smoke and temperature values will be exceeded, the Fibaro Smoke Sensor’s Black Box will record them. Time interval in which malfuntion alarm, if detected, is repeated using visual and acoustic alarms. Available settings: 1 - 255 (100 ms multiplier) [100ms-25,5s]. Default setting: 10 (1s) Time interval in which temperature alarm, if detected, is repeated using visual and acoustic alarms. Available settings: 1 - 255 (100 ms multiplier) [100ms-25,5s]. Default setting: 5 (500ms) Time interval in which lack of the Z-Wave network alarm, if detected, is repeated using visual and acoustic alarms. Available settings: 1 - 17280 (5s multiplier) [5s-24h]. Default setting: 360 (30min) Time interval in which low battery alarm, if detected, is repeated using visual and acoustic alarms. Available settings: 1 - 17280 (5s multiplier) [5s-24h]. Default setting: 360 (30min) This parameter allows for specifying the moment in which the Black Box starts recording data. After the specified smoke and temperature values will be exceeded, the Fibaro Smoke Sensor’s Black Box will record them. default setting: tamper alarm active, with cancellation option available open-zwave-1.5/config/fibaro/fgwpe.xml000066400000000000000000000334141264474202400200250ustar00rootroot00000000000000 Once activated, Wall Plug will keep a connected device constantly ON, will stop reacting to alarm frames and B-button push. "Always on" function turns the Plug into a power and energy meter. Also, connected device will not be turned off upon receiving an alarm frame from another Z-Wave device (parameter 35 will be ignored). In "Always on" mode, connected device may be turned off only after user defined power has been exceeded (parameter 70). In such a case, connected device can be turned on again by pushing the B-button or sending a control frame. By default, overload protection is inactive. Default setting: 1 Define how will the Plug react after the power supply is back on. Default setting: 1 Type of transmitted control frame for association group 1, activated via input IN1. The parameter allows to specify the type of alarm frame or to force transmission of control commands (BASIC_SET) Parameter defines how the Wall Plug will respond to alarms (device's status change) Default setting: 0. 0 - no reaction, 1 - turn on connected device. LED ring signals an alarm through defined time period (parameter 39) or untill the alarm is cancelled. 2 - turn off connected device. LED ring signals an alarm through defined time period (parameter 39) or untill the alarm is cancelled. 3 - cyclically change device state, each 1second. In alarm mode Wall Plug does not report status change, power changes, ignores alarm frames. After the defined time period has passed (parameter 39) or after the alarm cancellation, connected device is set to the previous state. NOTE: If "always on" function is active (parameter 1), this parameter's settings are ignored. Wall Plug's alarm mode duration. If a device sending an alarm frame through the Z-Wave network sets alarm duration as well, this parameter's settings are ignored. Default setting: 600 Parameter defines by how much power load must change, in percents, to be reported to the main controller, with the highest priority in the Z-Wave network. By default, Fibaro Wall Plug immediately sends power report if the power load changes by 80%. Default setting: 80 (%) Parameter defines by how much power load must change, in percents, to be reported to the main controller. By default, Fibaro Wall Plug sends power report if the power load changes by 15%. By default such changes in power load may be reported up to 5 times per 30 seconds. Wall Plug sends 5 reports during time period specified in paramater 43. Default setting: 15 (%) This parameter defines how frequently standard power reports (parameter 42) will be sent. By default Wall Plug sends up to 5 reports each 30 seconds, provided the power load changes by 15%. Default setting: 30 (s) New, reported energy value is calculated based on last reported value. Default setting: 10 (0,1 kWh). Available settings: 1 - 254 (0,01kWh - 2,54kWh). Value of 255 - changes in consumed energy will not be reported. Reports will be sent only in case of polling. Default Setting: 10 (0,1 kWh) Parameter defines time period between reports sent when changes in power load have not been recorded. By default, if power load changes have not been recorded, reports are sent every hour. Default setting: 3 600 (s), Available settings: 1 - 65534 (s). Value of 65535 - no periodic reports. Reports will be sent only in case of power load / energy consumption changes (parameters 40, 42, 43,45) or in case of polling. Default setting: 3600 This parameter determines whether energy metering should include the amount of energy consumed by the Wall Plug itself. Results are being added to energy consumed by controlled device. Default setting: 0 Lower power threshold, used in parameter 52. Default setting: 300 (30W) Available settings: 0 - 25000 (0,0W - 2500W) DOWN value cannot be higher than a value specified in parameter 51. Default setting: 300 (30W) Upper power threshold, used in parameter 52. Default setting: 500 (50W) Available settings: 1 - 25000 (0,1W - 2500W) UP value cannot be lower than a value specified in parameter 50. Default setting: 500 (50W) Parameter deifines the way 2nd association group devices are controlled, depending on the current power load. Default setting: 6. Available settings: 0 - function inactive, 1 - turn the associated devices on, once the power drops below DOWN value (parameter 50), 2 - turn the associated devices off, once the power drops below DOWN value (parameter 50), 3 - turn the associated devices on, once the power rises above UP value (parameter 51), 4 - turn the associated devices off, once the power rises above UP value (parameter 51), 5 - 1 and 4 combined. Turn the associated devices on, once the power drops below DOWN value (parameter 50). Turn the associated devices off, once the power rises above UP value (parameter 51). 6 - 2 and 3 combined. Turn the associated devices off, once the power drops below DOWN value (parameter 50). Turn the associated devices on, once the power rises above UP value (parameter 51). Default setting: 6 Function is active only when parameter 61 is set to 0 or 1. Default setting: 25000 (2500W) Available settings: 1000 - 32000 (100W - 3200W). Default setting: 25000 (2500W) 0 - LED ring illumination colour changes in predefined steps, depending on power consumption changes, 1 - LED ring illumination colour changes continuously, using full spectrum of available colorus, depending on power consumption changes. 2 - White illumination, 3 - Red illumination, 4 - Green illumination, 5 - Blue illumination, 6 - Yellow illumination, 7 - Cyan illumination, 8 - Magenta illumination, 9 - illumination turned off completely. Default setting: 1 0 - LED ring illumination colour takes on the color corresponding to the last measured power at the time when the device controlled was turn off, 1 - White illumination, 2 - Red illumination, 3 - Green illumination, 4 - Blue illumination, 5 - Yellow illumination, 6 - Cyan illumination, 7 - Magenta illumination, 8 - illumination turned off completely. Default setting: 8 0 - No change in colour. LED ring illumination colour determined by parameters 61 or 62 settings, 1 - LED ring flashes red / blue / white (default), 2 - White illumination, 3 - Red illumination, 4 - Green illumination, 5 - Blue illumination, 6 - Yellow illumination, 7 - Cyan illumination, 8 - Magenta illumination, 9 - illumination turned off completely. Default setting: 1 This function allows for turning off the controlled device in case of exceeding the defined power. Controlled device will be turned off even if "always on" function is active (parameter 1). Controlled device can be turned back on via B-button or sending a control frame. By default this function is inactive. Default setting: 65535 (6553,5W) Available settings: 10 - 65535 (1W - 6553,5W). Value higher than 32000 (3200W) turns the overload safety switch off, i.e. this functionality is turned off by default. Default setting: 65535 (6553,5W) open-zwave-1.5/config/fortrezz/000077500000000000000000000000001264474202400166115ustar00rootroot00000000000000open-zwave-1.5/config/fortrezz/mimolite.xml000066400000000000000000000114341264474202400211550ustar00rootroot00000000000000 Clear Pulse Meter Counts (actual value is “don’t 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. open-zwave-1.5/config/frostdale/000077500000000000000000000000001264474202400167075ustar00rootroot00000000000000open-zwave-1.5/config/frostdale/fdn2nxx.xml000066400000000000000000000002721264474202400210210ustar00rootroot00000000000000 open-zwave-1.5/config/ge/000077500000000000000000000000001264474202400153175ustar00rootroot00000000000000open-zwave-1.5/config/ge/dimmer.xml000066400000000000000000000056421264474202400173250ustar00rootroot00000000000000 In night-light mode the LED on the switch will turn ON when the switch is turned OFF. Change the top of the switch to OFF and the bottom of the switch to ON. Note: If you invert the switches and also install the product upside down, remember the load will now be controlled by the right, not the left switch. This dimmer will start dimming from its current level. 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. open-zwave-1.5/config/ge/dimmer_module.xml000066400000000000000000000047601264474202400206720ustar00rootroot00000000000000 Turn on the module when the attached load is connected This dimmer will start dimming from its current level. 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. open-zwave-1.5/config/ge/relay.xml000066400000000000000000000015261264474202400171610ustar00rootroot00000000000000 In night-light mode the LED on the switch will turn ON when the switch is turned OFF. Change the top of the switch to OFF and the bottom of the switch to ON. Note: If you invert the switches and also install the product upside down, remember the load will now be controlled by the right, not the left switch. open-zwave-1.5/config/greenwave/000077500000000000000000000000001264474202400167075ustar00rootroot00000000000000open-zwave-1.5/config/greenwave/powernode1.xml000066400000000000000000000035111264474202400215140ustar00rootroot00000000000000 After how many minutes the GreenWave device should start flashing if the controller didn't communicate with this device The room color (Corner wheel color) on the GreenWave device open-zwave-1.5/config/greenwave/powernode6.xml000066400000000000000000000035531264474202400215270ustar00rootroot00000000000000 After how many minutes the GreenWave device should start flashing if the controller didn't communicate with this device The room color (Corner wheel color) on the GreenWave device open-zwave-1.5/config/homeseer/000077500000000000000000000000001264474202400165335ustar00rootroot00000000000000open-zwave-1.5/config/homeseer/ezmotionplus.xml000066400000000000000000000115461264474202400220340ustar00rootroot00000000000000 Sensitivity sets the amount of motion required for the device to detect motion. A higher value makes it more sensitive and a lower value makes it less sensitive. Note that values above 200 are not recommended when the device is battery operated. Recommended values: 10 = Pet Immune. 100 = Medium sensitivity for hallways. 200(default) = Highly sensitive for rooms where people are sitting still. On Time sets the number of minutes that the lights stay on when motion has not been detected. A value of 0 On Time is a special mode where the lights are constantly sent a command to turn them on whenever motion is detected. The device will NOT turn the lights off in this mode. Note that this mode will significantly shorten battery life. Recommended values: 5 min for hallways. 20 min for an office environment. 60 min for a library or other room where someone may be sitting still for a long time. This may be inaccurate, but default for Homeseer HSM100 may actually be 3 minutes, instead of 20? LED ON/OFF turns the LED on or off. A slight improvement in battery life is obtained by turning the LED off. Setting LED ON/OFF to zero will turn the LED off and 255 turns it on. Default is On (255). Light Threshold is the percentage of light in the room above which the lights will not be turned on. Light Threshold is often used in room with a lot of natural daylight. Setting Light Threshold to a value of 50% will cause the device to not turn the lights on when the natural light in the room is already at the 50% value. This feature only prevents the lights from coming on when motion is first detected and the light level in the room is already above Light Threshold. It will not turn the lights off when the amount of natural light in the room increases. It will automatically turn on the lights in a room that has motion in it and that the amount of natural light has dropped below Light Threshold. A value of 100% turns off this feature (default). Recommended values: Usually a value between 40% and 60% will prevent the lights from coming on in a reasonably well light room and will turn them on as it is getting dark. Some experimentation is required with each room to determine the proper setting. Setting Stay Awake to a non-zero value will cause the device to always be awake. NOTE: this mode should NOT be used when the device is battery powered! Batteries will only last a few days in this mode. Stay Awake is NOT set to the factory default (0) when the device is Excluded (reset) from the Z-Wave network. Setting Stay Awake to a non-zero value will cause the Z-Wave Listening Bit to be set. The device will become a routing node in the Z-Wave Mesh-Network when the Listening Bit is set. To properly have the device included in the routing tables, set Stay Awake to a non-zero value, then reset the device (Exclude from the network), then add it back to the network. The new routing information will be used now that the listening bit is set. Defaults to 0. On Value is the value sent by the Z-Wave BASIC_SET command when motion is detected. A value of 0 will turn the lights off (not recommended). A value between 1 and 100 will set the dim level to between 1% and 100%. A value of 255 will turn the light on (default). NB! According to the manual, the value should not be set between 101-254 (inclusive). open-zwave-1.5/config/homeseer/hsm100.xml000066400000000000000000000115451264474202400202730ustar00rootroot00000000000000 Sensitivity sets the amount of motion required for the device to detect motion. A higher value makes it more sensitive and a lower value makes it less sensitive. Note that values above 200 are not recommended when the device is battery operated. Recommended values: 10 = Pet Immune. 100 = Medium sensitivity for hallways. 200(default) = Highly sensitive for rooms where people are sitting still. On Time sets the number of minutes that the lights stay on when motion has not been detected. A value of 0 On Time is a special mode where the lights are constantly sent a command to turn them on whenever motion is detected. The device will NOT turn the lights off in this mode. Note that this mode will significantly shorten battery life. Recommended values: 5 min for hallways. 20 min for an office environment. 60 min for a library or other room where someone may be sitting still for a long time. This may be inaccurate, but default for Homeseer HSM100 may actually be 3 minutes, instead of 20? LED ON/OFF turns the LED on or off. A slight improvement in battery life is obtained by turning the LED off. Setting LED ON/OFF to zero will turn the LED off and 255 turns it on. Default is On (255). Light Threshold is the percentage of light in the room above which the lights will not be turned on. Light Threshold is often used in room with a lot of natural daylight. Setting Light Threshold to a value of 50% will cause the device to not turn the lights on when the natural light in the room is already at the 50% value. This feature only prevents the lights from coming on when motion is first detected and the light level in the room is already above Light Threshold. It will not turn the lights off when the amount of natural light in the room increases. It will automatically turn on the lights in a room that has motion in it and that the amount of natural light has dropped below Light Threshold. A value of 100% turns off this feature (default). Recommended values: Usually a value between 40% and 60% will prevent the lights from coming on in a reasonably well light room and will turn them on as it is getting dark. Some experimentation is required with each room to determine the proper setting. Setting Stay Awake to a non-zero value will cause the device to always be awake. NOTE: this mode should NOT be used when the device is battery powered! Batteries will only last a few days in this mode. Stay Awake is NOT set to the factory default (0) when the device is Excluded (reset) from the Z-Wave network. Setting Stay Awake to a non-zero value will cause the Z-Wave Listening Bit to be set. The device will become a routing node in the Z-Wave Mesh-Network when the Listening Bit is set. To properly have the device included in the routing tables, set Stay Awake to a non-zero value, then reset the device (Exclude from the network), then add it back to the network. The new routing information will be used now that the listening bit is set. Defaults to 0. On Value is the value sent by the Z-Wave BASIC_SET command when motion is detected. A value of 0 will turn the lights off (not recommended). A value between 1 and 100 will set the dim level to between 1% and 100%. A value of 255 will turn the light on (default). NB! According to the manual, the value should not be set between 101-254 (inclusive). open-zwave-1.5/config/homeseer/hsm200.xml000066400000000000000000000064541264474202400202770ustar00rootroot00000000000000 Parameter #0 is undocumented: let us know if you know what it does! Attributes (type, units, min and max) are wild guesses, except default value. On Time sets the number of minutes that the lights stay on when motion has not been detected. A value of 0 On Time is a special mode where the lights are constantly sent a command to turn them on whenever motion is detected. The device will NOT turn the lights off in this mode. Note that this mode will significantly shorten battery life. Recommended values: 5 min for hallways. 20 min for an office environment. 60 min for a library or other room where someone may be sitting still for a long time. This may be inaccurate, but default for Homeseer HSM100 may actually be 3 minutes, instead of 20? OnLevel is the value sent by the Z-Wave BASIC_SET command to all Association Group 2 nodes when motion is detected. A value of 0 will turn the lights off (not recommended). A value between 1 and 99 will set the dim level to between 1% and 99% (99% is full on). A value of -1 will turn the light “on” which depends on the device but most will set the dim level to the last dim setting. LiteMinutes. A Luminance report is sent to the system controller every LiteMin minutes. A value of zero turns this mode off. Luminance values can still be obtained at any time by the home control application in this mode. TempMinutes. A Temperature report is sent to the controller every TempMin minutes. A value of zero turns this mode off. Temperature values can still be obtained at any time by polling the status of the temperature sensor. TempAdj. TempAdj is a twos-complement number that is used to adjust the temperature reading to make it more accurate. The value is in tenths of degree Fahrenheit. The temperature reading can be adjusted by +12.7F to -12.8F. A value of 1 will adjust the temperature reading by +0.1F. A value of -1 will adjust the temperature by -0.1F. A value of 123 will adjust the temperature by +12.3F. open-zwave-1.5/config/homeseer/ztroller.xml000066400000000000000000000002631264474202400211330ustar00rootroot00000000000000 open-zwave-1.5/config/honeywell/000077500000000000000000000000001264474202400167325ustar00rootroot00000000000000open-zwave-1.5/config/honeywell/th8320zw1000.xml000066400000000000000000000003741264474202400212720ustar00rootroot00000000000000 open-zwave-1.5/config/horstmann/000077500000000000000000000000001264474202400167355ustar00rootroot00000000000000open-zwave-1.5/config/horstmann/hrt4zw.xml000066400000000000000000000033161264474202400207240ustar00rootroot00000000000000 0-127 = Disabled. 128-255 = Enabled. 0-127 = Celsius. 128-255 = Fahrenheit. Delta T in steps of 0.1 degree. open-zwave-1.5/config/intermatic/000077500000000000000000000000001264474202400170635ustar00rootroot00000000000000open-zwave-1.5/config/intermatic/ca8900.xml000066400000000000000000000003251264474202400205110ustar00rootroot00000000000000 open-zwave-1.5/config/iris/000077500000000000000000000000001264474202400156725ustar00rootroot00000000000000open-zwave-1.5/config/iris/rangeextender.xml000066400000000000000000000003201264474202400212420ustar00rootroot00000000000000 open-zwave-1.5/config/leviton/000077500000000000000000000000001264474202400164045ustar00rootroot00000000000000open-zwave-1.5/config/leviton/rzi10.xml000066400000000000000000000003361264474202400200750ustar00rootroot00000000000000 open-zwave-1.5/config/leviton/vrcpg.xml000066400000000000000000000003361264474202400202510ustar00rootroot00000000000000 open-zwave-1.5/config/leviton/vrf01.xml000066400000000000000000000003361264474202400200660ustar00rootroot00000000000000 open-zwave-1.5/config/leviton/vri06.xml000066400000000000000000000003361264474202400200760ustar00rootroot00000000000000 open-zwave-1.5/config/leviton/vri10.xml000066400000000000000000000003361264474202400200710ustar00rootroot00000000000000 open-zwave-1.5/config/linear/000077500000000000000000000000001264474202400161765ustar00rootroot00000000000000open-zwave-1.5/config/linear/PD300Z-2.xml000066400000000000000000000015461264474202400177450ustar00rootroot00000000000000 Turn on the module when the attached load is connected. This dimmer will always start dimming from its current level, ignoring any commanded start level. open-zwave-1.5/config/linear/WD500Z-1.xml000066400000000000000000000022411264474202400177460ustar00rootroot00000000000000 In night-light mode the LED on the switch will turn ON when the switch is turned OFF, instead of folliwng the state of the load. 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. open-zwave-1.5/config/manufacturer_specific.xml000066400000000000000000001436351264474202400220230ustar00rootroot00000000000000 open-zwave-1.5/config/manufacturer_specific.xsd000066400000000000000000000022161264474202400220060ustar00rootroot00000000000000 open-zwave-1.5/config/mcohome/000077500000000000000000000000001264474202400163535ustar00rootroot00000000000000open-zwave-1.5/config/mcohome/mhs311.xml000066400000000000000000000014301264474202400201070ustar00rootroot00000000000000 Switch state saved or not when power down open-zwave-1.5/config/mcohome/mhs312.xml000066400000000000000000000016711264474202400201170ustar00rootroot00000000000000 Switch state saved or not when power down open-zwave-1.5/config/mcohome/mhs314.xml000066400000000000000000000022301264474202400201110ustar00rootroot00000000000000 Switch state saved or not when power down open-zwave-1.5/config/mcohome/mhs411.xml000066400000000000000000000014301264474202400201100ustar00rootroot00000000000000 Switch state saved or not when power down open-zwave-1.5/config/mcohome/mhs412.xml000066400000000000000000000016661264474202400201240ustar00rootroot00000000000000 Switch state saved or not when power down open-zwave-1.5/config/mcohome/mhs513.xml000066400000000000000000000020041264474202400201110ustar00rootroot00000000000000 Switch state saved or not when power down open-zwave-1.5/config/merten/000077500000000000000000000000001264474202400162165ustar00rootroot00000000000000open-zwave-1.5/config/merten/507801.xml000066400000000000000000000032271264474202400175100ustar00rootroot00000000000000 To configure the time (value * 0.1 sec) the motor waits before switching direction. To configure input 1 of the raising time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 1 of the raising time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 1 of the lowering time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 1 of the lowering time calculation (256 * Input 1 + Input 2) * 0.1 sec open-zwave-1.5/config/merten/50x5xx.xml000066400000000000000000000066531264474202400200330ustar00rootroot00000000000000 To configure if other radio recivers from Merten should be switched as well. To configure the time the motor waits before switching direction. To configure input 1 of the raising time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 1 of the raising time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 1 of the lowering time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 1 of the lowering time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure use of light sensor. Default: 0 . To configure brightness threshold for light sensor. To configure input 1 of reaction threshold for raising shutter time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 2 of reaction threshold for raising shutter time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 1 of reaction threshold for lowering shutter time calculation (256 * Input 1 + Input 2) * 0.1 sec To configure input 2 of reaction threshold for lowering shutter time calculation (256 * Input 1 + Input 2) * 0.1 sec open-zwave-1.5/config/nodon/000077500000000000000000000000001264474202400160415ustar00rootroot00000000000000open-zwave-1.5/config/nodon/asp3100SmartPlug.xml000066400000000000000000000173271264474202400215230ustar00rootroot00000000000000 After Power-On-Reset of the device, the Channel Output State is set in Default State This parameter allows unsolicited “Notification Report” Commands and/or “Basic Set” Commands to be sent when a power failure detection and/or a power failure recover occurs. Only the four least significant bits can be addressed. Bit 0: Enable or disable power failure detection and recover. Setting this bit to 1 automatically allows the product to send unsolicited report through Lifeline. If this bit is not set, it is not possible to enable Association Group 4, 5 and 6. Consequently, if a Configuration Set Command is received, enabling one or more Association Groups (4, 5 and / or 6), this bit will be automatically set. Bit 1: Enable or disable unsolicited Notification Report: Power Management – AC disconnected Command and Notification Report: Power Management – AC re-connected Command sent to associated nodes of Group 4, when, respectively, power failure is detected or power failure is recovered. Bit 2: Enable or disable Basic Set ON Command sent to associated nodes of Group 5, when power failure is detected. Bit 3: Enable or disable Basic Set OFF Command sent to associated nodes of Group 6, when power failure is detected. Bit 4: Enable or disable Basic Set ON Command sent to associated nodes of Group 7, when power recover is detected. Bit 5: Enable or disable Basic Set OFF Command sent to associated nodes of Group 8, when power recover is detected. 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: * 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 see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters see Appendix C - Description of Alarm Parameters open-zwave-1.5/config/nodon/crc3100OctanRemote.xml000066400000000000000000000114631264474202400220040ustar00rootroot00000000000000 This parameter configures the behavior of the buttons 1 and 3 when the product is in "Gateway Centric Mode" This parameter configures the behavior of the buttons 2 and 4 when the product is in "Gateway Centric Mode" This parameter configures the type of command sent when the product is in "Gateway Centric Mode", with buttons profile configuration set in "Scene Behavior". When button are set in Mono Button mode they can have 3 different behaviors : 1: They can directly control other nodes with Basic and multi-level command class 2: Send Switch All On command 3: Send Switch All Off command When button are set in Mono Button mode they can have 3 different behaviors : 1: They can directly control other nodes with Basic and multi-level command class 2: Send Switch All On command 3: Send Switch All Off command When button are set in Mono Button mode they can have 3 different behaviors : 1: They can directly control other nodes with Basic and multi-level command class 2: Send Switch All On command 3: Send Switch All Off command When button are set in Mono Button mode they can have 3 different behaviors : 1: They can directly control other nodes with Basic and multi-level command class 2: Send Switch All On command 3: Send Switch All Off command open-zwave-1.5/config/nodon/cws3101wallswitch.xml000066400000000000000000000114621264474202400217720ustar00rootroot00000000000000 This parameter configures the behavior of the buttons 1 and 3 when the product is in "Gateway Centric Mode" This parameter configures the behavior of the buttons 2 and 4 when the product is in "Gateway Centric Mode" This parameter configures the type of command sent when the product is in "Gateway Centric Mode", with buttons profile configuration set in "Scene Behavior". When button are set in Mono Button mode they can have 3 different behaviors : 1: They can directly control other nodes with Basic and multi-level command class 2: Send Switch All On command 3: Send Switch All Off command When button are set in Mono Button mode they can have 3 different behaviors : 1: They can directly control other nodes with Basic and multi-level command class 2: Send Switch All On command 3: Send Switch All Off command When button are set in Mono Button mode they can have 3 different behaviors : 1: They can directly control other nodes with Basic and multi-level command class 2: Send Switch All On command 3: Send Switch All Off command When button are set in Mono Button mode they can have 3 different behaviors : 1: They can directly control other nodes with Basic and multi-level command class 2: Send Switch All On command 3: Send Switch All Off command open-zwave-1.5/config/northq/000077500000000000000000000000001264474202400162375ustar00rootroot00000000000000open-zwave-1.5/config/northq/nq92021.xml000066400000000000000000000050721264474202400200010ustar00rootroot00000000000000 How many pulses are counted per 10 kWh. Defines the type of sensor. Additional time for feedback measurement.Should always be 0. Adjusts transmit signal so received signal will in average be equal to this values. Auto calibration might select another value than this. Wake device up this many times per second. This value also controls number of measurements per second on mechanical meters. Do not use. Set this value using WAKE_UP_INTERVAL_SET instead. Current pulse count in device (pulse count / pulse factor = kWh). How many 'ticks' before going back to sleep in normal wakeup mode. Set this to enter real-time mode from remote. Contains seconds * poll frequency before going back to sleep. If you press the button once this value will be set. open-zwave-1.5/config/options.xml000066400000000000000000000021421264474202400171400ustar00rootroot00000000000000 open-zwave-1.5/config/options.xsd000066400000000000000000000012021264474202400171320ustar00rootroot00000000000000 open-zwave-1.5/config/philio/000077500000000000000000000000001264474202400162105ustar00rootroot00000000000000open-zwave-1.5/config/philio/pan04.xml000066400000000000000000000046671264474202400176710ustar00rootroot00000000000000 If the setting is configured for 1hour (set value =720), the device will report its instant power consumption every 1 hour to Z-Wave Controller. Unit: 5 seconds. If the setting is configured for 1hour (set value =720), the device will report its power consumption in KWh every 1 hour to Z-Wave Controller. Unit: 5 seconds. 1: Relay 1 and Relay 2. 2: Relay 1. 3: Relay 2 Edge or Pulse mode or Edge-Togle mode defines the operating mode of the externally connected switch. Default: Edge Mode Threshold of Watt for Load Caution Threshold of kWh for Load Caution open-zwave-1.5/config/philio/psm02.xml000066400000000000000000000140431264474202400176750ustar00rootroot00000000000000 Setting the BASIC command value to turn on the light. The 0xFF (255) means turn on the light. For dimmer equipment 1 to 100 means the light strength. PIR sensitivity settings. 0 means disable the PIR motion. 1 means the lowest sensitivity. 99 means the highest sensitivity. High sensitivity means can detect long distance, but if there is more noise signal in the environment, it will re-trigger too frequently. Setting the illummination threshold to turn on the light. When the event triggered and the environment illumination lower then the threshold, the device will turn on the light. 0 means turn off illumination detected function and never turn on the light. 1 means darkest. 99 means brightest. 100 means turn off illumination detected function. And always turn on the light. * Notice * in none test mode, only the value in 1 to 99 will enable the illumination detected function and update the illumination value. Bit 0: 1 means security mode; 0 means home automation mode. Bit 1: 1 means enable test mode; 0 means disable test mode * Notice * Bit 0 and bit 1 will effect when the DIP Switch setting to program mode. If bit1 is enabled, the bit0 is useless. Bit 2: Reserved, always 1. Bit 3: Setting the temperature scale; 0: Fahrenheit, 1:Celsius Bit 4: Disable illumination report after event triggered. Bit 5: Disable temperature report after event triggered Multi-Sensor Function switch. Using bit to control. Bit 0: Reserved, always 1. Bit 1: Disable PIR integrate Illumination. Bit 2: Reserved, always 1. Bit 3: Reserved. Bit 4: Reserved. Bit 5: Reserved. Bit 6: Enable temperature monitoring. When this bit enabled, the temperature changed 3 degree Fahrenheit, it will report. And also the temperature over 140 degree Fahrenheit, it will report every 64 seconds. In the security mode, after the PIR report motion detected, setting the re-detect time. 8 seconds per tick, and minimum time is 24 seconds, 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 detecting. After turn on the light, setting the delay time to turn off the light when the PIR motion is not detected. 8 seconds per tick, and minimum time is 32 seconds, default tick is 4 (32 seconds). The interval time for auto report the battery level. 30 minutes per tick and minimum time is 30 minutes, default tick is 12 (6 hours) The interval time for auto report the illumination. 30 minutes per tick and minimum time is 30 minutes, default tick is 12 (6 hours) The interval time for auto report the temperature. 30 minutes per tick and minimum time is 30 minutes, default tick is 12 (6 hours) open-zwave-1.5/config/philio/pst02-1c.xml000066400000000000000000000157121264474202400202110ustar00rootroot00000000000000 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. Setting the illummination threshold to turn on the light. When the event triggered and the environment illumination lower then the threshold, the device will turn on the light. 0 means turn off illumination detected function and never turn on the light. 1 means darkest. 99 means brightest. 100 means turn off illumination detected function. And always turn on the light. * Notice * in none test mode, only the value in 1 to 99 will enable the illumination detected function and update the illumination value. Bit 0: Reserved Bit 1: Reserved Bit 2: Disable the door/window function (1: Disable, 0: Enable). Bit 3: Setting the temperature scale. 0: Fahrenheit, 1:Celsius. Bit 4: Disable the illumination report after event triggered (1: Disable, 0: Enable). Bit 5: Disable the temperature report after event triggered (1: Disable, 0: Enable). Multi-Sensor Function switch. Using bit to control. Bit 0: Disable magnetic integrate illumination to turn ON the lighting nodes in the association group 2 (1: Disable, 0: Enable). Bit 1: Reserved always 1 Bit 2: Reserved always 1 Bit 3: Reserved Bit 4: Disable delay 5 seconds to turn off the light, when door/window closed. Bit 5: Disable auto turn off the light, after door/window opened to turn on the light. Notice: If bit2 is zero, this setting is useless. Notice: If the configuration No.9 is zero, this setting is useless. Bit 6: Enable temperature monitoring. When this bit enabled the temperature changed 3 degree Fahrenheit. It will report. And also temp above 140 it will report every 64 seconds. Customer function switch, using bit control. Bit 0: Reserve. Bit 1: Enable sending motion OFF report. Note: Depends on the Bit4, 0: Report Notification CC, Type: 0x07, Event: 0xFE 1: Sensor Binary Report, Type: 0x0C, Value: 0x00. Bit 2: Enable PIR super sensitivity mode. Bit 3: Enable don't send out BASIC OFF after door closed. Bit 4: Notification Type, 0: Using Notification Report. 1: Using Sensor Binary Report. Bit 5: Disable Multi CC in auto report. Bit 6: Disable to report battery state when the device triggered. Bit 7: Reserve. 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 the door/window state. 0 means turn off auto report door/window state. The default value is 12. The tick time can setting by the configuration No.20. The interval time for auto report the illumination. 0 means turn off auto report illumination. The default value is 12. The tick time can setting by the configuration No.20. The interval time for auto report the temperature. 0 means turn off auto report temperature. 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. The temperature differential to report. 0 means turn off this function. The unit is Fahrenheit. Enable this function the device will detect every minutes. And when the temperature is over 140 degree Fahrenheit, it will continue report. Enable this functionality will cause some issue please see the detail in the "Temperature Report" section. The illumination differential to report.0 means turn off this function. The unit is percentage. Enable this function the device will detect every minutes. Enable this functionality will cause some issue please see the detail in the "Illumination Report" section. open-zwave-1.5/config/philio/pst02-b.xml000066400000000000000000000165531264474202400201330ustar00rootroot00000000000000 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. PIR sensitivity settings. 0 means disable the PIR motion. 1 means the lowest sensitivity, 99 means the highest sensitivity. High sensitivity means can detected long distance, but if there is more noise signal in the environment, it will re-trigger too frequency. Setting the illummination threshold to turn on the light. When the event triggered and the environment illumination lower then the threshold, the device will turn on the light. 0 means turn off illumination detected function and never turn on the light. 1 means darkest. 99 means brightest. 100 means turn off illumination detected function. And always turn on the light. * Notice * in none test mode, only the value in 1 to 99 will enable the illumination detected function and update the illumination value. Bit 0: Reserve. Bit 1: 1 means enable test mode, 0 means disable normal mode. Notice: This bit only effect by the DIP Switch setting to program mode. Bit 2: Reserve. Bit 3: Setting the temperature scale. 0: Fahrenheit, 1:Celsius. Bit 4: Disable the illumination report after event triggered (1: Disable, 0: Enable). Bit 5: Disable the temperature report after event triggered (1: Disable, 0: Enable). Bit 6: Reserve. Bit 7: Disable the back key release into test mode (1: Disable, 0: Enable). Multi-Sensor Function switch. Using bit to control. Bit 0: Reserve. Bit 1: Disable PIR integrate Illumination to turn ON the lighting nodes in the association group 2 (1: Disable, 0: Enable). Bit 2: Reserve. Bit 3: Reserve. Bit 4: Reserve. Bit 5: Reserve. Bit 6: Reserve. Bit 7: Reserve. Customer function switch, using bit control. Bit 0: Reserve. Bit 1: Enable sending motion OFF report. Note: Depends on the Bit4, 0: Report Notification CC, Type: 0x07, Event: 0xFE 1: Sensor Binary Report, Type: 0x0C, Value: 0x00. Bit 2: Enable PIR super sensitivity mode. Bit 3: Reserve. Bit 4: Notification Type, 0: Using Notification Report. 1: Using Sensor Binary Report. Bit 5: Disable Multi CC in auto report. Bit 6: Disable to report battery state when the device triggered. Bit 7: Reserve. 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 the illumination. 0 means turn off auto report illumination. The default value is 12. The tick time can setting by the configuration No.20. The interval time for auto report the temperature. 0 means turn off auto report temperature. 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. The temperature differential to report. 0 means turn off this function. The unit is Fahrenheit. Enable this function the device will detect every minutes. And when the temperature is over 140 degree Fahrenheit, it will continue report. Enable this functionality will cause some issue please see the detail in the "Temperature Report" section. The illumination differential to report.0 means turn off this function. The unit is percentage. Enable this function the device will detect every minutes. Enable this functionality will cause some issue please see the detail in the "Illumination Report" section. open-zwave-1.5/config/philio/pst02.xml000066400000000000000000000212241264474202400177030ustar00rootroot00000000000000 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. PIR sensitivity settings. 0 means disable the PIR motion. 1 means the lowest sensitivity, 99 means the highest sensitivity. High sensitivity means can detected long distance, but if there is more noise signal in the environment, it will re-trigger too frequency. Setting the illumination threshold to turn on the light. When the event triggered and the environment illumination lower then the threshold, the device will turn on the light. 0 means turn off illumination detected function and never turn on the light. 1 means darkest. 99 means brightest. 100 means turn off illumination detected function. And always turn on the light. * Notice * in none test mode, only the value in 1 to 99 will enable the illumination detected function and update the illumination value. Bit 0: Reserve. Bit 1: 1 means enable test mode, 0 means disable normal mode. Notice: This bit only effect by the DIP Switch setting to program mode. Bit 2: Disable the door/window function (1: Disable, 0: Enable). Bit 3: Setting the temperature scale. 0: Fahrenheit, 1:Celsius. Bit 4: Disable the illumination report after event triggered (1: Disable, 0: Enable). Bit 5: Disable the temperature report after event triggered (1: Disable, 0: Enable). Bit 6: Reserve. Bit 7: Disable the back key release into test mode (1: Disable, 0: Enable). Multi-Sensor Function switch. Using bit to control. Bit 0: Disable magnetic integrate illumination to turn ON the lighting nodes in the association group 2 (1: Disable, 0: Enable). Bit 1: Disable PIR integrate Illumination to turn ON the lighting nodes in the association group 2 (1: Disable, 0: Enable). Bit 2: Disable magnetic integrate PIR to turn ON the light the nodes in the association group 2 (1: Disable, 0: Enable) (Default is Disable). Bit 3: When Bit 2 is 0 (Enable), Are the device and the lighting in the same room? 0: In the same room (Default), 1: In the different room. Notice: If this bit is 1, it is recommended also set the Bit1 to 1, cause the PIR triggered, doesn't mean the people in that room. Bit 4: Disable delay 5 seconds to turn off the light, when door/window closed. Bit 5: Disable auto turn off the light, after door/window opened to turn on the light. Notice: If bit2 is zero, this setting is useless. Notice: If the configuration No.9 is zero, this setting is useless. Bit 6: Reserve. Bit 7: Reserve. Customer function switch, using bit control. Bit 0: Reserve. Bit 1: Enable sending motion OFF report. Note: Depends on the Bit4, 0: Report Notification CC, Type: 0x07, Event: 0xFE 1: Sensor Binary Report, Type: 0x0C, Value: 0x00. Bit 2: Enable PIR super sensitivity mode. Bit 3: Enable don't send out BASIC OFF after door closed. Bit 4: Notification Type, 0: Using Notification Report. 1: Using Sensor Binary Report. Bit 5: Disable Multi CC in auto report. Bit 6: Disable to report battery state when the device triggered. Bit 7: Reserve. 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 the door/window state. 0 means turn off auto report door/window state. The default value is 12. The tick time can setting by the configuration No.20. The interval time for auto report the illumination. 0 means turn off auto report illumination. The default value is 12. The tick time can setting by the configuration No.20. The interval time for auto report the temperature. 0 means turn off auto report temperature. 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. The temperature differential to report. 0 means turn off this function. The unit is Fahrenheit. Enable this function the device will detect every minutes. And when the temperature is over 140 degree Fahrenheit, it will continue report. Enable this functionality will cause some issue please see the detail in the "Temperature Report" section. The illumination differential to report.0 means turn off this function. The unit is percentage. Enable this function the device will detect every minutes. Enable this functionality will cause some issue please see the detail in the "Illumination Report" section. open-zwave-1.5/config/polycontrol/000077500000000000000000000000001264474202400173105ustar00rootroot00000000000000open-zwave-1.5/config/polycontrol/doorlock.xml000066400000000000000000000043671264474202400216600ustar00rootroot00000000000000 0=The motor goes clockwise when unlatched; 1= The motor goes counterclockwise when unlatched 1=Slowest ... 5=Fastest, accepts values between 1 and 5 0=Stepper motor mode wave drive (Power Saving); 1=Stepper motor mode full drive(Normal) Factor 10 turn degree( 1 = degrees, 9 = 90 degres, etc. ) How many seconds from the lock has been unlatched to it automatically close again. If 0 then it's disabled Enable or Disable the beep sound from latch or unlatch operations( 0 = Disable, 1 = Enable ) Set the type of battery that powers the device. This affect the returned battery state. 0 = 3.6V, 1=3.0V When the battery level is equal to, or under this value, the device will notify with a beep sound after latch or unlatch open-zwave-1.5/config/polycontrol/keypad.xml000066400000000000000000000015241264474202400213110ustar00rootroot00000000000000 open-zwave-1.5/config/polycontrol/polylock.xml000066400000000000000000000042101264474202400216630ustar00rootroot00000000000000 0=The motor goes clockwise when unlatched; 1= The motor goes counterclockwise when unlatched Motor/relay run time LOCK in sec 1-15 Motor/relay run time UNLOCK in sec 1-15 Value 0-15/0=fastest 15=slowest How the motor will turn according to torque and speed open-zwave-1.5/config/popp/000077500000000000000000000000001264474202400157025ustar00rootroot00000000000000open-zwave-1.5/config/popp/123580.xml000066400000000000000000000145511264474202400171740ustar00rootroot00000000000000 Set LED indication mode If not zero, automatically switch off after a user defined time. Unit: Sec, Min: 0, Max: 65535, Default: 0 Defines how to interpret RF Off command. Can be used in conjunction with Auto Off function: 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 logics; 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). Defines if the dimmer shall ignore start level in Start Level Change command despite it is specified or not Time to dim on button presses and Set command (if it has no duration specified). If not 0, dimming will be done smoothly to preserve bulb life. 0=Instantly, 1-255 in 10ms units (Default 30) Time to dim on button holds and Start Level Change command (if it has no duration specified). Unit in Seconds 1-255 (Default 3) Defines the dim level on command 'ON'. On default he dimmer restores last dim level. This parameter allows configuring the maximum level on second On command (if already On) or to always switch on to maximum level. Time to dim on double click Off button for Baby-Dim function. This function works only if the load is operated by single press and hold button action. If enabled, the device will wait for a click timeout to see if the second click would be pressed. This will introduce a small delay for single click commands. Unit in minutes 1-99 (0=Disable(Default) Target level on which to stop while executing Baby Dimming. Can be 0 to completely switch off the light. Unit in % 0-255 (0=Default) Typical time used to differentiate click, hold, double and triple clicks. in 10ms units (Default 50) Minimal level should be greater than maximal. 1-95 Level limit (Default 1) Maximal level should be greater than minimal. 0=Work as switch: use off and maximal level 10-99 Level limit (Default 99) Defines how the dimmer hall react on a simple ON Command. 0-99 0=Use previous light level (Default), 1 . 99 Define light level in % NB: Do not touch these settings if you are not sure what they mean! For dimmable LEDs and CFL with bypass use value 1. For other bulbs use default value. 5-60 (Default 28) NB: Do not touch these settings if you are not sure what they mean! For dimmable LEDs and CFL with bypass use value 40. For other bulbs use default value. 5-60 (Default 28) NB: Do not touch these settings if you are not sure what they mean! For dimmable LEDs and CFL with bypass use value 20. For other bulbs use default value. 3-20 (Default 10) NB: Do not touch these settings if you are not sure what they mean! (Default 0) open-zwave-1.5/config/popp/123601.xml000066400000000000000000000042351264474202400171640ustar00rootroot00000000000000 Set LED indication mode If not zero, automatically switch off after a user defined time. Unit: Sec, Min: 0, Max: 65535, Default: 0 Defines how to interpret RF Off command. Can be used in conjunction with Auto Off function: 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 logics; 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). Defines if the switch should restore switch state to the last state prior to device power off (power cycle). open-zwave-1.5/config/popp/123658.xml000066400000000000000000000033251264474202400171770ustar00rootroot00000000000000 If the setting is configured for 1 hour(set value=720), the device will report its instant power consumption every 1 hour to Z_Wave controller. Unit: 5 secs, Min: 1, Max: 32767, Default: 720 If the setting is configured for 1 hour(set value=6), the device will report its Accumulated power consumption (KW/h) every hour to Z_Wave controller. Unit: 10 min, Min: 1, Max: 32767, Default: 6 This is a warning when the wattage of load over the present threshold value, if the load wattage exceeds the setting value the device will send a warning alarm command to the controller. Min: 10, Max: 3000, Default: 3000 0 for Switch Off, 1 for Last Switch State (Default), 2 for Switch On open-zwave-1.5/config/popp/POPE009105.xml000066400000000000000000000063061264474202400176530ustar00rootroot00000000000000 Set LED indication mode If not zero, automatically switch device off after an user defined time. Unit: Sec, Min: 0, Max: 65535, Default: 0 Defines how to interpret RF Off-Command. Can be used in conjunction with Auto Off function: 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 logics; 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). Defines if the switch should restore switch state to the last prior to device power off (power cycle). Specify the consumption of the load in watts, for the calculation of power consumption. Maximum load 1800 W. Unit: Watts, Min: 0, Max: 3500, Default: 0 Color to OFF state Color to ON state open-zwave-1.5/config/qees/000077500000000000000000000000001264474202400156615ustar00rootroot00000000000000open-zwave-1.5/config/qees/reto-plugin-switch.xml000066400000000000000000000004311264474202400221450ustar00rootroot00000000000000 open-zwave-1.5/config/qubino/000077500000000000000000000000001264474202400162215ustar00rootroot00000000000000open-zwave-1.5/config/qubino/ZMNHAA2.xml000066400000000000000000000073361264474202400200140ustar00rootroot00000000000000 Flush 1 relay 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 - 65535 => 0,01 second - 655,35 seconds. Auto OFF enabled with define time, step is 10mseconds. 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 3 Set value means time interval (0 - 65535) in seconds, when power report is send. 0 - Reporting Disabled. 1 - 65535 = 1second - 65535 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) open-zwave-1.5/config/qubino/ZMNHAD1.xml000066400000000000000000000200541264474202400200060ustar00rootroot00000000000000 Flush 1 relay 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 Set value from 0 - 100 (0%- 100%). 0 = Reporting Disabled. 1 - 100 = 1% - 100% and 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 10% Set value means time interval (0 - 32535) in seconds, when power report is send. 0 = Reporting Disabled. 1 - 32535 = 1 second - 32535 seconds and reporting enabled. Power report is send with time interval set by entered value. Default value 300 (power report in Watts is send each 300s) Set value is added or subtracted to actual measured value by sensor. Available configuration parameters : default value 32536. 32536 offset is 0.0C. 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. Available configuration parameters : 0 = reporting disabled. 1 to 127 = 0,1°C to 12,7°C, step is 0,1°C. Default value is 5 = 0,5°C open-zwave-1.5/config/qubino/ZMNHBA2.xml000066400000000000000000000113021264474202400200010ustar00rootroot00000000000000 Flush 2 relays 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 - 65535 => 0,01 second - 655,35 seconds. Auto OFF enabled with define time, step is 10mseconds. Default value 0 0 - Auto OFF disabled. 1 - 65535 => 0,01 second - 655,35 seconds. Auto OFF enabled with define time, step is 10 mseconds. 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 1 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 1 Set value means time interval (0 1 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 300 (power report in Watts is send each 300s) Set value means time interval (0 1 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 300 (power report in Watts is send each 300s) open-zwave-1.5/config/qubino/ZMNHBD2.xml000066400000000000000000000167451264474202400200240ustar00rootroot00000000000000 Flush 2 relays 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 Q1 relay is ON it goes automatically OFF after set time. The timer is reset to zero every time the module receives an ON command from any source. Value is in 1s or 10ms depending on parameter 15 When Q1 relay is OFF it goes automatically ON after set time. The timer is reset to zero every time the module receives an OFF command from any source. Value is in 1s or 10ms depending on parameter 15 When Q2 relay is ON it goes automatically OFF after set time. The timer is reset to zero every time the module receives an ON command from any source. Value is in 1s or 10ms depending on parameter 15 When Q2 relay is OFF it goes automatically ON after set time. The timer is reset to zero every time the module receives an OFF command from any source. Value is in 1s or 10ms depending on parameter 15 Select the time units for auto on/off configuration. Applies tot he whole device 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 1 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 1 Set value means time interval (0 1 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 300 (power report in Watts is send each 300s) Set value means time interval (0 1 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 300 (power report in Watts is send each 300s) Type of device that is connected to the output (NC or NO) Type of device that is connected to the output (NC or NO) open-zwave-1.5/config/qubino/ZMNHCA2.xml000066400000000000000000000067521264474202400200170ustar00rootroot00000000000000 Flush 1 relay module 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 – 100 = 1% – 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 - 65535) in seconds, when power report is send. 0 - Reporting Disabled. 1 - 65535 = 1second - 65535 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) Module may include power and energy used by module itself in reports sent to the main controller This parameter defines shutter motor moving time of complete opening or complete closing. 0 – moving time disabled (working with limit switches). 1 – 65535 = 0,1seconds – 6553,5seconds After that time motor is stopped (relay goes to off state). Default value 0 Power threshold to be interpreted when motor reach the limit switch. Available settings: 0 – 255 (1-255 W). The value 0 means reaching a limit switch will not be detected. Default value: 10 (10W). By modifying the parameters setting from 0 to 1 a Shutter enters the calibration mode open-zwave-1.5/config/qubino/ZMNHCD.xml000066400000000000000000000215701264474202400177330ustar00rootroot00000000000000 Flush shutter responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controllers belonging to the system. Default is ALL ON active, ALL OFF active Set value means percentage, set value from 0 – 100 = 0% - 100%. Available configuration parameters : 0 - Reporting Disabled. 1 – 100 = 1% – 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%. NOTE: if power changed is less than 1W, the report is not send (pushed), independent of percentage set. Default value 1 Set value means time interval (0 – 32767) in seconds, when power report is send. Available configuration parameters : 0 – Reporting Disabled. 1 – 32767 = 1 second – 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) This parameter defines selection between two available operating modes. NOTE: When setting parameter, module needs to be excluded and included again! Default is shutter mode This parameter defines the time necessary for slats to make full turn (180 degrees). Configuration parameters : 0 – Tilting time disabled. 1 – 32767 = 0,01seconds – 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. Default value 150 (1,5 seconds) This parameter defines slats position after up/down movement through Z-wave or push-buttons. Default : slats return to previously set position in case of Z-wave control, push-button operation or when the lower limit switch is reached This parameter defines shutter motor moving time for complete opening or complete closing. Available configuration parameters : 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). NOTE: Important is that the reference position to manually set moving time is always shutter lower position! Set parameter 74 to 0 and move the shutter (using up/down push buttons or main controller UI) to the lowest desired position. On this shutter position, set parameter 74 to time for complete opening or complete closing. At this point shutter can be moved up (open) for set time, but can't be moved down because this position is already set as lower shutter position. To change shutter lower position below already set (manual recalibration), parameter 74 must be set to 0 and repeat the procedure described above. In case shutter has limit switches, but anyhow you would like to limit opening/closing position by time, you can still do it. In case you put time that is longer that opening/closing real time limited by limit switches, shutter will stop at limit switch, but the module relay will switch off after define time, not by shutter limit switch. Take in consideration that in this condition, the positioning with slider through UI will not show correct shutter position. Default value 0 Power threshold to be interpreted when motor reach the limit switch. Available configuration parameters: 0 – 127 = 1-127 W. The value 0 means reaching a limit switch will not be detected. Default value: 10 = 10W By modifying the parameters setting from 0 to 1 a Shutter enters the calibration mode. After shutter performs the calibration process, completing full cycle - up, down and up, set the parameter value back to disabled (default value) This parameter 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. Time is defined by entering it manually. Available configuration parameters : 0 = time is set automatically. 3 – 50 = 0,3seconds – 5seconds (100ms resolution). Default value 0 (auto) This parameter defines the minimum time delay between next motor movement (minimum time between switching motor off and on again). Available configuration parameters : 1 – 30 = 0,1seconds – 3seconds (100ms resolution). Default value 5 = 500ms Set value is added or subtracted to actual measured value by sensor. Available configuration parameters : 32536 – offset is 0.0C. 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. Default value 32536 (0.0C) digital temperature sensor is connected, module reports measured temperature on temperature change defined by this parameter. Available configuration parameters : 0 – Reporting disabled. 1-127 = 0,1°C – 12,7°C, step is 0,1°C. Default value 5 = 0.5°C open-zwave-1.5/config/qubino/ZMNHDA2.xml000066400000000000000000000116101264474202400200050ustar00rootroot00000000000000 Default value 0. Default value 0. Flush 1 relay module responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system. Default value 0. 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 - 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 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). 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). open-zwave-1.5/config/qubino/ZMNHDD1.xml000066400000000000000000000271651264474202400200230ustar00rootroot00000000000000 Default value 0. Default value 0. Default value 0. Default value 0. Flush dimmer module responds to commands ALL ON / ALL OFF that may be sent by the main controller or by other controller belonging to the system. Default value 255. 0 - Auto OFF disabled. Set value from 1 to 32536. 1 second – 32536 seconds Auto OFF enabled with defined time, step is 1 second. Default value 0. 0 - Auto ON disabled. Set value from 1 to 32535. 1 second – 32535 seconds Auto ON enabled with defined time, step is 1 second. Default value 0. Dimming is done by push button or switch connected to I1 (by default). Enabling 3-way switch, dimming can be controlled by push button or switch connected to I1 and I2. Default value 0. If Double click function is enabled, a fast double click on the push button will set dimming power at maximum dimming value. Default value 0. 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 - 32767 = 1 second - 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). 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. 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. 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. 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. Endpoint device type selection: notification sensor (1 - 6) sensor binary (9). NOTE: After parameter change, module has to be re included into the network in order setting to take effect! Default value 1. 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. Endpoint device type selection: notification sensor (1 - 6) sensor binary (9). NOTE: After parameter change, module has to be re included into the network in order setting to take effect! Default value 1. Set value is added or subtracted to actual measured value by sensor. 32536 – offset is 0.0C. 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. Default value 32536. If digital temperature sensor is connected, module reports measured temperature on temperature change defined by this parameter. 0 – Reporting disabled. 1- 127 = 0,1°C – 12,7°C, step is 0,1°C. Default value 5 = 0,5°C change. open-zwave-1.5/config/qubino/ZMNHIA2.xml000066400000000000000000000122501264474202400200130ustar00rootroot00000000000000 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. 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 - 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 300 (power report in Watts is send each 300s) 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 255 where 0 to 128 means from 0.0 °C to 12.8 °C and from 129 to 255 means from - 0.0 °C to -12.8 °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 255 where 0 to 128 means from 0.0 °C to 12.8 °C and from 129 to 255 means from - 0.0 °C to -12.8 °C. Set value means at which temperature the heating will be turned on even if the thermostat was manually set to off. The parameter can be set from 0 to 255 where 0 to 128 means from 0.0 °C to 12.8 °C and from 129 to 255 means from - 0.0 °C to -12.8 °C. Set value means the type of the heating device that is connected to the relay output. The heating device type can be normally open (NO) or normally close (NC). open-zwave-1.5/config/qubino/ZMNHJA2.xml000066400000000000000000000102641264474202400200170ustar00rootroot00000000000000 open-zwave-1.5/config/qubino/ZMNHJD1.xml000066400000000000000000000100251264474202400200140ustar00rootroot00000000000000 open-zwave-1.5/config/qubino/ZMNHND1.xml000066400000000000000000000132341264474202400200250ustar00rootroot00000000000000 Flush 1 relay 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 Set value is added or subtracted to actual measured value by sensor. Available configuration parameters : default value 32536. 32536 offset is 0.0C. 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. Available configuration parameters : 0 = reporting disabled. 1 to 127 = 0,1°C to 12,7°C, step is 0,1°C. Default value is 5 = 0,5°C open-zwave-1.5/config/rcs/000077500000000000000000000000001264474202400155135ustar00rootroot00000000000000open-zwave-1.5/config/rcs/em52-zw.xml000066400000000000000000000004221264474202400174410ustar00rootroot00000000000000 open-zwave-1.5/config/rcs/pm12-zw.xml000066400000000000000000000004231264474202400174510ustar00rootroot00000000000000 open-zwave-1.5/config/rcs/therm0005.xml000066400000000000000000000015071264474202400176640ustar00rootroot00000000000000 open-zwave-1.5/config/rcs/therm0007.xml000066400000000000000000000033511264474202400176650ustar00rootroot00000000000000 open-zwave-1.5/config/rcs/therm0009.xml000066400000000000000000000003731264474202400176700ustar00rootroot00000000000000 open-zwave-1.5/config/remotec/000077500000000000000000000000001264474202400163625ustar00rootroot00000000000000open-zwave-1.5/config/remotec/zfm-80.xml000066400000000000000000000026571264474202400201370ustar00rootroot00000000000000 Set external switch type. Set timeout period. Configure Node ID number for Z-Wave command source. Set relay output status if timeout period has been reached. open-zwave-1.5/config/remotec/zurc.xml000066400000000000000000000033171264474202400200730ustar00rootroot00000000000000 open-zwave-1.5/config/remotec/zxt-120.xml000066400000000000000000000055001264474202400202310ustar00rootroot00000000000000 In case none of the code on the code list works for the targeted air conditioner, user can use IR code learning function. See manual at section "IR Code Learning" for a description of the procedure. Value 0-22 Note: The status value 0x01 and 0x04 will be reset to 0 when the ZXT-120 receive a get command to this parameter. Value 1 idle - this IR channel is idle (default). Value 2 OK - the latest learning process successful and completed. Value 3 Learning - the ZXT- 120 is busy processing previous learning request. Value 4 Failed - the latest learning request failed. Look up the code list of ZXT-120 according to your AC brand. Value 0 normal power mode. Value 255 high power mode (default) Value 0 disable Surround IR Emitters. value 255 enable Surround IR Emitters (default). Value 0 SWING OFF. Value 255 SWING AUTO (Default). open-zwave-1.5/config/schlage/000077500000000000000000000000001264474202400163325ustar00rootroot00000000000000open-zwave-1.5/config/schlage/BE469NXCEN.xml000066400000000000000000000141201264474202400203770ustar00rootroot00000000000000 Enable or disable the beeper. Prevents all user codes from unlocking the deadbolt. Enable for extra security while you are away for an extended period of time. When enabled: Press the Outside Schlage Button to lock the deadbolt. (Default setting). When disabled: Press the Outside Schlage Button and then enter a user code to lock the deadbolt. The alarm is turned off by default. After installation, you’ll need to turn on your alarm. Activity Alarms when the door opens or closes. Perfect for monitoring doors while you’re at home. After the alarm is triggered, there is a built-in 3-second delay for it to reset. Sounds two short beeps. Tamper Alarms when the lock is disturbed, while locked. Senses subtle activity at the lock. Sounds 15 second Alarm (90 dB) Forced Entry Alarms when significant force pushes against the door, while locked. Perfect for nighttime or when you’re away from home. • Least sensitive mode Sounds three-minute shrill, steady alarm (90 dB) Each alarm mode is preset to a sensitivity level of three. 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 three. 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 three. 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. Enables/Disables local alarm on/off, mode change, sensitivity changes Each failed electronic attempt increments this count by one. When enabled, the lock will automatically relock 30 seconds after unlocking. (Disabled by default.) User Code PIN length, a value between 4 and 8. IMPORTANT: All user codes must be the same length. A subset of Electronic transition count, the number of transitions with high preload. The version of the bootloader open-zwave-1.5/config/schlagelink/000077500000000000000000000000001264474202400172105ustar00rootroot00000000000000open-zwave-1.5/config/schlagelink/itemp.xml000066400000000000000000000032061264474202400210510ustar00rootroot00000000000000 Attention: This will delete all your configuration, but the device will remain in the network. Handle with care. Configure what the external contact sends when trigger Defines if the sensor is in normal wakeup-mode or always on. This function shall be used only for testing since it draining the battery very fast. Offset to the temperature. This parameter can be used to calibrate the temperature sensor function if needed. Note. As factory default the temperature sensor function is calibrated. 0 = 0K (default), not 0 = Temperature Offset in K open-zwave-1.5/config/schlagelink/minikeypad.xml000066400000000000000000000035161264474202400220710ustar00rootroot00000000000000 Set all configuration values to default values (factory settings) if set to 0xff. To configure the time the beep is automatically turned off in seconds. 0 means disabled. 255 is endless To configure the timeout to wait for a WAKEUP_NO_MORE_INFORMATION before the error beep is automatically sound. The error beeps are fixed 8 beeps shortly after each other. 0 means disabled To configure the number of beeps per second. Every beep is fixed about 10ms. To configure the operating mode. If any mode other then 3, that value will be reported after a get but will be handled in SW as mode 1. open-zwave-1.5/config/sensative/000077500000000000000000000000001264474202400167255ustar00rootroot00000000000000open-zwave-1.5/config/sensative/strips-mazw.xml000077500000000000000000000024261264474202400217560ustar00rootroot00000000000000 Define the notification type. Specify if LED should indicate special event. open-zwave-1.5/config/swiid/000077500000000000000000000000001264474202400160435ustar00rootroot00000000000000open-zwave-1.5/config/swiid/swiidinter.xml000066400000000000000000000016521264474202400207520ustar00rootroot00000000000000 Activate/Deactive ALL ON/OFF open-zwave-1.5/config/swiid/swiidplug.xml000066400000000000000000000014361264474202400206000ustar00rootroot00000000000000 Activate/Deactive ALL ON/OFF open-zwave-1.5/config/thermofloor/000077500000000000000000000000001264474202400172645ustar00rootroot00000000000000open-zwave-1.5/config/thermofloor/multireg.xml000066400000000000000000000100231264474202400216320ustar00rootroot00000000000000 3-30 (0,2°C - 3.0°C) 50-400 (5.0°C - 40.0°C) 50-400 (5.0°C - 40.0°C) 50-400 (5.0°C - 40.0°C) 50-400 (5.0°C - 40.0°C) 0-9. Min temperature in Power Regulator Mode (setting 2. Temperature sensor - P) 50-400 (5.0°C - 40.0°C) 50-400 (5.0°C - 40.0°C) 0-10 open-zwave-1.5/config/trane/000077500000000000000000000000001264474202400160355ustar00rootroot00000000000000open-zwave-1.5/config/trane/TZEMT400AB32MAA.xml000066400000000000000000001053351264474202400206040ustar00rootroot00000000000000 0 = Gas/Elec, 1 = HeatPump 0 = Gas, 1 = Elec 0 = w/Cool, 1 = w/Heat 0 = C, 1 = F 0 = Unlocked, 1 = Locked Sets the minimum off time before another heating/cooling cycle can begin to provide compressor short cycle protection. The thermostat screen will display WAIT when minimum off time is being enforced. Sets the minimum run time before a heating/cooling cycle can turn off to prevent rapid cycling. Thermostat screen will display "Cool ON" or "Heat ON" while the minimum run time is being enforced. Sets the delta from setpoint that stage 1 heating starts. Sets the delta from setpoint that stage 1 heating stops. Stage 1 turns off at setpoint minus (-) Delta Stage 1. Sets the delta from setpoint that stage 2 heating starts. Sets the delta from setpoint that stage 2 heating stops. Stage 1 turns off at setpoint minus (-) Delta Stage 2. Sets the delta from setpoint that stage 3 heating starts. Sets the delta from setpoint that stage 3 heating stops. Stage 1 turns off at setpoint minus (-) Delta Stage 3. Sets the delta from setpoint that stage 1 cooling starts. Sets the delta from setpoint that stage 1 cooling stops. Stage 1 turns off at setpoint minus (-) Delta Stage 1. Sets the delta from setpoint that stage 2 cooling starts. Sets the delta from setpoint that stage 2 cooling stops. Stage 1 turns off at setpoint minus (-) Delta Stage 2. Sets the minimum separation between the heating and cooling setpoints. Attempts to lower the cooling below the heating setpoint by this amount will PUSH the heating setpoint down to maintain this separation. Same for setting the heating setpoint above the cooling setpoint, it will PUSH the cooling setpoint up to maintain this separation. Settings in F. 0 = No Setback, 1 = Setback, 2 if ESM Energy Saving Mode (ESM) Setpoints are the setpoints used when the Energy Saving Mode schedule is selected in the Schedule Mode screen (or via Z-Wave control). Setting in F. Energy Saving Mode (ESM) Setpoints are the setpoints used when the Energy Saving Mode schedule is selected in the Schedule Mode screen (or via Z-Wave control). The fan cycler function cycles the HVAC system fan for an ON period followed by an OFF period continuously. Used to provide minimum air ventilation requirements. When the Fan ON time is set to a value greater than 0, an additional Cycler Fan mode is present when pressing the FAN button on the thermostat. The fan cycler function cycles the HVAC system fan for an ON period followed by an OFF period continuously. Used to provide minimum air ventilation requirements. When the Fan ON time is set to a value greater than 0, an additional Cycler Fan mode is present when pressing the FAN button on the thermostat. 0 = no 2nd stage heat, 1 = 2nd stage heat. 0 = no aux heat, 1 = aux heat enabled. 0 = no 2nd stage cool, 1 = 2nd stage cool Set to 1 if running schedule (RUN is displayed on the thermostat screen). Default: HOLD 80F / 26C RUN 84F / xxC ESM Heating 1 Setpoint (does this vary with ESM, etc. or is this for the "Hold" setting? Default: HOLD 55F / 13C RUN 60F / xxC ESM 64F / xxC (unless parameter xx has been changed) Backlight Timeout is the time (in seconds) from the last button press to the backlight going out. The time-out can be set between 0 and 120 seconds. When set to 0, the backlight will remain always on. Default: 30 Sets the maximum heating setpoint value. Will not ramp or accept setpoints higher than this maximum. Minimum: 55F / xxC Maximum: 90F / xxC Default: 90F / 32C Sets the minimum cooling setpoint value. Will not ramp or accept setpoints lower than this minimum. Minimum: 60F / xxC Maximum: 99F / xxC Default: 60F / 15C This is the time before any screen reverts to the Minimized Screen (temperature display only), after you stop pushing buttons. Minimized Screen feature is disabled by setting this time to 0. Default: 0 The internal temperature sensor can be calibrated to report values different from its actual reading. The offset can range from -7 degrees to +7 degrees. Default: 0 The Screen Contrast sets the contrast level of the LCD display. The contrast can be set between 0 and 20. If the display is too light, use a higher number. If dark lines appear on the screen, use a lower number. Default: 10 0x2c after reset 0xf4 after reset 0x2c after reset 0xf4 after reset 0xb8 after reset 0xe4 after reset 0xb8 after reset 0xe4 after reset When enabled (set to 1), the local thermostat's scheduler function is enabled. Default: 0 0xff after reset 0xff after reset 0xff after reset 0xff after reset 0xff after reset 0xff after reset 0xff after reset Recovery enable? Default: 1 0x00 This value holds information about the first schedule setpoints for Sundays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Sundays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Sundays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Sundays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Mondays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Mondays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Mondays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Mondays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Tuesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Tuesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Tuesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Tuesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Wednesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Wednesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Wednesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Wednesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Thursdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Thursdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Thursdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Thursdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Fridays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Fridays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Fridays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Fridays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Saturdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Saturdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Saturdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Saturdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C open-zwave-1.5/config/trane/TZEMT400BB32MAA.xml000066400000000000000000001053351264474202400206050ustar00rootroot00000000000000 0 = Gas/Elec, 1 = HeatPump 0 = Gas, 1 = Elec 0 = w/Cool, 1 = w/Heat 0 = C, 1 = F 0 = Unlocked, 1 = Locked Sets the minimum off time before another heating/cooling cycle can begin to provide compressor short cycle protection. The thermostat screen will display WAIT when minimum off time is being enforced. Sets the minimum run time before a heating/cooling cycle can turn off to prevent rapid cycling. Thermostat screen will display "Cool ON" or "Heat ON" while the minimum run time is being enforced. Sets the delta from setpoint that stage 1 heating starts. Sets the delta from setpoint that stage 1 heating stops. Stage 1 turns off at setpoint minus (-) Delta Stage 1. Sets the delta from setpoint that stage 2 heating starts. Sets the delta from setpoint that stage 2 heating stops. Stage 1 turns off at setpoint minus (-) Delta Stage 2. Sets the delta from setpoint that stage 3 heating starts. Sets the delta from setpoint that stage 3 heating stops. Stage 1 turns off at setpoint minus (-) Delta Stage 3. Sets the delta from setpoint that stage 1 cooling starts. Sets the delta from setpoint that stage 1 cooling stops. Stage 1 turns off at setpoint minus (-) Delta Stage 1. Sets the delta from setpoint that stage 2 cooling starts. Sets the delta from setpoint that stage 2 cooling stops. Stage 1 turns off at setpoint minus (-) Delta Stage 2. Sets the minimum separation between the heating and cooling setpoints. Attempts to lower the cooling below the heating setpoint by this amount will PUSH the heating setpoint down to maintain this separation. Same for setting the heating setpoint above the cooling setpoint, it will PUSH the cooling setpoint up to maintain this separation. Settings in F. 0 = No Setback, 1 = Setback, 2 if ESM Energy Saving Mode (ESM) Setpoints are the setpoints used when the Energy Saving Mode schedule is selected in the Schedule Mode screen (or via Z-Wave control). Setting in F. Energy Saving Mode (ESM) Setpoints are the setpoints used when the Energy Saving Mode schedule is selected in the Schedule Mode screen (or via Z-Wave control). The fan cycler function cycles the HVAC system fan for an ON period followed by an OFF period continuously. Used to provide minimum air ventilation requirements. When the Fan ON time is set to a value greater than 0, an additional Cycler Fan mode is present when pressing the FAN button on the thermostat. The fan cycler function cycles the HVAC system fan for an ON period followed by an OFF period continuously. Used to provide minimum air ventilation requirements. When the Fan ON time is set to a value greater than 0, an additional Cycler Fan mode is present when pressing the FAN button on the thermostat. 0 = no 2nd stage heat, 1 = 2nd stage heat. 0 = no aux heat, 1 = aux heat enabled. 0 = no 2nd stage cool, 1 = 2nd stage cool Set to 1 if running schedule (RUN is displayed on the thermostat screen). Default: HOLD 80F / 26C RUN 84F / xxC ESM Heating 1 Setpoint (does this vary with ESM, etc. or is this for the "Hold" setting? Default: HOLD 55F / 13C RUN 60F / xxC ESM 64F / xxC (unless parameter xx has been changed) Backlight Timeout is the time (in seconds) from the last button press to the backlight going out. The time-out can be set between 0 and 120 seconds. When set to 0, the backlight will remain always on. Default: 30 Sets the maximum heating setpoint value. Will not ramp or accept setpoints higher than this maximum. Minimum: 55F / xxC Maximum: 90F / xxC Default: 90F / 32C Sets the minimum cooling setpoint value. Will not ramp or accept setpoints lower than this minimum. Minimum: 60F / xxC Maximum: 99F / xxC Default: 60F / 15C This is the time before any screen reverts to the Minimized Screen (temperature display only), after you stop pushing buttons. Minimized Screen feature is disabled by setting this time to 0. Default: 0 The internal temperature sensor can be calibrated to report values different from its actual reading. The offset can range from -7 degrees to +7 degrees. Default: 0 The Screen Contrast sets the contrast level of the LCD display. The contrast can be set between 0 and 20. If the display is too light, use a higher number. If dark lines appear on the screen, use a lower number. Default: 10 0x2c after reset 0xf4 after reset 0x2c after reset 0xf4 after reset 0xb8 after reset 0xe4 after reset 0xb8 after reset 0xe4 after reset When enabled (set to 1), the local thermostat's scheduler function is enabled. Default: 0 0xff after reset 0xff after reset 0xff after reset 0xff after reset 0xff after reset 0xff after reset 0xff after reset Recovery enable? Default: 1 0x00 This value holds information about the first schedule setpoints for Sundays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Sundays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Sundays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Sundays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Mondays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Mondays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Mondays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Mondays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Tuesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Tuesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Tuesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Tuesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Wednesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Wednesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Wednesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Wednesdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Thursdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Thursdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Thursdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Thursdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Fridays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Fridays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Fridays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Fridays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C This value holds information about the first schedule setpoints for Saturdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x06004643 06:00AM 70F / 67F 0x06001519 06:00AM 21C / 25C This value holds information about the second schedule setpoints for Saturdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x08003e55 08:00AM 62F / 85F 0x0800101d 08:00AM 16C / 29C This value holds information about the third schedule setpoints for Saturdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x1200464e 06:00PM 70F / 78F 0x12001519 06:00PM 21C / 25C This value holds information about the fourth schedule setpoints for Saturdays. Byte 1: Hour (0-23) Byte 2: Minute (0-59) Byte 3: Heat Setpoint (degrees) Byte 4: Cool Setpoint (degrees) Default: 0x16003e52 10:00PM 62F / 82F 0x1600101b 10:00PM 16C / 27C open-zwave-1.5/config/vision/000077500000000000000000000000001264474202400162335ustar00rootroot00000000000000open-zwave-1.5/config/vision/zd2102.xml000066400000000000000000000012561264474202400177030ustar00rootroot00000000000000 External Switch Status open-zwave-1.5/config/vision/zm1601eu.xml000066400000000000000000000020261264474202400202450ustar00rootroot00000000000000 Defines the reaction of the siren: [0] Strobe and Siren, [1] Siren, [2] Strobe (Default setting: 0) Defines the auto time out of the alarm indication: [0] 30 seconds, [1] 60 seconds, [2] 120 seconds, [3] Continuous (Default setting: 0) open-zwave-1.5/config/vision/zm1602eu.xml000066400000000000000000000020031264474202400202410ustar00rootroot00000000000000 Defines the reaction of the siren: [0] Strobe and Siren, [1] Siren, [2] Strobe (Default setting: 0) Defines the auto time out of the alarm indication: [0] 30 seconds, [1] 60 seconds, [2] 120 seconds, [3] Continuous (Default setting: 0) open-zwave-1.5/config/vision/zp3102.xml000066400000000000000000000042551264474202400177220ustar00rootroot00000000000000 Time until an associated device will turn off if no new movement is detected Report temperature in Celcius or Fahrenheit Sensitivity 1-7 (1 = most sensitive, 7 = most insensitive. 4 is default) -10 to -1, 0 to 10 (Signed decimal: 246 to 255, 0 to 10) open-zwave-1.5/config/vision/zs5101eu.xml000066400000000000000000000005001264474202400202450ustar00rootroot00000000000000 open-zwave-1.5/config/vitrum/000077500000000000000000000000001264474202400162525ustar00rootroot00000000000000open-zwave-1.5/config/vitrum/vitrumBS.xml000066400000000000000000000003501264474202400205450ustar00rootroot00000000000000 open-zwave-1.5/config/waynedalton/000077500000000000000000000000001264474202400172515ustar00rootroot00000000000000open-zwave-1.5/config/waynedalton/WDTC-20.xml000066400000000000000000000004121264474202400207500ustar00rootroot00000000000000 open-zwave-1.5/config/wenzhou/000077500000000000000000000000001264474202400164235ustar00rootroot00000000000000open-zwave-1.5/config/wenzhou/sm103.xml000066400000000000000000000025361264474202400200160ustar00rootroot00000000000000 Defines the level in the event sent when the sensor is triggered. Default is 99 (full brightness for a Z-Wave dimmer). 100-127 will set device on to the last value it was when turned off. On Time sets the number of seconds the sensor stays alerted before the off event is sent. Enable/Disable power saving mode. 0 enables. open-zwave-1.5/config/wenzhou/tsp01.xml000066400000000000000000000127121264474202400201170ustar00rootroot00000000000000 Setting the BASIC command value to turn on the light. The 0xFF (255) means turn on the light. For dimmer equipment 1 to 100 means the light strength. PIR sensitivity settings. 0 means disable the PIR motion. 1 means the lowest sensitivity. 99 means the highest sensitivity. High sensitivity means can detect long distance, but if there is more noise signal in the environment, it will re-trigger too frequently. Setting the illummination threshold to turn on the light. When the event triggered and the environment illumination lower then the threshold, the device will turn on the light. 0 means turn off illumination detected function and never turn on the light. 1 means darkest. 99 means brightest. 100 means turn off illumination detected function. And always turn on the light. * Notice * in none test mode, only the value in 1 to 99 will enable the illumination detected function and update the illumination value. Bit 0: 1 means security mode; 0 means home automation mode. Bit 1: 1 means enable test mode; 0 means disable test mode. * Notice * Bit 0 and bit 1 will effect when the DIP Switch setting to program mode. If bit1 is enabled, the bit0 is useless. Bit 2: Reserved, always 1. Bit 3: Setting the temperature scale; 0: Fahrenheit, 1:Celsius Bit 4: Disable illumination report after event triggered. Bit 5: Disable temperature report after event triggered. Multi-Sensor Function switch. Using bit to control. Bit 0: Reserved, always 1. Bit 1: Disable PIR integrate Illumination. Bit 2: Reserved, always 1. Bit 3: Reserved. Bit 4: Reserved. Bit 5: Reserved. Bit 6: Enable temperature monitoring. When this bit enabled, the temperature changed 3 degree Fahrenheit, it will report. And also the temperature over 140 degree Fahrenheit, it will report every 64 seconds. In the security mode, after the PIR report motion detected, setting the re-detect time. 8 seconds per tick, and minimum time is 24 seconds, 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 detecting. After turn on the light, setting the delay time to turn off the light when the PIR motion is not detected. 8 seconds per tick, and minimum time is 32 seconds, default tick is 4 (32 seconds). The interval time for auto report the battery level. 30 minutes per tick and minimum time is 30 minutes, default tick is 12 (6 hours) The interval time for auto report the illumination. 30 minutes per tick and minimum time is 30 minutes, default tick is 12 (6 hours) The interval time for auto report the temperature. 30 minutes per tick and minimum time is 30 minutes, default tick is 12 (6 hours) open-zwave-1.5/config/wenzhou/tz65d.xml000066400000000000000000000075351264474202400201330ustar00rootroot00000000000000 If the bit is set to 1, the dimmer will ignore the start level and instead start dimming from its current level. If this bit is set to 0, the dimmer will not ignore the start level. Setting this parameter to the value of 1 will stop theTZ66D from transmitting to devices that are associated into Group 4. The LED on the TZ65D 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. To change the top of the switch to OFF and the bottom of the switch ON , set parameter 4 to 1. The TZ66D can operate shade control devices via its Group 2 if this configuration parameter is set to 1. The TZ66D can operate shade control devices via its Group 3 if this configuration parameter is set to 1. The TZ66-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 TZ66D is set to flicker for only 1 second. The TZ66D can operate shade control devices via its Group 3 if this configuration parameter is set to 1. If value is 0, the TZ66D will not poll Group 2. If value is 1, the TZ66D will poll Group 2 at the interval set in Configuration Parameter 20. open-zwave-1.5/config/wenzhou/tz66d.xml000066400000000000000000000055201264474202400201240ustar00rootroot00000000000000 If the bit is set to 1, the dimmer will ignore the start level and instead start dimming from its current level. If this bit is set to 0, the dimmer will not ignore the start level. Setting this parameter to the value of 1 will stop theTZ66D from transmitting to devices that are associated into Group 4. The LED on the TZ66D 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. To change the top of the switch to OFF and the bottom of the switch ON , set parameter 4 to 1. The TZ66D can operate shade control devices via its Group 2 if this configuration parameter is set to 1. The TZ66D can operate shade control devices via its Group 3 if this configuration parameter is set to 1. The TZ66-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 TZ66D is set to flicker for only 1 second. The TZ66D can operate shade control devices via its Group 3 if this configuration parameter is set to 1. If value is 0, the TZ66D will not poll Group 2. If value is 1, the TZ66D will poll Group 2 at the interval set in Configuration Parameter 20. open-zwave-1.5/config/wenzhou/tz67.xml000066400000000000000000000007041264474202400177600ustar00rootroot00000000000000 Defines the behavior of the blue LED. Default: 0 open-zwave-1.5/config/wenzhou/tz68.xml000066400000000000000000000011301264474202400177530ustar00rootroot00000000000000 0 -> night light - LED ON when the load attached is turned OFF (default). 1 -> on indicator - LED ON when the load attached is turned ON. open-zwave-1.5/config/wenzhou/tz88.xml000066400000000000000000000013711264474202400177640ustar00rootroot00000000000000 If the setting is configured for 1 hour (value=720), the TZ88 will report its instant power consumption every 1 hour. If the setting is configured for 1 hour (value=6), the TZ88 will report its accumulated power consumption (kWh) every 1 hour. open-zwave-1.5/config/widom/000077500000000000000000000000001264474202400160435ustar00rootroot00000000000000open-zwave-1.5/config/widom/UBS104.xml000066400000000000000000000331651264474202400174530ustar00rootroot00000000000000 Device status when the external switch receives 1 click Device status when the external switch receives 2 clicks Device status when the external switch receives 3 clicks Device status when the external switch is held down Action on the associated devices when the external switch receives 1 click" Action on the associated devices when the external switch receives 2 clicks Action on the associated devices when the external switch receives 3 clicks Action on the associated devices when the external switch is held down Action performed on all network devices when the external switch receives 1 click Action performed on all network devices when the external switch receives 2 clicks Action performed on all network devices when the external switch receives 3 clicks Action performed on all network devices when the external switch is held down Device status upon receipt of a Basic Set ON_LEVEL value used for devices belonging to Group 2 (1 Click association group). Set value from 0 to 255 (Default: 255) OFF_LEVEL value used for devices belonging to Group 2 (1 Click association group). Set value from 0 to 255 (Default: 0) ON_LEVEL value used for devices belonging to Group 3 (2 Click association group). Set value from 0 to 255 (Default: 255) OFF_LEVEL value used for devices belonging to Group 3 (2 Click association group). Set value from 0 to 255 (Default: 0) ON_LEVEL value used for devices belonging to Group 4 (3 Click association group). Set value from 0 to 255 (Default: 255) OFF_LEVEL value used for devices belonging to Group 4 (3 Click association group). Set value from 0 to 255 (Default: 0) ON_LEVEL value used for devices belonging to Group 5 (Hold association group). Set value from 0 to 255 (Default: 255) OFF_LEVEL value used for devices belonging to Group 5 (Hold association group). Set value from 0 to 255 (Default: 0) Timer associated with the 1 click event on the external switch Timer associated with the 2 click event on the external switch Timer associated with the 3 click event on the external switch Timer associated with the hold event on the external switch Timer associated with the reception of a Basic Set command Time in seconds (1 3600). Default: 600 (10 minutes) Switch-off timer validity Smoke Alarm, CO, CO2 Action Heat Allarm Water Allarm Home Security ON time during flashing. Set value from 0 to 255 (Default: 5) OFF time during flashing. Set value from 0 to 255 (Default: 5) Duration of flashing phase. Set value from 0 to 255 (Default: 10) Startup Status Configuration Reset Type of external switch Sensitivity. Set value from 0 to 255 (Default: 9) Load protection. Time in seconds (3600). Default: 0 Learn Mode open-zwave-1.5/config/widom/UME304C_S.xml000066400000000000000000000336111264474202400200330ustar00rootroot00000000000000 Device status when the external switch receives 1 click Device status when ZWave command Basic Set is received C VERSION. Sets the current level above which the time spent above that level is measured. For S VERSION. Sets to 1250 the default and max current level above which the time spent above that level is measured (Hundredths of Amperes) Sets the time beyond which, in the case of overcurrent at a level higher than that established in parameter 30, an OverCurrent event occurs (seconds) Defines the next state of the device if an overcurrent event has occurred. Provides total operating time from last meter reset. When set to 0 it resets the cumulated values of energy and total operating time. Determines whether energy events are related to energy consumed or energy produced C VERSION. Sets the level of instantaneous power in Watts beyond which time of permanence above this level is calculated. For S VERSION. Sets to 3000 the default and max level of instantaneous power in Watts beyond which time of permanence above this level is calculated. Sets the time in seconds beyond which, if instantaneous power remains at levels exceeding threshold defined by parameter 35, a UP Power event occurs. Defines the next state of the device if an overcurrent event has occurred. Defines the status of associated devices in the presence of a UP Power event. From: 1 to 99 for dimming purpose. .0 (OFF) and -1(ON) for switching ON/OFF Sets the level of instantaneous power in Watts beyond which time of permanence below this level is calculated. Sets the time in seconds beyond which, if instantaneous power remains at levels below threshold defined by parameter 39, a DOWN Power event occurs. Defines the next state of the device in the case of a DOWN Power event occurring. Defines the status of associated devices in the presence of a DOWN Power event. From: 1 to 99 for dimming purpose. 0 (OFF) and -1(ON) for switching ON/OFF. the energy level that once exceeded an Energy Limit event occurs. From 0 to 2.000.000 KWh Default value: 2.000.000 KWh Defines the next state of the device in the case of an Energy Limit event occurs Defines the percentage variation of instantaneous power determining the sending of the report.(Default: 10%) Defines the maximum time in minutes since the previous report beyond which an Instantaneous Power Report will still be sent. (Default: 10 minutes) Defines the increase of total energy required to generate a report listing the level of total energy to the devices associated to the Energy Notification Group. Defines the nominal voltage value in tenths of volts. Together with parameter No. 49 this is used by the automatic notification system to send reports on variations of voltage. Defines, as a percentage, the nominal value for permitted fall in maximum voltage.(default 10%) Defines which electric parameters, other than power, will be subjected to automatic notification. The value to be set for this parameter must be calculated as the sum of values associated to the individual electric parameter indicated in the table.(default 30) Byte 1 : Bit 7: reserved; Bit 6:reserved; Bit 5: Multilevel Sensor: Power Report; Bit 4: Power factor; Bit 3: Current; Bit 2: Voltage; Bit 1: Energy; Bit 0: Power; Returns the value of voltage RMS at the time of the reading expressed in tenths of Volts.. Returns the value of current RMS expressed in hundredths of Amperes. Returns the value of power factor as a percentage. Returns the value of total energy consumed expressed in Wh (thousandths of KWh). Returns the value of total energy produced expressed in Wh (thousandths of KWh). Defines the status of the device following a restart(default 3) Defines which parameters should be reset to default values.(default 4) Defines the type of external switch connected to the device.(default 4) Defines the load control mode.(default 1) open-zwave-1.5/config/zipato/000077500000000000000000000000001264474202400162325ustar00rootroot00000000000000open-zwave-1.5/config/zipato/MiniKeypad.xml000066400000000000000000000036541264474202400210160ustar00rootroot00000000000000 Set all configuration values to default values (factory settings). To configure the time the beep is automatically turned off in seconds. To configure the timeout to wait for a WAKEUP_NO_MORE_INFORMATION before the error beep is automatically sound. The error beeps are fixed 8 beeps shortly after each other. To configure the number of beeps per second. Every beep is fixed about 10ms. To configure the operating mode. If any mode other then 3, that value will be reported after a get but will be handled in SW as mode 1. open-zwave-1.5/config/zipato/RGBBulb.xml000066400000000000000000000017101264474202400201720ustar00rootroot00000000000000 Color Temperature Shock sensor : 0=Maximum sensitivity ; 32=minimum sensitivity open-zwave-1.5/config/zwave.me/000077500000000000000000000000001264474202400164605ustar00rootroot00000000000000open-zwave-1.5/config/zwave.me/ZME_05431.xml000066400000000000000000000145421264474202400203770ustar00rootroot00000000000000 If not zero, automatically switch off/close blind after a user defined time If not zero, automatically switch off/close blind after a user defined time Defines if the dimmer shall ignore start level in StartLevelChange command despite it is specified or not. Defines if the switch should restore switch state to the last state prior to device power off (power cycle). Typical time used to differentiate click, hold, double and triple clicks. If disabled, the local operations by buttons will not switch the load, but only send commands to On/Off association group. In this mode buttons are not linked with the switch anymore. They can be used separately: buttons to control remote device, switch will operate by RF commands only. Defines which command should be sent on button single press or hold. Basic commands are sent to Association group. Switch All commands are sent broadcast. Defines which command should be sent on button double press or press-hold. Basic commands are sent to Association group. Switch All commands are sent broadcast. If not disabled, the device will wait for a click timeout to see if the second click would be pressed. This will introduce a small delay for single click commands. open-zwave-1.5/config/zwave.me/ZME_06433.xml000066400000000000000000000223751264474202400204050ustar00rootroot00000000000000 If not zero, automatically switch off after a user defined time Defines how to interpret RF Off command. Can be used in conjunction with Auto Off function: 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 logics; 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). Defines if the dimmer shall ignore start level in StartLevelChange command despite it is specified or not. Time to dim on button presses and Set command (if it has no duration specified). If not 0, dimming will be done smoothly to preserve bulb life. Time to dim on button holds and StartLevel Change command (if it has no duration specified). Defines if the dimmer shall set maximum light level on On command. By default on On command dimmer restores last level. This parameter allows to configure to set maximum level on second On command (if already On) or to always switch on to maximum level. Time to dim on double click Off button for Baby- Dim function. This function works only if the load is operated by single press and hold button action. If enabled, the device will wait for a click timeout to see if the second click would be pressed. This will introduce a small delay for single click commands, unprotected. Target level on which to stop while executing Baby Dimming. Can be 0 to completely switch off the light. Typical time used to differentiate click, hold, double and triple clicks. If disabled, the local operations by buttons will not switch the load, but only send commands to On/Off association group. In this mode buttons are not linked with the switch anymore. They can be used separately: buttons to control remote device, switch will operate by RF commands only. Defines which command should be sent on button single press or hold. Basic and Scene Activation commands are sent to Association group. Use Scene Controller Conf to set up Scene ID for Scene Activation. Switch All commands are sent broadcast. Defines which command should be sent on button double press or press-hold. Basic and Scene Activation commands are sent to Association group. Use Scene Controller Conf to set up Scene ID for Scene Activation. Switch All commands are sent broadcast. If not disabled, the device will wait for a click timeout to see if the second click would be pressed. This will introduce a small delay for single click commands. Maximum level should be greater than minimal level. Set to 0 to work as a switch (off or full on only), or set to 10 - 99 Set to 0 to use previous light level, or set to 1 - 99 NB: Do not touch these settings if you are not sure what they mean! For dimmable LEDs and CFL with bypass use value 1. For other bulbs use default value. NB: Do not touch these settings if you are not sure what they mean! For dimmable LEDs and CFL with bypass use value 40. For other bulbs use default value. NB: Do not touch these settings if you are not sure what they mean! For dimmable LEDs and CFL with bypass use value 20. For other bulbs use default value. NB: Do not touch these settings if you are not sure what they mean! open-zwave-1.5/config/zwave.me/ZME_06436.xml000066400000000000000000000156471264474202400204140ustar00rootroot00000000000000 If not zero, automatically switch off/close blind after a user defined time If not zero, automatically switch off/close blind after a user defined time Time to go from opened to closed state. Used to estimate the current level. Note that in Permanent motion mode the reported value would a be Closed or Opened, while all Basic and Multilevel Set values (1-99, 255) would Open except 0 value that would Close. Time to go from closed to open state. This value may differ from Full close time for some blinds due to gravity. Used to estimate the current level. Note that in Permanent motion mode the reported value would a be Closed or Opened, while all Basic and Multilevel Set values (1-99, 255) would Open except 0 value that would Close. Id of the device which commands would be interpreted not as Open/Close, but as block/unblock. Usefull with door opening detector: if the door is open, block the blind not to break shades while they move. Defines which command from blocking device to interpret as closed door and hence, unprotected. Defines behaviour on open press while closing and vice versa. To allow Stop behavior when switched by remote, use Stop by Basic Allow exchanging open and close relays if blind control is wired to the motor incorrectly Typical time used to differentiate click, hold, double and triple clicks. If disabled, the local operations by buttons will not switch the load, but only send commands to On/Off association group. In this mode buttons are not linked with the switch anymore. They can be used separately: buttons to control remote device, switch will operate by RF commands only. Defines which command should be sent on button single press or hold. Basic commands are sent to Association group. Switch All commands are sent broadcast. Defines which command should be sent on button double press or press-hold. Basic commands are sent to Association group. Switch All commands are sent broadcast. If not disabled, the device will wait for a click timeout to see if the second click would be pressed. This will introduce a small delay for single click commands. open-zwave-1.5/config/zwave.me/ZME_064381.xml000066400000000000000000000063061264474202400204670ustar00rootroot00000000000000 Set LED indication mode If not zero, automatically switch device off after an user defined time. Unit: Sec, Min: 0, Max: 65535, Default: 0 Defines how to interpret RF Off-Command. Can be used in conjunction with Auto Off function: 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 logics; 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). Defines if the switch should restore switch state to the last prior to device power off (power cycle). Specify the consumption of the load in watts, for the calculation of power consumption. Maximum load 1800 W. Unit: Watts, Min: 0, Max: 3500, Default: 0 Color to OFF state Color to ON state open-zwave-1.5/config/zwave.me/ZME_064435.xml000066400000000000000000000063031264474202400204640ustar00rootroot00000000000000 Typical time used to differentiate click, hold, double and triple clicks Values: 1 – 100 in 10 ms units (default is 50, that is equivalent to 500 ms) Defines which command should be sent on button single press or hold. Basic commands are sent to Association group. Switch All commands are sent broadcast. Defines which command should be sent on button double press or press-hold. Basic commands are sent to Association group. Switch All commands are sent broadcast. If not disabled, the device will wait for a click timeout to see if the second click would be pressed. This will introduce a small delay for single click commands. Send unsolicited battery report on wakeup. open-zwave-1.5/config/zwave.me/ZME_KFOB-S.xml000066400000000000000000000157551264474202400206530ustar00rootroot00000000000000 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 group B, button 4 with groups D. Click is On, Hold is dimming Up, Double click is Off, Click-Hold is dimming Down. In pair button 2/4 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 Send the following Switch All ON/OFF commands Invert meaning of On/Dim up and Off/Dim down in pairs of buttons. This applies only to pairs in grouped mode. Buttons 1 and 2 will become Off/Dim down, buttons 3 and 4 On/Dim up. If the KFOB wakes up and there is no controller nearby, several unsuccessful communication attempts will drain battery open-zwave-1.5/config/zwave.me/ZME_WALLC-S.xml000066400000000000000000000154461264474202400207710ustar00rootroot00000000000000 In separate mode button 1 works with group 1, button 3 with groups 3. 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 1, double click with group 3. In separate mode button 2 works with group 2, button 4 with groups 4. Click is On, Hold is dimming Up, Double click is Off, Click-Hold is dimming Down. In pair button 2/4 are Up/Down correspondingly. Click is On/Off, Hold is dimming Up/Down. Single clicks works with group 2, double click with group 4. In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop Typical time used to differentiate click, hold and double clicks 1-100 in 10 ms units (default is 50, that is equivalent to 500 ms) Send the following Switch All ON/OFF commands Invert meaning of On/Dim up and Off/Dim down in pairs of buttons. This applies only to pairs in grouped mode. Buttons 1 and 2 will become Off/Dim down, buttons 3 and 4 On/Dim up. To save batteries LED confirmation can be disabled. open-zwave-1.5/config/zwave.me/ZME_WCD2.xml000066400000000000000000000162731264474202400204250ustar00rootroot00000000000000 Button 1 and 3 pair mode (Parameter Number 1, Parameter Size 1) In separate mode button 1 works with group 1, button 3 with groups 3. 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 1, double click with group 3. Button 2 and 4 pair mode (Parameter Number 2, Parameter Size 1) In separate mode button 2 works with group 2, button 4 with groups 4. Click is On, Hold is dimming Up, Double click is Off, Click-Hold is dimming Down. In pair button 2/4 are Up/Down correspondingly. Click is On/Off, Hold is dimming Up/Down. Single clicks works with group 2, double click with group 4. Action on group 1 (Parameter Number 11, Parameter Size 1) In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop Action on group 2 (Parameter Number 12, Parameter Size 1) In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop Action on group 3 (Parameter Number 13, Parameter Size 1) In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop Action on group 4 (Parameter Number 14, Parameter Size 1) In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop Typical time used to differenciate click, hold and double clicks This allows to save battery open-zwave-1.5/config/zwave.me/iTemp.xml000066400000000000000000000002201264474202400202520ustar00rootroot00000000000000 open-zwave-1.5/config/zwave.me/kfob.xml000066400000000000000000000171051264474202400201270ustar00rootroot00000000000000 In separate mode button 1 works with group 1, button 3 with groups 3. 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 1, double click with group 3. In separate mode button 2 works with group 2, button 4 with groups 4. Click is On, Hold is dimming Up, Double click is Off, Click-Hold is dimming Down. In pair button 2/4 are Up/Down correspondingly. Click is On/Off, Hold is dimming Up/Down. Single clicks works with group 2, double click with group 4. In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop In Switch On/Off only mode On command is sent on Dim Up, Off on Dim Down. In Scenes mode the scene ID sent is (10 * group + ActionID), where ActionID is: 1 = On, 2 = Off, 3 = Dim Up Start, 4 = Dim Down Start, 5 = Dim Up Stop, 6 = Dim Down Stop Typical time used to differentiate click, hold and double clicks 1-100 in 10 ms units (default is 50, that is equivalent to 500 ms) Send the following Switch All ON/OFF commands Invert meaning of On/Dim up and Off/Dim down in pairs of buttons. This applies only to pairs in grouped mode. Buttons 1 and 2 will become Off/Dim down, buttons 3 and 4 On/Dim up. To save batteries LED confirmation can be disabled. If the KFOB wakes up and there is no controller nearby, several unsuccessful communication attempts will drain battery open-zwave-1.5/config/zwcfg.xsd000066400000000000000000000210031264474202400165600ustar00rootroot00000000000000 open-zwave-1.5/config/zwscene.xsd000066400000000000000000000020151264474202400171200ustar00rootroot00000000000000 open-zwave-1.5/cpp/000077500000000000000000000000001264474202400142415ustar00rootroot00000000000000open-zwave-1.5/cpp/build/000077500000000000000000000000001264474202400153405ustar00rootroot00000000000000open-zwave-1.5/cpp/build/Makefile000066400000000000000000000214621264474202400170050ustar00rootroot00000000000000# # Makefile for OpenZWave Linux build # Greg Satz # GNU make only # Linux requires libudev-dev # FreeBSD requires port misc/e2fsprogs-libuuid #these variables can be modified by the user if needed # what flags we will use for compiling in debug mode DEBUG_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-inline -Wno-format -Werror -Wno-error=sequence-point -Wno-sequence-point -ggdb -DDEBUG -fPIC -DSYSCONFDIR="\"$(PREFIX)/etc/openzwave/\"" # what flags we will use for compiling in release mode RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Werror -Wno-format -Wno-error=sequence-point -Wno-sequence-point -O3 -DNDEBUG -fPIC -DSYSCONFDIR="\"$(PREFIX)/etc/openzwave/\"" #what flags we will use for linking in debug mode DEBUG_LDFLAGS := -g top_srcdir := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))../../) include $(top_srcdir)/cpp/build/support.mk #Mac prefers a dylib, not a so ifeq ($(UNAME),Darwin) SHARED_LIB_NAME=libopenzwave-$(VERSION).dylib SHARED_LIB_UNVERSIONED=libopenzwave.dylib else SHARED_LIB_NAME=libopenzwave.so.$(VERSION) SHARED_LIB_UNVERSIONED=libopenzwave.so endif #if we are on a Mac, add these flags and libs to the compile and link phases ifeq ($(UNAME),Darwin) CFLAGS += -c -DDARWIN TARCH += -arch i386 -arch x86_64 LDFLAGS += -dynamiclib LIBS += -framework IOKit -framework CoreFoundation -arch i386 -arch x86_64 else ifeq ($(UNAME),FreeBSD) # FreeBSD 10 has native iconv.h; for older, we look in /usr/local, and libiconv must be installed from ports. ifeq (,$(wildcard /usr/include/iconv.h)) CFLAGS += -I/usr/local/include endif LDFLAGS+= -shared -lusb else LDFLAGS += -shared -Wl,-soname,libopenzwave.so.$(VERSION) LIBS += -ludev endif CFLAGS += $(CPPFLAGS) #where to put the temporary library LIBDIR ?= $(top_builddir) INCLUDES := -I $(top_srcdir)/cpp/src -I $(top_srcdir)/cpp/tinyxml/ -I $(top_srcdir)/cpp/hidapi/hidapi/ ifeq ($(UNAME),Darwin) SOURCES_HIDAPI =$(top_srcdir)/cpp/hidapi/mac else ifeq ($(UNAME),FreeBSD) SOURCES_HIDAPI =$(top_srcdir)/cpp/hidapi/libusb else SOURCES_HIDAPI =$(top_srcdir)/cpp/hidapi/linux endif SOURCES := $(top_srcdir)/cpp/src $(top_srcdir)/cpp/src/command_classes $(top_srcdir)/cpp/tinyxml \ $(top_srcdir)/cpp/src/value_classes $(top_srcdir)/cpp/src/platform $(top_srcdir)/cpp/src/platform/unix $(SOURCES_HIDAPI) $(top_srcdir)/cpp/src/aes/ VPATH = $(top_srcdir)/cpp/src:$(top_srcdir)/cpp/src/command_classes:$(top_srcdir)/cpp/tinyxml:\ $(top_srcdir)/cpp/src/value_classes:$(top_srcdir)/cpp/src/platform:$(top_srcdir)/cpp/src/platform/unix:$(SOURCES_HIDAPI):$(top_srcdir)/cpp/src/aes/ tinyxml := $(notdir $(wildcard $(top_srcdir)/cpp/tinyxml/*.cpp)) ifeq ($(UNAME),Darwin) hidapi := $(notdir $(wildcard $(top_srcdir)/cpp/hidapi/mac/*.c)) else ifeq ($(UNAME),FreeBSD) hidapi := $(notdir $(wildcard $(top_srcdir)/cpp/hidapi/libusb/*.c)) else hidapi := $(notdir $(wildcard $(top_srcdir)/cpp/hidapi/linux/*.c)) # we do not want the libusb version endif cclasses := $(notdir $(wildcard $(top_srcdir)/cpp/src/command_classes/*.cpp)) vclasses := $(notdir $(wildcard $(top_srcdir)/cpp/src/value_classes/*.cpp)) pform := $(notdir $(wildcard $(top_srcdir)/cpp/src/platform/*.cpp)) \ $(notdir $(wildcard $(top_srcdir)/cpp/src/platform/unix/*.cpp)) indep := $(notdir $(filter-out $(top_srcdir)/cpp/src/vers.cpp, $(wildcard $(top_srcdir)/cpp/src/*.cpp))) aes := $(notdir $(wildcard $(top_srcdir)/cpp/src/aes/*.c)) default: printversion $(LIBDIR)/libopenzwave.a $(LIBDIR)/$(SHARED_LIB_NAME) $(top_builddir)/ozw_config clean: @rm -rf $(DEPDIR) $(OBJDIR) $(LIBDIR)/libopenzwave.so* $(LIBDIR)/libopenzwave*.dylib $(LIBDIR)/libopenzwave.a $(top_builddir)/libopenzwave.pc $(top_builddir)/docs/api $(top_builddir)/Doxyfile $(top_srcdir)/cpp/src/vers.cpp printversion: @echo "Building OpenZWave Version $(GITVERSION)" -include $(patsubst %.cpp,$(DEPDIR)/%.d,$(tinyxml)) -include $(patsubst %.c,$(DEPDIR)/%.d,$(hidapi)) -include $(patsubst %.cpp,$(DEPDIR)/%.d,$(cclasses)) -include $(patsubst %.cpp,$(DEPDIR)/%.d,$(vclasses)) -include $(patsubst %.cpp,$(DEPDIR)/%.d,$(pform)) -include $(patsubst %.cpp,$(DEPDIR)/%.d,$(indep)) -include $(patsubst %.c,$(DEPDIR)/%.d,$(aes)) #create a vers.cpp file that contains our version and subversion revisions $(top_srcdir)/cpp/src/vers.cpp: @echo "Creating vers.cpp" @echo '#include "Defs.h"' > $(top_srcdir)/cpp/src/vers.cpp @echo 'uint16_t ozw_vers_major = $(VERSION_MAJ);' >> $(top_srcdir)/cpp/src/vers.cpp @echo 'uint16_t ozw_vers_minor = $(VERSION_MIN);' >> $(top_srcdir)/cpp/src/vers.cpp @echo 'uint16_t ozw_vers_revision = $(VERSION_REV);' >> $(top_srcdir)/cpp/src/vers.cpp @echo 'char ozw_version_string[] = "$(GITVERSION)";' >> $(top_srcdir)/cpp/src/vers.cpp #$(OBJDIR)/vers.o: $(top_builddir)/vers.cpp $(LIBDIR)/libopenzwave.a: $(patsubst %.cpp,$(OBJDIR)/%.o,$(tinyxml)) \ $(patsubst %.c,$(OBJDIR)/%.o,$(hidapi)) \ $(patsubst %.c,$(OBJDIR)/%.o,$(aes)) \ $(patsubst %.cpp,$(OBJDIR)/%.o,$(cclasses)) \ $(patsubst %.cpp,$(OBJDIR)/%.o,$(vclasses)) \ $(patsubst %.cpp,$(OBJDIR)/%.o,$(pform)) \ $(patsubst %.cpp,$(OBJDIR)/%.o,$(indep)) \ $(OBJDIR)/vers.o @echo "Linking Static Library" @$(AR) $@ $+ @$(RANLIB) $@ $(LIBDIR)/$(SHARED_LIB_NAME): $(patsubst %.cpp,$(OBJDIR)/%.o,$(tinyxml)) \ $(patsubst %.c,$(OBJDIR)/%.o,$(hidapi)) \ $(patsubst %.c,$(OBJDIR)/%.o,$(aes)) \ $(patsubst %.cpp,$(OBJDIR)/%.o,$(cclasses)) \ $(patsubst %.cpp,$(OBJDIR)/%.o,$(vclasses)) \ $(patsubst %.cpp,$(OBJDIR)/%.o,$(pform)) \ $(patsubst %.cpp,$(OBJDIR)/%.o,$(indep)) \ $(OBJDIR)/vers.o @echo "Linking Shared Library" @$(LD) $(LDFLAGS) $(TARCH) -o $@ $+ $(LIBS) @ln -sf $(SHARED_LIB_NAME) $(LIBDIR)/$(SHARED_LIB_UNVERSIONED) $(top_builddir)/libopenzwave.pc: $(top_srcdir)/cpp/build/libopenzwave.pc.in $(PKGCONFIG) @echo "Making libopenzwave pkg-config file" @$(SED) \ -e 's|[@]prefix@|$(PREFIX)|g' \ -e 's|[@]exec_prefix@|$(PREFIX)/bin|g' \ -e 's|[@]libdir@|$(instlibdir)|g' \ -e 's|[@]includedir@|$(PREFIX)/include/openzwave/|g' \ -e 's|[@]sysconfdir@|$(PREFIX)/etc/openzwave/|g' \ -e 's|[@]gitversion@|$(GITVERSION)|g' \ -e 's|[@]docdir@|$(docdir)/|g' \ -e 's|[@]VERSION@|$(VERSION)|g' \ < "$<" > "$@" $(top_builddir)/ozw_config: $(top_srcdir)/cpp/build/ozw_config.in @echo "Making ozw_config file" @$(SED) \ -e 's|[@]pkgconfigfile@|$(pkgconfigdir)/libopenzwave.pc|g' \ < "$<" > "$@" @chmod +x $(top_builddir)/ozw_config ifeq ($(DOT),) HAVE_DOT = -e 's|[@]HAVE_DOT@|NO|g' else HAVE_DOT = -e 's|[@]HAVE_DOT@|YES|g' endif $(top_builddir)/Doxyfile: $(top_srcdir)/docs/Doxyfile.in $(top_srcdir)/cpp/src/vers.cpp @mkdir -p $(top_builddir)/docs/api/ @$(SED) \ -e 's|[@]OUTPUT_DIR@|$(top_builddir)/docs/api/|g' \ -e 's|[@]TOPSRC_DIR@|$(top_srcdir)|g' \ $(HAVE_DOT) \ -e 's|[@]VERSION@|$(VERSION).$(VERSION_REV)|g' \ < "$<" > "$@" ifeq ($(DOXYGEN),) doc: $(warning Documentation not being built) else doc: $(top_builddir)/Doxyfile @echo "Creating Documentation at $(top_builddir)/docs/api/" @mkdir -p $(top_builddir)/docs/api/ @cd $(top_builddir); $(DOXYGEN) endif install: $(LIBDIR)/$(SHARED_LIB_NAME) doc $(top_builddir)/libopenzwave.pc $(top_builddir)/ozw_config @echo "Installing Shared Library" @install -d $(DESTDIR)/$(instlibdir)/ @cp $(LIBDIR)/$(SHARED_LIB_NAME) $(DESTDIR)/$(instlibdir)/$(SHARED_LIB_NAME) @ln -sf $(SHARED_LIB_NAME) $(DESTDIR)/$(instlibdir)/$(SHARED_LIB_UNVERSIONED) @echo "Installing Headers" @install -d $(DESTDIR)/$(includedir) @install -m 0644 $(top_srcdir)/cpp/src/*.h $(DESTDIR)/$(includedir) @install -d $(DESTDIR)/$(includedir)/command_classes/ @install -m 0644 $(top_srcdir)/cpp/src/command_classes/*.h $(DESTDIR)/$(includedir)/command_classes/ @install -d $(DESTDIR)/$(includedir)/value_classes/ @install -m 0644 $(top_srcdir)/cpp/src/value_classes/*.h $(DESTDIR)/$(includedir)/value_classes/ @install -d $(DESTDIR)/$(includedir)/platform/ @install -m 0644 $(top_srcdir)/cpp/src/platform/*.h $(DESTDIR)/$(includedir)/platform/ @install -d $(DESTDIR)/$(includedir)/platform/unix/ @install -m 0644 $(top_srcdir)/cpp/src/platform/unix/*.h $(DESTDIR)/$(includedir)/platform/unix/ @install -d $(DESTDIR)/$(includedir)/aes/ @install -m 0644 $(top_srcdir)/cpp/src/aes/*.h $(DESTDIR)/$(includedir)/aes/ @install -d $(DESTDIR)/$(sysconfdir)/ @echo "Installing Config Database" @cp -r $(top_srcdir)/config/* $(DESTDIR)/$(sysconfdir) @echo "Installing Documentation" @install -d $(DESTDIR)/$(docdir)/ @cp -r $(top_srcdir)/docs/* $(DESTDIR)/$(docdir) @if [ -d "$(top_builddir)/docs/html/" ]; then cp -r $(top_builddir)/docs/html/* $(DESTDIR)/$(docdir); fi @echo "Installing Pkg-config Files" @install -d $(DESTDIR)/$(pkgconfigdir) @cp $(top_builddir)/libopenzwave.pc $(DESTDIR)/$(pkgconfigdir) @install -d $(DESTDIR)/$(PREFIX)/bin/ @cp $(top_builddir)/ozw_config $(DESTDIR)/$(PREFIX)/bin/ozw_config @chmod 755 $(DESTDIR)/$(PREFIX)/bin/ozw_config .SUFFIXES: .d .cpp .o .a .PHONY: default clean install doc open-zwave-1.5/cpp/build/OZW_RunTests.sh000077500000000000000000000014421264474202400202260ustar00rootroot00000000000000#/bin/sh #### Include the library . `dirname $0`/sh2ju.sh topsrcdir=$1 #### Clean old reports juLogClean #### A call to a customized method CheckXML() { xmllint --noout --schema $* return $? } juLog -name=CheckDeviceClassesXML CheckXML "$topsrcdir/config/device_classes.xsd $topsrcdir/config/device_classes.xml" juLog -name=CheckOptionsXML CheckXML "$topsrcdir/config/options.xsd $topsrcdir/config/options.xml" juLog -name=CheckManufactureSpecificXML CheckXML "$topsrcdir/config/manufacturer_specific.xsd $topsrcdir/config/manufacturer_specific.xml" for file in $(find $topsrcdir/config/ \( -name "*.xml" ! -name "device_classes.xml" ! -name "options.xml" ! -name "manufacturer_specific.xml" \) ) do juLog -name=$file CheckXML "$topsrcdir/config/device_configuration.xsd $file" done open-zwave-1.5/cpp/build/libopenzwave.pc.in000066400000000000000000000005371264474202400210030ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ sysconfdir=@sysconfdir@ gitversion=@gitversion@ docdir=@docdir@ Name: libopenzwave Description: A Open Source implementation of the ZWave Serial API URL: http://www.openzwave.org/ Version: @VERSION@ Libs: -L${libdir} -lopenzwave Cflags: -I${includedir} open-zwave-1.5/cpp/build/ozw_config.in000077500000000000000000000022011264474202400200320ustar00rootroot00000000000000#!/bin/sh # Little Utility Application to get the OpenZwave Build Configuration # # You can use it in Makefiles etc as: # gcc `ozw_config --Libs` `ozw_config --Cflags` test.c -o test echoerr() { echo "$@" 1>&2; } function getValue { IFS="=: " while read -r name value do if [ "--"$name == $1 ] then echo "${value//\"/}" | tr -d '\r\n' fi done <<< $inputfile } pcfile=@pkgconfigfile@ key=$1 if [ "$key" == "--with-pc" ] then pcfile=$2 key=$3 fi if [ ! -f $pcfile ] then echoerr "$pcfile does not exist" exit 128 fi inputfile=`cat $pcfile | grep -vE '^(\s*$|#)'` if [ ! -z $key ] || [ "$key" == "--help" ] then if [ "$key" == "--Libs" ] then value="-L$(getValue "--libdir") -lopenzwave" elif [ "$key" == "--Cflags" ] then value="-I$(getValue "--includedir")" else value=$(getValue $key) fi if [ ! -z "$value" ] then echo $value else exit 128 fi else echo "OpenZWave Build Configuration Utility" echo "" echo "Options Available:" echo "--with-pc - Use a Alternative pc file" echo "" echo "Get Build Variables:" IFS="=: " while read -r name value do echo "--${name//\"/}" done <<< $inputfile fi open-zwave-1.5/cpp/build/sh2ju.sh000066400000000000000000000073061264474202400167350ustar00rootroot00000000000000#!/bin/sh ### Copyright 2010 Manuel Carrasco Moñino. (manolo at apache.org) ### ### Licensed under the Apache License, Version 2.0. ### You may obtain a copy of it at ### http://www.apache.org/licenses/LICENSE-2.0 ### ### A library for shell scripts which creates reports in jUnit format. ### These reports can be used in Jenkins, or any other CI. ### ### Usage: ### - Include this file in your shell script ### - Use juLog to call your command any time you want to produce a new report ### Usage: juLog command arguments ### options: ### -name="TestName" : the test name which will be shown in the junit report ### -error="RegExp" : a regexp which sets the test as failure when the output matches it ### -ierror="RegExp" : same as -error but case insensitive ### - Junit reports are left in the folder 'result' under the directory where the script is executed. ### - Configure Jenkins to parse junit files from the generated folder ### asserts=00; errors=0; total=0; content="" date=`which gdate || which date` # create output folder juDIR=`pwd`/results mkdir -p "$juDIR" || exit # The name of the suite is calculated based in your script name suite=`basename $0 | sed -e 's/.sh$//' | tr "." "_"` # A wrapper for the eval method witch allows catching seg-faults and use tee errfile=/tmp/evErr.$$.log eVal() { eval "$1" echo $? | tr -d "\n" >$errfile } # Method to clean old tests juLogClean() { echo "+++ Removing old junit reports from: $juDIR " rm -f "$juDIR"/TEST-* } # Execute a command and record its results juLog() { # parse arguments ya=""; icase="" while [ -z "$ya" ]; do case "$1" in -name=*) name=$asserts-`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;; esac done # use first arg as name if it was not given if [ -z "$name" ]; then name="$asserts-$1" shift fi # calculate command to eval [ -z "$1" ] && return cmd="$1"; shift while [ -n "$1" ] do cmd="$cmd \"$1\"" shift done # eval the command sending output to a file outf=/var/tmp/ju$$.txt >$outf echo "" | tee -a $outf echo "+++ Running case: $name " | tee -a $outf echo "+++ working dir: "`pwd` | tee -a $outf echo "+++ command: $cmd" | tee -a $outf ini=`$date +%s.%N` eVal "$cmd" 2>&1 | tee -a $outf evErr=`cat $errfile` rm -f $errfile end=`$date +%s.%N` echo "+++ exit code: $evErr" | tee -a $outf # set the appropriate error, based in the exit code and the regex [ $evErr != 0 ] && err=1 || err=0 out=`cat $outf | sed -e 's/^\([^+]\)/| \1/g'` if [ $err = 0 -a -n "$ereg" ]; then H=`echo "$out" | egrep $icase "$ereg"` [ -n "$H" ] && err=1 fi echo "+++ error: $err" | tee -a $outf rm -f $outf # calculate vars asserts=`expr $asserts + 1` asserts=`printf "%.2d" $asserts` errors=`expr $errors + $err` time=`echo "$end - $ini" | bc -l` total=`echo "$total + $time" | bc -l` # write the junit xml report ## failure tag [ $err = 0 ] && failure="" || failure=" " ## testcase tag content="$content $failure " ## testsuite block cat < "$juDIR/TEST-$suite.xml" $content EOF } open-zwave-1.5/cpp/build/support.mk000066400000000000000000000100751264474202400174100ustar00rootroot00000000000000#The Major Version Number VERSION_MAJ ?= 1 #The Minor Version Number VERSION_MIN ?= 4 #the build type we are making (release or debug) BUILD ?= release #the prefix to install the library into PREFIX ?= /usr/local #the System we are building on UNAME := $(shell uname -s) #the location of Doxygen to generate our api documentation DOXYGEN := $(shell which doxygen) #dot is required for doxygen (part of Graphviz) DOT := $(shell which dot) #the machine type we are building on (i686 or x86_64) MACHINE := $(shell uname -m) #the location of xmllink for checking our config files XMLLINT := $(shell which xmllint) #temp directory to build our tarfile for make dist target TMP := /tmp #pkg-config binary for package config files PKGCONFIG := $(shell which pkg-config) #svn binary for doing a make dist export GIT := $(shell which git) # if svnversion is not installed, then set the revision to 0 ifeq ($(GIT),) VERSION_REV ?= 0 else GITVERSION := $(shell $(GIT) describe --long --tags --dirty 2>/dev/null | sed s/^v//) ifeq ($(GITVERSION),) GITVERSION := $(VERSION_MAJ).$(VERSION_MIN).-1 VERSION_REV := 0 else VERSION_REV ?= $(shell echo $(GITVERSION) | awk '{split($$0,a,"-"); print a[2]}') endif endif ifeq ($(VERSION_REV),) VERSION_REV ?= 0 endif # version number to use on the shared library VERSION := $(VERSION_MAJ).$(VERSION_MIN) # support Cross Compiling options ifeq ($(UNAME),FreeBSD) # Actually hide behind c++ which works for both clang based 10.0 and earlier(?) CC := $(CROSS_COMPILE)cc CXX := $(CROSS_COMPILE)c++ LD := $(CROSS_COMPILE)c++ else CC := $(CROSS_COMPILE)gcc CXX := $(CROSS_COMPILE)g++ LD := $(CROSS_COMPILE)g++ endif ifeq ($(UNAME),Darwin) AR := libtool -static -o RANLIB := ranlib else AR := $(CROSS_COMPILE)ar rc RANLIB := $(CROSS_COMPILE)ranlib endif SED := sed #determine if we are release or debug Build and set appropriate flags ifeq ($(BUILD), release) CFLAGS += -c $(RELEASE_CFLAGS) LDFLAGS += $(RELEASE_LDFLAGS) else CFLAGS += -c $(DEBUG_CFLAGS) LDFLAGS += $(DEBUG_LDFLAGS) endif #if /lib64 exists, then setup x86_64 library path to lib64 (good indication if a linux has /lib and lib64). #Else, if it doesnt, then set as /lib. This is used in the make install target ifeq ($(wildcard /lib64),) instlibdir.x86_64 = /lib/ else instlibdir.x86_64 = /lib64/ endif instlibdir.default = /lib/ #our actual install location for the library ifneq ($(instlibdir.$(MACHINE)),) instlibdir ?= $(PREFIX)$(instlibdir.$(MACHINE)) else instlibdir ?= $(PREFIX)$(instlibdir.default) endif #pkg-config doesn't exist, lets try to guess best place to put the pc file ifeq ($(PKGCONFIG),) pkgconfigdir ?= $(shell if [ -d "/usr/lib64/pkgconfig" ]; then echo "/usr/lib64/pkgconfig"; else echo "/usr/lib/pkgconfig"; fi) else pkgconfigdir ?= $(shell pkg-config --variable pc_path pkg-config | awk '{split($$0,a,":"); print a[1]}') endif sysconfdir ?= $(PREFIX)/etc/openzwave/ includedir ?= $(PREFIX)/include/openzwave/ docdir ?= $(PREFIX)/share/doc/openzwave-$(VERSION).$(VERSION_REV) top_builddir ?= $(CURDIR) export top_builddir OBJDIR = $(top_builddir)/.lib DEPDIR = $(top_builddir)/.dep $(OBJDIR)/%.o : %.cpp @echo "Building $(notdir $@)" @$(CXX) -MM $(CFLAGS) $(INCLUDES) $< > $(DEPDIR)/$*.d @mv -f $(DEPDIR)/$*.d $(DEPDIR)/$*.d.tmp @$(SED) -e 's|.*:|$(OBJDIR)/$*.o: $(DEPDIR)/$*.d|' < $(DEPDIR)/$*.d.tmp > $(DEPDIR)/$*.d; @$(SED) -e 's/.*://' -e 's/\\$$//' < $(DEPDIR)/$*.d.tmp | fmt -1 | \ $(SED) -e 's/^ *//' -e 's/$$/:/' >> $(DEPDIR)/.$*.d; @rm -f $(DEPDIR)/$*.d.tmp @$(CXX) $(CFLAGS) $(TARCH) $(INCLUDES) -o $@ $< $(OBJDIR)/%.o : %.c @echo "Building $(notdir $@)" @$(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; @$(SED) -e 's/.*://' -e 's/\\$$//' < $(DEPDIR)/$*.d.tmp | fmt -1 | \ $(SED) -e 's/^ *//' -e 's/$$/:/' >> $(DEPDIR)/.$*.d; @rm -f $(DEPDIR)/$*.d.tmp @$(CC) $(CFLAGS) $(TARCH) $(INCLUDES) -o $@ $< dummy := $(shell test -d $(OBJDIR) || mkdir -p $(OBJDIR)) dummy := $(shell test -d $(DEPDIR) || mkdir -p $(DEPDIR)) open-zwave-1.5/cpp/build/winRT/000077500000000000000000000000001264474202400164035ustar00rootroot00000000000000open-zwave-1.5/cpp/build/winRT/vs2015/000077500000000000000000000000001264474202400173435ustar00rootroot00000000000000open-zwave-1.5/cpp/build/winRT/vs2015/OpenZWave.sln000066400000000000000000000031651264474202400217440ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 14 VisualStudioVersion = 14.0.23107.0 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "OpenZWave.vcxproj", "{E830F9D6-8173-4B0B-9ECE-CAADFA531B54}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|ARM = Debug|ARM Debug|x64 = Debug|x64 Debug|x86 = Debug|x86 Release|ARM = Release|ARM Release|x64 = Release|x64 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Debug|ARM.ActiveCfg = Debug|ARM {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Debug|ARM.Build.0 = Debug|ARM {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Debug|x64.ActiveCfg = Debug|x64 {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Debug|x64.Build.0 = Debug|x64 {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Debug|x86.ActiveCfg = Debug|Win32 {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Debug|x86.Build.0 = Debug|Win32 {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Release|ARM.ActiveCfg = Release|ARM {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Release|ARM.Build.0 = Release|ARM {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Release|x64.ActiveCfg = Release|x64 {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Release|x64.Build.0 = Release|x64 {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Release|x86.ActiveCfg = Release|Win32 {E830F9D6-8173-4B0B-9ECE-CAADFA531B54}.Release|x86.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal open-zwave-1.5/cpp/build/winRT/vs2015/OpenZWave.vcxproj000066400000000000000000001227221264474202400226440ustar00rootroot00000000000000 Debug ARM Debug Win32 Debug x64 Release ARM Release Win32 Release x64 false false false false false false false false false false false false false false false false false false false false false false false false true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true true {e830f9d6-8173-4b0b-9ece-caadfa531b54} StaticLibrary OpenZWave OpenZWave en-US 14.0 true Windows Store 10.0.10240.0 10.0.10240.0 10.0 StaticLibrary true v140 StaticLibrary true v140 StaticLibrary true v140 StaticLibrary false true v140 StaticLibrary false true v140 StaticLibrary false true v140 false $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ $(PlatformTarget)\$(Configuration)\ false $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ $(PlatformTarget)\$(Configuration)\ false $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ $(PlatformTarget)\$(Configuration)\ false $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ $(PlatformTarget)\$(Configuration)\ false $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ $(PlatformTarget)\$(Configuration)\ false $(SolutionDir)$(PlatformTarget)\$(Configuration)\$(MSBuildProjectName)\ $(PlatformTarget)\$(Configuration)\ NotUsing true true WINRT;%(PreprocessorDefinitions) ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) Console false false del ..\..\windows\winversion.cpp CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" Xcopy /E /I /Y ..\..\..\..\config config\ exit 0 NotUsing true true WINRT;%(PreprocessorDefinitions) ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) Console false false del ..\..\windows\winversion.cpp CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" Xcopy /E /I /Y ..\..\..\..\config config\ exit 0 NotUsing true true LITTLE_ENDIAN;WINRT;%(PreprocessorDefinitions) ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) Console false false del ..\..\windows\winversion.cpp CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" Xcopy /E /I /Y ..\..\..\..\config config\ exit 0 NotUsing true true LITTLE_ENDIAN;WINRT;%(PreprocessorDefinitions) ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) Console false false del ..\..\windows\winversion.cpp CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" Xcopy /E /I /Y ..\..\..\..\config config\ exit 0 NotUsing true true WINRT;%(PreprocessorDefinitions) ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) Console false false del ..\..\windows\winversion.cpp CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" Xcopy /E /I /Y ..\..\..\..\config config\ exit 0 MachineX64 NotUsing true true WINRT;%(PreprocessorDefinitions) ..\..\..\tinyxml;..\..\..\src;%(AdditionalIncludeDirectories) Console false false del ..\..\windows\winversion.cpp CALL $(ProjectDir)\..\..\windows\GIT-VS-VERSION-GEN.bat "$(ProjectDir)\" "..\..\windows\winversion.cpp" Xcopy /E /I /Y ..\..\..\..\config config\ exit 0 MachineX64 open-zwave-1.5/cpp/build/winRT/vs2015/OpenZWave.vcxproj.filters000066400000000000000000001202671264474202400243150ustar00rootroot00000000000000 {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms {ad9f0909-64c6-4295-90a6-3a8fd944f6fa} {320ad2da-52a3-4cda-a17e-1e32b837539e} {7949eeba-8cef-4504-887d-a08c9ea0ad3d} {02437854-1343-4032-906a-be36f5d1a90f} {0a3fdc63-a605-4f13-8674-bf166df28af5} {a24496cb-7034-4cad-af79-15d2983c84dc} {1f415adf-d268-4000-a737-1409f46c6534} {d141dfa6-424a-465c-b339-38ca596a6c12} AES AES AES AES AES AES Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Main Main Main Main Main Main Main Main Main Main Main Main Main Main Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform Platform Platform Platform Platform Platform Platform Platform Platform Platform Platform TinyXML TinyXML Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes AES AES AES AES Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Main Main Main Main Main Main Main Main Main Main Main Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform\WinRT Platform Platform Platform Platform Platform Platform Platform Platform Platform Platform TinyXML TinyXML TinyXML TinyXML Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes AES config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config config open-zwave-1.5/cpp/build/windows/000077500000000000000000000000001264474202400170325ustar00rootroot00000000000000open-zwave-1.5/cpp/build/windows/GIT-VS-VERSION-GEN.bat000066400000000000000000000176121264474202400222340ustar00rootroot00000000000000@ECHO OFF SETLOCAL REM Script for generation of rc VERSIONINFO & StringFileInfo REM ==================== REM Installation Variables REM ==================== :: VERSION_FILE - Untracked file to be included in packaged source releases. :: it should contain a single line in the format: :: $Project_Name VERSION $tag (ie: Foobar VERSION v1.0.0-alpha0) SET VERSION_FILE=GIT-VS-VERSION-FILE :: DEFAULT_VERSION - Version string to be processed when neither Git nor a :: packed version file is available. SET DEFAULT_VERSION=v1.4.0-NoGit :: COUNT_PATCHES_FROM - Determines which tag to count the number of patches from :: for the final portion of the digital version number. :: Valid values are: :: major - count from earliest Major.0.0* tag. :: minor - count from earliest Major.Minor.0* tag. :: fix - count from earliest Major.Minor.Fix tag. SET COUNT_PATCHES_FROM=fix :: USES_PRERELEASE_TAGS - numeric bool value to determine if GET_GIT_PATCHES :: function should read the number of patches in the format of :: (Default) 1 - Major.Minor.Fix-Stage#-'CommitCount' :: 0 - Major.Minor.Fix-'CommitCount' SET USE_PRERELEASE_TAGS=1 :: -------------------- :CHECK_ARGS :: -------------------- :: Console output only. IF [%1] == [] GOTO START IF "%~1" == "--help" GOTO USAGE IF "%~1" == "--quiet" SET fQUIET=1& SHIFT IF "%~1" == "--force" SET fFORCE=1& SHIFT :: Un-documented switch IF "%~1" == "--test" GOTO TEST IF EXIST %~1\NUL ( :: %1 is a path SET CACHE_FILE=%~s1\%VERSION_FILE% SHIFT ) IF [%~nx1] NEQ [] ( :: %1 is a file SET HEADER_OUT_FILE=%~fs1 SHIFT ) :: This should always be the last argument. IF [%1] NEQ [] GOTO USAGE :: Some basic sanity checks. IF DEFINED fQUIET ( IF NOT DEFINED HEADER_OUT_FILE GOTO USAGE ) IF DEFINED CACHE_FILE ( SET CACHE_FILE=%CACHE_FILE:\\=\% IF NOT DEFINED HEADER_OUT_FILE GOTO USAGE ) GOTO START :: -------------------- :USAGE :: -------------------- ECHO usage: [--help] ^| ^| [--quiet] [--force] [CACHE PATH] [OUT FILE] ECHO. ECHO When called without arguments version information writes to console. ECHO. ECHO --help - displays this output. ECHO. ECHO --quiet - Suppress console output. ECHO --force - Ignore cached version information. ECHO CACHE PATH - Path for non-tracked file to store git-describe version. ECHO OUT FILE - Path to writable file that is included in the project's rc file. ECHO. ECHO Version information is expected to be in the format: vMajor.Minor.Fix[-stage#] ECHO Where -stage# is alpha, beta, or rc. ( example: v1.0.0-alpha0 ) ECHO. ECHO Example pre-build event: ECHO CALL $(SolutionDir)..\scripts\GIT-VS-VERSION-GEN.bat "$(IntDir)\" "$(SolutionDir)..\src\gen-versioninfo.h" ECHO. GOTO END REM =================== REM Entry Point REM =================== :START ECHO. CALL :INIT_VARS CALL :GET_VERSION_STRING IF DEFINED fGIT_AVAILABLE ( IF DEFINED fLEAVE_NOW GOTO END IF DEFINED CACHE_FILE ( CALL :CHECK_CACHE ) ) IF DEFINED fLEAVE_NOW GOTO END CALL :SET_BUILD_PARTS CALL :PREP_OUT CALL :WRITE_OUT GOTO END REM ==================== REM FUNCTIONS REM ==================== :: -------------------- :INIT_VARS :: -------------------- :: The following variables are used for the final version output. :: String Version: Major.Minor.Fix.Stage#[.Patches.SHA1[.dirty]] SET strFILE_VERSION= :: Digital Version: Major, Minor, Fix, Patches SET nbMAJOR_PART=0 SET nbMINOR_PART=0 SET nbFIX_PART=0 SET nbPATCHES_PART=0 :: VERSIONINFO VS_FF_ flags SET fPRIVATE=0 SET fPATCHED=0 SET fPRE_RELEASE=0 :: Supporting StringFileInfo - not used for clean release builds. SET strPRIVATE_BUILD= SET strCOMMENT= GOTO :EOF :: -------------------- :GET_VERSION_STRING :: -------------------- :: Precedence is Git, VERSION_FILE, then DEFAULT_VERSION. :: Check if git is available by testing git describe. CALL git describe>NUL 2>&1 IF NOT ERRORLEVEL 1 ( SET fGIT_AVAILABLE=1 :: Parse git version string CALL :PARSE_GIT_STRING ) ELSE ( :: Use the VERSION_FILE if it exists. IF EXIST "%VERSION_FILE%" ( FOR /F "tokens=3" %%A IN (%VERSION_FILE%) DO ( SET strFILE_VERSION=%%A ) ) ELSE ( :: Default to the DEFAULT_VERSION SET strFILE_VERSION=%DEFAULT_VERSION% ) ) SET strFILE_VERSION=%strFILE_VERSION:~1% SET strFILE_VERSION=%strFILE_VERSION:-=.% GOTO :EOF :: -------------------- :PARSE_GIT_STRING :: -------------------- FOR /F "tokens=*" %%A IN ('"git describe --long --tags --dirty "') DO ( SET strFILE_VERSION=%%A ) echo %strFILE_VERSION% :: If HEAD is dirty then this is not part of an official build and even if a :: commit hasn't been made it should still be marked as dirty and patched. SET tmp= GOTO :EOF :: -------------------- :CHECK_CACHE :: -------------------- :: Exit early if a cached git built version matches the current version. IF DEFINED HEADER_OUT_FILE ( IF EXIST "%HEADER_OUT_FILE%" ( IF [%fFORCE%] EQU [1] DEL "%CACHE_FILE%" IF EXIST "%CACHE_FILE%" ( FOR /F "tokens=*" %%A IN (%CACHE_FILE%) DO ( IF "%%A" == "%strFILE_VERSION%" ( IF NOT DEFINED fQUIET ( ECHO Build version is assumed unchanged from: %strFILE_VERSION%. ) SET fLEAVE_NOW=1 ) ) ) ) ECHO %strFILE_VERSION%> "%CACHE_FILE%" ) GOTO :EOF :: -------------------- :SET_BUILD_PARTS :: -------------------- :: The min version is X.Y.Z and the max is X.Y.Z.Stage#.Commits.SHA.dirty :: strTMP_STAGE_PART is a holder for anything past 'X.Y.Z.'. FOR /F "tokens=1,2,3,* delims=." %%A IN ("%strFile_Version%") DO ( SET nbMAJOR_PART=%%A SET nbMINOR_PART=%%B SET nbFIX_PART=%%C SET strTMP_STAGE_PART=%%D ) GOTO :EOF :: -------------------- :PREP_OUT :: -------------------- SET csvFILE_VERSION=%nbMAJOR_PART%,%nbMINOR_PART%,%nbFIX_PART%,%nbPATCHES_PART% SET hexFILE_VERSION= CALL :SET_HEX IF NOT %fPRIVATE% EQU 0 SET fPRIVATE=VS_FF_PRIVATEBUILD IF NOT %fPATCHED% EQU 0 SET fPATCHED=VS_FF_PATCHED IF NOT %fPRE_RELEASE% EQU 0 SET fPRE_RELEASE=VS_FF_PRERELEASE GOTO :EOF :: -------------------- :SET_HEX :: -------------------- :: Iterate Major, Minor, Fix, Patches as set in csvFILEVERSION and convert to :: hex while appending to the hexFILE_VERION string to give a padded 32bit :: end result. ie: v1.0.1.34 = 0x0001000000010022 SET hex_values=0123456789ABCDEF FOR /F "tokens=1-4 delims=," %%A IN ("%csvFILE_VERSION%") DO ( CALL :int2hex %%A CALL :int2hex %%B CALL :int2hex %%C CALL :int2hex %%D ) SET hexFILE_VERSION=0x%hexFILE_VERSION% SET hex_values= GOTO :EOF :int2hex SETLOCAL ENABLEDELAYEDEXPANSION SET /A pad=4 SET /A iVal=%1 :hex_loop SET /A pad=%pad% - 1 SET /A hVal=%iVal% %% 16 SET hVal=!hex_values:~%hVal%,1! SET hex_word=%hVal%%hex_word% SET /A iVal=%iVal% / 16 IF %iVal% GTR 0 GOTO hex_loop :hex_pad_loop FOR /L %%A in (1,1,%pad%) DO SET hex_word=0!hex_word! ENDLOCAL& SET hexFILE_VERSION=%hexFILE_VERSION%%hex_word% GOTO :EOF :: -------------------- :WRITE_OUT :: -------------------- :: HEADER_OUT falls through to CON_OUT which checks for the QUIET flag. IF DEFINED HEADER_OUT_FILE ( CALL :OUT_HEADER ) ELSE ( IF NOT DEFINED TESTING ( CALL :CON_OUT ) ELSE ( CALL :TEST_OUT ) ) GOTO :EOF :: -------------------- :OUT_HEADER :: -------------------- ECHO unsigned short ozw_vers_major = %nbMAJOR_PART%; >> "%HEADER_OUT_FILE%" ECHO unsigned short ozw_vers_minor = %nbMINOR_PART%; >> "%HEADER_OUT_FILE%" ECHO unsigned short ozw_vers_revision = %nbFIX_PART%; >> "%HEADER_OUT_FILE%" ECHO char ozw_version_string[] = "%strFILE_VERSION%\0"; >> "%HEADER_OUT_FILE%" SET nbMAJOR_PART=0 SET nbMINOR_PART=0 SET nbFIX_PART=0 SET nbPATCHES_PART=0 :: -------------------- :CON_OUT :: -------------------- IF DEFINED fQUIET GOTO :EOF ECHO Version String: %strFILE_VERSION% ECHO Digital Version ID: %csvFILE_VERSION% ECHO Hex Version ID: %hexFILE_VERSION% GOTO :EOF :: -------------------- :END :: -------------------- open-zwave-1.5/cpp/build/windows/installer/000077500000000000000000000000001264474202400210275ustar00rootroot00000000000000open-zwave-1.5/cpp/build/windows/installer/buildall.bat000066400000000000000000000014351264474202400233120ustar00rootroot00000000000000msbuild ..\..\..\examples\windows\MinOZW\vs2010\MinOZW.sln /t:Rebuild /p:Configuration="Debug" msbuild ..\..\..\examples\windows\MinOZW\vs2010\MinOZW.sln /t:Rebuild /p:Configuration="DebugDLL" msbuild ..\..\..\examples\windows\MinOZW\vs2010\MinOZW.sln /t:Rebuild /p:Configuration="Release" msbuild ..\..\..\examples\windows\MinOZW\vs2010\MinOZW.sln /t:Rebuild /p:Configuration="ReleaseDLL" copy ..\..\..\..\dotnet\examples/OZWForm\build\vs2010\*.sln ..\..\..\..\dotnet\examples\OZWForm\src\ copy ..\..\..\..\dotnet\examples/OZWForm\build\vs2010\*.csproj ..\..\..\..\dotnet\examples\OZWForm\src\ msbuild ..\..\..\..\dotnet\examples\OZWForm\src\OZWForm.sln /t:Rebuild /p:Configuration="Debug" msbuild ..\..\..\..\dotnet\examples\OZWForm\src\OZWForm.sln /t:Rebuild /p:Configuration="Release" open-zwave-1.5/cpp/build/windows/installer/openzwave.nsi000066400000000000000000000047271264474202400235720ustar00rootroot00000000000000installDir "$PROGRAMFILES\OpenZWave" Name "OpenZWave" outFile "setup.exe" Page license Page components Page directory Page instfiles UninstPage uninstConfirm UninstPage instfiles LicenseData ..\..\..\..\license\lgpl.txt Section "Core Files" SectionIn RO setOutPath "$INSTDIR" File ..\..\..\..\license\lgpl.txt File ..\..\..\examples\windows\MinOZW\vs2010\ReleaseDLL\OpenZWave.dll setOutPath "$INSTDIR\docs\" File ..\..\..\..\docs\default.htm setOutPath "$INSTDIR\docs\images+css\" File ..\..\..\..\docs\images+css\* setOutPath "$INSTDIR\docs\general\" File ..\..\..\..\docs\general\* createShortCut "$SMPROGRAMS\OpenZWave\Getting Started.lnk" "$INSTDIR\docs\default.htm" SectionEnd Section /o "Development Files" setOutPath "$INSTDIR\development\DebugDLL" File ..\..\..\examples\windows\MinOZW\vs2010\DebugDLL\OpenZWaved.dll File ..\..\..\examples\windows\MinOZW\vs2010\DebugDLL\OpenZWaved.lib setOutPath "$INSTDIR\development\Debug" File ..\..\..\..\dotnet\examples\OZWForm\src\Debug\OpenZWave.lib setOutPath "$INSTDIR\development\ReleaseDLL" File ..\..\..\examples\windows\MinOZW\vs2010\ReleaseDLL\OpenZWave.dll File ..\..\..\examples\windows\MinOZW\vs2010\ReleaseDLL\OpenZWave.lib setOutPath "$INSTDIR\development\Release" File ..\..\..\..\dotnet\examples\OZWForm\src\Release\OpenZWave.lib setOutPath "$INSTDIR\development\include\openzwave\" File ..\..\..\src\*.h setOutPath "$INSTDIR\development\include\openzwave\command_classes\" file ..\..\..\src\command_classes\*.h setOutPath "$INSTDIR\development\include\openzwave\value_classes\" file ..\..\..\src\value_classes\*.h setOutPath "$INSTDIR\development\include\openzwave\platform\" file ..\..\..\src\platform\*.h setOutPath "$INSTDIR\development\include\openzwave\platform\windows\" file ..\..\..\src\platform\windows\*.h SectionEnd Section ".Net Component" SectionIn RO setOutPath "$INSTDIR\dotnet\" File ..\..\..\..\dotnet\examples\OZWForm\src\Debug\OpenZWaveDotNetd.dll File ..\..\..\..\dotnet\examples\OZWForm\src\Debug\OpenZWaveDotNetd.lib File ..\..\..\..\dotnet\examples\OZWForm\src\Release\OpenZWaveDotNet.dll File ..\..\..\..\dotnet\examples\OZWForm\src\Release\OpenZWaveDotNet.lib SectionEnd Section "Examples" setOutPath "$INSTDIR\dotnet\" File ..\..\..\examples\windows\MinOZW\vs2010\ReleaseDLL\MinOZW.exe File ..\..\..\..\dotnet\examples\OZWForm\src\bin\x86\Release\OZWForm.exe createShortCut "$SMPROGRAMS\OpenZWave\OpenZWave Form.lnk" "$INSTDIR\OZWForm.exe" SectionEnd open-zwave-1.5/cpp/build/windows/mingw32/000077500000000000000000000000001264474202400203205ustar00rootroot00000000000000open-zwave-1.5/cpp/build/windows/mingw32/Makefile000066400000000000000000000046501264474202400217650ustar00rootroot00000000000000# # Makefile for OpenZWave MingW32 build # Maarten Damen .SUFFIXES: .d .cpp .o .a .PHONY: default clean CC := $(CROSS_COMPILE)gcc CXX := $(CROSS_COMPILE)g++ LD := $(CROSS_COMPILE)g++ AR := $(CROSS_COMPILE)ar rc RANLIB := $(CROSS_COMPILE)ranlib DEBUG_CFLAGS := -Wall -Wno-format -g -DDEBUG -DLOG_STDERR -DMINGW RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O3 -DMINGW DEBUG_LDFLAGS := -g # Change for DEBUG or RELEASE CFLAGS := -c $(DEBUG_CFLAGS) LDFLAGS := $(DEBUG_LDFLAGS) LIBDIR := ../../../lib/windows-mingw32 INCLUDES := -I ../../../src -I ../../../src/command_classes/ -I ../../../src/value_classes/ \ -I ../../../src/platform/ -I ../../../src/platform/windows -I ../../../tinyxml/ -I ../../../hidapi/hidapi/ SOURCES := ../../../src ../../../src/command_classes ../../../tinyxml ../../../hidapi/windows \ ../../../src/value_classes ../../../src/platform ../../../src/platform/windows VPATH = ../../../src:../../../src/command_classes:../../../tinyxml:../../../hidapi/windows:\ ../../../src/value_classes:../../../src/platform:../../../src/platform/windows %.d : %.cpp @set -e; rm -f $@; \ $(CXX) -MM $(INCLUDES) $< > $@.$$$$; \ sed 's,\($*\)\.o[ :]*,\1.o $@ : ,g' < $@.$$$$ > $@; \ rm -f $@.$$$$ tinyxml := $(notdir $(wildcard ../../../tinyxml/*.cpp)) hidapi := $(notdir $(wildcard ../../../hidapi/linux/hid.c)) # we do not want the libusb version cclasses := $(notdir $(wildcard ../../../src/command_classes/*.cpp)) vclasses := $(notdir $(wildcard ../../../src/value_classes/*.cpp)) pform := $(notdir $(wildcard ../../../src/platform/*.cpp)) \ $(notdir $(wildcard ../../../src/platform/windows/*.cpp)) indep := $(notdir $(wildcard ../../../src/*.cpp)) %.o : %.cpp $(CXX) $(CFLAGS) $(INCLUDES) -o $@ $< %.o : %.c $(CC) $(CFLAGS) $(INCLUDES) -o $@ $< default: $(LIBDIR)/openzwave.a clean: rm -f *.d *.o -include $(tinyxml:.cpp=.d) -include $(hidapi:.c=.d) -include $(cclasses:.cpp=.d) -include $(vclasses:.cpp=.d) -include $(pform:.cpp=.d) -include $(indep:.cpp=.d) vers.c: echo 'char ozw_vers[] = "OpenZWave version 1.0.'`svnversion ../..`'";' > vers.c vers.o: vers.c $(LIBDIR)/openzwave.a: $(patsubst %.cpp,%.o,$(tinyxml)) \ $(patsubst %.c,%.o,$(hidapi)) \ $(patsubst %.cpp,%.o,$(cclasses)) \ $(patsubst %.cpp,%.o,$(vclasses)) \ $(patsubst %.cpp,%.o,$(pform)) \ $(patsubst %.cpp,%.o,$(indep)) vers.o $(AR) $@ $? open-zwave-1.5/cpp/build/windows/vs2008/000077500000000000000000000000001264474202400177745ustar00rootroot00000000000000open-zwave-1.5/cpp/build/windows/vs2008/OpenZWave.sln000066400000000000000000000024351264474202400223740ustar00rootroot00000000000000 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 open-zwave-1.5/cpp/build/windows/vs2008/OpenZWave.vcproj000066400000000000000000000560471264474202400231130ustar00rootroot00000000000000 open-zwave-1.5/cpp/build/windows/vs2010/000077500000000000000000000000001264474202400177655ustar00rootroot00000000000000open-zwave-1.5/cpp/build/windows/vs2010/OpenZWave.sln000066400000000000000000000024271264474202400223660ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "OpenZWave.vcxproj", "{497F9828-DEC2-4C80-B9E0-AD066CCB587C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 DebugDLL|Win32 = DebugDLL|Win32 Release|Win32 = Release|Win32 ReleaseDLL|Win32 = ReleaseDLL|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}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.Build.0 = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal open-zwave-1.5/cpp/build/windows/vs2010/OpenZWave.vcxproj000066400000000000000000000626441264474202400232740ustar00rootroot00000000000000 DebugDLL Win32 Debug Win32 ReleaseDLL Win32 Release Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C} OpenZWave Win32Proj StaticLibrary MultiByte true StaticLibrary MultiByte DynamicLibrary MultiByte DynamicLibrary MultiByte <_ProjectFileVersion>10.0.30319.1 $(Configuration)\ $(Configuration)\ $(Configuration)\ $(Configuration)\ AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset $(ProjectName) $(ProjectName)d $(ProjectName) .dll .dll Disabled WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 ProgramDatabase ..\..\..\src;..\..\..\tinyxml;..\..\..\hidapi\hidapi;%(AdditionalIncludeDirectories) $(OutDir)\$(ProjectName).lib setupapi.lib MachineX86 del ..\winversion.cpp CALL "$(ProjectDir)\..\GIT-VS-VERSION-GEN.bat" "$(ProjectDir)\" "..\winversion.cpp" exit 0 Export GIT Revision Disabled WIN32;_DEBUG;_LIB;OPENZWAVE_MAKEDLL;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 ProgramDatabase 4251 ..\..\..\src;..\..\..\tinyxml;..\..\..\hidapi\hidapi;%(AdditionalIncludeDirectories) $(OutDir)\$(ProjectName).dll setupapi.lib MachineX86 $(OutDir)$(TargetName)$(TargetExt) Setupapi.lib;%(AdditionalDependencies) true del ..\winversion.cpp CALL "$(ProjectDir)\..\GIT-VS-VERSION-GEN.bat" "$(ProjectDir)\" "..\winversion.cpp" exit 0 Export GIT Revision MaxSpeed WIN32;_LIB;OPENZWAVE_MAKEDLL;%(PreprocessorDefinitions) true Default MultiThreadedDLL Level3 ProgramDatabase 4251 ..\..\..\src;..\..\..\tinyxml;..\..\..\hidapi\hidapi;%(AdditionalIncludeDirectories) $(OutDir)\$(ProjectName).lib setupapi.lib MachineX86 Setupapi.lib;%(AdditionalDependencies) Export GIT Revision del ..\winversion.cpp CALL "$(ProjectDir)\..\GIT-VS-VERSION-GEN.bat" "$(ProjectDir)\" "..\winversion.cpp" exit 0 MaxSpeed true WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) MultiThreadedDLL true Level3 ProgramDatabase ..\..\..\src;..\..\..\tinyxml;..\..\..\hidapi\hidapi;%(AdditionalIncludeDirectories) $(OutDir)\$(ProjectName).lib setupapi.lib del ..\winversion.cpp CALL "$(ProjectDir)\..\GIT-VS-VERSION-GEN.bat" "$(ProjectDir)\" "..\winversion.cpp" exit 0 Export GIT Revision open-zwave-1.5/cpp/build/windows/vs2010/OpenZWave.vcxproj.filters000066400000000000000000000655341264474202400247440ustar00rootroot00000000000000 {c333a1d6-215b-44ad-b8ee-406d5106109e} {44c66a53-03d9-4046-ac24-d3812170e342} {e177d532-917f-42e3-b495-f50646eb9490} {910fd85c-3052-49a4-a9be-3ba6ca7f87c3} {f3912321-42c6-42bf-8c89-cf61f2a985ed} {8a2f2f41-ba21-4299-b85d-cd7511e1de0e} {e7067898-f602-4a8b-af4b-8bcedcd0d0c0} {c511568c-3f02-4010-b603-90e65d6caad2} TinyXML TinyXML Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Main Main Main Main Main Main Main Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Platform Platform Platform Platform Platform\Windows Platform\Windows Platform\Windows Platform\Windows Main Main Main Command Classes Platform Platform\Windows HIDAPI Platform Main Main Platform Platform Platform\Windows Platform\Windows Platform Platform Platform Main Command Classes Command Classes Command Classes Command Classes Value Classes Command Classes AES AES AES AES AES Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Main Main Main Main Main Main Platform Platform Platform Platform Platform Platform\Windows Platform\Windows Platform\Windows Platform\Windows Platform\Windows TinyXML TinyXML TinyXML TinyXML Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Value Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes Value Classes Value Classes Main Main Main Command Classes Platform Platform\Windows HIDAPI Platform Main Platform Platform Platform\Windows Platform\Windows Platform Platform Main Command Classes Command Classes Value Classes Command Classes Command Classes Main AES AES AES AES Command Classes Command Classes Command Classes Command Classes Command Classes Command Classes open-zwave-1.5/cpp/build/windows/winversion.tmpl000066400000000000000000000001531264474202400221320ustar00rootroot00000000000000unsigned short ozw_vers_minor = 1; unsigned short ozw_vers_major = 4; unsigned short ozw_vers_revision = 0;open-zwave-1.5/cpp/examples/000077500000000000000000000000001264474202400160575ustar00rootroot00000000000000open-zwave-1.5/cpp/examples/MinOZW/000077500000000000000000000000001264474202400172025ustar00rootroot00000000000000open-zwave-1.5/cpp/examples/MinOZW/Main.cpp000066400000000000000000000266221264474202400206020ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Main.cpp // // Minimal application to test OpenZWave. // // Creates an OpenZWave::Driver and the waits. In Debug builds // you should see verbose logging to the console, which will // indicate that communications with the Z-Wave network are working. // // 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 . // //----------------------------------------------------------------------------- #include #include #include #include "Options.h" #include "Manager.h" #include "Driver.h" #include "Node.h" #include "Group.h" #include "Notification.h" #include "value_classes/ValueStore.h" #include "value_classes/Value.h" #include "value_classes/ValueBool.h" #include "platform/Log.h" using namespace OpenZWave; bool temp = false; static uint32 g_homeId = 0; static bool g_initFailed = false; typedef struct { uint32 m_homeId; uint8 m_nodeId; bool m_polled; list m_values; }NodeInfo; static list g_nodes; static pthread_mutex_t g_criticalSection; static pthread_cond_t initCond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t initMutex = PTHREAD_MUTEX_INITIALIZER; //----------------------------------------------------------------------------- // // Return the NodeInfo object associated with this notification //----------------------------------------------------------------------------- NodeInfo* GetNodeInfo ( Notification const* _notification ) { uint32 const homeId = _notification->GetHomeId(); uint8 const nodeId = _notification->GetNodeId(); for( list::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it ) { NodeInfo* nodeInfo = *it; if( ( nodeInfo->m_homeId == homeId ) && ( nodeInfo->m_nodeId == nodeId ) ) { return nodeInfo; } } return NULL; } //----------------------------------------------------------------------------- // // Callback that is triggered when a value, group or node changes //----------------------------------------------------------------------------- void OnNotification ( Notification const* _notification, void* _context ) { // Must do this inside a critical section to avoid conflicts with the main thread pthread_mutex_lock( &g_criticalSection ); switch( _notification->GetType() ) { case Notification::Type_ValueAdded: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // Add the new value to our list nodeInfo->m_values.push_back( _notification->GetValueID() ); } break; } case Notification::Type_ValueRemoved: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // Remove the value from out list for( list::iterator it = nodeInfo->m_values.begin(); it != nodeInfo->m_values.end(); ++it ) { if( (*it) == _notification->GetValueID() ) { nodeInfo->m_values.erase( it ); break; } } } break; } case Notification::Type_ValueChanged: { // One of the node values has changed if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo = nodeInfo; // placeholder for real action } break; } case Notification::Type_Group: { // One of the node's association groups has changed if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo = nodeInfo; // placeholder for real action } break; } case Notification::Type_NodeAdded: { // Add the new node to our list NodeInfo* nodeInfo = new NodeInfo(); nodeInfo->m_homeId = _notification->GetHomeId(); nodeInfo->m_nodeId = _notification->GetNodeId(); nodeInfo->m_polled = false; g_nodes.push_back( nodeInfo ); if (temp == true) { Manager::Get()->CancelControllerCommand( _notification->GetHomeId() ); } break; } case Notification::Type_NodeRemoved: { // Remove the node from our list uint32 const homeId = _notification->GetHomeId(); uint8 const nodeId = _notification->GetNodeId(); for( list::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it ) { NodeInfo* nodeInfo = *it; if( ( nodeInfo->m_homeId == homeId ) && ( nodeInfo->m_nodeId == nodeId ) ) { g_nodes.erase( it ); delete nodeInfo; break; } } break; } case Notification::Type_NodeEvent: { // We have received an event from the node, caused by a // basic_set or hail message. if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo = nodeInfo; // placeholder for real action } break; } case Notification::Type_PollingDisabled: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo->m_polled = false; } break; } case Notification::Type_PollingEnabled: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo->m_polled = true; } break; } case Notification::Type_DriverReady: { g_homeId = _notification->GetHomeId(); break; } case Notification::Type_DriverFailed: { g_initFailed = true; pthread_cond_broadcast(&initCond); break; } case Notification::Type_AwakeNodesQueried: case Notification::Type_AllNodesQueried: case Notification::Type_AllNodesQueriedSomeDead: { pthread_cond_broadcast(&initCond); break; } case Notification::Type_DriverReset: case Notification::Type_Notification: case Notification::Type_NodeNaming: case Notification::Type_NodeProtocolInfo: case Notification::Type_NodeQueriesComplete: default: { } } pthread_mutex_unlock( &g_criticalSection ); } //----------------------------------------------------------------------------- //
// Create the driver and then wait //----------------------------------------------------------------------------- int main( int argc, char* argv[] ) { pthread_mutexattr_t mutexattr; pthread_mutexattr_init ( &mutexattr ); pthread_mutexattr_settype( &mutexattr, PTHREAD_MUTEX_RECURSIVE ); pthread_mutex_init( &g_criticalSection, &mutexattr ); pthread_mutexattr_destroy( &mutexattr ); pthread_mutex_lock( &initMutex ); printf("Starting MinOZW with OpenZWave Version %s\n", Manager::getVersionAsString().c_str()); // Create the OpenZWave Manager. // The first argument is the path to the config files (where the manufacturer_specific.xml file is located // The second argument is the path for saved Z-Wave network state and the log file. If you leave it NULL // the log file will appear in the program's working directory. Options::Create( "../../../config/", "", "" ); Options::Get()->AddOptionInt( "SaveLogLevel", LogLevel_Detail ); Options::Get()->AddOptionInt( "QueueLogLevel", LogLevel_Debug ); Options::Get()->AddOptionInt( "DumpTrigger", LogLevel_Error ); Options::Get()->AddOptionInt( "PollInterval", 500 ); Options::Get()->AddOptionBool( "IntervalBetweenPolls", true ); Options::Get()->AddOptionBool("ValidateValueChanges", true); Options::Get()->Lock(); Manager::Create(); // Add a callback handler to the manager. The second argument is a context that // is passed to the OnNotification method. If the OnNotification is a method of // a class, the context would usually be a pointer to that class object, to // avoid the need for the notification handler to be a static. Manager::Get()->AddWatcher( OnNotification, NULL ); // Add a Z-Wave Driver // Modify this line to set the correct serial port for your PC interface. #ifdef DARWIN string port = "/dev/cu.usbserial"; #elif WIN32 string port = "\\\\.\\COM6"; #else string port = "/dev/ttyUSB0"; #endif if ( argc > 1 ) { port = argv[1]; } if( strcasecmp( port.c_str(), "usb" ) == 0 ) { Manager::Get()->AddDriver( "HID Controller", Driver::ControllerInterface_Hid ); } else { Manager::Get()->AddDriver( port ); } // Now we just wait for either the AwakeNodesQueried or AllNodesQueried notification, // then write out the config file. // In a normal app, we would be handling notifications and building a UI for the user. pthread_cond_wait( &initCond, &initMutex ); // Since the configuration file contains command class information that is only // known after the nodes on the network are queried, wait until all of the nodes // on the network have been queried (at least the "listening" ones) before // writing the configuration file. (Maybe write again after sleeping nodes have // been queried as well.) if( !g_initFailed ) { // The section below demonstrates setting up polling for a variable. In this simple // example, it has been hardwired to poll COMMAND_CLASS_BASIC on the each node that // supports this setting. pthread_mutex_lock( &g_criticalSection ); for( list::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it ) { NodeInfo* nodeInfo = *it; // skip the controller (most likely node 1) if( nodeInfo->m_nodeId == 1) continue; for( list::iterator it2 = nodeInfo->m_values.begin(); it2 != nodeInfo->m_values.end(); ++it2 ) { ValueID v = *it2; if( v.GetCommandClassId() == 0x20 ) { // Manager::Get()->EnablePoll( v, 2 ); // enables polling with "intensity" of 2, though this is irrelevant with only one value polled break; } } } pthread_mutex_unlock( &g_criticalSection ); // If we want to access our NodeInfo list, that has been built from all the // notification callbacks we received from the library, we have to do so // from inside a Critical Section. This is because the callbacks occur on other // threads, and we cannot risk the list being changed while we are using it. // We must hold the critical section for as short a time as possible, to avoid // 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 ); // but NodeInfo list and similar data should be inside critical section pthread_mutex_unlock( &g_criticalSection ); sleep(1); } Driver::DriverData data; Manager::Get()->GetDriverStatistics( g_homeId, &data ); printf("SOF: %d ACK Waiting: %d Read Aborts: %d Bad Checksums: %d\n", data.m_SOFCnt, data.m_ACKWaiting, data.m_readAborts, data.m_badChecksum); printf("Reads: %d Writes: %d CAN: %d NAK: %d ACK: %d Out of Frame: %d\n", data.m_readCnt, data.m_writeCnt, data.m_CANCnt, data.m_NAKCnt, data.m_ACKCnt, data.m_OOFCnt); printf("Dropped: %d Retries: %d\n", data.m_dropped, data.m_retries); } // program exit (clean up) if( strcasecmp( port.c_str(), "usb" ) == 0 ) { Manager::Get()->RemoveDriver( "HID Controller" ); } else { Manager::Get()->RemoveDriver( port ); } Manager::Get()->RemoveWatcher( OnNotification, NULL ); Manager::Destroy(); Options::Destroy(); pthread_mutex_destroy( &g_criticalSection ); return 0; } open-zwave-1.5/cpp/examples/MinOZW/Makefile000066400000000000000000000043261264474202400206470ustar00rootroot00000000000000# # Makefile for OpenzWave Mac OS X applications # Greg Satz # GNU make only # requires libudev-dev .SUFFIXES: .d .cpp .o .a .PHONY: default clean DEBUG_CFLAGS := -Wall -Wno-format -ggdb -DDEBUG $(CPPFLAGS) RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O3 $(CPPFLAGS) DEBUG_LDFLAGS := -g top_srcdir := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))../../../) INCLUDES := -I $(top_srcdir)/cpp/src -I $(top_srcdir)/cpp/tinyxml/ -I $(top_srcdir)/cpp/hidapi/hidapi/ LIBS = $(wildcard $(LIBDIR)/*.so $(LIBDIR)/*.dylib $(top_builddir)/*.so $(top_builddir)/*.dylib $(top_builddir)/cpp/build/*.so $(top_builddir)/cpp/build/*.dylib ) LIBSDIR = $(abspath $(dir $(firstword $(LIBS)))) minozwsrc := $(notdir $(wildcard $(top_srcdir)/cpp/examples/MinOZW/*.cpp)) VPATH := $(top_srcdir)/cpp/examples/MinOZW top_builddir ?= $(CURDIR) default: $(top_builddir)/MinOZW include $(top_srcdir)/cpp/build/support.mk -include $(patsubst %.cpp,$(DEPDIR)/%.d,$(minozwsrc)) #if we are on a Mac, add these flags and libs to the compile and link phases ifeq ($(UNAME),Darwin) CFLAGS += -DDARWIN TARCH += -arch i386 -arch x86_64 endif # Dup from main makefile, but that is not included when building here.. ifeq ($(UNAME),FreeBSD) ifeq (,$(wildcard /usr/include/iconv.h)) CFLAGS += -I/usr/local/include LDFLAGS+= -L/usr/local/lib -liconv endif LDFLAGS+= -lusb endif $(OBJDIR)/MinOZW: $(patsubst %.cpp,$(OBJDIR)/%.o,$(minozwsrc)) @echo "Linking $(OBJDIR)/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" @$(SED) \ -e 's|[@]LDPATH@|$(LIBSDIR)|g' \ < "$<" > "$@" @chmod +x $(top_builddir)/MinOZW clean: @rm -rf $(DEPDIR) $(OBJDIR) $(top_builddir)/MinOZW ifeq ($(XMLLINT),) xmltest: $(XMLLINT) $(error xmllint command not found.) else xmltest: $(XMLLINT) @$(XMLLINT) --noout --schema ../../../config/zwcfg.xsd zwcfg_*.xml @$(XMLLINT) --noout --schema ../../../config/zwscene.xsd zwscene.xml endif install: $(OBJDIR)/MinOZW @echo "Installing into Prefix: $(PREFIX)" @install -d $(DESTDIR)/$(PREFIX)/bin/ @cp $(OBJDIR)/MinOZW $(DESTDIR)/$(PREFIX)/bin/MinOZW @chmod 755 $(DESTDIR)/$(PREFIX)/bin/MinOZW open-zwave-1.5/cpp/examples/MinOZW/MinOZW.in000066400000000000000000000004241264474202400206550ustar00rootroot00000000000000#!/bin/sh LD_PATH=@LDPATH@ if test $# -gt 0; then if test $1 == "gdb"; then LD_LIBRARY_PATH="$LD_PATH:$LD_LIBRARY_PATH" gdb .lib/MinOZW else LD_LIBRARY_PATH="$LD_PATH:$LD_LIBRARY_PATH" .lib/MinOZW $@ fi else LD_LIBRARY_PATH="$LD_PATH:$LD_LIBRARY_PATH" .lib/MinOZW fi open-zwave-1.5/cpp/examples/windows/000077500000000000000000000000001264474202400175515ustar00rootroot00000000000000open-zwave-1.5/cpp/examples/windows/MinOZW/000077500000000000000000000000001264474202400206745ustar00rootroot00000000000000open-zwave-1.5/cpp/examples/windows/MinOZW/Main.cpp000066400000000000000000000254411264474202400222720ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Main.cpp // // Minimal application to test OpenZWave. // // Creates an OpenZWave::Driver and the waits. In Debug builds // you should see verbose logging to the console, which will // indicate that communications with the Z-Wave network are working. // // 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 . // //----------------------------------------------------------------------------- #include "Windows.h" #include "Options.h" #include "Manager.h" #include "Driver.h" #include "Node.h" #include "Group.h" #include "Notification.h" #include "value_classes/ValueStore.h" #include "value_classes/Value.h" #include "value_classes/ValueBool.h" #include "platform/Log.h" using namespace OpenZWave; static uint32 g_homeId = 0; static bool g_initFailed = false; static bool g_nodesQueried = false; typedef struct { uint32 m_homeId; uint8 m_nodeId; bool m_polled; list m_values; }NodeInfo; static list g_nodes; static CRITICAL_SECTION g_criticalSection; //----------------------------------------------------------------------------- // // Return the NodeInfo object associated with this notification //----------------------------------------------------------------------------- NodeInfo* GetNodeInfo ( Notification const* _notification ) { uint32 const homeId = _notification->GetHomeId(); uint8 const nodeId = _notification->GetNodeId(); for( list::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it ) { NodeInfo* nodeInfo = *it; if( ( nodeInfo->m_homeId == homeId ) && ( nodeInfo->m_nodeId == nodeId ) ) { return nodeInfo; } } return NULL; } //----------------------------------------------------------------------------- // // Callback that is triggered when a value, group or node changes //----------------------------------------------------------------------------- void OnNotification ( Notification const* _notification, void* _context ) { // Must do this inside a critical section to avoid conflicts with the main thread EnterCriticalSection( &g_criticalSection ); switch( _notification->GetType() ) { case Notification::Type_ValueAdded: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // Add the new value to our list nodeInfo->m_values.push_back( _notification->GetValueID() ); } break; } case Notification::Type_ValueRemoved: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { // Remove the value from out list for( list::iterator it = nodeInfo->m_values.begin(); it != nodeInfo->m_values.end(); ++it ) { if( (*it) == _notification->GetValueID() ) { nodeInfo->m_values.erase( it ); break; } } } break; } case Notification::Type_ValueChanged: { // One of the node values has changed if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo = nodeInfo; // placeholder for real action } break; } case Notification::Type_Group: { // One of the node's association groups has changed if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo = nodeInfo; // placeholder for real action } break; } case Notification::Type_NodeAdded: { // Add the new node to our list NodeInfo* nodeInfo = new NodeInfo(); nodeInfo->m_homeId = _notification->GetHomeId(); nodeInfo->m_nodeId = _notification->GetNodeId(); nodeInfo->m_polled = false; g_nodes.push_back( nodeInfo ); break; } case Notification::Type_NodeRemoved: { // Remove the node from our list uint32 const homeId = _notification->GetHomeId(); uint8 const nodeId = _notification->GetNodeId(); for( list::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it ) { NodeInfo* nodeInfo = *it; if( ( nodeInfo->m_homeId == homeId ) && ( nodeInfo->m_nodeId == nodeId ) ) { g_nodes.erase( it ); delete nodeInfo; break; } } break; } case Notification::Type_NodeEvent: { // We have received an event from the node, caused by a // basic_set or hail message. if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo = nodeInfo; // placeholder for real action } break; } case Notification::Type_PollingDisabled: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo->m_polled = false; } break; } case Notification::Type_PollingEnabled: { if( NodeInfo* nodeInfo = GetNodeInfo( _notification ) ) { nodeInfo->m_polled = true; } break; } case Notification::Type_DriverReady: { g_homeId = _notification->GetHomeId(); break; } case Notification::Type_DriverFailed: { g_initFailed = true; break; } case Notification::Type_AwakeNodesQueried: case Notification::Type_AllNodesQueried: case Notification::Type_AllNodesQueriedSomeDead: { g_nodesQueried = true; break; } case Notification::Type_DriverReset: case Notification::Type_NodeNaming: case Notification::Type_NodeProtocolInfo: case Notification::Type_NodeQueriesComplete: default: { } } LeaveCriticalSection( &g_criticalSection ); } //----------------------------------------------------------------------------- //
// Create the driver and then wait //----------------------------------------------------------------------------- int main( int argc, char* argv[] ) { InitializeCriticalSection( &g_criticalSection ); // Create the OpenZWave Manager. // The first argument is the path to the config files (where the manufacturer_specific.xml file is located // The second argument is the path for saved Z-Wave network state and the log file. If you leave it NULL // the log file will appear in the program's working directory. Options::Create( "../../../../../../config/", "", "" ); Options::Get()->AddOptionInt( "SaveLogLevel", LogLevel_Detail ); Options::Get()->AddOptionInt( "QueueLogLevel", LogLevel_Debug ); Options::Get()->AddOptionInt( "DumpTrigger", LogLevel_Error ); Options::Get()->AddOptionInt( "PollInterval", 500 ); Options::Get()->AddOptionBool( "IntervalBetweenPolls", true ); Options::Get()->AddOptionBool("ValidateValueChanges", true); Options::Get()->Lock(); Manager::Create(); // Add a callback handler to the manager. The second argument is a context that // is passed to the OnNotification method. If the OnNotification is a method of // a class, the context would usually be a pointer to that class object, to // avoid the need for the notification handler to be a static. Manager::Get()->AddWatcher( OnNotification, NULL ); // Add a Z-Wave Driver // Modify this line to set the correct serial port for your PC interface. string port = "\\\\.\\COM6"; Manager::Get()->AddDriver( ( argc > 1 ) ? argv[1] : port ); //Manager::Get()->AddDriver( "HID Controller", Driver::ControllerInterface_Hid ); // Now we just wait for either the AwakeNodesQueried or AllNodesQueried notification, // then write out the config file. // In a normal app, we would be handling notifications and building a UI for the user. // Since the configuration file contains command class information that is only // known after the nodes on the network are queried, wait until all of the nodes // on the network have been queried (at least the "listening" ones) before // writing the configuration file. (Maybe write again after sleeping nodes have // been queried as well.) while( !g_nodesQueried ) { Sleep( 1000 ); } if( !g_initFailed ) { Manager::Get()->WriteConfig( g_homeId ); // The section below demonstrates setting up polling for a variable. In this simple // example, it has been hardwired to poll COMMAND_CLASS_BASIC on the each node that // supports this setting. EnterCriticalSection( &g_criticalSection ); for( list::iterator it = g_nodes.begin(); it != g_nodes.end(); ++it ) { NodeInfo* nodeInfo = *it; // skip the controller (most likely node 1) if( nodeInfo->m_nodeId == 1) continue; for( list::iterator it2 = nodeInfo->m_values.begin(); it2 != nodeInfo->m_values.end(); ++it2 ) { ValueID v = *it2; if( v.GetCommandClassId() == 0x20 ) { Manager::Get()->EnablePoll( v, 2 ); // enables polling with "intensity" of 2, though this is irrelevant with only one value polled break; } } } LeaveCriticalSection( &g_criticalSection ); // If we want to access our NodeInfo list, that has been built from all the // notification callbacks we received from the library, we have to do so // from inside a Critical Section. This is because the callbacks occur on other // threads, and we cannot risk the list being changed while we are using it. // We must hold the critical section for as short a time as possible, to avoid // 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*10; i++ ) { Sleep(90); // do most of your work outside critical section EnterCriticalSection( &g_criticalSection ); Sleep(10); // but NodeInfo list and similar data should be inside critical section LeaveCriticalSection( &g_criticalSection ); } Driver::DriverData data; Manager::Get()->GetDriverStatistics( g_homeId, &data ); printf("SOF: %d ACK Waiting: %d Read Aborts: %d Bad Checksums: %d\n", data.m_SOFCnt, data.m_ACKWaiting, data.m_readAborts, data.m_badChecksum); printf("Reads: %d Writes: %d CAN: %d NAK: %d ACK: %d Out of Frame: %d\n", data.m_readCnt, data.m_writeCnt, data.m_CANCnt, data.m_NAKCnt, data.m_ACKCnt, data.m_OOFCnt); printf("Dropped: %d Retries: %d\n", data.m_dropped, data.m_retries); } // program exit (clean up) Manager::Destroy(); Options::Destroy(); DeleteCriticalSection( &g_criticalSection ); return 0; } open-zwave-1.5/cpp/examples/windows/MinOZW/vs2008/000077500000000000000000000000001264474202400216365ustar00rootroot00000000000000open-zwave-1.5/cpp/examples/windows/MinOZW/vs2008/MinOZW.sln000066400000000000000000000043661264474202400235100ustar00rootroot00000000000000 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 open-zwave-1.5/cpp/examples/windows/MinOZW/vs2008/MinOZW.vcproj000066400000000000000000000161251264474202400242130ustar00rootroot00000000000000 open-zwave-1.5/cpp/examples/windows/MinOZW/vs2010/000077500000000000000000000000001264474202400216275ustar00rootroot00000000000000open-zwave-1.5/cpp/examples/windows/MinOZW/vs2010/MinOZW.sln000066400000000000000000000043511264474202400234730ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C++ Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MinOZW", "MinOZW.vcxproj", "{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\vs2010\OpenZWave.vcxproj", "{497F9828-DEC2-4C80-B9E0-AD066CCB587C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 DebugDLL|Win32 = DebugDLL|Win32 Release|Win32 = Release|Win32 ReleaseDLL|Win32 = ReleaseDLL|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}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 {22847D76-B1CF-4921-8B7A-61E248412C4A}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {22847D76-B1CF-4921-8B7A-61E248412C4A}.Release|Win32.ActiveCfg = Release|Win32 {22847D76-B1CF-4921-8B7A-61E248412C4A}.Release|Win32.Build.0 = Release|Win32 {22847D76-B1CF-4921-8B7A-61E248412C4A}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 {22847D76-B1CF-4921-8B7A-61E248412C4A}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|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}.DebugDLL|Win32.ActiveCfg = DebugDLL|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.DebugDLL|Win32.Build.0 = DebugDLL|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.Build.0 = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.ReleaseDLL|Win32.ActiveCfg = ReleaseDLL|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.ReleaseDLL|Win32.Build.0 = ReleaseDLL|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal open-zwave-1.5/cpp/examples/windows/MinOZW/vs2010/MinOZW.vcxproj000066400000000000000000000254121264474202400243730ustar00rootroot00000000000000 DebugDLL Win32 Debug Win32 ReleaseDLL Win32 Release Win32 {22847D76-B1CF-4921-8B7A-61E248412C4A} MinOZW Win32Proj Application MultiByte true Application MultiByte Application MultiByte Application MultiByte <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)$(Configuration)\ $(SolutionDir)$(Configuration)\ $(Configuration)\ $(Configuration)\ true true $(SolutionDir)$(Configuration)\ $(SolutionDir)$(Configuration)\ $(Configuration)\ $(Configuration)\ false false AllRules.ruleset AllRules.ruleset AllRules.ruleset AllRules.ruleset Disabled ..\..\..\..\src;..\..\..\..\src\platform;..\..\..\..\src\value_classes;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 EditAndContinue $(OutDir)\OpenZWave.lib;%(AdditionalDependencies) true Console MachineX86 Disabled ..\..\..\..\src;..\..\..\..\src\platform;..\..\..\..\src\value_classes;%(AdditionalIncludeDirectories) WIN32;_DEBUG;_CONSOLE;OPENZWAVE_USEDLL;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL Level3 EditAndContinue 4251 $(OutDir)\OpenZWaved.lib;%(AdditionalDependencies) true Console MachineX86 MaxSpeed true ..\..\..\..\src;..\..\..\..\src\platform;..\..\..\..\src\value_classes;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) MultiThreadedDLL true Level3 ProgramDatabase $(OutDir)\OpenZWave.lib;%(AdditionalDependencies) true Console true true MachineX86 MaxSpeed true ..\..\..\..\src;..\..\..\..\src\platform;..\..\..\..\src\value_classes;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;OPENZWAVE_USEDLL;%(PreprocessorDefinitions) MultiThreadedDLL true Level3 ProgramDatabase 4251 $(OutDir)\OpenZWave.lib;%(AdditionalDependencies) true Console true true MachineX86 open-zwave-1.5/cpp/examples/windows/MinOZW/vs2010/MinOZW.vcxproj.filters000066400000000000000000000007741264474202400260460ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx Source Files open-zwave-1.5/cpp/hidapi/000077500000000000000000000000001264474202400154775ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/AUTHORS.txt000066400000000000000000000005441264474202400173700ustar00rootroot00000000000000 HIDAPI Authors: Alan Ott : Original Author and Maintainer Linux, Windows, and Mac implementations Ludovic Rousseau : Formatting for Doxygen documentation Bug fixes Correctness fixes For a comprehensive list of contributions, see the commit list at github: http://github.com/signal11/hidapi/commits/master open-zwave-1.5/cpp/hidapi/HACKING.txt000066400000000000000000000005471264474202400173120ustar00rootroot00000000000000This file is mostly for the maintainer. 1. Build hidapi.dll 2. Build hidtest.exe in DEBUG and RELEASE 3. Commit all 4. Run the Following export VERSION=0.1.0 export TAG_NAME=hidapi-$VERSION git tag $TAG_NAME git archive --format zip --prefix $TAG_NAME/ $TAG_NAME >../$TAG_NAME.zip 5. Test the zip file. 6. Run the following: git push origin $TAG_NAME open-zwave-1.5/cpp/hidapi/LICENSE-bsd.txt000066400000000000000000000027761264474202400201040ustar00rootroot00000000000000Copyright (c) 2010, Alan Ott, Signal 11 Software 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 Signal 11 Software 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 HOLDER 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. open-zwave-1.5/cpp/hidapi/LICENSE-gpl3.txt000066400000000000000000001045131264474202400201710ustar00rootroot00000000000000 GNU 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. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . open-zwave-1.5/cpp/hidapi/LICENSE-orig.txt000066400000000000000000000004101264474202400202530ustar00rootroot00000000000000 HIDAPI - Multi-Platform library for communication with HID devices. Copyright 2009, Alan Ott, Signal 11 Software. All Rights Reserved. This software may be used by anyone for any reason so long as the copyright notice in the source files remains intact. open-zwave-1.5/cpp/hidapi/LICENSE.txt000066400000000000000000000010121264474202400173140ustar00rootroot00000000000000HIDAPI can be used under one of three licenses. 1. The GNU Public License, version 3.0, in LICENSE-gpl3.txt 2. A BSD-Style License, in LICENSE-bsd.txt. 3. The more liberal original HIDAPI license. LICENSE-orig.txt The license chosen is at the discretion of the user of HIDAPI. For example: 1. An author of GPL software would likely use HIDAPI under the terms of the GPL. 2. An author of commercial closed-source software would likely use HIDAPI under the terms of the BSD-style license or the original HIDAPI license. open-zwave-1.5/cpp/hidapi/Makefile.am000066400000000000000000000021001264474202400175240ustar00rootroot00000000000000 ACLOCAL_AMFLAGS = -I m4 if OS_FREEBSD pkgconfigdir=$(prefix)/libdata/pkgconfig else pkgconfigdir=$(libdir)/pkgconfig endif if OS_LINUX pkgconfig_DATA=pc/hidapi-hidraw.pc pc/hidapi-libusb.pc else pkgconfig_DATA=pc/hidapi.pc endif SUBDIRS= if OS_LINUX SUBDIRS += linux libusb endif if OS_DARWIN SUBDIRS += mac endif if OS_FREEBSD SUBDIRS += libusb endif if OS_WINDOWS SUBDIRS += windows endif SUBDIRS += hidtest if BUILD_TESTGUI SUBDIRS += testgui endif EXTRA_DIST = udev doxygen dist_doc_DATA = \ README.txt \ AUTHORS.txt \ LICENSE-bsd.txt \ LICENSE-gpl3.txt \ LICENSE-orig.txt \ LICENSE.txt SCMCLEAN_TARGETS= \ aclocal.m4 \ config.guess \ config.sub \ configure \ config.h.in \ depcomp \ install-sh \ ltmain.sh \ missing \ mac/Makefile.in \ testgui/Makefile.in \ libusb/Makefile.in \ Makefile.in \ linux/Makefile.in \ windows/Makefile.in \ m4/libtool.m4 \ m4/lt~obsolete.m4 \ m4/ltoptions.m4 \ m4/ltsugar.m4 \ m4/ltversion.m4 SCMCLEAN_DIR_TARGETS = \ autom4te.cache scm-clean: distclean rm -f $(SCMCLEAN_TARGETS) rm -Rf $(SCMCLEAN_DIR_TARGETS) open-zwave-1.5/cpp/hidapi/README.txt000066400000000000000000000276201264474202400172040ustar00rootroot00000000000000 HIDAPI library for Windows, Linux, FreeBSD and Mac OS X ========================================================= About ====== HIDAPI is a multi-platform library which allows an application to interface with USB and Bluetooth HID-Class devices on Windows, Linux, FreeBSD, and Mac OS X. HIDAPI can be either built as a shared library (.so or .dll) or can be embedded directly into a target application by adding a single source file (per platform) and a single header. HIDAPI has four back-ends: * Windows (using hid.dll) * Linux/hidraw (using the Kernel's hidraw driver) * Linux/libusb (using libusb-1.0) * FreeBSD (using libusb-1.0) * Mac (using IOHidManager) On Linux, either the hidraw or the libusb back-end can be used. There are tradeoffs, and the functionality supported is slightly different. Linux/hidraw (linux/hid.c): This back-end uses the hidraw interface in the Linux kernel. While this back-end will support both USB and Bluetooth, it has some limitations on kernels prior to 2.6.39, including the inability to send or receive feature reports. In addition, it will only communicate with devices which have hidraw nodes associated with them. Keyboards, mice, and some other devices which are blacklisted from having hidraw nodes will not work. Fortunately, for nearly all the uses of hidraw, this is not a problem. Linux/FreeBSD/libusb (libusb/hid-libusb.c): This back-end uses libusb-1.0 to communicate directly to a USB device. This back-end will of course not work with Bluetooth devices. HIDAPI also comes with a Test GUI. The Test GUI is cross-platform and uses Fox Toolkit (http://www.fox-toolkit.org). It will build on every platform which HIDAPI supports. Since it relies on a 3rd party library, building it is optional but recommended because it is so useful when debugging hardware. What Does the API Look Like? ============================= The API provides the the most commonly used HID functions including sending and receiving of input, output, and feature reports. The sample program, which communicates with a heavily hacked up version of the Microchip USB Generic HID sample looks like this (with error checking removed for simplicity): #ifdef WIN32 #include #endif #include #include #include "hidapi.h" #define MAX_STR 255 int main(int argc, char* argv[]) { int res; unsigned char buf[65]; wchar_t wstr[MAX_STR]; hid_device *handle; int i; // Initialize the hidapi library res = hid_init(); // Open the device using the VID, PID, // and optionally the Serial number. handle = hid_open(0x4d8, 0x3f, NULL); // Read the Manufacturer String res = hid_get_manufacturer_string(handle, wstr, MAX_STR); wprintf(L"Manufacturer String: %s\n", wstr); // Read the Product String res = hid_get_product_string(handle, wstr, MAX_STR); wprintf(L"Product String: %s\n", wstr); // Read the Serial Number String res = hid_get_serial_number_string(handle, wstr, MAX_STR); wprintf(L"Serial Number String: (%d) %s\n", wstr[0], wstr); // Read Indexed String 1 res = hid_get_indexed_string(handle, 1, wstr, MAX_STR); wprintf(L"Indexed String 1: %s\n", wstr); // Toggle LED (cmd 0x80). The first byte is the report number (0x0). buf[0] = 0x0; buf[1] = 0x80; res = hid_write(handle, buf, 65); // Request state (cmd 0x81). The first byte is the report number (0x0). buf[0] = 0x0; buf[1] = 0x81; res = hid_write(handle, buf, 65); // Read requested state res = hid_read(handle, buf, 65); // Print out the returned buffer. for (i = 0; i < 4; i++) printf("buf[%d]: %d\n", i, buf[i]); // Finalize the hidapi library res = hid_exit(); return 0; } If you have your own simple test programs which communicate with standard hardware development boards (such as those from Microchip, TI, Atmel, FreeScale and others), please consider sending me something like the above for inclusion into the HIDAPI source. This will help others who have the same hardware as you do. License ======== HIDAPI may be used by one of three licenses as outlined in LICENSE.txt. Download ========= HIDAPI can be downloaded from github git clone git://github.com/signal11/hidapi.git Build Instructions =================== This section is long. Don't be put off by this. It's not long because it's complicated to build HIDAPI; it's quite the opposite. This section is long because of the flexibility of HIDAPI and the large number of ways in which it can be built and used. You will likely pick a single build method. HIDAPI can be built in several different ways. If you elect to build a shared library, you will need to build it from the HIDAPI source distribution. If you choose instead to embed HIDAPI directly into your application, you can skip the building and look at the provided platform Makefiles for guidance. These platform Makefiles are located in linux/ libusb/ mac/ and windows/ and are called Makefile-manual. In addition, Visual Studio projects are provided. Even if you're going to embed HIDAPI into your project, it is still beneficial to build the example programs. Prerequisites: --------------- Linux: ------- On Linux, you will need to install development packages for libudev, libusb and optionally Fox-toolkit (for the test GUI). On Debian/Ubuntu systems these can be installed by running: sudo apt-get install libudev-dev libusb-1.0-0-dev libfox-1.6-dev If you downloaded the source directly from the git repository (using git clone), you'll need Autotools: sudo apt-get install autotools-dev FreeBSD: --------- On FreeBSD you will need to install GNU make, libiconv, and optionally Fox-Toolkit (for the test GUI). This is done by running the following: pkg_add -r gmake libiconv fox16 If you downloaded the source directly from the git repository (using git clone), you'll need Autotools: pkg_add -r autotools Mac: ----- On Mac, you will need to install Fox-Toolkit if you wish to build the Test GUI. There are two ways to do this, and each has a slight complication. Which method you use depends on your use case. If you wish to build the Test GUI just for your own testing on your own computer, then the easiest method is to install Fox-Toolkit using ports: sudo port install fox If you wish to build the TestGUI app bundle to redistribute to others, you will need to install Fox-toolkit from source. This is because the version of fox that gets installed using ports uses the ports X11 libraries which are not compatible with the Apple X11 libraries. If you install Fox with ports and then try to distribute your built app bundle, it will simply fail to run on other systems. To install Fox-Toolkit manually, download the source package from http://www.fox-toolkit.org, extract it, and run the following from within the extracted source: ./configure && make && make install Windows: --------- On Windows, if you want to build the test GUI, you will need to get the hidapi-externals.zip package from the download site. This contains pre-built binaries for Fox-toolkit. Extract hidapi-externals.zip just outside of hidapi, so that hidapi-externals and hidapi are on the same level, as shown: Parent_Folder | +hidapi +hidapi-externals Again, this step is not required if you do not wish to build the test GUI. Building HIDAPI into a shared library on Unix Platforms: --------------------------------------------------------- On Unix-like systems such as Linux, FreeBSD, Mac, and even Windows, using Mingw or Cygwin, the easiest way to build a standard system-installed shared library is to use the GNU Autotools build system. If you checked out the source from the git repository, run the following: ./bootstrap ./configure make make install <----- as root, or using sudo If you downloaded a source package (ie: if you did not run git clone), you can skip the ./bootstrap step. ./configure can take several arguments which control the build. The two most likely to be used are: --enable-testgui Enable build of the Test GUI. This requires Fox toolkit to be installed. Instructions for installing Fox-Toolkit on each platform are in the Prerequisites section above. --prefix=/usr Specify where you want the output headers and libraries to be installed. The example above will put the headers in /usr/include and the binaries in /usr/lib. The default is to install into /usr/local which is fine on most systems. Building the manual way on Unix platforms: ------------------------------------------- Manual Makefiles are provided mostly to give the user and idea what it takes to build a program which embeds HIDAPI directly inside of it. These should really be used as examples only. If you want to build a system-wide shared library, use the Autotools method described above. To build HIDAPI using the manual makefiles, change to the directory of your platform and run make. For example, on Linux run: cd linux/ make -f Makefile-manual To build the Test GUI using the manual makefiles: cd testgui/ make -f Makefile-manual Building on Windows: --------------------- To build the HIDAPI DLL on Windows using Visual Studio, build the .sln file in the windows/ directory. To build the Test GUI on windows using Visual Studio, build the .sln file in the testgui/ directory. To build HIDAPI using MinGW or Cygwin using Autotools, use the instructions in the section titled "Building HIDAPI into a shared library on Unix Platforms" above. Note that building the Test GUI with MinGW or Cygwin will require the Windows procedure in the Prerequisites section above (ie: hidapi-externals.zip). To build HIDAPI using MinGW using the Manual Makefiles, see the section "Building the manual way on Unix platforms" above. HIDAPI can also be built using the Windows DDK (now also called the Windows Driver Kit or WDK). This method was originally required for the HIDAPI build but not anymore. However, some users still prefer this method. It is not as well supported anymore but should still work. Patches are welcome if it does not. To build using the DDK: 1. Install the Windows Driver Kit (WDK) from Microsoft. 2. From the Start menu, in the Windows Driver Kits folder, select Build Environments, then your operating system, then the x86 Free Build Environment (or one that is appropriate for your system). 3. From the console, change directory to the windows/ddk_build/ directory, which is part of the HIDAPI distribution. 4. Type build. 5. You can find the output files (DLL and LIB) in a subdirectory created by the build system which is appropriate for your environment. On Windows XP, this directory is objfre_wxp_x86/i386. Cross Compiling ================ This section talks about cross compiling HIDAPI for Linux using autotools. This is useful for using HIDAPI on embedded Linux targets. These instructions assume the most raw kind of embedded Linux build, where all prerequisites will need to be built first. This process will of course vary based on your embedded Linux build system if you are using one, such as OpenEmbedded or Buildroot. For the purpose of this section, it will be assumed that the following environment variables are exported. $ export STAGING=$HOME/out $ export HOST=arm-linux STAGING and HOST can be modified to suit your setup. Prerequisites -------------- Note that the build of libudev is the very basic configuration. Build Libusb. From the libusb source directory, run: ./configure --host=$HOST --prefix=$STAGING make make install Build libudev. From the libudev source directory, run: ./configure --disable-gudev --disable-introspection --disable-hwdb \ --host=$HOST --prefix=$STAGING make make install Building HIDAPI ---------------- Build HIDAPI: PKG_CONFIG_DIR= \ PKG_CONFIG_LIBDIR=$STAGING/lib/pkgconfig:$STAGING/share/pkgconfig \ PKG_CONFIG_SYSROOT_DIR=$STAGING \ ./configure --host=$HOST --prefix=$STAGING Signal 11 Software - 2010-04-11 2010-07-28 2011-09-10 2012-05-01 2012-07-03 open-zwave-1.5/cpp/hidapi/bootstrap000077500000000000000000000000641264474202400174420ustar00rootroot00000000000000#!/bin/sh -x autoreconf --install --verbose --force open-zwave-1.5/cpp/hidapi/configure.ac000066400000000000000000000145561264474202400200000ustar00rootroot00000000000000AC_PREREQ(2.63) # Version number. This is currently the only place. m4_define([HIDAPI_MAJOR], 0) m4_define([HIDAPI_MINOR], 7) m4_define([HIDAPI_RELEASE], 0) m4_define([HIDAPI_RC], +) m4_define([VERSION_STRING], HIDAPI_MAJOR[.]HIDAPI_MINOR[.]HIDAPI_RELEASE[]HIDAPI_RC) AC_INIT([hidapi],[VERSION_STRING],[alan@signal11.us]) # Library soname version # Follow the following rules (particularly the ones in the second link): # http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html # http://sourceware.org/autobook/autobook/autobook_91.html lt_current="0" lt_revision="0" lt_age="0" LTLDFLAGS="-version-info ${lt_current}:${lt_revision}:${lt_age}" AC_CONFIG_MACRO_DIR([m4]) AM_INIT_AUTOMAKE([foreign -Wall -Werror]) AC_CONFIG_MACRO_DIR([m4]) m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) LT_INIT AC_PROG_CC AC_PROG_CXX AC_PROG_OBJC PKG_PROG_PKG_CONFIG m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) hidapi_lib_error() { echo "" echo " Library $1 was not found on this system." echo " Please install it and re-run ./configure" echo "" exit 1 } hidapi_prog_error() { echo "" echo " Program $1 was not found on this system." echo " This program is part of $2." echo " Please install it and re-run ./configure" echo "" exit 1 } AC_MSG_CHECKING([operating system]) AC_MSG_RESULT($host) case $host in *-linux*) AC_MSG_RESULT([ (Linux back-end)]) AC_DEFINE(OS_LINUX, 1, [Linux implementations]) AC_SUBST(OS_LINUX) backend="linux" os="linux" threads="pthreads" # HIDAPI/hidraw libs PKG_CHECK_MODULES([libudev], [libudev], true, [hidapi_lib_error libudev]) LIBS_HIDRAW_PR+=" $libudev_LIBS" CFLAGS_HIDRAW+=" $libudev_CFLAGS" # HIDAPI/libusb libs AC_CHECK_LIB([rt], [clock_gettime], [LIBS_LIBUSB_PRIVATE+=" -lrt"], [hidapi_lib_error librt]) PKG_CHECK_MODULES([libusb], [libusb-1.0], true, [hidapi_lib_error libusb-1.0]) LIBS_LIBUSB_PRIVATE+=" $libusb_LIBS" CFLAGS_LIBUSB+=" $libusb_CFLAGS" ;; *-darwin*) AC_MSG_RESULT([ (Mac OS X back-end)]) AC_DEFINE(OS_DARWIN, 1, [Mac implementation]) AC_SUBST(OS_DARWIN) backend="mac" os="darwin" threads="pthreads" LIBS="${LIBS} -framework IOKit -framework CoreFoundation" ;; *-freebsd*) AC_MSG_RESULT([ (FreeBSD back-end)]) AC_DEFINE(OS_FREEBSD, 1, [FreeBSD implementation]) AC_SUBST(OS_FREEBSD) backend="libusb" os="freebsd" threads="pthreads" CFLAGS="$CFLAGS -I/usr/local/include" LDFLAGS="$LDFLAGS -L/usr/local/lib" LIBS="${LIBS}" AC_CHECK_LIB([usb], [libusb_init], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -lusb"], [hidapi_lib_error libusb]) AC_CHECK_LIB([iconv], [iconv_open], [LIBS_LIBUSB_PRIVATE="${LIBS_LIBUSB_PRIVATE} -liconv"], [hidapi_lib_error libiconv]) echo libs_priv: $LIBS_LIBUSB_PRIVATE ;; *-mingw*) AC_MSG_RESULT([ (Windows back-end, using MinGW)]) backend="windows" os="windows" threads="windows" win_implementation="mingw" ;; *-cygwin*) AC_MSG_RESULT([ (Windows back-end, using Cygwin)]) backend="windows" os="windows" threads="windows" win_implementation="cygwin" ;; *) AC_MSG_ERROR([HIDAPI is not supported on your operating system yet]) esac LIBS_HIDRAW="${LIBS} ${LIBS_HIDRAW_PR}" LIBS_LIBUSB="${LIBS} ${LIBS_LIBUSB_PRIVATE}" AC_SUBST([LIBS_HIDRAW]) AC_SUBST([LIBS_LIBUSB]) AC_SUBST([CFLAGS_LIBUSB]) AC_SUBST([CFLAGS_HIDRAW]) if test "x$os" = xwindows; then AC_DEFINE(OS_WINDOWS, 1, [Windows implementations]) AC_SUBST(OS_WINDOWS) LDFLAGS="${LDFLAGS} -no-undefined" LIBS="${LIBS} -lsetupapi" fi if test "x$threads" = xpthreads; then AX_PTHREAD([found_pthreads=yes], [found_pthreads=no]) if test "x$found_pthreads" = xyes; then if test "x$os" = xlinux; then # Only use pthreads for libusb implementation on Linux. LIBS_LIBUSB="$PTHREAD_LIBS $LIBS_LIBUSB" CFLAGS_LIBUSB="$CFLAGS_LIBUSB $PTHREAD_CFLAGS" # There's no separate CC on Linux for threading, # so it's ok that both implementations use $PTHREAD_CC CC="$PTHREAD_CC" else LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" CC="$PTHREAD_CC" fi fi fi # Test GUI AC_ARG_ENABLE([testgui], [AS_HELP_STRING([--enable-testgui], [enable building of test GUI (default n)])], [testgui_enabled=$enableval], [testgui_enabled='no']) AM_CONDITIONAL([BUILD_TESTGUI], [test "x$testgui_enabled" != "xno"]) # Configure the MacOS TestGUI app bundle rm -Rf testgui/TestGUI.app mkdir -p testgui/TestGUI.app cp -R ${srcdir}/testgui/TestGUI.app.in/* testgui/TestGUI.app chmod -R u+w testgui/TestGUI.app mkdir testgui/TestGUI.app/Contents/MacOS/ if test "x$testgui_enabled" != "xno"; then if test "x$os" = xdarwin; then # On Mac OS, don't use pkg-config. AC_CHECK_PROG([foxconfig], [fox-config], [fox-config], false) if test "x$foxconfig" = "xfalse"; then hidapi_prog_error fox-config "FOX Toolkit" fi LIBS_TESTGUI+=`$foxconfig --libs` LIBS_TESTGUI+=" -framework Cocoa -L/usr/X11R6/lib" CFLAGS_TESTGUI+=`$foxconfig --cflags` OBJCFLAGS+=" -x objective-c++" elif test "x$os" = xwindows; then # On Windows, just set the paths for Fox toolkit if test "x$win_implementation" = xmingw; then CFLAGS_TESTGUI="-I\$(srcdir)/../../hidapi-externals/fox/include -g -c" LIBS_TESTGUI=" -mwindows \$(srcdir)/../../hidapi-externals/fox/lib/libFOX-1.6.a -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32" else # Cygwin CFLAGS_TESTGUI="-DWIN32 -I\$(srcdir)/../../hidapi-externals/fox/include -g -c" LIBS_TESTGUI="\$(srcdir)/../../hidapi-externals/fox/lib/libFOX-cygwin-1.6.a -lgdi32 -Wl,--enable-auto-import -static-libgcc -static-libstdc++ -lkernel32" fi else # On Linux and FreeBSD platforms, use pkg-config to find fox. PKG_CHECK_MODULES([fox], [fox]) LIBS_TESTGUI="${LIBS_TESTGUI} $fox_LIBS" if test "x$os" = xfreebsd; then LIBS_TESTGUI="${LIBS_TESTGUI} -L/usr/local/lib" fi CFLAGS_TESTGUI="${CFLAGS_TESTGUI} $fox_CFLAGS" fi fi AC_SUBST([LIBS_TESTGUI]) AC_SUBST([CFLAGS_TESTGUI]) AC_SUBST([backend]) # OS info for Automake AM_CONDITIONAL(OS_LINUX, test "x$os" = xlinux) AM_CONDITIONAL(OS_DARWIN, test "x$os" = xdarwin) AM_CONDITIONAL(OS_FREEBSD, test "x$os" = xfreebsd) AM_CONDITIONAL(OS_WINDOWS, test "x$os" = xwindows) AC_CONFIG_HEADERS([config.h]) if test "x$os" = "xlinux"; then AC_CONFIG_FILES([pc/hidapi-hidraw.pc]) AC_CONFIG_FILES([pc/hidapi-libusb.pc]) else AC_CONFIG_FILES([pc/hidapi.pc]) fi AC_SUBST(LTLDFLAGS) AC_CONFIG_FILES([Makefile \ hidtest/Makefile \ libusb/Makefile \ linux/Makefile \ mac/Makefile \ testgui/Makefile \ windows/Makefile]) AC_OUTPUT open-zwave-1.5/cpp/hidapi/doxygen/000077500000000000000000000000001264474202400171545ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/doxygen/Doxyfile000066400000000000000000002044741264474202400206750ustar00rootroot00000000000000# Doxyfile 1.7.1 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project # # All text after a hash (#) is considered a comment and will be ignored # The format is: # TAG = value [value, ...] # For lists items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (" ") #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all # text before the first occurrence of this tag. Doxygen uses libiconv (or the # iconv built into libc) for the transcoding. See # http://www.gnu.org/software/libiconv for the list of possible encodings. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded # by quotes) that should identify the project. PROJECT_NAME = hidapi # The PROJECT_NUMBER tag can be used to enter a project or revision number. # This could be handy for archiving the generated documentation or # if some version control system is used. PROJECT_NUMBER = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) # base path where the generated documentation will be put. # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. OUTPUT_DIRECTORY = # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output # format and will distribute the generated files over these directories. # Enabling this option can be useful when feeding doxygen a huge amount of # source files, where putting all generated files in the same directory would # otherwise cause performance problems for the file system. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # The default language is English, other supported languages are: # Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, # Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, # Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English # messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, # Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, # Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will # include brief member descriptions after the members that are listed in # the file and class documentation (similar to JavaDoc). # Set to NO to disable this. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend # the brief description of a member or function before the detailed description. # Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator # that is used to form the text in various listings. Each string # in this list, if found as the leading text of the brief description, will be # stripped from the text and the result after processing the whole list, is # used as the annotated text. Otherwise, the brief description is used as-is. # If left blank, the following values are used ("$name" is automatically # replaced with the name of the entity): "The $name class" "The $name widget" # "The $name file" "is" "provides" "specifies" "contains" # "represents" "a" "an" "the" ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # Doxygen will generate a detailed section even if there is only a brief # description. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full # path before files name in the file list and in the header files. If set # to NO the shortest path that makes the file name unique will be used. FULL_PATH_NAMES = YES # If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag # can be used to strip a user-defined part of the path. Stripping is # only done if one of the specified strings matches the left-hand part of # the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the # path to strip. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of # the path mentioned in the documentation of a class, which tells # the reader which header file to include in order to use a class. # If left blank only the name of the header file containing the class # definition is used. Otherwise one should specify the include paths that # are normally passed to the compiler using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter # (but less readable) file names. This can be useful is your file systems # doesn't support long names like on DOS, Mac, or CD-ROM. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen # will interpret the first line (until the first dot) of a JavaDoc-style # comment as the brief description. If set to NO, the JavaDoc # comments will behave just like regular Qt-style comments # (thus requiring an explicit @brief command for a brief description.) JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then Doxygen will # interpret the first line (until the first dot) of a Qt-style # comment as the brief description. If set to NO, the comments # will behave just like regular Qt-style comments (thus requiring # an explicit \brief command for a brief description.) QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen # treat a multi-line C++ special comment block (i.e. a block of //! or /// # comments) as a brief description. This used to be the default behaviour. # The new default is to treat a multi-line C++ comment block as a detailed # description. Set this tag to YES if you prefer the old behaviour instead. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES (the default) then an undocumented # member inherits the documentation from any documented member that it # re-implements. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce # a new page for each member. If set to NO, the documentation of a member will # be part of the file/class/namespace that contains it. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. # Doxygen uses this value to replace tabs by spaces in code fragments. TAB_SIZE = 8 # This tag can be used to specify a number of aliases that acts # as commands in the documentation. An alias has the form "name=value". # For example adding "sideeffect=\par Side Effects:\n" will allow you to # put the command \sideeffect (or @sideeffect) in the documentation, which # will result in a user-defined paragraph with heading "Side Effects:". # You can put \n's in the value part of an alias to insert newlines. ALIASES = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C # sources only. Doxygen will then generate output that is more tailored for C. # For instance, some of the names that are used will be different. The list # of all members will be omitted, etc. OPTIMIZE_OUTPUT_FOR_C = YES # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java # sources only. Doxygen will then generate output that is more tailored for # Java. For instance, namespaces will be presented as packages, qualified # scopes will look different, etc. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources only. Doxygen will then generate output that is more tailored for # Fortran. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for # VHDL. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given extension. # Doxygen has a built-in mapping, but you can override or extend it using this # tag. The format is ext=language, where ext is a file extension, and language # is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, # C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions # you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. EXTENSION_MAPPING = # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should # set this tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); v.s. # func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. # Doxygen will parse them like normal C++ but will assume all classes use public # instead of private inheritance when no explicit protection keyword is present. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate getter # and setter methods for a property. Setting this option to YES (the default) # will make doxygen to replace the get and set methods by a property in the # documentation. This will only work if the methods are indeed getting or # setting a simple type. If this is not the case, or you want to show the # methods anyway, you should set this option to NO. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES (the default) to allow class member groups of # the same type (for instance a group of public functions) to be put as a # subgroup of that type (e.g. under the Public Functions section). Set it to # NO to prevent subgrouping. Alternatively, this can be done per class using # the \nosubgrouping command. SUBGROUPING = YES # When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum # is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically # be useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. TYPEDEF_HIDES_STRUCT = NO # The SYMBOL_CACHE_SIZE determines the size of the internal cache use to # determine which symbols to keep in memory and which to flush to disk. # When the cache is full, less often used symbols will be written to disk. # For small to medium size projects (<1000 input files) the default value is # probably good enough. For larger projects a too small cache size can cause # doxygen to be busy swapping symbols to and from disk most of the time # causing a significant performance penality. # If the system has enough physical memory increasing the cache will improve the # performance by keeping more symbols in memory. Note that the value works on # a logarithmic scale so increasing the size by one will rougly double the # memory usage. The cache size is given by this formula: # 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, # corresponding to a cache size of 2^16 = 65536 symbols SYMBOL_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. # Private class members and static file members will be hidden unless # the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES EXTRACT_ALL = NO # If the EXTRACT_PRIVATE tag is set to YES all private members of a class # will be included in the documentation. EXTRACT_PRIVATE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. # If set to NO only classes defined in header files are included. EXTRACT_LOCAL_CLASSES = YES # This flag is only useful for Objective-C code. When set to YES local # methods, which are defined in the implementation section but not in # the interface are included in the documentation. # If set to NO (the default) only methods in the interface are included. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base # name of the file that contains the anonymous namespace. By default # anonymous namespace are hidden. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all # undocumented members of documented classes, files or namespaces. # If set to NO (the default) these members will be included in the # various overviews, but no documentation section is generated. # This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. # If set to NO (the default) these classes will be included in the various # overviews. This option has no effect if EXTRACT_ALL is enabled. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all # friend (class|struct|union) declarations. # If set to NO (the default) these declarations will be included in the # documentation. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any # documentation blocks found inside the body of a function. # If set to NO (the default) these blocks will be appended to the # function's detailed documentation block. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation # that is typed after a \internal command is included. If the tag is set # to NO (the default) then the documentation will be excluded. # Set it to YES to include the internal documentation. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate # file names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen # will show members with their full class and namespace scopes in the # documentation. If set to YES the scope will be hidden. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen # will put a list of the files that are included by a file in the documentation # of that file. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen # will list include files with double quotes in the documentation # rather than with sharp brackets. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES (the default) then a tag [inline] # is inserted in the documentation for inline members. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen # will sort the (detailed) documentation of file and class members # alphabetically by member name. If set to NO the members will appear in # declaration order. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the # brief documentation of file, namespace and class members alphabetically # by member name. If set to NO (the default) the members will appear in # declaration order. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen # will sort the (brief and detailed) documentation of class members so that # constructors and destructors are listed first. If set to NO (the default) # the constructors will appear in the respective orders defined by # SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. # This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO # and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the # hierarchy of group names into alphabetical order. If set to NO (the default) # the group names will appear in their defined order. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be # sorted by fully-qualified names, including namespaces. If set to # NO (the default), the class list will be sorted only by class name, # not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the # alphabetical list. SORT_BY_SCOPE_NAME = NO # The GENERATE_TODOLIST tag can be used to enable (YES) or # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test # commands in the documentation. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable (YES) or # disable (NO) the bug list. This list is created by putting \bug # commands in the documentation. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or # disable (NO) the deprecated list. This list is created by putting # \deprecated commands in the documentation. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional # documentation sections, marked by \if sectionname ... \endif. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines # the initial value of a variable or define consists of for it to appear in # the documentation. If the initializer consists of more lines than specified # here it will be hidden. Use a value of 0 to hide initializers completely. # The appearance of the initializer of individual variables and defines in the # documentation can be controlled using \showinitializer or \hideinitializer # command in the documentation regardless of this setting. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated # at the bottom of the documentation of classes and structs. If set to YES the # list will mention the files that were used to generate the documentation. SHOW_USED_FILES = YES # If the sources in your project are distributed over multiple directories # then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy # in the documentation. The default is NO. SHOW_DIRECTORIES = NO # Set the SHOW_FILES tag to NO to disable the generation of the Files page. # This will remove the Files entry from the Quick Index and from the # Folder Tree View (if specified). The default is YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the # Namespaces page. # This will remove the Namespaces entry from the Quick Index # and from the Folder Tree View (if specified). The default is YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command , where is the value of # the FILE_VERSION_FILTER tag, and is the name of an input file # provided by doxygen. Whatever the program writes to standard output # is used as the file version. See the manual for examples. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. The create the layout file # that represents doxygen's defaults, run doxygen with the -l option. # You can optionally specify a file name after the option, if omitted # DoxygenLayout.xml will be used as the name of the layout file. LAYOUT_FILE = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated # by doxygen. Possible values are YES and NO. If left blank NO is used. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are # generated by doxygen. Possible values are YES and NO. If left blank # NO is used. WARNINGS = YES # If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings # for undocumented members. If EXTRACT_ALL is set to YES then this flag will # automatically be disabled. WARN_IF_UNDOCUMENTED = YES # If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some # parameters in a documented function, or documenting parameters that # don't exist or using markup commands wrongly. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be abled to get warnings for # functions that are documented, but have no documentation for their parameters # or return value. If set to NO (the default) doxygen will only warn about # wrong or incomplete parameter documentation, but not about the absence of # documentation. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that # doxygen can produce. The string should contain the $file, $line, and $text # tags, which will be replaced by the file and line number from which the # warning originated and the warning text. Optionally the format may contain # $version, which will be replaced by the version of the file (if it could # be obtained via FILE_VERSION_FILTER) WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning # and error messages should be written. If left blank the output is written # to stderr. WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag can be used to specify the files and/or directories that contain # documented source files. You may enter file names like "myfile.cpp" or # directories like "/usr/src/myproject". Separate the files or directories # with spaces. INPUT = ../hidapi # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is # also the default input encoding. Doxygen uses libiconv (or the iconv built # into libc) for the transcoding. See http://www.gnu.org/software/libiconv for # the list of possible encodings. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank the following patterns are tested: # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 FILE_PATTERNS = # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. # If left blank NO is used. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used select whether or not files or # directories that are symbolic links (a Unix filesystem feature) are excluded # from the input. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. Note that the wildcards are matched # against the file with absolute path, so to exclude all test directories # for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or # directories that contain example code fragments that are included (see # the \include command). EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp # and *.h) to filter out the source-files in the directories. If left # blank all files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude # commands irrespective of the value of the RECURSIVE tag. # Possible values are YES and NO. If left blank NO is used. EXAMPLE_RECURSIVE = NO # The IMAGE_PATH tag can be used to specify one or more files or # directories that contain image that are included in the documentation (see # the \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command , where # is the value of the INPUT_FILTER tag, and is the name of an # input file. Doxygen will then use the output that the filter program writes # to standard output. # If FILTER_PATTERNS is specified, this tag will be # ignored. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. # Doxygen will compare the file name with each pattern and apply the # filter if there is a match. # The filters are a list of the form: # pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further # info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER # is applied to all files. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER) will be used to filter the input files when producing source # files to browse (i.e. when SOURCE_BROWSER is set to YES). FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will # be generated. Documented entities will be cross-referenced with these sources. # Note: To get rid of all source code in the generated output, make sure also # VERBATIM_HEADERS is set to NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body # of functions and classes directly in the documentation. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct # doxygen to hide any special comment blocks from generated source code # fragments. Normal C and C++ comments will always remain visible. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES # then for each documented function all documented # functions referencing it will be listed. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES # then for each documented function all documented entities # called/used by that function will be listed. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES (the default) # and SOURCE_BROWSER tag is set to YES, then the hyperlinks from # functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will # link to the source code. # Otherwise they will link to the documentation. REFERENCES_LINK_SOURCE = YES # If the USE_HTAGS tag is set to YES then the references to source code # will point to the HTML generated by the htags(1) tool instead of doxygen # built-in source browser. The htags tool is part of GNU's global source # tagging system (see http://www.gnu.org/software/global/global.html). You # will need version 4.8.6 or higher. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen # will generate a verbatim copy of the header file for each class for # which an include is specified. Set to NO to disable this. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index # of all compounds will be generated. Enable this if the project # contains a lot of classes, structs, unions or interfaces. ALPHABETICAL_INDEX = YES # If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then # the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns # in which this list will be split (can be a number in the range [1..20]) COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all # classes will be put under the same header in the alphabetical index. # The IGNORE_PREFIX tag can be used to specify one or more prefixes that # should be ignored while generating the index headers. IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES (the default) Doxygen will # generate HTML output. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `html' will be used as the default path. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for # each generated HTML page (for example: .htm,.php,.asp). If it is left blank # doxygen will generate files with .html extension. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a personal HTML header for # each generated HTML page. If it is left blank doxygen will generate a # standard header. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a personal HTML footer for # each generated HTML page. If it is left blank doxygen will generate a # standard footer. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading # style sheet that is used by each HTML page. It can be used to # fine-tune the look of the HTML output. If the tag is left blank doxygen # will generate a default style sheet. Note that doxygen will try to copy # the style sheet file to the HTML output directory, so don't put your own # stylesheet in the HTML output directory as well, or it will be erased! HTML_STYLESHEET = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. # Doxygen will adjust the colors in the stylesheet and background images # according to this color. Hue is specified as an angle on a colorwheel, # see http://en.wikipedia.org/wiki/Hue for more information. # For instance the value 0 represents red, 60 is yellow, 120 is green, # 180 is cyan, 240 is blue, 300 purple, and 360 is red again. # The allowed range is 0 to 359. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of # the colors in the HTML output. For a value of 0 the output will use # grayscales only. A value of 255 will produce the most vivid colors. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to # the luminance component of the colors in the HTML output. Values below # 100 gradually make the output lighter, whereas values above 100 make # the output darker. The value divided by 100 is the actual gamma applied, # so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, # and 100 does not change the gamma. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting # this to NO can help when comparing the output of multiple runs. HTML_TIMESTAMP = YES # If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, # files or namespaces will be aligned in HTML using tables. If set to # NO a bullet list will be used. HTML_ALIGN_MEMBERS = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. For this to work a browser that supports # JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox # Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari). HTML_DYNAMIC_SECTIONS = NO # If the GENERATE_DOCSET tag is set to YES, additional index files # will be generated that can be used as input for Apple's Xcode 3 # integrated development environment, introduced with OSX 10.5 (Leopard). # To create a documentation set, doxygen will generate a Makefile in the # HTML output directory. Running make will produce the docset in that # directory and running "make install" will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find # it at startup. # See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. GENERATE_DOCSET = NO # When GENERATE_DOCSET tag is set to YES, this tag determines the name of the # feed. A documentation feed provides an umbrella under which multiple # documentation sets from a single provider (such as a company or product suite) # can be grouped. DOCSET_FEEDNAME = "Doxygen generated docs" # When GENERATE_DOCSET tag is set to YES, this tag specifies a string that # should uniquely identify the documentation set bundle. This should be a # reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen # will append .docset to the name. DOCSET_BUNDLE_ID = org.doxygen.Project # When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES, additional index files # will be generated that can be used as input for tools like the # Microsoft HTML help workshop to generate a compiled HTML help file (.chm) # of the generated HTML documentation. GENERATE_HTMLHELP = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can # be used to specify the file name of the resulting .chm file. You # can add a path in front of the file if the result should not be # written to the html output directory. CHM_FILE = # If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can # be used to specify the location (absolute path including file name) of # the HTML help compiler (hhc.exe). If non-empty doxygen will try to run # the HTML help compiler on the generated index.hhp. HHC_LOCATION = # If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag # controls if a separate .chi index file is generated (YES) or that # it should be included in the master .chm file (NO). GENERATE_CHI = NO # If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING # is used to encode HtmlHelp index (hhk), content (hhc) and project file # content. CHM_INDEX_ENCODING = # If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag # controls whether a binary table of contents is generated (YES) or a # normal table of contents (NO) in the .chm file. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members # to the contents of the HTML help documentation and to the tree view. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated # that can be used as input for Qt's qhelpgenerator to generate a # Qt Compressed Help (.qch) of the generated HTML documentation. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can # be used to specify the file name of the resulting .qch file. # The path specified is relative to the HTML output folder. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#namespace QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating # Qt Help Project output. For more information please see # http://doc.trolltech.com/qthelpproject.html#virtual-folders QHP_VIRTUAL_FOLDER = doc # If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to # add. For more information please see # http://doc.trolltech.com/qthelpproject.html#custom-filters QHP_CUST_FILTER_NAME = # The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see # # Qt Help Project / Custom Filters. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's # filter section matches. # # Qt Help Project / Filter Attributes. QHP_SECT_FILTER_ATTRS = # If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can # be used to specify the location of Qt's qhelpgenerator. # If non-empty doxygen will try to run qhelpgenerator on the generated # .qhp file. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files # will be generated, which together with the HTML files, form an Eclipse help # plugin. To install this plugin and make it available under the help contents # menu in Eclipse, the contents of the directory containing the HTML and XML # files needs to be copied into the plugins directory of eclipse. The name of # the directory within the plugins directory should be the same as # the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before # the help appears. GENERATE_ECLIPSEHELP = NO # A unique identifier for the eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have # this name. ECLIPSE_DOC_ID = org.doxygen.Project # The DISABLE_INDEX tag can be used to turn on/off the condensed index at # top of each HTML page. The value NO (the default) enables the index and # the value YES disables it. DISABLE_INDEX = NO # This tag can be used to set the number of enum values (range [1..20]) # that doxygen will group on one line in the generated HTML documentation. ENUM_VALUES_PER_LINE = 4 # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. # If the tag value is set to YES, a side panel will be generated # containing a tree-like index structure (just like the one that # is generated for HTML Help). For this to work a browser that supports # JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). # Windows users are probably better off using the HTML help feature. GENERATE_TREEVIEW = NO # By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, # and Class Hierarchy pages using a tree view instead of an ordered list. USE_INLINE_TREES = NO # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be # used to set the initial width (in pixels) of the frame in which the tree # is shown. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open # links to external symbols imported via tag files in a separate window. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of Latex formulas included # as images in the HTML documentation. The default is 10. Note that # when you change the font size after a successful doxygen run you need # to manually remove any form_*.png images from the HTML output directory # to force them to be regenerated. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are # not supported properly for IE 6.0, but are supported on all modern browsers. # Note that when changing this option you need to delete any form_*.png files # in the HTML output before the changes have effect. FORMULA_TRANSPARENT = YES # When the SEARCHENGINE tag is enabled doxygen will generate a search box # for the HTML output. The underlying search engine uses javascript # and DHTML and should work on any modern browser. Note that when using # HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets # (GENERATE_DOCSET) there is already a search function so this one should # typically be disabled. For large projects the javascript based search engine # can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a PHP enabled web server instead of at the web client # using Javascript. Doxygen will generate the search PHP script and index # file to put on the web server. The advantage of the server # based approach is that it scales better to large projects and allows # full text search. The disadvances is that it is more difficult to setup # and does not have live searching capabilities. SERVER_BASED_SEARCH = NO #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- # If the GENERATE_LATEX tag is set to YES (the default) Doxygen will # generate Latex output. GENERATE_LATEX = NO # The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `latex' will be used as the default path. LATEX_OUTPUT = latex # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be # invoked. If left blank `latex' will be used as the default command name. # Note that when enabling USE_PDFLATEX this option is only used for # generating bitmaps for formulas in the HTML output, but not in the # Makefile that is written to the output directory. LATEX_CMD_NAME = latex # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to # generate index for LaTeX. If left blank `makeindex' will be used as the # default command name. MAKEINDEX_CMD_NAME = makeindex # If the COMPACT_LATEX tag is set to YES Doxygen generates more compact # LaTeX documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_LATEX = NO # The PAPER_TYPE tag can be used to set the paper type that is used # by the printer. Possible values are: a4, a4wide, letter, legal and # executive. If left blank a4wide will be used. PAPER_TYPE = a4wide # The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX # packages that should be included in the LaTeX output. EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for # the generated latex document. The header should contain everything until # the first chapter. If it is left blank doxygen will generate a # standard header. Notice: only use this tag if you know what you are doing! LATEX_HEADER = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated # is prepared for conversion to pdf (using ps2pdf). The pdf file will # contain links (just like the HTML output) instead of page references # This makes the output suitable for online browsing using a pdf viewer. PDF_HYPERLINKS = YES # If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of # plain latex in the generated Makefile. Set this option to YES to get a # higher quality PDF documentation. USE_PDFLATEX = YES # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. # command to the generated LaTeX files. This will instruct LaTeX to keep # running if errors occur, instead of asking the user for help. # This option is also used when generating formulas in HTML. LATEX_BATCHMODE = NO # If LATEX_HIDE_INDICES is set to YES then doxygen will not # include the index chapters (such as File Index, Compound Index, etc.) # in the output. LATEX_HIDE_INDICES = NO # If LATEX_SOURCE_CODE is set to YES then doxygen will include # source code with syntax highlighting in the LaTeX output. # Note that which sources are shown also depends on other settings # such as SOURCE_BROWSER. LATEX_SOURCE_CODE = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- # If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output # The RTF output is optimized for Word 97 and may not look very pretty with # other RTF readers or editors. GENERATE_RTF = NO # The RTF_OUTPUT tag is used to specify where the RTF docs will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `rtf' will be used as the default path. RTF_OUTPUT = rtf # If the COMPACT_RTF tag is set to YES Doxygen generates more compact # RTF documents. This may be useful for small projects and may help to # save some trees in general. COMPACT_RTF = NO # If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated # will contain hyperlink fields. The RTF file will # contain links (just like the HTML output) instead of page references. # This makes the output suitable for online browsing using WORD or other # programs which support those fields. # Note: wordpad (write) and others do not support links. RTF_HYPERLINKS = NO # Load stylesheet definitions from file. Syntax is similar to doxygen's # config file, i.e. a series of assignments. You only have to provide # replacements, missing definitions are set to their default value. RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an rtf document. # Syntax is similar to doxygen's config file. RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- # If the GENERATE_MAN tag is set to YES (the default) Doxygen will # generate man pages GENERATE_MAN = NO # The MAN_OUTPUT tag is used to specify where the man pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `man' will be used as the default path. MAN_OUTPUT = man # The MAN_EXTENSION tag determines the extension that is added to # the generated man pages (default is the subroutine's section .3) MAN_EXTENSION = .3 # If the MAN_LINKS tag is set to YES and Doxygen generates man output, # then it will generate one additional man file for each entity # documented in the real man page(s). These additional files # only source the real man page, but without them the man command # would be unable to find the correct page. The default is NO. MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- # If the GENERATE_XML tag is set to YES Doxygen will # generate an XML file that captures the structure of # the code including all documentation. GENERATE_XML = NO # The XML_OUTPUT tag is used to specify where the XML pages will be put. # If a relative path is entered the value of OUTPUT_DIRECTORY will be # put in front of it. If left blank `xml' will be used as the default path. XML_OUTPUT = xml # The XML_SCHEMA tag can be used to specify an XML schema, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_SCHEMA = # The XML_DTD tag can be used to specify an XML DTD, # which can be used by a validating XML parser to check the # syntax of the XML files. XML_DTD = # If the XML_PROGRAMLISTING tag is set to YES Doxygen will # dump the program listings (including syntax highlighting # and cross-referencing information) to the XML output. Note that # enabling this will significantly increase the size of the XML output. XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- # If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will # generate an AutoGen Definitions (see autogen.sf.net) file # that captures the structure of the code including all # documentation. Note that this feature is still experimental # and incomplete at the moment. GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- # If the GENERATE_PERLMOD tag is set to YES Doxygen will # generate a Perl module file that captures the structure of # the code including all documentation. Note that this # feature is still experimental and incomplete at the # moment. GENERATE_PERLMOD = NO # If the PERLMOD_LATEX tag is set to YES Doxygen will generate # the necessary Makefile rules, Perl scripts and LaTeX code to be able # to generate PDF and DVI output from the Perl module output. PERLMOD_LATEX = NO # If the PERLMOD_PRETTY tag is set to YES the Perl module output will be # nicely formatted so it can be parsed by a human reader. # This is useful # if you want to understand what is going on. # On the other hand, if this # tag is set to NO the size of the Perl module output will be much smaller # and Perl will parse it just the same. PERLMOD_PRETTY = YES # The names of the make variables in the generated doxyrules.make file # are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. # This is useful so different doxyrules.make files included by the same # Makefile don't overwrite each other's variables. PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- # If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will # evaluate all C-preprocessor directives found in the sources and include # files. ENABLE_PREPROCESSING = YES # If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro # names in the source code. If set to NO (the default) only conditional # compilation will be performed. Macro expansion can be done in a controlled # way by setting EXPAND_ONLY_PREDEF to YES. MACRO_EXPANSION = NO # If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES # then the macro expansion is limited to the macros specified with the # PREDEFINED and EXPAND_AS_DEFINED tags. EXPAND_ONLY_PREDEF = NO # If the SEARCH_INCLUDES tag is set to YES (the default) the includes files # in the INCLUDE_PATH (see below) will be search if a #include is found. SEARCH_INCLUDES = YES # The INCLUDE_PATH tag can be used to specify one or more directories that # contain include files that are not input files but should be processed by # the preprocessor. INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the # directories. If left blank, the patterns specified with FILE_PATTERNS will # be used. INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that # are defined before the preprocessor is started (similar to the -D option of # gcc). The argument of the tag is a list of macros of the form: name # or name=definition (no spaces). If the definition and the = are # omitted =1 is assumed. To prevent a macro definition from being # undefined via #undef or recursively expanded use the := operator # instead of the = operator. PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then # this tag can be used to specify a list of macro names that should be expanded. # The macro definition that is found in the sources will be used. # Use the PREDEFINED tag if you want to use a different macro definition. EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then # doxygen's preprocessor will remove all function-like macros that are alone # on a line, have an all uppercase name, and do not end with a semicolon. Such # function macros are typically used for boiler-plate code, and will confuse # the parser if not removed. SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- # The TAGFILES option can be used to specify one or more tagfiles. # Optionally an initial location of the external documentation # can be added for each tagfile. The format of a tag file without # this location is as follows: # # TAGFILES = file1 file2 ... # Adding location for the tag files is done as follows: # # TAGFILES = file1=loc1 "file2 = loc2" ... # where "loc1" and "loc2" can be relative or absolute paths or # URLs. If a location is present for each tag, the installdox tool # does not have to be run to correct the links. # Note that each tag file must have a unique name # (where the name does NOT include the path) # If a tag file is not located in the directory in which doxygen # is run, you must also specify the path to the tagfile here. TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create # a tag file that is based on the input files it reads. GENERATE_TAGFILE = # If the ALLEXTERNALS tag is set to YES all external classes will be listed # in the class index. If set to NO only the inherited external classes # will be listed. ALLEXTERNALS = NO # If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed # in the modules index. If set to NO, only the current project's groups will # be listed. EXTERNAL_GROUPS = YES # The PERL_PATH should be the absolute path and name of the perl script # interpreter (i.e. the result of `which perl'). PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- # If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will # generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base # or super classes. Setting the tag to NO turns the diagrams off. Note that # this option is superseded by the HAVE_DOT option below. This is only a # fallback. It is recommended to install and use dot, since it yields more # powerful graphs. CLASS_DIAGRAMS = YES # You can define message sequence charts within doxygen comments using the \msc # command. Doxygen will then run the mscgen tool (see # http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the # documentation. The MSCGEN_PATH tag allows you to specify the directory where # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. MSCGEN_PATH = # If set to YES, the inheritance and collaboration graphs will hide # inheritance and usage relations if the target is undocumented # or is not a class. HIDE_UNDOC_RELATIONS = YES # If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is # available from the path. This tool is part of Graphviz, a graph visualization # toolkit from AT&T and Lucent Bell Labs. The other options in this section # have no effect if this option is set to NO (the default) HAVE_DOT = NO # The DOT_NUM_THREADS specifies the number of dot invocations doxygen is # allowed to run in parallel. When set to 0 (the default) doxygen will # base this on the number of processors available in the system. You can set it # explicitly to a value larger than 0 to get control over the balance # between CPU load and processing speed. DOT_NUM_THREADS = 0 # By default doxygen will write a font called FreeSans.ttf to the output # directory and reference it in all dot files that doxygen generates. This # font does not include all possible unicode characters however, so when you need # these (or just want a differently looking font) you can specify the font name # using DOT_FONTNAME. You need need to make sure dot is able to find the font, # which can be done by putting it in a standard location or by setting the # DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory # containing the font. DOT_FONTNAME = FreeSans.ttf # The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. # The default size is 10pt. DOT_FONTSIZE = 10 # By default doxygen will tell dot to use the output directory to look for the # FreeSans.ttf font (which doxygen will put there itself). If you specify a # different font using DOT_FONTNAME you can set the path where dot # can find it using this tag. DOT_FONTPATH = # If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect inheritance relations. Setting this tag to YES will force the # the CLASS_DIAGRAMS tag to NO. CLASS_GRAPH = YES # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and # indirect implementation dependencies (inheritance, containment, and # class references variables) of the class with other documented classes. COLLABORATION_GRAPH = YES # If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen # will generate a graph for groups, showing the direct groups dependencies GROUP_GRAPHS = YES # If the UML_LOOK tag is set to YES doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. UML_LOOK = NO # If set to YES, the inheritance and collaboration graphs will show the # relations between templates and their instances. TEMPLATE_RELATIONS = NO # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT # tags are set to YES then doxygen will generate a graph for each documented # file showing the direct and indirect include dependencies of the file with # other documented files. INCLUDE_GRAPH = YES # If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and # HAVE_DOT tags are set to YES then doxygen will generate a graph for each # documented header file showing the documented files that directly or # indirectly include this file. INCLUDED_BY_GRAPH = YES # If the CALL_GRAPH and HAVE_DOT options are set to YES then # doxygen will generate a call dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function # or class method. Note that enabling this option will significantly increase # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will graphical hierarchy of all classes instead of a textual one. GRAPHICAL_HIERARCHY = YES # If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES # then doxygen will show the dependencies a directory has on other directories # in a graphical way. The dependency relations are determined by the #include # relations between the files in the directories. DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images # generated by dot. Possible values are png, jpg, or gif # If left blank png will be used. DOT_IMAGE_FORMAT = png # The tag DOT_PATH can be used to specify the path where the dot tool can be # found. If left blank, it is assumed the dot tool can be found in the path. DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the # \dotfile command). DOTFILE_DIRS = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of # nodes that will be shown in the graph. If the number of nodes in a graph # becomes larger than this value, doxygen will truncate the graph, which is # visualized by representing a node as a red box. Note that doxygen if the # number of direct children of the root node in a graph is already larger than # DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note # that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. DOT_GRAPH_MAX_NODES = 50 # The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the # graphs generated by dot. A depth value of 3 means that only nodes reachable # from the root by following a path via at most 3 edges will be shown. Nodes # that lay further from the root node will be omitted. Note that setting this # option to 1 or 2 may greatly reduce the computation time needed for large # code bases. Also note that the size of a graph can be further restricted by # DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. MAX_DOT_GRAPH_DEPTH = 0 # Set the DOT_TRANSPARENT tag to YES to generate images with a transparent # background. This is disabled by default, because dot on Windows does not # seem to support this out of the box. Warning: Depending on the platform used, # enabling this option may lead to badly anti-aliased labels on the edges of # a graph (i.e. they become hard to read). DOT_TRANSPARENT = NO # Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) # support this, this feature is disabled by default. DOT_MULTI_TARGETS = YES # If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will # generate a legend page explaining the meaning of the various boxes and # arrows in the dot generated graphs. GENERATE_LEGEND = YES # If the DOT_CLEANUP tag is set to YES (the default) Doxygen will # remove the intermediate dot files that are used to generate # the various graphs. DOT_CLEANUP = YES open-zwave-1.5/cpp/hidapi/hidapi/000077500000000000000000000000001264474202400167355ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/hidapi/hidapi.h000066400000000000000000000321651264474202400203530ustar00rootroot00000000000000/******************************************************* HIDAPI - Multi-Platform library for communication with HID devices. Alan Ott Signal 11 Software 8/22/2009 Copyright 2009, All Rights Reserved. At the discretion of the user of this library, this software may be licensed under the terms of the GNU Public License v3, a BSD-Style license, or the original HIDAPI license as outlined in the LICENSE.txt, LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt files located at the root of the source distribution. These files may also be found in the public source code repository located at: http://github.com/signal11/hidapi . ********************************************************/ /** @file * @defgroup API hidapi API */ #ifndef HIDAPI_H__ #define HIDAPI_H__ #include #ifdef _WIN32 #define HID_API_EXPORT __declspec(dllexport) #define HID_API_CALL #else #define HID_API_EXPORT /**< API export macro */ #define HID_API_CALL /**< API call macro */ #endif #define HID_API_EXPORT_CALL HID_API_EXPORT HID_API_CALL /**< API export and call macro*/ #ifdef __cplusplus extern "C" { #endif struct hid_device_; typedef struct hid_device_ hid_device; /**< opaque hidapi structure */ /** hidapi info structure */ struct hid_device_info { /** Platform-specific device path */ char *path; /** Device Vendor ID */ unsigned short vendor_id; /** Device Product ID */ unsigned short product_id; /** Serial Number */ wchar_t *serial_number; /** Device Release Number in binary-coded decimal, also known as Device Version Number */ unsigned short release_number; /** Manufacturer String */ wchar_t *manufacturer_string; /** Product string */ wchar_t *product_string; /** Usage Page for this Device/Interface (Windows/Mac only). */ unsigned short usage_page; /** Usage for this Device/Interface (Windows/Mac only).*/ unsigned short usage; /** The USB interface which this logical device represents. Valid on both Linux implementations in all cases, and valid on the Windows implementation only if the device contains more than one interface. */ int interface_number; /** Pointer to the next device */ struct hid_device_info *next; }; /** @brief Initialize the HIDAPI library. This function initializes the HIDAPI library. Calling it is not strictly necessary, as it will be called automatically by hid_enumerate() and any of the hid_open_*() functions if it is needed. This function should be called at the beginning of execution however, if there is a chance of HIDAPI handles being opened by different threads simultaneously. @ingroup API @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_init(void); /** @brief Finalize the HIDAPI library. This function frees all of the static data associated with HIDAPI. It should be called at the end of execution to avoid memory leaks. @ingroup API @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_exit(void); /** @brief Enumerate the HID Devices. This function returns a linked list of all the HID devices attached to the system which match vendor_id and product_id. If @p vendor_id is set to 0 then any vendor matches. If @p product_id is set to 0 then any product matches. If @p vendor_id and @p product_id are both set to 0, then all HID devices will be returned. @ingroup API @param vendor_id The Vendor ID (VID) of the types of device to open. @param product_id The Product ID (PID) of the types of device to open. @returns This function returns a pointer to a linked list of type struct #hid_device, containing information about the HID devices attached to the system, or NULL in the case of failure. Free this linked list by calling hid_free_enumeration(). */ struct hid_device_info HID_API_EXPORT * HID_API_CALL hid_enumerate(unsigned short vendor_id, unsigned short product_id); /** @brief Free an enumeration Linked List This function frees a linked list created by hid_enumerate(). @ingroup API @param devs Pointer to a list of struct_device returned from hid_enumerate(). */ void HID_API_EXPORT HID_API_CALL hid_free_enumeration(struct hid_device_info *devs); /** @brief Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally a serial number. If @p serial_number is NULL, the first device with the specified VID and PID is opened. @ingroup API @param vendor_id The Vendor ID (VID) of the device to open. @param product_id The Product ID (PID) of the device to open. @param serial_number The Serial Number of the device to open (Optionally NULL). @returns This function returns a pointer to a #hid_device object on success or NULL on failure. */ HID_API_EXPORT hid_device * HID_API_CALL hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number); /** @brief Open a HID device by its path name. The path name be determined by calling hid_enumerate(), or a platform-specific path name can be used (eg: /dev/hidraw0 on Linux). @ingroup API @param path The path name of the device to open @returns This function returns a pointer to a #hid_device object on success or NULL on failure. */ HID_API_EXPORT hid_device * HID_API_CALL hid_open_path(const char *path); /** @brief Write an Output report to a HID device. The first byte of @p data[] must contain the Report ID. For devices which only support a single report, this must be set to 0x0. The remaining bytes contain the report data. Since the Report ID is mandatory, calls to hid_write() will always contain one more byte than the report contains. For example, if a hid report is 16 bytes long, 17 bytes must be passed to hid_write(), the Report ID (or 0x0, for devices with a single report), followed by the report data (16 bytes). In this example, the length passed in would be 17. hid_write() will send the data on the first OUT endpoint, if one exists. If it does not, it will send the data through the Control Endpoint (Endpoint 0). @ingroup API @param device A device handle returned from hid_open(). @param data The data to send, including the report number as the first byte. @param length The length in bytes of the data to send. @returns This function returns the actual number of bytes written and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_write(hid_device *device, const unsigned char *data, size_t length); /** @brief Read an Input report from a HID device with timeout. Input reports are returned to the host through the INTERRUPT IN endpoint. The first byte will contain the Report number if the device uses numbered reports. @ingroup API @param device A device handle returned from hid_open(). @param data A buffer to put the read data into. @param length The number of bytes to read. For devices with multiple reports, make sure to read an extra byte for the report number. @param milliseconds timeout in milliseconds or -1 for blocking wait. @returns This function returns the actual number of bytes read and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds); /** @brief Read an Input report from a HID device. Input reports are returned to the host through the INTERRUPT IN endpoint. The first byte will contain the Report number if the device uses numbered reports. @ingroup API @param device A device handle returned from hid_open(). @param data A buffer to put the read data into. @param length The number of bytes to read. For devices with multiple reports, make sure to read an extra byte for the report number. @returns This function returns the actual number of bytes read and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_read(hid_device *device, unsigned char *data, size_t length); /** @brief Set the device handle to be non-blocking. In non-blocking mode calls to hid_read() will return immediately with a value of 0 if there is no data to be read. In blocking mode, hid_read() will wait (block) until there is data to read before returning. Nonblocking can be turned on and off at any time. @ingroup API @param device A device handle returned from hid_open(). @param nonblock enable or not the nonblocking reads - 1 to enable nonblocking - 0 to disable nonblocking. @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_set_nonblocking(hid_device *device, int nonblock); /** @brief Send a Feature report to the device. Feature reports are sent over the Control endpoint as a Set_Report transfer. The first byte of @p data[] must contain the Report ID. For devices which only support a single report, this must be set to 0x0. The remaining bytes contain the report data. Since the Report ID is mandatory, calls to hid_send_feature_report() will always contain one more byte than the report contains. For example, if a hid report is 16 bytes long, 17 bytes must be passed to hid_send_feature_report(): the Report ID (or 0x0, for devices which do not use numbered reports), followed by the report data (16 bytes). In this example, the length passed in would be 17. @ingroup API @param device A device handle returned from hid_open(). @param data The data to send, including the report number as the first byte. @param length The length in bytes of the data to send, including the report number. @returns This function returns the actual number of bytes written and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_send_feature_report(hid_device *device, const unsigned char *data, size_t length); /** @brief Get a feature report from a HID device. Make sure to set the first byte of @p data[] to the Report ID of the report to be read. Make sure to allow space for this extra byte in @p data[]. @ingroup API @param device A device handle returned from hid_open(). @param data A buffer to put the read data into, including the Report ID. Set the first byte of @p data[] to the Report ID of the report to be read. @param length The number of bytes to read, including an extra byte for the report ID. The buffer can be longer than the actual report. @returns This function returns the number of bytes read and -1 on error. */ int HID_API_EXPORT HID_API_CALL hid_get_feature_report(hid_device *device, unsigned char *data, size_t length); /** @brief Close a HID device. @ingroup API @param device A device handle returned from hid_open(). */ void HID_API_EXPORT HID_API_CALL hid_close(hid_device *device); /** @brief Get The Manufacturer String from a HID device. @ingroup API @param device A device handle returned from hid_open(). @param string A wide string buffer to put the data into. @param maxlen The length of the buffer in multiples of wchar_t. @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *device, wchar_t *string, size_t maxlen); /** @brief Get The Product String from a HID device. @ingroup API @param device A device handle returned from hid_open(). @param string A wide string buffer to put the data into. @param maxlen The length of the buffer in multiples of wchar_t. @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT_CALL hid_get_product_string(hid_device *device, wchar_t *string, size_t maxlen); /** @brief Get The Serial Number String from a HID device. @ingroup API @param device A device handle returned from hid_open(). @param string A wide string buffer to put the data into. @param maxlen The length of the buffer in multiples of wchar_t. @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *device, wchar_t *string, size_t maxlen); /** @brief Get a string from a HID device, based on its string index. @ingroup API @param device A device handle returned from hid_open(). @param string_index The index of the string to get. @param string A wide string buffer to put the data into. @param maxlen The length of the buffer in multiples of wchar_t. @returns This function returns 0 on success and -1 on error. */ int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *device, int string_index, wchar_t *string, size_t maxlen); /** @brief Get a string describing the last error which occurred. @ingroup API @param device A device handle returned from hid_open(). @returns This function returns a string containing the last error which occurred or NULL if none has occurred. */ HID_API_EXPORT const wchar_t* HID_API_CALL hid_error(hid_device *device); #ifdef __cplusplus } #endif #endif open-zwave-1.5/cpp/hidapi/libusb/000077500000000000000000000000001264474202400167575ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/libusb/Makefile-manual000066400000000000000000000003641264474202400216750ustar00rootroot00000000000000 OS=$(shell uname) ifeq ($(OS), Linux) FILE=Makefile.linux endif ifeq ($(OS), FreeBSD) FILE=Makefile.freebsd endif ifeq ($(FILE), ) all: $(error Your platform ${OS} is not supported by hidapi/libusb at this time.) endif include $(FILE) open-zwave-1.5/cpp/hidapi/libusb/Makefile.am000066400000000000000000000007551264474202400210220ustar00rootroot00000000000000AM_CPPFLAGS = -I$(top_srcdir)/hidapi $(CFLAGS_LIBUSB) if OS_LINUX lib_LTLIBRARIES = libhidapi-libusb.la libhidapi_libusb_la_SOURCES = hid.c libhidapi_libusb_la_LDFLAGS = $(LTLDFLAGS) libhidapi_libusb_la_LIBADD = $(LIBS_LIBUSB) endif if OS_FREEBSD lib_LTLIBRARIES = libhidapi.la libhidapi_la_SOURCES = hid.c libhidapi_la_LDFLAGS = $(LTLDFLAGS) libhidapi_la_LIBADD = $(LIBS_LIBUSB) endif hdrdir = $(includedir)/hidapi hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h EXTRA_DIST = Makefile-manual open-zwave-1.5/cpp/hidapi/libusb/Makefile.freebsd000066400000000000000000000016071264474202400220340ustar00rootroot00000000000000########################################### # Simple Makefile for HIDAPI test program # # Alan Ott # Signal 11 Software # 2010-06-01 ########################################### all: hidtest libs libs: libhidapi.so CC ?= cc CFLAGS ?= -Wall -g -fPIC CXX ?= c++ CXXFLAGS ?= -Wall -g COBJS = hid.o CPPOBJS = ../hidtest/hidtest.o OBJS = $(COBJS) $(CPPOBJS) INCLUDES = -I../hidapi -I/usr/local/include LDFLAGS = -L/usr/local/lib LIBS = -lusb -liconv -pthread # Console Test Program hidtest: $(OBJS) $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(LIBS) # Shared Libs libhidapi.so: $(COBJS) $(CC) $(LDFLAGS) -shared -Wl,-soname,$@.0 $^ -o $@ $(LIBS) # Objects $(COBJS): %.o: %.c $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@ $(CPPOBJS): %.o: %.cpp $(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@ clean: rm -f $(OBJS) hidtest libhidapi.so ../hidtest/hidtest.o .PHONY: clean libs open-zwave-1.5/cpp/hidapi/libusb/Makefile.linux000066400000000000000000000020431264474202400215540ustar00rootroot00000000000000########################################### # Simple Makefile for HIDAPI test program # # Alan Ott # Signal 11 Software # 2010-06-01 ########################################### all: hidtest-libusb libs libs: libhidapi-libusb.so CC ?= gcc CFLAGS ?= -Wall -g -fpic CXX ?= g++ CXXFLAGS ?= -Wall -g -fpic LDFLAGS ?= -Wall -g COBJS_LIBUSB = hid.o COBJS = $(COBJS_LIBUSB) CPPOBJS = ../hidtest/hidtest.o OBJS = $(COBJS) $(CPPOBJS) LIBS_USB = `pkg-config libusb-1.0 --libs` -lrt -lpthread LIBS = $(LIBS_USB) INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags` # Console Test Program hidtest-libusb: $(COBJS_LIBUSB) $(CPPOBJS) $(CXX) $(LDFLAGS) $^ $(LIBS_USB) -o $@ # Shared Libs libhidapi-libusb.so: $(COBJS_LIBUSB) $(CC) $(LDFLAGS) $(LIBS_USB) -shared -fpic -Wl,-soname,$@.0 $^ -o $@ # Objects $(COBJS): %.o: %.c $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@ $(CPPOBJS): %.o: %.cpp $(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@ clean: rm -f $(OBJS) hidtest-libusb libhidapi-libusb.so ../hidtest/hidtest.o .PHONY: clean libs open-zwave-1.5/cpp/hidapi/libusb/hid.c000066400000000000000000001133241264474202400176730ustar00rootroot00000000000000/******************************************************* HIDAPI - Multi-Platform library for communication with HID devices. Alan Ott Signal 11 Software 8/22/2009 Linux Version - 6/2/2010 Libusb Version - 8/13/2010 FreeBSD Version - 11/1/2011 Copyright 2009, All Rights Reserved. At the discretion of the user of this library, this software may be licensed under the terms of the GNU Public License v3, a BSD-Style license, or the original HIDAPI license as outlined in the LICENSE.txt, LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt files located at the root of the source distribution. These files may also be found in the public source code repository located at: http://github.com/signal11/hidapi . ********************************************************/ #define _GNU_SOURCE /* needed for wcsdup() before glibc 2.10 */ /* C */ #include #include #include #include #include #include /* Unix */ #include #include #include #include #include #include #include #include /* GNU / LibUSB */ #include "libusb.h" #include "iconv.h" #include "hidapi.h" #ifdef __cplusplus extern "C" { #endif #ifdef DEBUG_PRINTF #define LOG(...) fprintf(stderr, __VA_ARGS__) #else #define LOG(...) do {} while (0) #endif #ifndef __FreeBSD__ #define DETACH_KERNEL_DRIVER #else /* Get __FreeBSD_version */ #include #endif /* Uncomment to enable the retrieval of Usage and Usage Page in hid_enumerate(). Warning, on platforms different from FreeBSD this is very invasive as it requires the detach and re-attach of the kernel driver. See comments inside hid_enumerate(). libusb HIDAPI programs are encouraged to use the interface number instead to differentiate between interfaces on a composite HID device. */ /*#define INVASIVE_GET_USAGE*/ /* Linked List of input reports received from the device. */ struct input_report { uint8_t *data; size_t len; struct input_report *next; }; struct hid_device_ { /* Handle to the actual device. */ libusb_device_handle *device_handle; /* Endpoint information */ int input_endpoint; int output_endpoint; int input_ep_max_packet_size; /* The interface number of the HID */ int interface; /* Indexes of Strings */ int manufacturer_index; int product_index; int serial_index; /* Whether blocking reads are used */ int blocking; /* boolean */ /* Read thread objects */ pthread_t thread; pthread_mutex_t mutex; /* Protects input_reports */ pthread_cond_t condition; pthread_barrier_t barrier; /* Ensures correct startup sequence */ int shutdown_thread; struct libusb_transfer *transfer; /* List of received input reports. */ struct input_report *input_reports; }; static libusb_context *usb_context = NULL; uint16_t get_usb_code_for_current_locale(void); static int return_data(hid_device *dev, unsigned char *data, size_t length); static hid_device *new_hid_device(void) { hid_device *dev = calloc(1, sizeof(hid_device)); dev->blocking = 1; pthread_mutex_init(&dev->mutex, NULL); pthread_cond_init(&dev->condition, NULL); pthread_barrier_init(&dev->barrier, NULL, 2); return dev; } static void free_hid_device(hid_device *dev) { /* Clean up the thread objects */ pthread_barrier_destroy(&dev->barrier); pthread_cond_destroy(&dev->condition); pthread_mutex_destroy(&dev->mutex); /* Free the device itself */ free(dev); } #if 0 /*TODO: Implement this funciton on hidapi/libusb.. */ static void register_error(hid_device *device, const char *op) { } #endif #ifdef INVASIVE_GET_USAGE /* Get bytes from a HID Report Descriptor. Only call with a num_bytes of 0, 1, 2, or 4. */ static uint32_t get_bytes(uint8_t *rpt, size_t len, size_t num_bytes, size_t cur) { /* Return if there aren't enough bytes. */ if (cur + num_bytes >= len) return 0; if (num_bytes == 0) return 0; else if (num_bytes == 1) { return rpt[cur+1]; } else if (num_bytes == 2) { return (rpt[cur+2] * 256 + rpt[cur+1]); } else if (num_bytes == 4) { return (rpt[cur+4] * 0x01000000 + rpt[cur+3] * 0x00010000 + rpt[cur+2] * 0x00000100 + rpt[cur+1] * 0x00000001); } else return 0; } /* Retrieves the device's Usage Page and Usage from the report descriptor. The algorithm is simple, as it just returns the first Usage and Usage Page that it finds in the descriptor. The return value is 0 on success and -1 on failure. */ static int get_usage(uint8_t *report_descriptor, size_t size, unsigned short *usage_page, unsigned short *usage) { unsigned int i = 0; int size_code; int data_len, key_size; int usage_found = 0, usage_page_found = 0; while (i < size) { int key = report_descriptor[i]; int key_cmd = key & 0xfc; //printf("key: %02hhx\n", key); if ((key & 0xf0) == 0xf0) { /* This is a Long Item. The next byte contains the length of the data section (value) for this key. See the HID specification, version 1.11, section 6.2.2.3, titled "Long Items." */ if (i+1 < size) data_len = report_descriptor[i+1]; else data_len = 0; /* malformed report */ key_size = 3; } else { /* This is a Short Item. The bottom two bits of the key contain the size code for the data section (value) for this key. Refer to the HID specification, version 1.11, section 6.2.2.2, titled "Short Items." */ size_code = key & 0x3; switch (size_code) { case 0: case 1: case 2: data_len = size_code; break; case 3: data_len = 4; break; default: /* Can't ever happen since size_code is & 0x3 */ data_len = 0; break; }; key_size = 1; } if (key_cmd == 0x4) { *usage_page = get_bytes(report_descriptor, size, data_len, i); usage_page_found = 1; //printf("Usage Page: %x\n", (uint32_t)*usage_page); } if (key_cmd == 0x8) { *usage = get_bytes(report_descriptor, size, data_len, i); usage_found = 1; //printf("Usage: %x\n", (uint32_t)*usage); } if (usage_page_found && usage_found) return 0; /* success */ /* Skip over this key and it's associated data */ i += data_len + key_size; } return -1; /* failure */ } #endif /* INVASIVE_GET_USAGE */ #if defined(__FreeBSD__) && __FreeBSD_version < 1000000 /* The FreeBSD version of libusb doesn't have this funciton. In mainline libusb, it's inlined in libusb.h. This function will bear a striking resemblence to that one, because there's about one way to code it. Note that the data parameter is Unicode in UTF-16LE encoding. Return value is the number of bytes in data, or LIBUSB_ERROR_*. */ static inline int libusb_get_string_descriptor(libusb_device_handle *dev, uint8_t descriptor_index, uint16_t lang_id, unsigned char *data, int length) { return libusb_control_transfer(dev, LIBUSB_ENDPOINT_IN | 0x0, /* Endpoint 0 IN */ LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_STRING << 8) | descriptor_index, lang_id, data, (uint16_t) length, 1000); } #endif /* Get the first language the device says it reports. This comes from USB string #0. */ static uint16_t get_first_language(libusb_device_handle *dev) { uint16_t buf[32]; int len; /* Get the string from libusb. */ len = libusb_get_string_descriptor(dev, 0x0, /* String ID */ 0x0, /* Language */ (unsigned char*)buf, sizeof(buf)); if (len < 4) return 0x0; return buf[1]; /* First two bytes are len and descriptor type. */ } static int is_language_supported(libusb_device_handle *dev, uint16_t lang) { uint16_t buf[32]; int len; int i; /* Get the string from libusb. */ len = libusb_get_string_descriptor(dev, 0x0, /* String ID */ 0x0, /* Language */ (unsigned char*)buf, sizeof(buf)); if (len < 4) return 0x0; len /= 2; /* language IDs are two-bytes each. */ /* Start at index 1 because there are two bytes of protocol data. */ for (i = 1; i < len; i++) { if (buf[i] == lang) return 1; } return 0; } /* This function returns a newly allocated wide string containing the USB device string numbered by the index. The returned string must be freed by using free(). */ static wchar_t *get_usb_string(libusb_device_handle *dev, uint8_t idx) { char buf[512]; int len; wchar_t *str = NULL; wchar_t wbuf[256]; /* iconv variables */ iconv_t ic; size_t inbytes; size_t outbytes; size_t res; const char *inptr; char *outptr; /* Determine which language to use. */ uint16_t lang; lang = get_usb_code_for_current_locale(); if (!is_language_supported(dev, lang)) lang = get_first_language(dev); /* Get the string from libusb. */ len = libusb_get_string_descriptor(dev, idx, lang, (unsigned char*)buf, sizeof(buf)); if (len < 0) return NULL; /* buf does not need to be explicitly NULL-terminated because it is only passed into iconv() which does not need it. */ /* Initialize iconv. */ ic = iconv_open("WCHAR_T", "UTF-16LE"); if (ic == (iconv_t)-1) { LOG("iconv_open() failed\n"); return NULL; } /* Convert to native wchar_t (UTF-32 on glibc/BSD systems). Skip the first character (2-bytes). */ inptr = buf+2; inbytes = len-2; outptr = (char*) wbuf; outbytes = sizeof(wbuf); res = iconv(ic, &inptr, &inbytes, &outptr, &outbytes); if (res == (size_t)-1) { LOG("iconv() failed\n"); goto err; } /* Write the terminating NULL. */ wbuf[sizeof(wbuf)/sizeof(wbuf[0])-1] = 0x00000000; if (outbytes >= sizeof(wbuf[0])) *((wchar_t*)outptr) = 0x00000000; /* Allocate and copy the string. */ str = wcsdup(wbuf); err: iconv_close(ic); return str; } static char *make_path(libusb_device *dev, int interface_number) { char str[64]; snprintf(str, sizeof(str), "%04x:%04x:%02x", libusb_get_bus_number(dev), libusb_get_device_address(dev), interface_number); str[sizeof(str)-1] = '\0'; return strdup(str); } int HID_API_EXPORT hid_init(void) { if (!usb_context) { const char *locale; /* Init Libusb */ if (libusb_init(&usb_context)) return -1; /* Set the locale if it's not set. */ locale = setlocale(LC_CTYPE, NULL); if (!locale) setlocale(LC_CTYPE, ""); } return 0; } int HID_API_EXPORT hid_exit(void) { if (usb_context) { libusb_exit(usb_context); usb_context = NULL; } return 0; } struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { libusb_device **devs; libusb_device *dev; libusb_device_handle *handle; ssize_t num_devs; int i = 0; struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; hid_init(); num_devs = libusb_get_device_list(usb_context, &devs); if (num_devs < 0) return NULL; while ((dev = devs[i++]) != NULL) { struct libusb_device_descriptor desc; struct libusb_config_descriptor *conf_desc = NULL; int j, k; int interface_num = 0; int res = libusb_get_device_descriptor(dev, &desc); unsigned short dev_vid = desc.idVendor; unsigned short dev_pid = desc.idProduct; /* HID's are defined at the interface level. */ if (desc.bDeviceClass != LIBUSB_CLASS_PER_INTERFACE) continue; res = libusb_get_active_config_descriptor(dev, &conf_desc); if (res < 0) libusb_get_config_descriptor(dev, 0, &conf_desc); if (conf_desc) { for (j = 0; j < conf_desc->bNumInterfaces; j++) { const struct libusb_interface *intf = &conf_desc->interface[j]; for (k = 0; k < intf->num_altsetting; k++) { const struct libusb_interface_descriptor *intf_desc; intf_desc = &intf->altsetting[k]; if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { interface_num = intf_desc->bInterfaceNumber; /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 || vendor_id == dev_vid) && (product_id == 0x0 || product_id == dev_pid)) { struct hid_device_info *tmp; /* VID/PID match. Create the record. */ tmp = calloc(1, sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Fill out the record */ cur_dev->next = NULL; cur_dev->path = make_path(dev, interface_num); res = libusb_open(dev, &handle); if (res >= 0) { /* Serial Number */ if (desc.iSerialNumber > 0) cur_dev->serial_number = get_usb_string(handle, desc.iSerialNumber); /* Manufacturer and Product strings */ if (desc.iManufacturer > 0) cur_dev->manufacturer_string = get_usb_string(handle, desc.iManufacturer); if (desc.iProduct > 0) cur_dev->product_string = get_usb_string(handle, desc.iProduct); #ifdef INVASIVE_GET_USAGE { /* This section is removed because it is too invasive on the system. Getting a Usage Page and Usage requires parsing the HID Report descriptor. Getting a HID Report descriptor involves claiming the interface. Claiming the interface involves detaching the kernel driver. Detaching the kernel driver is hard on the system because it will unclaim interfaces (if another app has them claimed) and the re-attachment of the driver will sometimes change /dev entry names. It is for these reasons that this section is #if 0. For composite devices, use the interface field in the hid_device_info struct to distinguish between interfaces. */ unsigned char data[256]; #ifdef DETACH_KERNEL_DRIVER int detached = 0; /* Usage Page and Usage */ res = libusb_kernel_driver_active(handle, interface_num); if (res == 1) { res = libusb_detach_kernel_driver(handle, interface_num); if (res < 0) LOG("Couldn't detach kernel driver, even though a kernel driver was attached."); else detached = 1; } #endif res = libusb_claim_interface(handle, interface_num); if (res >= 0) { /* Get the HID Report Descriptor. */ res = libusb_control_transfer(handle, LIBUSB_ENDPOINT_IN|LIBUSB_RECIPIENT_INTERFACE, LIBUSB_REQUEST_GET_DESCRIPTOR, (LIBUSB_DT_REPORT << 8)|interface_num, 0, data, sizeof(data), 5000); if (res >= 0) { unsigned short page=0, usage=0; /* Parse the usage and usage page out of the report descriptor. */ get_usage(data, res, &page, &usage); cur_dev->usage_page = page; cur_dev->usage = usage; } else LOG("libusb_control_transfer() for getting the HID report failed with %d\n", res); /* Release the interface */ res = libusb_release_interface(handle, interface_num); if (res < 0) LOG("Can't release the interface.\n"); } else LOG("Can't claim interface %d\n", res); #ifdef DETACH_KERNEL_DRIVER /* Re-attach kernel driver if necessary. */ if (detached) { res = libusb_attach_kernel_driver(handle, interface_num); if (res < 0) LOG("Couldn't re-attach kernel driver.\n"); } #endif } #endif /* INVASIVE_GET_USAGE */ libusb_close(handle); } /* VID/PID */ cur_dev->vendor_id = dev_vid; cur_dev->product_id = dev_pid; /* Release Number */ cur_dev->release_number = desc.bcdDevice; /* Interface Number */ cur_dev->interface_number = interface_num; } } } /* altsettings */ } /* interfaces */ libusb_free_config_descriptor(conf_desc); } } libusb_free_device_list(devs, 1); return root; } void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) { struct hid_device_info *d = devs; while (d) { struct hid_device_info *next = d->next; free(d->path); free(d->serial_number); free(d->manufacturer_string); free(d->product_string); free(d); d = next; } } hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) { struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device *handle = NULL; devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; while (cur_dev) { if (cur_dev->vendor_id == vendor_id && cur_dev->product_id == product_id) { if (serial_number) { if (wcscmp(serial_number, cur_dev->serial_number) == 0) { path_to_open = cur_dev->path; break; } } else { path_to_open = cur_dev->path; break; } } cur_dev = cur_dev->next; } if (path_to_open) { /* Open the device */ handle = hid_open_path(path_to_open); } hid_free_enumeration(devs); return handle; } static void read_callback(struct libusb_transfer *transfer) { hid_device *dev = transfer->user_data; int res; if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { struct input_report *rpt = malloc(sizeof(*rpt)); rpt->data = malloc(transfer->actual_length); memcpy(rpt->data, transfer->buffer, transfer->actual_length); rpt->len = transfer->actual_length; rpt->next = NULL; pthread_mutex_lock(&dev->mutex); /* Attach the new report object to the end of the list. */ if (dev->input_reports == NULL) { /* The list is empty. Put it at the root. */ dev->input_reports = rpt; pthread_cond_signal(&dev->condition); } else { /* Find the end of the list and attach. */ struct input_report *cur = dev->input_reports; int num_queued = 0; while (cur->next != NULL) { cur = cur->next; num_queued++; } cur->next = rpt; /* Pop one off if we've reached 30 in the queue. This way we don't grow forever if the user never reads anything from the device. */ if (num_queued > 30) { return_data(dev, NULL, 0); } } pthread_mutex_unlock(&dev->mutex); } else if (transfer->status == LIBUSB_TRANSFER_CANCELLED) { dev->shutdown_thread = 1; return; } else if (transfer->status == LIBUSB_TRANSFER_NO_DEVICE) { dev->shutdown_thread = 1; return; } else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { //LOG("Timeout (normal)\n"); } else { LOG("Unknown transfer code: %d\n", transfer->status); } /* Re-submit the transfer object. */ res = libusb_submit_transfer(transfer); if (res != 0) { LOG("Unable to submit URB. libusb error code: %d\n", res); dev->shutdown_thread = 1; } } static void *read_thread(void *param) { hid_device *dev = param; unsigned char *buf; const size_t length = dev->input_ep_max_packet_size; /* Set up the transfer object. */ buf = malloc(length); dev->transfer = libusb_alloc_transfer(0); libusb_fill_interrupt_transfer(dev->transfer, dev->device_handle, dev->input_endpoint, buf, length, read_callback, dev, 5000/*timeout*/); /* Make the first submission. Further submissions are made from inside read_callback() */ libusb_submit_transfer(dev->transfer); /* Notify the main thread that the read thread is up and running. */ pthread_barrier_wait(&dev->barrier); /* Handle all the events. */ while (!dev->shutdown_thread) { int res; res = libusb_handle_events(usb_context); if (res < 0) { /* There was an error. */ LOG("read_thread(): libusb reports error # %d\n", res); /* Break out of this loop only on fatal error.*/ if (res != LIBUSB_ERROR_BUSY && res != LIBUSB_ERROR_TIMEOUT && res != LIBUSB_ERROR_OVERFLOW && res != LIBUSB_ERROR_INTERRUPTED) { break; } } } /* Cancel any transfer that may be pending. This call will fail if no transfers are pending, but that's OK. */ if (libusb_cancel_transfer(dev->transfer) == 0) { /* The transfer was cancelled, so wait for its completion. */ libusb_handle_events(usb_context); } /* Now that the read thread is stopping, Wake any threads which are waiting on data (in hid_read_timeout()). Do this under a mutex to make sure that a thread which is about to go to sleep waiting on the condition acutally will go to sleep before the condition is signaled. */ pthread_mutex_lock(&dev->mutex); pthread_cond_broadcast(&dev->condition); pthread_mutex_unlock(&dev->mutex); /* The dev->transfer->buffer and dev->transfer objects are cleaned up in hid_close(). They are not cleaned up here because this thread could end either due to a disconnect or due to a user call to hid_close(). In both cases the objects can be safely cleaned up after the call to pthread_join() (in hid_close()), but since hid_close() calls libusb_cancel_transfer(), on these objects, they can not be cleaned up here. */ return NULL; } hid_device * HID_API_EXPORT hid_open_path(const char *path) { hid_device *dev = NULL; libusb_device **devs; libusb_device *usb_dev; int res; int d = 0; int good_open = 0; dev = new_hid_device(); hid_init(); libusb_get_device_list(usb_context, &devs); while ((usb_dev = devs[d++]) != NULL) { struct libusb_device_descriptor desc; struct libusb_config_descriptor *conf_desc = NULL; int i,j,k; libusb_get_device_descriptor(usb_dev, &desc); if (libusb_get_active_config_descriptor(usb_dev, &conf_desc) < 0) continue; for (j = 0; j < conf_desc->bNumInterfaces; j++) { const struct libusb_interface *intf = &conf_desc->interface[j]; for (k = 0; k < intf->num_altsetting; k++) { const struct libusb_interface_descriptor *intf_desc; intf_desc = &intf->altsetting[k]; if (intf_desc->bInterfaceClass == LIBUSB_CLASS_HID) { char *dev_path = make_path(usb_dev, intf_desc->bInterfaceNumber); if (!strcmp(dev_path, path)) { /* Matched Paths. Open this device */ /* OPEN HERE */ res = libusb_open(usb_dev, &dev->device_handle); if (res < 0) { LOG("can't open device\n"); free(dev_path); break; } good_open = 1; #ifdef DETACH_KERNEL_DRIVER /* Detach the kernel driver, but only if the device is managed by the kernel */ if (libusb_kernel_driver_active(dev->device_handle, intf_desc->bInterfaceNumber) == 1) { res = libusb_detach_kernel_driver(dev->device_handle, intf_desc->bInterfaceNumber); if (res < 0) { libusb_close(dev->device_handle); LOG("Unable to detach Kernel Driver\n"); free(dev_path); good_open = 0; break; } } #endif res = libusb_claim_interface(dev->device_handle, intf_desc->bInterfaceNumber); if (res < 0) { LOG("can't claim interface %d: %d\n", intf_desc->bInterfaceNumber, res); free(dev_path); libusb_close(dev->device_handle); good_open = 0; break; } /* Store off the string descriptor indexes */ dev->manufacturer_index = desc.iManufacturer; dev->product_index = desc.iProduct; dev->serial_index = desc.iSerialNumber; /* Store off the interface number */ dev->interface = intf_desc->bInterfaceNumber; /* Find the INPUT and OUTPUT endpoints. An OUTPUT endpoint is not required. */ for (i = 0; i < intf_desc->bNumEndpoints; i++) { const struct libusb_endpoint_descriptor *ep = &intf_desc->endpoint[i]; /* Determine the type and direction of this endpoint. */ int is_interrupt = (ep->bmAttributes & LIBUSB_TRANSFER_TYPE_MASK) == LIBUSB_TRANSFER_TYPE_INTERRUPT; int is_output = (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT; int is_input = (ep->bEndpointAddress & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN; /* Decide whether to use it for intput or output. */ if (dev->input_endpoint == 0 && is_interrupt && is_input) { /* Use this endpoint for INPUT */ dev->input_endpoint = ep->bEndpointAddress; dev->input_ep_max_packet_size = ep->wMaxPacketSize; } if (dev->output_endpoint == 0 && is_interrupt && is_output) { /* Use this endpoint for OUTPUT */ dev->output_endpoint = ep->bEndpointAddress; } } pthread_create(&dev->thread, NULL, read_thread, dev); /* Wait here for the read thread to be initialized. */ pthread_barrier_wait(&dev->barrier); } free(dev_path); } } } libusb_free_config_descriptor(conf_desc); } libusb_free_device_list(devs, 1); /* If we have a good handle, return it. */ if (good_open) { return dev; } else { /* Unable to open any devices. */ free_hid_device(dev); return NULL; } } int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) { int res; int report_number = data[0]; int skipped_report_id = 0; if (report_number == 0x0) { data++; length--; skipped_report_id = 1; } if (dev->output_endpoint <= 0) { /* No interrput out endpoint. Use the Control Endpoint */ res = libusb_control_transfer(dev->device_handle, LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, 0x09/*HID Set_Report*/, (2/*HID output*/ << 8) | report_number, dev->interface, (unsigned char *)data, length, 1000/*timeout millis*/); if (res < 0) return -1; if (skipped_report_id) length++; return length; } else { /* Use the interrupt out endpoint */ int actual_length; res = libusb_interrupt_transfer(dev->device_handle, dev->output_endpoint, (unsigned char*)data, length, &actual_length, 1000); if (res < 0) return -1; if (skipped_report_id) actual_length++; return actual_length; } } /* Helper function, to simplify hid_read(). This should be called with dev->mutex locked. */ static int return_data(hid_device *dev, unsigned char *data, size_t length) { /* Copy the data out of the linked list item (rpt) into the return buffer (data), and delete the liked list item. */ struct input_report *rpt = dev->input_reports; size_t len = (length < rpt->len)? length: rpt->len; if (len > 0) memcpy(data, rpt->data, len); dev->input_reports = rpt->next; free(rpt->data); free(rpt); return len; } static void cleanup_mutex(void *param) { hid_device *dev = param; pthread_mutex_unlock(&dev->mutex); } int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) { int bytes_read = -1; #if 0 int transferred; int res = libusb_interrupt_transfer(dev->device_handle, dev->input_endpoint, data, length, &transferred, 5000); LOG("transferred: %d\n", transferred); return transferred; #endif pthread_mutex_lock(&dev->mutex); pthread_cleanup_push(&cleanup_mutex, dev); /* There's an input report queued up. Return it. */ if (dev->input_reports) { /* Return the first one */ bytes_read = return_data(dev, data, length); goto ret; } if (dev->shutdown_thread) { /* This means the device has been disconnected. An error code of -1 should be returned. */ bytes_read = -1; goto ret; } if (milliseconds == -1) { /* Blocking */ while (!dev->input_reports && !dev->shutdown_thread) { pthread_cond_wait(&dev->condition, &dev->mutex); } if (dev->input_reports) { bytes_read = return_data(dev, data, length); } } else if (milliseconds > 0) { /* Non-blocking, but called with timeout. */ int res; struct timespec ts; clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += milliseconds / 1000; ts.tv_nsec += (milliseconds % 1000) * 1000000; if (ts.tv_nsec >= 1000000000L) { ts.tv_sec++; ts.tv_nsec -= 1000000000L; } while (!dev->input_reports && !dev->shutdown_thread) { res = pthread_cond_timedwait(&dev->condition, &dev->mutex, &ts); if (res == 0) { if (dev->input_reports) { bytes_read = return_data(dev, data, length); break; } /* If we're here, there was a spurious wake up or the read thread was shutdown. Run the loop again (ie: don't break). */ } else if (res == ETIMEDOUT) { /* Timed out. */ bytes_read = 0; break; } else { /* Error. */ bytes_read = -1; break; } } } else { /* Purely non-blocking */ bytes_read = 0; } ret: pthread_mutex_unlock(&dev->mutex); pthread_cleanup_pop(0); return bytes_read; } int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) { return hid_read_timeout(dev, data, length, dev->blocking ? -1 : 0); } int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) { dev->blocking = !nonblock; return 0; } int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { int res = -1; int skipped_report_id = 0; int report_number = data[0]; if (report_number == 0x0) { data++; length--; skipped_report_id = 1; } res = libusb_control_transfer(dev->device_handle, LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_OUT, 0x09/*HID set_report*/, (3/*HID feature*/ << 8) | report_number, dev->interface, (unsigned char *)data, length, 1000/*timeout millis*/); if (res < 0) return -1; /* Account for the report ID */ if (skipped_report_id) length++; return length; } int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) { int res = -1; int skipped_report_id = 0; int report_number = data[0]; if (report_number == 0x0) { /* Offset the return buffer by 1, so that the report ID will remain in byte 0. */ data++; length--; skipped_report_id = 1; } res = libusb_control_transfer(dev->device_handle, LIBUSB_REQUEST_TYPE_CLASS|LIBUSB_RECIPIENT_INTERFACE|LIBUSB_ENDPOINT_IN, 0x01/*HID get_report*/, (3/*HID feature*/ << 8) | report_number, dev->interface, (unsigned char *)data, length, 1000/*timeout millis*/); if (res < 0) return -1; if (skipped_report_id) res++; return res; } void HID_API_EXPORT hid_close(hid_device *dev) { if (!dev) return; /* Cause read_thread() to stop. */ dev->shutdown_thread = 1; libusb_cancel_transfer(dev->transfer); /* Wait for read_thread() to end. */ pthread_join(dev->thread, NULL); /* Clean up the Transfer objects allocated in read_thread(). */ free(dev->transfer->buffer); libusb_free_transfer(dev->transfer); /* release the interface */ libusb_release_interface(dev->device_handle, dev->interface); /* Close the handle */ libusb_close(dev->device_handle); /* Clear out the queue of received reports. */ pthread_mutex_lock(&dev->mutex); while (dev->input_reports) { return_data(dev, NULL, 0); } pthread_mutex_unlock(&dev->mutex); free_hid_device(dev); } int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { return hid_get_indexed_string(dev, dev->manufacturer_index, string, maxlen); } int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { return hid_get_indexed_string(dev, dev->product_index, string, maxlen); } int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { return hid_get_indexed_string(dev, dev->serial_index, string, maxlen); } int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { wchar_t *str; str = get_usb_string(dev->device_handle, string_index); if (str) { wcsncpy(string, str, maxlen); string[maxlen-1] = L'\0'; free(str); return 0; } else return -1; } HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) { return NULL; } struct lang_map_entry { const char *name; const char *string_code; uint16_t usb_code; }; #define LANG(name,code,usb_code) { name, code, usb_code } static struct lang_map_entry lang_map[] = { LANG("Afrikaans", "af", 0x0436), LANG("Albanian", "sq", 0x041C), LANG("Arabic - United Arab Emirates", "ar_ae", 0x3801), LANG("Arabic - Bahrain", "ar_bh", 0x3C01), LANG("Arabic - Algeria", "ar_dz", 0x1401), LANG("Arabic - Egypt", "ar_eg", 0x0C01), LANG("Arabic - Iraq", "ar_iq", 0x0801), LANG("Arabic - Jordan", "ar_jo", 0x2C01), LANG("Arabic - Kuwait", "ar_kw", 0x3401), LANG("Arabic - Lebanon", "ar_lb", 0x3001), LANG("Arabic - Libya", "ar_ly", 0x1001), LANG("Arabic - Morocco", "ar_ma", 0x1801), LANG("Arabic - Oman", "ar_om", 0x2001), LANG("Arabic - Qatar", "ar_qa", 0x4001), LANG("Arabic - Saudi Arabia", "ar_sa", 0x0401), LANG("Arabic - Syria", "ar_sy", 0x2801), LANG("Arabic - Tunisia", "ar_tn", 0x1C01), LANG("Arabic - Yemen", "ar_ye", 0x2401), LANG("Armenian", "hy", 0x042B), LANG("Azeri - Latin", "az_az", 0x042C), LANG("Azeri - Cyrillic", "az_az", 0x082C), LANG("Basque", "eu", 0x042D), LANG("Belarusian", "be", 0x0423), LANG("Bulgarian", "bg", 0x0402), LANG("Catalan", "ca", 0x0403), LANG("Chinese - China", "zh_cn", 0x0804), LANG("Chinese - Hong Kong SAR", "zh_hk", 0x0C04), LANG("Chinese - Macau SAR", "zh_mo", 0x1404), LANG("Chinese - Singapore", "zh_sg", 0x1004), LANG("Chinese - Taiwan", "zh_tw", 0x0404), LANG("Croatian", "hr", 0x041A), LANG("Czech", "cs", 0x0405), LANG("Danish", "da", 0x0406), LANG("Dutch - Netherlands", "nl_nl", 0x0413), LANG("Dutch - Belgium", "nl_be", 0x0813), LANG("English - Australia", "en_au", 0x0C09), LANG("English - Belize", "en_bz", 0x2809), LANG("English - Canada", "en_ca", 0x1009), LANG("English - Caribbean", "en_cb", 0x2409), LANG("English - Ireland", "en_ie", 0x1809), LANG("English - Jamaica", "en_jm", 0x2009), LANG("English - New Zealand", "en_nz", 0x1409), LANG("English - Phillippines", "en_ph", 0x3409), LANG("English - Southern Africa", "en_za", 0x1C09), LANG("English - Trinidad", "en_tt", 0x2C09), LANG("English - Great Britain", "en_gb", 0x0809), LANG("English - United States", "en_us", 0x0409), LANG("Estonian", "et", 0x0425), LANG("Farsi", "fa", 0x0429), LANG("Finnish", "fi", 0x040B), LANG("Faroese", "fo", 0x0438), LANG("French - France", "fr_fr", 0x040C), LANG("French - Belgium", "fr_be", 0x080C), LANG("French - Canada", "fr_ca", 0x0C0C), LANG("French - Luxembourg", "fr_lu", 0x140C), LANG("French - Switzerland", "fr_ch", 0x100C), LANG("Gaelic - Ireland", "gd_ie", 0x083C), LANG("Gaelic - Scotland", "gd", 0x043C), LANG("German - Germany", "de_de", 0x0407), LANG("German - Austria", "de_at", 0x0C07), LANG("German - Liechtenstein", "de_li", 0x1407), LANG("German - Luxembourg", "de_lu", 0x1007), LANG("German - Switzerland", "de_ch", 0x0807), LANG("Greek", "el", 0x0408), LANG("Hebrew", "he", 0x040D), LANG("Hindi", "hi", 0x0439), LANG("Hungarian", "hu", 0x040E), LANG("Icelandic", "is", 0x040F), LANG("Indonesian", "id", 0x0421), LANG("Italian - Italy", "it_it", 0x0410), LANG("Italian - Switzerland", "it_ch", 0x0810), LANG("Japanese", "ja", 0x0411), LANG("Korean", "ko", 0x0412), LANG("Latvian", "lv", 0x0426), LANG("Lithuanian", "lt", 0x0427), LANG("F.Y.R.O. Macedonia", "mk", 0x042F), LANG("Malay - Malaysia", "ms_my", 0x043E), LANG("Malay – Brunei", "ms_bn", 0x083E), LANG("Maltese", "mt", 0x043A), LANG("Marathi", "mr", 0x044E), LANG("Norwegian - Bokml", "no_no", 0x0414), LANG("Norwegian - Nynorsk", "no_no", 0x0814), LANG("Polish", "pl", 0x0415), LANG("Portuguese - Portugal", "pt_pt", 0x0816), LANG("Portuguese - Brazil", "pt_br", 0x0416), LANG("Raeto-Romance", "rm", 0x0417), LANG("Romanian - Romania", "ro", 0x0418), LANG("Romanian - Republic of Moldova", "ro_mo", 0x0818), LANG("Russian", "ru", 0x0419), LANG("Russian - Republic of Moldova", "ru_mo", 0x0819), LANG("Sanskrit", "sa", 0x044F), LANG("Serbian - Cyrillic", "sr_sp", 0x0C1A), LANG("Serbian - Latin", "sr_sp", 0x081A), LANG("Setsuana", "tn", 0x0432), LANG("Slovenian", "sl", 0x0424), LANG("Slovak", "sk", 0x041B), LANG("Sorbian", "sb", 0x042E), LANG("Spanish - Spain (Traditional)", "es_es", 0x040A), LANG("Spanish - Argentina", "es_ar", 0x2C0A), LANG("Spanish - Bolivia", "es_bo", 0x400A), LANG("Spanish - Chile", "es_cl", 0x340A), LANG("Spanish - Colombia", "es_co", 0x240A), LANG("Spanish - Costa Rica", "es_cr", 0x140A), LANG("Spanish - Dominican Republic", "es_do", 0x1C0A), LANG("Spanish - Ecuador", "es_ec", 0x300A), LANG("Spanish - Guatemala", "es_gt", 0x100A), LANG("Spanish - Honduras", "es_hn", 0x480A), LANG("Spanish - Mexico", "es_mx", 0x080A), LANG("Spanish - Nicaragua", "es_ni", 0x4C0A), LANG("Spanish - Panama", "es_pa", 0x180A), LANG("Spanish - Peru", "es_pe", 0x280A), LANG("Spanish - Puerto Rico", "es_pr", 0x500A), LANG("Spanish - Paraguay", "es_py", 0x3C0A), LANG("Spanish - El Salvador", "es_sv", 0x440A), LANG("Spanish - Uruguay", "es_uy", 0x380A), LANG("Spanish - Venezuela", "es_ve", 0x200A), LANG("Southern Sotho", "st", 0x0430), LANG("Swahili", "sw", 0x0441), LANG("Swedish - Sweden", "sv_se", 0x041D), LANG("Swedish - Finland", "sv_fi", 0x081D), LANG("Tamil", "ta", 0x0449), LANG("Tatar", "tt", 0X0444), LANG("Thai", "th", 0x041E), LANG("Turkish", "tr", 0x041F), LANG("Tsonga", "ts", 0x0431), LANG("Ukrainian", "uk", 0x0422), LANG("Urdu", "ur", 0x0420), LANG("Uzbek - Cyrillic", "uz_uz", 0x0843), LANG("Uzbek – Latin", "uz_uz", 0x0443), LANG("Vietnamese", "vi", 0x042A), LANG("Xhosa", "xh", 0x0434), LANG("Yiddish", "yi", 0x043D), LANG("Zulu", "zu", 0x0435), LANG(NULL, NULL, 0x0), }; uint16_t get_usb_code_for_current_locale(void) { char *locale; char search_string[64]; char *ptr; struct lang_map_entry *lang; /* Get the current locale. */ locale = setlocale(0, NULL); if (!locale) return 0x0; /* Make a copy of the current locale string. */ strncpy(search_string, locale, sizeof(search_string)); search_string[sizeof(search_string)-1] = '\0'; /* Chop off the encoding part, and make it lower case. */ ptr = search_string; while (*ptr) { *ptr = tolower(*ptr); if (*ptr == '.') { *ptr = '\0'; break; } ptr++; } /* Find the entry which matches the string code of our locale. */ lang = lang_map; while (lang->string_code) { if (!strcmp(lang->string_code, search_string)) { return lang->usb_code; } lang++; } /* There was no match. Find with just the language only. */ /* Chop off the variant. Chop it off at the '_'. */ ptr = search_string; while (*ptr) { *ptr = tolower(*ptr); if (*ptr == '_') { *ptr = '\0'; break; } ptr++; } #if 0 /* TODO: Do we need this? */ /* Find the entry which matches the string code of our language. */ lang = lang_map; while (lang->string_code) { if (!strcmp(lang->string_code, search_string)) { return lang->usb_code; } lang++; } #endif /* Found nothing. */ return 0x0; } #ifdef __cplusplus } #endif open-zwave-1.5/cpp/hidapi/linux/000077500000000000000000000000001264474202400166365ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/linux/.gitignore000066400000000000000000000001241264474202400206230ustar00rootroot00000000000000Debug Release *.exp *.ilk *.lib *.suo *.vcproj.* *.ncb *.suo *.dll *.pdb *.o hidtestopen-zwave-1.5/cpp/hidapi/linux/Makefile-manual000066400000000000000000000017611264474202400215560ustar00rootroot00000000000000########################################### # Simple Makefile for HIDAPI test program # # Alan Ott # Signal 11 Software # 2010-06-01 ########################################### all: hidtest-hidraw libs libs: libhidapi-hidraw.so CC ?= gcc CFLAGS ?= -Wall -g -fpic CXX ?= g++ CXXFLAGS ?= -Wall -g -fpic LDFLAGS ?= -Wall -g COBJS = hid.o CPPOBJS = ../hidtest/hidtest.o OBJS = $(COBJS) $(CPPOBJS) LIBS_UDEV = `pkg-config libudev --libs` -lrt LIBS = $(LIBS_UDEV) INCLUDES ?= -I../hidapi `pkg-config libusb-1.0 --cflags` # Console Test Program hidtest-hidraw: $(COBJS) $(CPPOBJS) $(CXX) $(LDFLAGS) $^ $(LIBS_UDEV) -o $@ # Shared Libs libhidapi-hidraw.so: $(COBJS) $(CC) $(LDFLAGS) $(LIBS_UDEV) -shared -fpic -Wl,-soname,$@.0 $^ -o $@ # Objects $(COBJS): %.o: %.c $(CC) $(CFLAGS) -c $(INCLUDES) $< -o $@ $(CPPOBJS): %.o: %.cpp $(CXX) $(CXXFLAGS) -c $(INCLUDES) $< -o $@ clean: rm -f $(OBJS) hidtest-hidraw libhidapi-hidraw.so ../hidtest/hidtest.o .PHONY: clean libs open-zwave-1.5/cpp/hidapi/linux/Makefile.am000066400000000000000000000005011264474202400206660ustar00rootroot00000000000000lib_LTLIBRARIES = libhidapi-hidraw.la libhidapi_hidraw_la_SOURCES = hid.c libhidapi_hidraw_la_LDFLAGS = $(LTLDFLAGS) AM_CPPFLAGS = -I$(top_srcdir)/hidapi/ $(CFLAGS_HIDRAW) libhidapi_hidraw_la_LIBADD = $(LIBS_HIDRAW) hdrdir = $(includedir)/hidapi hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h EXTRA_DIST = Makefile-manual open-zwave-1.5/cpp/hidapi/linux/README.txt000066400000000000000000000057551264474202400203500ustar00rootroot00000000000000 There are two implementations of HIDAPI for Linux. One (hid.c) uses the Linux hidraw driver, and the other (hid-libusb.c) uses libusb. Which one you use depends on your application. Complete functionality of the hidraw version depends on patches to the Linux kernel which are not currently in the mainline. These patches have to do with sending and receiving feature reports. The libusb implementation uses libusb to talk directly to the device, bypassing any Linux HID driver. The disadvantage of the libusb version is that it will only work with USB devices, while the hidraw implementation will work with Bluetooth devices as well. To use HIDAPI, simply drop either hid.c or hid-libusb.c into your application and build using the build parameters in the Makefile. By default, on Linux, the Makefile in this directory is configured to use the libusb implementation. To switch to the hidraw implementation, simply change hid-libusb.c to hid.c in the Makefile. Libusb Implementation notes ---------------------------- For the libusb implementation, libusb-1.0 must be installed. Libusb 1.0 is different than the legacy libusb 0.1 which is installed on many systems. To install libusb-1.0 on Ubuntu and other Debian-based systems, run: sudo apt-get install libusb-1.0-0-dev Hidraw Implementation notes ---------------------------- For the hidraw implementation, libudev headers and libraries are required to build hidapi programs. To install libudev libraries on Ubuntu, and other Debian-based systems, run: sudo apt-get install libudev-dev On Redhat-based systems, run the following as root: yum install libudev-devel Unfortunately, the hidraw driver, which the linux version of hidapi is based on, contains bugs in kernel versions < 2.6.36, which the client application should be aware of. Bugs (hidraw implementation only): ----------------------------------- On Kernel versions < 2.6.34, if your device uses numbered reports, an extra byte will be returned at the beginning of all reports returned from read() for hidraw devices. This is worked around in the libary. No action should be necessary in the client library. On Kernel versions < 2.6.35, reports will only be sent using a Set_Report transfer on the CONTROL endpoint. No data will ever be sent on an Interrupt Out endpoint if one exists. This is fixed in 2.6.35. In 2.6.35, OUTPUT reports will be sent to the device on the first INTERRUPT OUT endpoint if it exists; If it does not exist, OUTPUT reports will be sent on the CONTROL endpoint. On Kernel versions < 2.6.36, add an extra byte containing the report number to sent reports if numbered reports are used, and the device does not contain an INTERRPUT OUT endpoint for OUTPUT transfers. For example, if your device uses numbered reports and wants to send {0x2 0xff 0xff 0xff} to the device (0x2 is the report number), you must send {0x2 0x2 0xff 0xff 0xff}. If your device has the optional Interrupt OUT endpoint, this does not apply (but really on 2.6.35 only, because 2.6.34 won't use the interrupt out endpoint). open-zwave-1.5/cpp/hidapi/linux/hid.c000066400000000000000000000461061264474202400175550ustar00rootroot00000000000000/******************************************************* HIDAPI - Multi-Platform library for communication with HID devices. Alan Ott Signal 11 Software 8/22/2009 Linux Version - 6/2/2009 Copyright 2009, All Rights Reserved. At the discretion of the user of this library, this software may be licensed under the terms of the GNU Public License v3, a BSD-Style license, or the original HIDAPI license as outlined in the LICENSE.txt, LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt files located at the root of the source distribution. These files may also be found in the public source code repository located at: http://github.com/signal11/hidapi . ********************************************************/ /* C */ #include #include #include #include #include /* Unix */ #include #include #include #include #include #include #include /* Linux */ #include #include #include #include #include "hidapi.h" /* Definitions from linux/hidraw.h. Since these are new, some distros may not have header files which contain them. */ #ifndef HIDIOCSFEATURE #define HIDIOCSFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x06, len) #endif #ifndef HIDIOCGFEATURE #define HIDIOCGFEATURE(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x07, len) #endif /* USB HID device property names */ const char *device_string_names[] = { "manufacturer", "product", "serial", }; /* Symbolic names for the properties above */ enum device_string_id { DEVICE_STRING_MANUFACTURER, DEVICE_STRING_PRODUCT, DEVICE_STRING_SERIAL, DEVICE_STRING_COUNT, }; struct hid_device_ { int device_handle; int blocking; int uses_numbered_reports; }; static __u32 kernel_version = 0; static hid_device *new_hid_device(void) { hid_device *dev = calloc(1, sizeof(hid_device)); dev->device_handle = -1; dev->blocking = 1; dev->uses_numbered_reports = 0; return dev; } /* The caller must free the returned string with free(). */ static wchar_t *utf8_to_wchar_t(const char *utf8) { wchar_t *ret = NULL; if (utf8) { size_t wlen = mbstowcs(NULL, utf8, 0); if ((size_t) -1 == wlen) { return wcsdup(L""); } ret = calloc(wlen+1, sizeof(wchar_t)); mbstowcs(ret, utf8, wlen+1); ret[wlen] = 0x0000; } return ret; } /* Get an attribute value from a udev_device and return it as a whar_t string. The returned string must be freed with free() when done.*/ static wchar_t *copy_udev_string(struct udev_device *dev, const char *udev_name) { return utf8_to_wchar_t(udev_device_get_sysattr_value(dev, udev_name)); } /* uses_numbered_reports() returns 1 if report_descriptor describes a device which contains numbered reports. */ static int uses_numbered_reports(__u8 *report_descriptor, __u32 size) { unsigned int i = 0; int size_code; int data_len, key_size; while (i < size) { int key = report_descriptor[i]; /* Check for the Report ID key */ if (key == 0x85/*Report ID*/) { /* This device has a Report ID, which means it uses numbered reports. */ return 1; } //printf("key: %02hhx\n", key); if ((key & 0xf0) == 0xf0) { /* This is a Long Item. The next byte contains the length of the data section (value) for this key. See the HID specification, version 1.11, section 6.2.2.3, titled "Long Items." */ if (i+1 < size) data_len = report_descriptor[i+1]; else data_len = 0; /* malformed report */ key_size = 3; } else { /* This is a Short Item. The bottom two bits of the key contain the size code for the data section (value) for this key. Refer to the HID specification, version 1.11, section 6.2.2.2, titled "Short Items." */ size_code = key & 0x3; switch (size_code) { case 0: case 1: case 2: data_len = size_code; break; case 3: data_len = 4; break; default: /* Can't ever happen since size_code is & 0x3 */ data_len = 0; break; }; key_size = 1; } /* Skip over this key and it's associated data */ i += data_len + key_size; } /* Didn't find a Report ID key. Device doesn't use numbered reports. */ return 0; } /* * The caller is responsible for free()ing the (newly-allocated) character * strings pointed to by serial_number_utf8 and product_name_utf8 after use. */ static int parse_uevent_info(const char *uevent, int *bus_type, unsigned short *vendor_id, unsigned short *product_id, char **serial_number_utf8, char **product_name_utf8) { char *tmp = strdup(uevent); char *saveptr = NULL; char *line; char *key; char *value; int found_id = 0; int found_serial = 0; int found_name = 0; line = strtok_r(tmp, "\n", &saveptr); while (line != NULL) { /* line: "KEY=value" */ key = line; value = strchr(line, '='); if (!value) { goto next_line; } *value = '\0'; value++; if (strcmp(key, "HID_ID") == 0) { /** * type vendor product * HID_ID=0003:000005AC:00008242 **/ int ret = sscanf(value, "%x:%hx:%hx", bus_type, vendor_id, product_id); if (ret == 3) { found_id = 1; } } else if (strcmp(key, "HID_NAME") == 0) { /* The caller has to free the product name */ *product_name_utf8 = strdup(value); found_name = 1; } else if (strcmp(key, "HID_UNIQ") == 0) { /* The caller has to free the serial number */ *serial_number_utf8 = strdup(value); found_serial = 1; } next_line: line = strtok_r(NULL, "\n", &saveptr); } free(tmp); return (found_id && found_name && found_serial); } static int get_device_string(hid_device *dev, enum device_string_id key, wchar_t *string, size_t maxlen) { struct udev *udev; struct udev_device *udev_dev, *parent, *hid_dev; struct stat s; int ret = -1; char *serial_number_utf8 = NULL; char *product_name_utf8 = NULL; /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); return -1; } /* Get the dev_t (major/minor numbers) from the file handle. */ fstat(dev->device_handle, &s); /* Open a udev device from the dev_t. 'c' means character device. */ udev_dev = udev_device_new_from_devnum(udev, 'c', s.st_rdev); if (udev_dev) { hid_dev = udev_device_get_parent_with_subsystem_devtype( udev_dev, "hid", NULL); if (hid_dev) { unsigned short dev_vid; unsigned short dev_pid; int bus_type; size_t retm; ret = parse_uevent_info( udev_device_get_sysattr_value(hid_dev, "uevent"), &bus_type, &dev_vid, &dev_pid, &serial_number_utf8, &product_name_utf8); if (bus_type == BUS_BLUETOOTH) { switch (key) { case DEVICE_STRING_MANUFACTURER: wcsncpy(string, L"", maxlen); ret = 0; break; case DEVICE_STRING_PRODUCT: retm = mbstowcs(string, product_name_utf8, maxlen); ret = (retm == (size_t)-1)? -1: 0; break; case DEVICE_STRING_SERIAL: retm = mbstowcs(string, serial_number_utf8, maxlen); ret = (retm == (size_t)-1)? -1: 0; break; case DEVICE_STRING_COUNT: default: ret = -1; break; } } else { /* This is a USB device. Find its parent USB Device node. */ parent = udev_device_get_parent_with_subsystem_devtype( udev_dev, "usb", "usb_device"); if (parent) { const char *str; const char *key_str = NULL; if (key >= 0 && key < DEVICE_STRING_COUNT) { key_str = device_string_names[key]; } else { ret = -1; goto end; } str = udev_device_get_sysattr_value(parent, key_str); if (str) { /* Convert the string from UTF-8 to wchar_t */ retm = mbstowcs(string, str, maxlen); ret = (retm == (size_t)-1)? -1: 0; goto end; } } } } } end: free(serial_number_utf8); free(product_name_utf8); udev_device_unref(udev_dev); /* parent and hid_dev don't need to be (and can't be) unref'd. I'm not sure why, but they'll throw double-free() errors. */ udev_unref(udev); return ret; } int HID_API_EXPORT hid_init(void) { /* Refer to http://code.google.com/p/open-zwave/issues/detail?id=254 * We should not be setting the Locale and let the application set it */ // const char *locale; /* Set the locale if it's not set. */ // locale = setlocale(LC_CTYPE, NULL); // if (!locale) // setlocale(LC_CTYPE, ""); return 0; } int HID_API_EXPORT hid_exit(void) { /* Nothing to do for this in the Linux/hidraw implementation. */ return 0; } struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct udev *udev; struct udev_enumerate *enumerate; struct udev_list_entry *devices, *dev_list_entry; struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; struct hid_device_info *prev_dev = NULL; /* previous device */ hid_init(); /* Create the udev object */ udev = udev_new(); if (!udev) { printf("Can't create udev\n"); return NULL; } /* Create a list of the devices in the 'hidraw' subsystem. */ enumerate = udev_enumerate_new(udev); udev_enumerate_add_match_subsystem(enumerate, "hidraw"); udev_enumerate_scan_devices(enumerate); devices = udev_enumerate_get_list_entry(enumerate); /* For each item, see if it matches the vid/pid, and if so create a udev_device record for it */ udev_list_entry_foreach(dev_list_entry, devices) { const char *sysfs_path; const char *dev_path; const char *str; struct udev_device *raw_dev; /* The device's hidraw udev node. */ struct udev_device *hid_dev; /* The device's HID udev node. */ struct udev_device *usb_dev; /* The device's USB udev node. */ struct udev_device *intf_dev; /* The device's interface (in the USB sense). */ unsigned short dev_vid; unsigned short dev_pid; char *serial_number_utf8 = NULL; char *product_name_utf8 = NULL; int bus_type; int result; /* Get the filename of the /sys entry for the device and create a udev_device object (dev) representing it */ sysfs_path = udev_list_entry_get_name(dev_list_entry); raw_dev = udev_device_new_from_syspath(udev, sysfs_path); dev_path = udev_device_get_devnode(raw_dev); hid_dev = udev_device_get_parent_with_subsystem_devtype( raw_dev, "hid", NULL); if (!hid_dev) { /* Unable to find parent hid device. */ goto next; } result = parse_uevent_info( udev_device_get_sysattr_value(hid_dev, "uevent"), &bus_type, &dev_vid, &dev_pid, &serial_number_utf8, &product_name_utf8); if (!result) { /* parse_uevent_info() failed for at least one field. */ goto next; } if (bus_type != BUS_USB && bus_type != BUS_BLUETOOTH) { /* We only know how to handle USB and BT devices. */ goto next; } /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 || vendor_id == dev_vid) && (product_id == 0x0 || product_id == dev_pid)) { struct hid_device_info *tmp; /* VID/PID match. Create the record. */ tmp = malloc(sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } prev_dev = cur_dev; cur_dev = tmp; /* Fill out the record */ cur_dev->next = NULL; cur_dev->path = dev_path? strdup(dev_path): NULL; /* VID/PID */ cur_dev->vendor_id = dev_vid; cur_dev->product_id = dev_pid; /* Serial Number */ cur_dev->serial_number = utf8_to_wchar_t(serial_number_utf8); /* Release Number */ cur_dev->release_number = 0x0; /* Interface Number */ cur_dev->interface_number = -1; switch (bus_type) { case BUS_USB: /* The device pointed to by raw_dev contains information about the hidraw device. In order to get information about the USB device, get the parent device with the subsystem/devtype pair of "usb"/"usb_device". This will be several levels up the tree, but the function will find it. */ usb_dev = udev_device_get_parent_with_subsystem_devtype( raw_dev, "usb", "usb_device"); if (!usb_dev) { /* Free this device */ free(cur_dev->serial_number); free(cur_dev->path); free(cur_dev); /* Take it off the device list. */ if (prev_dev) { prev_dev->next = NULL; cur_dev = prev_dev; } else { cur_dev = root = NULL; } goto next; } /* Manufacturer and Product strings */ cur_dev->manufacturer_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_MANUFACTURER]); cur_dev->product_string = copy_udev_string(usb_dev, device_string_names[DEVICE_STRING_PRODUCT]); /* Release Number */ str = udev_device_get_sysattr_value(usb_dev, "bcdDevice"); cur_dev->release_number = (str)? strtol(str, NULL, 16): 0x0; /* Get a handle to the interface's udev node. */ intf_dev = udev_device_get_parent_with_subsystem_devtype( raw_dev, "usb", "usb_interface"); if (intf_dev) { str = udev_device_get_sysattr_value(intf_dev, "bInterfaceNumber"); cur_dev->interface_number = (str)? strtol(str, NULL, 16): -1; } break; case BUS_BLUETOOTH: /* Manufacturer and Product strings */ cur_dev->manufacturer_string = wcsdup(L""); cur_dev->product_string = utf8_to_wchar_t(product_name_utf8); break; default: /* Unknown device type - this should never happen, as we * check for USB and Bluetooth devices above */ break; } } next: free(serial_number_utf8); free(product_name_utf8); udev_device_unref(raw_dev); /* hid_dev, usb_dev and intf_dev don't need to be (and can't be) unref()d. It will cause a double-free() error. I'm not sure why. */ } /* Free the enumerator and udev objects. */ udev_enumerate_unref(enumerate); udev_unref(udev); return root; } void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) { struct hid_device_info *d = devs; while (d) { struct hid_device_info *next = d->next; free(d->path); free(d->serial_number); free(d->manufacturer_string); free(d->product_string); free(d); d = next; } } hid_device * hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) { struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device *handle = NULL; devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; while (cur_dev) { if (cur_dev->vendor_id == vendor_id && cur_dev->product_id == product_id) { if (serial_number) { if (wcscmp(serial_number, cur_dev->serial_number) == 0) { path_to_open = cur_dev->path; break; } } else { path_to_open = cur_dev->path; break; } } cur_dev = cur_dev->next; } if (path_to_open) { /* Open the device */ handle = hid_open_path(path_to_open); } hid_free_enumeration(devs); return handle; } hid_device * HID_API_EXPORT hid_open_path(const char *path) { hid_device *dev = NULL; hid_init(); dev = new_hid_device(); if (kernel_version == 0) { struct utsname name; int major, minor, release; int ret; uname(&name); ret = sscanf(name.release, "%d.%d.%d", &major, &minor, &release); if (ret == 3) { kernel_version = major << 16 | minor << 8 | release; //printf("Kernel Version: %d\n", kernel_version); } else { printf("Couldn't sscanf() version string %s\n", name.release); } } /* OPEN HERE */ dev->device_handle = open(path, O_RDWR); /* If we have a good handle, return it. */ if (dev->device_handle > 0) { /* Get the report descriptor */ int res, desc_size = 0; struct hidraw_report_descriptor rpt_desc; memset(&rpt_desc, 0x0, sizeof(rpt_desc)); /* Get Report Descriptor Size */ res = ioctl(dev->device_handle, HIDIOCGRDESCSIZE, &desc_size); if (res < 0) perror("HIDIOCGRDESCSIZE"); /* Get Report Descriptor */ rpt_desc.size = desc_size; res = ioctl(dev->device_handle, HIDIOCGRDESC, &rpt_desc); if (res < 0) { perror("HIDIOCGRDESC"); } else { /* Determine if this device uses numbered reports. */ dev->uses_numbered_reports = uses_numbered_reports(rpt_desc.value, rpt_desc.size); } return dev; } else { /* Unable to open any devices. */ free(dev); return NULL; } } int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) { int bytes_written; bytes_written = write(dev->device_handle, data, length); return bytes_written; } int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) { int bytes_read; if (milliseconds != 0) { /* milliseconds is -1 or > 0. In both cases, we want to call poll() and wait for data to arrive. -1 means INFINITE. */ int ret; struct pollfd fds; fds.fd = dev->device_handle; fds.events = POLLIN; fds.revents = 0; ret = poll(&fds, 1, milliseconds); if (ret == -1 || ret == 0) /* Error or timeout */ return ret; } bytes_read = read(dev->device_handle, data, length); if (bytes_read < 0 && (errno == EAGAIN || errno == EINPROGRESS)) bytes_read = 0; if (bytes_read >= 0 && kernel_version < KERNEL_VERSION(2,6,34) && dev->uses_numbered_reports) { /* Work around a kernel bug. Chop off the first byte. */ memmove(data, data+1, bytes_read); bytes_read--; } return bytes_read; } int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) { return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); } int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) { int flags, res; flags = fcntl(dev->device_handle, F_GETFL, 0); if (flags >= 0) { if (nonblock) res = fcntl(dev->device_handle, F_SETFL, flags | O_NONBLOCK); else res = fcntl(dev->device_handle, F_SETFL, flags & ~O_NONBLOCK); } else return -1; if (res < 0) { return -1; } else { dev->blocking = !nonblock; return 0; /* Success */ } } int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { int res; res = ioctl(dev->device_handle, HIDIOCSFEATURE(length), data); if (res < 0) perror("ioctl (SFEATURE)"); return res; } int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) { int res; res = ioctl(dev->device_handle, HIDIOCGFEATURE(length), data); if (res < 0) perror("ioctl (GFEATURE)"); return res; } void HID_API_EXPORT hid_close(hid_device *dev) { if (!dev) return; close(dev->device_handle); free(dev); } int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { return get_device_string(dev, DEVICE_STRING_MANUFACTURER, string, maxlen); } int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { return get_device_string(dev, DEVICE_STRING_PRODUCT, string, maxlen); } int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { return get_device_string(dev, DEVICE_STRING_SERIAL, string, maxlen); } int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { return -1; } HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) { return NULL; } open-zwave-1.5/cpp/hidapi/m4/000077500000000000000000000000001264474202400160175ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/m4/ax_pthread.m4000066400000000000000000000303661264474202400204100ustar00rootroot00000000000000# =========================================================================== # http://www.gnu.org/software/autoconf-archive/ax_pthread.html # =========================================================================== # # SYNOPSIS # # AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]]) # # DESCRIPTION # # This macro figures out how to build C programs using POSIX threads. It # sets the PTHREAD_LIBS output variable to the threads library and linker # flags, and the PTHREAD_CFLAGS output variable to any special C compiler # flags that are needed. (The user can also force certain compiler # flags/libs to be tested by setting these environment variables.) # # Also sets PTHREAD_CC to any special C compiler that is needed for # multi-threaded programs (defaults to the value of CC otherwise). (This # is necessary on AIX to use the special cc_r compiler alias.) # # NOTE: You are assumed to not only compile your program with these flags, # but also link it with them as well. e.g. you should link with # $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS # # If you are only building threads programs, you may wish to use these # variables in your default LIBS, CFLAGS, and CC: # # LIBS="$PTHREAD_LIBS $LIBS" # CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # CC="$PTHREAD_CC" # # In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant # has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name # (e.g. PTHREAD_CREATE_UNDETACHED on AIX). # # Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the # PTHREAD_PRIO_INHERIT symbol is defined when compiling with # PTHREAD_CFLAGS. # # ACTION-IF-FOUND is a list of shell commands to run if a threads library # is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it # is not found. If ACTION-IF-FOUND is not specified, the default action # will define HAVE_PTHREAD. # # Please let the authors know if this macro fails on any platform, or if # you have any other suggestions or comments. This macro was based on work # by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help # from M. Frigo), as well as ac_pthread and hb_pthread macros posted by # Alejandro Forero Cuervo to the autoconf macro repository. We are also # grateful for the helpful feedback of numerous users. # # Updated for Autoconf 2.68 by Daniel Richard G. # # LICENSE # # Copyright (c) 2008 Steven G. Johnson # Copyright (c) 2011 Daniel Richard G. # # This program is free software: you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation, either version 3 of the License, or (at your # option) any later version. # # This program 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 General # Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program. If not, see . # # As a special exception, the respective Autoconf Macro's copyright owner # gives unlimited permission to copy, distribute and modify the configure # scripts that are the output of Autoconf when processing the Macro. You # need not follow the terms of the GNU General Public License when using # or distributing such scripts, even though portions of the text of the # Macro appear in them. The GNU General Public License (GPL) does govern # all other use of the material that constitutes the Autoconf Macro. # # This special exception to the GPL applies to versions of the Autoconf # Macro released by the Autoconf Archive. When you make and distribute a # modified version of the Autoconf Macro, you may extend this special # exception to the GPL to apply to your modified version as well. #serial 18 AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD]) AC_DEFUN([AX_PTHREAD], [ AC_REQUIRE([AC_CANONICAL_HOST]) AC_LANG_PUSH([C]) ax_pthread_ok=no # We used to check for pthread.h first, but this fails if pthread.h # requires special compiler flags (e.g. on True64 or Sequent). # It gets checked for in the link test anyway. # First of all, check if the user has set any of the PTHREAD_LIBS, # etcetera environment variables, and if threads linking works using # them: if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS]) AC_TRY_LINK_FUNC(pthread_join, ax_pthread_ok=yes) AC_MSG_RESULT($ax_pthread_ok) if test x"$ax_pthread_ok" = xno; then PTHREAD_LIBS="" PTHREAD_CFLAGS="" fi LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" fi # We must check for the threads library under a number of different # names; the ordering is very important because some systems # (e.g. DEC) have both -lpthread and -lpthreads, where one of the # libraries is broken (non-POSIX). # Create a list of thread flags to try. Items starting with a "-" are # C compiler flags, and other items are library names, except for "none" # which indicates that we try without any flags at all, and "pthread-config" # which is a program returning the flags for the Pth emulation library. ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config" # The ordering *is* (sometimes) important. Some notes on the # individual items follow: # pthreads: AIX (must check this before -lpthread) # none: in case threads are in libc; should be tried before -Kthread and # other compiler flags to prevent continual compiler warnings # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) # lthread: LinuxThreads port on FreeBSD (also preferred to -pthread) # -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads) # -pthreads: Solaris/gcc # -mthreads: Mingw32/gcc, Lynx/gcc # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it # doesn't hurt to check since this sometimes defines pthreads too; # also defines -D_REENTRANT) # ... -mt is also the pthreads flag for HP/aCC # pthread: Linux, etcetera # --thread-safe: KAI C++ # pthread-config: use pthread-config program (for GNU Pth library) case ${host_os} in solaris*) # On Solaris (at least, for some versions), libc contains stubbed # (non-functional) versions of the pthreads routines, so link-based # tests will erroneously succeed. (We need to link with -pthreads/-mt/ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather # a function called by this macro, so we could check for that, but # who knows whether they'll stub that too in a future libc.) So, # we'll just look for -pthreads and -lpthread first: ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags" ;; darwin*) ax_pthread_flags="-pthread $ax_pthread_flags" ;; esac if test x"$ax_pthread_ok" = xno; then for flag in $ax_pthread_flags; do case $flag in none) AC_MSG_CHECKING([whether pthreads work without any flags]) ;; -*) AC_MSG_CHECKING([whether pthreads work with $flag]) PTHREAD_CFLAGS="$flag" ;; pthread-config) AC_CHECK_PROG(ax_pthread_config, pthread-config, yes, no) if test x"$ax_pthread_config" = xno; then continue; fi PTHREAD_CFLAGS="`pthread-config --cflags`" PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`" ;; *) AC_MSG_CHECKING([for the pthreads library -l$flag]) PTHREAD_LIBS="-l$flag" ;; esac save_LIBS="$LIBS" save_CFLAGS="$CFLAGS" LIBS="$PTHREAD_LIBS $LIBS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Check for various functions. We must include pthread.h, # since some functions may be macros. (On the Sequent, we # need a special flag -Kthread to make this header compile.) # We check for pthread_join because it is in -lpthread on IRIX # while pthread_create is in libc. We check for pthread_attr_init # due to DEC craziness with -lpthreads. We check for # pthread_cleanup_push because it is one of the few pthread # functions on Solaris that doesn't have a non-functional libc stub. # We try pthread_create on general principles. AC_LINK_IFELSE([AC_LANG_PROGRAM([#include static void routine(void *a) { a = 0; } static void *start_routine(void *a) { return a; }], [pthread_t th; pthread_attr_t attr; pthread_create(&th, 0, start_routine, 0); pthread_join(th, 0); pthread_attr_init(&attr); pthread_cleanup_push(routine, 0); pthread_cleanup_pop(0) /* ; */])], [ax_pthread_ok=yes], []) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" AC_MSG_RESULT($ax_pthread_ok) if test "x$ax_pthread_ok" = xyes; then break; fi PTHREAD_LIBS="" PTHREAD_CFLAGS="" done fi # Various other checks: if test "x$ax_pthread_ok" = xyes; then save_LIBS="$LIBS" LIBS="$PTHREAD_LIBS $LIBS" save_CFLAGS="$CFLAGS" CFLAGS="$CFLAGS $PTHREAD_CFLAGS" # Detect AIX lossage: JOINABLE attribute is called UNDETACHED. AC_MSG_CHECKING([for joinable pthread attribute]) attr_name=unknown for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do AC_LINK_IFELSE([AC_LANG_PROGRAM([#include ], [int attr = $attr; return attr /* ; */])], [attr_name=$attr; break], []) done AC_MSG_RESULT($attr_name) if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then AC_DEFINE_UNQUOTED(PTHREAD_CREATE_JOINABLE, $attr_name, [Define to necessary symbol if this constant uses a non-standard name on your system.]) fi AC_MSG_CHECKING([if more special flags are required for pthreads]) flag=no case ${host_os} in aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";; osf* | hpux*) flag="-D_REENTRANT";; solaris*) if test "$GCC" = "yes"; then flag="-D_REENTRANT" else flag="-mt -D_REENTRANT" fi ;; esac AC_MSG_RESULT(${flag}) if test "x$flag" != xno; then PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS" fi AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT], ax_cv_PTHREAD_PRIO_INHERIT, [ AC_LINK_IFELSE([ AC_LANG_PROGRAM([[#include ]], [[int i = PTHREAD_PRIO_INHERIT;]])], [ax_cv_PTHREAD_PRIO_INHERIT=yes], [ax_cv_PTHREAD_PRIO_INHERIT=no]) ]) AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"], AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], 1, [Have PTHREAD_PRIO_INHERIT.])) LIBS="$save_LIBS" CFLAGS="$save_CFLAGS" # More AIX lossage: must compile with xlc_r or cc_r if test x"$GCC" != xyes; then AC_CHECK_PROGS(PTHREAD_CC, xlc_r cc_r, ${CC}) else PTHREAD_CC=$CC fi else PTHREAD_CC="$CC" fi AC_SUBST(PTHREAD_LIBS) AC_SUBST(PTHREAD_CFLAGS) AC_SUBST(PTHREAD_CC) # Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND: if test x"$ax_pthread_ok" = xyes; then ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1]) : else ax_pthread_ok=no $2 fi AC_LANG_POP ])dnl AX_PTHREAD open-zwave-1.5/cpp/hidapi/m4/pkg.m4000066400000000000000000000121451264474202400170450ustar00rootroot00000000000000# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- # # Copyright © 2004 Scott James Remnant . # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program 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 # General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a # configuration script generated by Autoconf, you may include it under # the same distribution terms that you use for the rest of that program. # PKG_PROG_PKG_CONFIG([MIN-VERSION]) # ---------------------------------- AC_DEFUN([PKG_PROG_PKG_CONFIG], [m4_pattern_forbid([^_?PKG_[A-Z_]+$]) m4_pattern_allow([^PKG_CONFIG(_PATH)?$]) AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) fi if test -n "$PKG_CONFIG"; then _pkg_min_version=m4_default([$1], [0.9.0]) AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no]) PKG_CONFIG="" fi fi[]dnl ])# PKG_PROG_PKG_CONFIG # PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) # # Check to see whether a particular set of modules exists. Similar # to PKG_CHECK_MODULES(), but does not set variables or print errors. # # # Similar to PKG_CHECK_MODULES, make sure that the first instance of # this or PKG_CHECK_MODULES is called, or make sure to call # PKG_CHECK_EXISTS manually # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_EXISTS], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl if test -n "$PKG_CONFIG" && \ AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then m4_ifval([$2], [$2], [:]) m4_ifvaln([$3], [else $3])dnl fi]) # _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) # --------------------------------------------- m4_define([_PKG_CONFIG], [if test -n "$PKG_CONFIG"; then if test -n "$$1"; then pkg_cv_[]$1="$$1" else PKG_CHECK_EXISTS([$3], [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`], [pkg_failed=yes]) fi else pkg_failed=untried fi[]dnl ])# _PKG_CONFIG # _PKG_SHORT_ERRORS_SUPPORTED # ----------------------------- AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], [AC_REQUIRE([PKG_PROG_PKG_CONFIG]) if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then _pkg_short_errors_supported=yes else _pkg_short_errors_supported=no fi[]dnl ])# _PKG_SHORT_ERRORS_SUPPORTED # PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], # [ACTION-IF-NOT-FOUND]) # # # Note that if there is a possibility the first call to # PKG_CHECK_MODULES might not happen, you should be sure to include an # explicit call to PKG_PROG_PKG_CONFIG in your configure.ac # # # -------------------------------------------------------------- AC_DEFUN([PKG_CHECK_MODULES], [AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl pkg_failed=no AC_MSG_CHECKING([for $1]) _PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) _PKG_CONFIG([$1][_LIBS], [libs], [$2]) m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS and $1[]_LIBS to avoid the need to call pkg-config. See the pkg-config man page for more details.]) if test $pkg_failed = yes; then _PKG_SHORT_ERRORS_SUPPORTED if test $_pkg_short_errors_supported = yes; then $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "$2"` else $1[]_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"` fi # Put the nasty error message in config.log where it belongs echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD ifelse([$4], , [AC_MSG_ERROR(dnl [Package requirements ($2) were not met: $$1_PKG_ERRORS Consider adjusting the PKG_CONFIG_PATH environment variable if you installed software in a non-standard prefix. _PKG_TEXT ])], [AC_MSG_RESULT([no]) $4]) elif test $pkg_failed = untried; then ifelse([$4], , [AC_MSG_FAILURE(dnl [The pkg-config script could not be found or is too old. Make sure it is in your PATH or set the PKG_CONFIG environment variable to the full path to pkg-config. _PKG_TEXT To get pkg-config, see .])], [$4]) else $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS $1[]_LIBS=$pkg_cv_[]$1[]_LIBS AC_MSG_RESULT([yes]) ifelse([$3], , :, [$3]) fi[]dnl ])# PKG_CHECK_MODULES open-zwave-1.5/cpp/hidapi/mac/000077500000000000000000000000001264474202400162375ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/mac/.gitignore000066400000000000000000000001241264474202400202240ustar00rootroot00000000000000Debug Release *.exp *.ilk *.lib *.suo *.vcproj.* *.ncb *.suo *.dll *.pdb *.o hidtestopen-zwave-1.5/cpp/hidapi/mac/Makefile-manual000066400000000000000000000010571264474202400211550ustar00rootroot00000000000000########################################### # Simple Makefile for HIDAPI test program # # Alan Ott # Signal 11 Software # 2010-07-03 ########################################### all: hidtest CC=gcc CXX=g++ COBJS=hid.o CPPOBJS=../hidtest/hidtest.o OBJS=$(COBJS) $(CPPOBJS) CFLAGS+=-I../hidapi -Wall -g -c LIBS=-framework IOKit -framework CoreFoundation hidtest: $(OBJS) g++ -Wall -g $^ $(LIBS) -o hidtest $(COBJS): %.o: %.c $(CC) $(CFLAGS) $< -o $@ $(CPPOBJS): %.o: %.cpp $(CXX) $(CFLAGS) $< -o $@ clean: rm -f *.o hidtest $(CPPOBJS) .PHONY: clean open-zwave-1.5/cpp/hidapi/mac/Makefile.am000066400000000000000000000003571264474202400203000ustar00rootroot00000000000000lib_LTLIBRARIES = libhidapi.la libhidapi_la_SOURCES = hid.c libhidapi_la_LDFLAGS = $(LTLDFLAGS) AM_CPPFLAGS = -I$(top_srcdir)/hidapi/ hdrdir = $(includedir)/hidapi hdr_HEADERS = $(top_srcdir)/hidapi/hidapi.h EXTRA_DIST = Makefile-manual open-zwave-1.5/cpp/hidapi/mac/hid.c000066400000000000000000000673151264474202400171630ustar00rootroot00000000000000/******************************************************* HIDAPI - Multi-Platform library for communication with HID devices. Alan Ott Signal 11 Software 2010-07-03 Copyright 2010, All Rights Reserved. At the discretion of the user of this library, this software may be licensed under the terms of the GNU Public License v3, a BSD-Style license, or the original HIDAPI license as outlined in the LICENSE.txt, LICENSE-gpl3.txt, LICENSE-bsd.txt, and LICENSE-orig.txt files located at the root of the source distribution. These files may also be found in the public source code repository located at: http://github.com/signal11/hidapi . ********************************************************/ /* See Apple Technical Note TN2187 for details on IOHidManager. */ #include #include #include #include #include #include #include #include #include "hidapi.h" /* Barrier implementation because Mac OSX doesn't have pthread_barrier. It also doesn't have clock_gettime(). So much for POSIX and SUSv2. This implementation came from Brent Priddy and was posted on StackOverflow. It is used with his permission. */ typedef int pthread_barrierattr_t; typedef struct pthread_barrier { pthread_mutex_t mutex; pthread_cond_t cond; int count; int trip_count; } pthread_barrier_t; static int pthread_barrier_init(pthread_barrier_t *barrier, const pthread_barrierattr_t *attr, unsigned int count) { if(count == 0) { errno = EINVAL; return -1; } if(pthread_mutex_init(&barrier->mutex, 0) < 0) { return -1; } if(pthread_cond_init(&barrier->cond, 0) < 0) { pthread_mutex_destroy(&barrier->mutex); return -1; } barrier->trip_count = count; barrier->count = 0; return 0; } static int pthread_barrier_destroy(pthread_barrier_t *barrier) { pthread_cond_destroy(&barrier->cond); pthread_mutex_destroy(&barrier->mutex); return 0; } static int pthread_barrier_wait(pthread_barrier_t *barrier) { pthread_mutex_lock(&barrier->mutex); ++(barrier->count); if(barrier->count >= barrier->trip_count) { barrier->count = 0; pthread_cond_broadcast(&barrier->cond); pthread_mutex_unlock(&barrier->mutex); return 1; } else { pthread_cond_wait(&barrier->cond, &(barrier->mutex)); pthread_mutex_unlock(&barrier->mutex); return 0; } } static int return_data(hid_device *dev, unsigned char *data, size_t length); /* Linked List of input reports received from the device. */ struct input_report { uint8_t *data; size_t len; struct input_report *next; }; struct hid_device_ { IOHIDDeviceRef device_handle; int blocking; int uses_numbered_reports; int disconnected; CFStringRef run_loop_mode; CFRunLoopRef run_loop; CFRunLoopSourceRef source; uint8_t *input_report_buf; CFIndex max_input_report_len; struct input_report *input_reports; pthread_t thread; pthread_mutex_t mutex; /* Protects input_reports */ pthread_cond_t condition; pthread_barrier_t barrier; /* Ensures correct startup sequence */ pthread_barrier_t shutdown_barrier; /* Ensures correct shutdown sequence */ int shutdown_thread; }; static hid_device *new_hid_device(void) { hid_device *dev = calloc(1, sizeof(hid_device)); dev->device_handle = NULL; dev->blocking = 1; dev->uses_numbered_reports = 0; dev->disconnected = 0; dev->run_loop_mode = NULL; dev->run_loop = NULL; dev->source = NULL; dev->input_report_buf = NULL; dev->input_reports = NULL; dev->shutdown_thread = 0; /* Thread objects */ pthread_mutex_init(&dev->mutex, NULL); pthread_cond_init(&dev->condition, NULL); pthread_barrier_init(&dev->barrier, NULL, 2); pthread_barrier_init(&dev->shutdown_barrier, NULL, 2); return dev; } static void free_hid_device(hid_device *dev) { if (!dev) return; /* Delete any input reports still left over. */ struct input_report *rpt = dev->input_reports; while (rpt) { struct input_report *next = rpt->next; free(rpt->data); free(rpt); rpt = next; } /* Free the string and the report buffer. The check for NULL is necessary here as CFRelease() doesn't handle NULL like free() and others do. */ if (dev->run_loop_mode) CFRelease(dev->run_loop_mode); if (dev->source) CFRelease(dev->source); free(dev->input_report_buf); /* Clean up the thread objects */ pthread_barrier_destroy(&dev->shutdown_barrier); pthread_barrier_destroy(&dev->barrier); pthread_cond_destroy(&dev->condition); pthread_mutex_destroy(&dev->mutex); /* Free the structure itself. */ free(dev); } static IOHIDManagerRef hid_mgr = 0x0; #if 0 static void register_error(hid_device *device, const char *op) { } #endif static int32_t get_int_property(IOHIDDeviceRef device, CFStringRef key) { CFTypeRef ref; int32_t value; ref = IOHIDDeviceGetProperty(device, key); if (ref) { if (CFGetTypeID(ref) == CFNumberGetTypeID()) { CFNumberGetValue((CFNumberRef) ref, kCFNumberSInt32Type, &value); return value; } } return 0; } static unsigned short get_vendor_id(IOHIDDeviceRef device) { return get_int_property(device, CFSTR(kIOHIDVendorIDKey)); } static unsigned short get_product_id(IOHIDDeviceRef device) { return get_int_property(device, CFSTR(kIOHIDProductIDKey)); } static int32_t get_location_id(IOHIDDeviceRef device) { return get_int_property(device, CFSTR(kIOHIDLocationIDKey)); } static int32_t get_max_report_length(IOHIDDeviceRef device) { return get_int_property(device, CFSTR(kIOHIDMaxInputReportSizeKey)); } static int get_string_property(IOHIDDeviceRef device, CFStringRef prop, wchar_t *buf, size_t len) { CFStringRef str; if (!len) return 0; str = IOHIDDeviceGetProperty(device, prop); buf[0] = 0; if (str) { CFIndex str_len = CFStringGetLength(str); CFRange range; CFIndex used_buf_len; CFIndex chars_copied; len --; range.location = 0; range.length = ((size_t)str_len > len)? len: (size_t)str_len; chars_copied = CFStringGetBytes(str, range, kCFStringEncodingUTF32LE, (char)'?', FALSE, (UInt8*)buf, len * sizeof(wchar_t), &used_buf_len); if (chars_copied == len) buf[len] = 0; /* len is decremented above */ else buf[chars_copied] = 0; return 0; } else return -1; } static int get_string_property_utf8(IOHIDDeviceRef device, CFStringRef prop, char *buf, size_t len) { CFStringRef str; if (!len) return 0; str = IOHIDDeviceGetProperty(device, prop); buf[0] = 0; if (str) { len--; CFIndex str_len = CFStringGetLength(str); CFRange range; range.location = 0; range.length = str_len; CFIndex used_buf_len; CFIndex chars_copied; chars_copied = CFStringGetBytes(str, range, kCFStringEncodingUTF8, (char)'?', FALSE, (UInt8*)buf, len, &used_buf_len); if (used_buf_len == len) buf[len] = 0; /* len is decremented above */ else buf[used_buf_len] = 0; return used_buf_len; } else return 0; } static int get_serial_number(IOHIDDeviceRef device, wchar_t *buf, size_t len) { return get_string_property(device, CFSTR(kIOHIDSerialNumberKey), buf, len); } static int get_manufacturer_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) { return get_string_property(device, CFSTR(kIOHIDManufacturerKey), buf, len); } static int get_product_string(IOHIDDeviceRef device, wchar_t *buf, size_t len) { return get_string_property(device, CFSTR(kIOHIDProductKey), buf, len); } /* Implementation of wcsdup() for Mac. */ static wchar_t *dup_wcs(const wchar_t *s) { size_t len = wcslen(s); wchar_t *ret = malloc((len+1)*sizeof(wchar_t)); wcscpy(ret, s); return ret; } static int make_path(IOHIDDeviceRef device, char *buf, size_t len) { int res; unsigned short vid, pid; char transport[32]; int32_t location; buf[0] = '\0'; res = get_string_property_utf8( device, CFSTR(kIOHIDTransportKey), transport, sizeof(transport)); if (!res) return -1; location = get_location_id(device); vid = get_vendor_id(device); pid = get_product_id(device); res = snprintf(buf, len, "%s_%04hx_%04hx_%x", transport, vid, pid, location); buf[len-1] = '\0'; return res+1; } /* Initialize the IOHIDManager. Return 0 for success and -1 for failure. */ static int init_hid_manager(void) { /* Initialize all the HID Manager Objects */ hid_mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); if (hid_mgr) { IOHIDManagerSetDeviceMatching(hid_mgr, NULL); IOHIDManagerScheduleWithRunLoop(hid_mgr, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); return 0; } return -1; } /* Initialize the IOHIDManager if necessary. This is the public function, and it is safe to call this function repeatedly. Return 0 for success and -1 for failure. */ int HID_API_EXPORT hid_init(void) { if (!hid_mgr) { return init_hid_manager(); } /* Already initialized. */ return 0; } int HID_API_EXPORT hid_exit(void) { if (hid_mgr) { /* Close the HID manager. */ IOHIDManagerClose(hid_mgr, kIOHIDOptionsTypeNone); CFRelease(hid_mgr); hid_mgr = NULL; } return 0; } static void process_pending_events(void) { SInt32 res; do { res = CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0.001, FALSE); } while(res != kCFRunLoopRunFinished && res != kCFRunLoopRunTimedOut); } struct hid_device_info HID_API_EXPORT *hid_enumerate(unsigned short vendor_id, unsigned short product_id) { struct hid_device_info *root = NULL; /* return object */ struct hid_device_info *cur_dev = NULL; CFIndex num_devices; int i; /* Set up the HID Manager if it hasn't been done */ if (hid_init() < 0) return NULL; /* give the IOHIDManager a chance to update itself */ process_pending_events(); /* Get a list of the Devices */ CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); /* Convert the list into a C array so we can iterate easily. */ num_devices = CFSetGetCount(device_set); IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); CFSetGetValues(device_set, (const void **) device_array); /* Iterate over each device, making an entry for it. */ for (i = 0; i < num_devices; i++) { unsigned short dev_vid; unsigned short dev_pid; #define BUF_LEN 256 wchar_t buf[BUF_LEN]; char cbuf[BUF_LEN]; IOHIDDeviceRef dev = device_array[i]; if (!dev) { continue; } dev_vid = get_vendor_id(dev); dev_pid = get_product_id(dev); /* Check the VID/PID against the arguments */ if ((vendor_id == 0x0 || vendor_id == dev_vid) && (product_id == 0x0 || product_id == dev_pid)) { struct hid_device_info *tmp; size_t len; /* VID/PID match. Create the record. */ tmp = malloc(sizeof(struct hid_device_info)); if (cur_dev) { cur_dev->next = tmp; } else { root = tmp; } cur_dev = tmp; /* Get the Usage Page and Usage for this device. */ cur_dev->usage_page = get_int_property(dev, CFSTR(kIOHIDPrimaryUsagePageKey)); cur_dev->usage = get_int_property(dev, CFSTR(kIOHIDPrimaryUsageKey)); /* Fill out the record */ cur_dev->next = NULL; len = make_path(dev, cbuf, sizeof(cbuf)); cur_dev->path = strdup(cbuf); /* Serial Number */ get_serial_number(dev, buf, BUF_LEN); cur_dev->serial_number = dup_wcs(buf); /* Manufacturer and Product strings */ get_manufacturer_string(dev, buf, BUF_LEN); cur_dev->manufacturer_string = dup_wcs(buf); get_product_string(dev, buf, BUF_LEN); cur_dev->product_string = dup_wcs(buf); /* VID/PID */ cur_dev->vendor_id = dev_vid; cur_dev->product_id = dev_pid; /* Release Number */ cur_dev->release_number = get_int_property(dev, CFSTR(kIOHIDVersionNumberKey)); /* Interface Number (Unsupported on Mac)*/ cur_dev->interface_number = -1; } } free(device_array); CFRelease(device_set); return root; } void HID_API_EXPORT hid_free_enumeration(struct hid_device_info *devs) { /* This function is identical to the Linux version. Platform independent. */ struct hid_device_info *d = devs; while (d) { struct hid_device_info *next = d->next; free(d->path); free(d->serial_number); free(d->manufacturer_string); free(d->product_string); free(d); d = next; } } hid_device * HID_API_EXPORT hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number) { /* This function is identical to the Linux version. Platform independent. */ struct hid_device_info *devs, *cur_dev; const char *path_to_open = NULL; hid_device * handle = NULL; devs = hid_enumerate(vendor_id, product_id); cur_dev = devs; while (cur_dev) { if (cur_dev->vendor_id == vendor_id && cur_dev->product_id == product_id) { if (serial_number) { if (wcscmp(serial_number, cur_dev->serial_number) == 0) { path_to_open = cur_dev->path; break; } } else { path_to_open = cur_dev->path; break; } } cur_dev = cur_dev->next; } if (path_to_open) { /* Open the device */ handle = hid_open_path(path_to_open); } hid_free_enumeration(devs); return handle; } static void hid_device_removal_callback(void *context, IOReturn result, void *sender) { /* Stop the Run Loop for this device. */ hid_device *d = context; d->disconnected = 1; CFRunLoopStop(d->run_loop); } /* The Run Loop calls this function for each input report received. This function puts the data into a linked list to be picked up by hid_read(). */ static void hid_report_callback(void *context, IOReturn result, void *sender, IOHIDReportType report_type, uint32_t report_id, uint8_t *report, CFIndex report_length) { struct input_report *rpt; hid_device *dev = context; /* Make a new Input Report object */ rpt = calloc(1, sizeof(struct input_report)); rpt->data = calloc(1, report_length); memcpy(rpt->data, report, report_length); rpt->len = report_length; rpt->next = NULL; /* Lock this section */ pthread_mutex_lock(&dev->mutex); /* Attach the new report object to the end of the list. */ if (dev->input_reports == NULL) { /* The list is empty. Put it at the root. */ dev->input_reports = rpt; } else { /* Find the end of the list and attach. */ struct input_report *cur = dev->input_reports; int num_queued = 0; while (cur->next != NULL) { cur = cur->next; num_queued++; } cur->next = rpt; /* Pop one off if we've reached 30 in the queue. This way we don't grow forever if the user never reads anything from the device. */ if (num_queued > 30) { return_data(dev, NULL, 0); } } /* Signal a waiting thread that there is data. */ pthread_cond_signal(&dev->condition); /* Unlock */ pthread_mutex_unlock(&dev->mutex); } /* This gets called when the read_thred's run loop gets signaled by hid_close(), and serves to stop the read_thread's run loop. */ static void perform_signal_callback(void *context) { hid_device *dev = context; CFRunLoopStop(dev->run_loop); /*TODO: CFRunLoopGetCurrent()*/ } static void *read_thread(void *param) { hid_device *dev = param; SInt32 code; /* Move the device's run loop to this thread. */ IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetCurrent(), dev->run_loop_mode); /* Create the RunLoopSource which is used to signal the event loop to stop when hid_close() is called. */ CFRunLoopSourceContext ctx; memset(&ctx, 0, sizeof(ctx)); ctx.version = 0; ctx.info = dev; ctx.perform = &perform_signal_callback; dev->source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0/*order*/, &ctx); CFRunLoopAddSource(CFRunLoopGetCurrent(), dev->source, dev->run_loop_mode); /* Store off the Run Loop so it can be stopped from hid_close() and on device disconnection. */ dev->run_loop = CFRunLoopGetCurrent(); /* Notify the main thread that the read thread is up and running. */ pthread_barrier_wait(&dev->barrier); /* Run the Event Loop. CFRunLoopRunInMode() will dispatch HID input reports into the hid_report_callback(). */ while (!dev->shutdown_thread && !dev->disconnected) { code = CFRunLoopRunInMode(dev->run_loop_mode, 1000/*sec*/, FALSE); /* Return if the device has been disconnected */ if (code == kCFRunLoopRunFinished) { dev->disconnected = 1; break; } /* Break if The Run Loop returns Finished or Stopped. */ if (code != kCFRunLoopRunTimedOut && code != kCFRunLoopRunHandledSource) { /* There was some kind of error. Setting shutdown seems to make sense, but there may be something else more appropriate */ dev->shutdown_thread = 1; break; } } /* Now that the read thread is stopping, Wake any threads which are waiting on data (in hid_read_timeout()). Do this under a mutex to make sure that a thread which is about to go to sleep waiting on the condition acutally will go to sleep before the condition is signaled. */ pthread_mutex_lock(&dev->mutex); pthread_cond_broadcast(&dev->condition); pthread_mutex_unlock(&dev->mutex); /* Wait here until hid_close() is called and makes it past the call to CFRunLoopWakeUp(). This thread still needs to be valid when that function is called on the other thread. */ pthread_barrier_wait(&dev->shutdown_barrier); return NULL; } hid_device * HID_API_EXPORT hid_open_path(const char *path) { int i; hid_device *dev = NULL; CFIndex num_devices; dev = new_hid_device(); /* Set up the HID Manager if it hasn't been done */ if (hid_init() < 0) return NULL; /* give the IOHIDManager a chance to update itself */ process_pending_events(); CFSetRef device_set = IOHIDManagerCopyDevices(hid_mgr); num_devices = CFSetGetCount(device_set); IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); CFSetGetValues(device_set, (const void **) device_array); for (i = 0; i < num_devices; i++) { char cbuf[BUF_LEN]; size_t len; IOHIDDeviceRef os_dev = device_array[i]; len = make_path(os_dev, cbuf, sizeof(cbuf)); if (!strcmp(cbuf, path)) { /* Matched Paths. Open this Device. */ IOReturn ret = IOHIDDeviceOpen(os_dev, kIOHIDOptionsTypeSeizeDevice); if (ret == kIOReturnSuccess) { char str[32]; free(device_array); CFRetain(os_dev); CFRelease(device_set); dev->device_handle = os_dev; /* Create the buffers for receiving data */ dev->max_input_report_len = (CFIndex) get_max_report_length(os_dev); dev->input_report_buf = calloc(dev->max_input_report_len, sizeof(uint8_t)); /* Create the Run Loop Mode for this device. printing the reference seems to work. */ sprintf(str, "HIDAPI_%p", os_dev); dev->run_loop_mode = CFStringCreateWithCString(NULL, str, kCFStringEncodingASCII); /* Attach the device to a Run Loop */ IOHIDDeviceRegisterInputReportCallback( os_dev, dev->input_report_buf, dev->max_input_report_len, &hid_report_callback, dev); IOHIDDeviceRegisterRemovalCallback(dev->device_handle, hid_device_removal_callback, dev); /* Start the read thread */ pthread_create(&dev->thread, NULL, read_thread, dev); /* Wait here for the read thread to be initialized. */ pthread_barrier_wait(&dev->barrier); return dev; } else { goto return_error; } } } return_error: free(device_array); CFRelease(device_set); free_hid_device(dev); return NULL; } static int set_report(hid_device *dev, IOHIDReportType type, const unsigned char *data, size_t length) { const unsigned char *data_to_send; size_t length_to_send; IOReturn res; /* Return if the device has been disconnected. */ if (dev->disconnected) return -1; if (data[0] == 0x0) { /* Not using numbered Reports. Don't send the report number. */ data_to_send = data+1; length_to_send = length-1; } else { /* Using numbered Reports. Send the Report Number */ data_to_send = data; length_to_send = length; } if (!dev->disconnected) { res = IOHIDDeviceSetReport(dev->device_handle, type, data[0], /* Report ID*/ data_to_send, length_to_send); if (res == kIOReturnSuccess) { return length; } else return -1; } return -1; } int HID_API_EXPORT hid_write(hid_device *dev, const unsigned char *data, size_t length) { return set_report(dev, kIOHIDReportTypeOutput, data, length); } /* Helper function, so that this isn't duplicated in hid_read(). */ static int return_data(hid_device *dev, unsigned char *data, size_t length) { /* Copy the data out of the linked list item (rpt) into the return buffer (data), and delete the liked list item. */ struct input_report *rpt = dev->input_reports; size_t len = (length < rpt->len)? length: rpt->len; memcpy(data, rpt->data, len); dev->input_reports = rpt->next; free(rpt->data); free(rpt); return len; } static int cond_wait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex) { while (!dev->input_reports) { int res = pthread_cond_wait(cond, mutex); if (res != 0) return res; /* A res of 0 means we may have been signaled or it may be a spurious wakeup. Check to see that there's acutally data in the queue before returning, and if not, go back to sleep. See the pthread_cond_timedwait() man page for details. */ if (dev->shutdown_thread || dev->disconnected) return -1; } return 0; } static int cond_timedwait(const hid_device *dev, pthread_cond_t *cond, pthread_mutex_t *mutex, const struct timespec *abstime) { while (!dev->input_reports) { int res = pthread_cond_timedwait(cond, mutex, abstime); if (res != 0) return res; /* A res of 0 means we may have been signaled or it may be a spurious wakeup. Check to see that there's acutally data in the queue before returning, and if not, go back to sleep. See the pthread_cond_timedwait() man page for details. */ if (dev->shutdown_thread || dev->disconnected) return -1; } return 0; } int HID_API_EXPORT hid_read_timeout(hid_device *dev, unsigned char *data, size_t length, int milliseconds) { int bytes_read = -1; /* Lock the access to the report list. */ pthread_mutex_lock(&dev->mutex); /* There's an input report queued up. Return it. */ if (dev->input_reports) { /* Return the first one */ bytes_read = return_data(dev, data, length); goto ret; } /* Return if the device has been disconnected. */ if (dev->disconnected) { bytes_read = -1; goto ret; } if (dev->shutdown_thread) { /* This means the device has been closed (or there has been an error. An error code of -1 should be returned. */ bytes_read = -1; goto ret; } /* There is no data. Go to sleep and wait for data. */ if (milliseconds == -1) { /* Blocking */ int res; res = cond_wait(dev, &dev->condition, &dev->mutex); if (res == 0) bytes_read = return_data(dev, data, length); else { /* There was an error, or a device disconnection. */ bytes_read = -1; } } else if (milliseconds > 0) { /* Non-blocking, but called with timeout. */ int res; struct timespec ts; struct timeval tv; gettimeofday(&tv, NULL); TIMEVAL_TO_TIMESPEC(&tv, &ts); ts.tv_sec += milliseconds / 1000; ts.tv_nsec += (milliseconds % 1000) * 1000000; if (ts.tv_nsec >= 1000000000L) { ts.tv_sec++; ts.tv_nsec -= 1000000000L; } res = cond_timedwait(dev, &dev->condition, &dev->mutex, &ts); if (res == 0) bytes_read = return_data(dev, data, length); else if (res == ETIMEDOUT) bytes_read = 0; else bytes_read = -1; } else { /* Purely non-blocking */ bytes_read = 0; } ret: /* Unlock */ pthread_mutex_unlock(&dev->mutex); return bytes_read; } int HID_API_EXPORT hid_read(hid_device *dev, unsigned char *data, size_t length) { return hid_read_timeout(dev, data, length, (dev->blocking)? -1: 0); } int HID_API_EXPORT hid_set_nonblocking(hid_device *dev, int nonblock) { /* All Nonblocking operation is handled by the library. */ dev->blocking = !nonblock; return 0; } int HID_API_EXPORT hid_send_feature_report(hid_device *dev, const unsigned char *data, size_t length) { return set_report(dev, kIOHIDReportTypeFeature, data, length); } int HID_API_EXPORT hid_get_feature_report(hid_device *dev, unsigned char *data, size_t length) { CFIndex len = length; IOReturn res; /* Return if the device has been unplugged. */ if (dev->disconnected) return -1; res = IOHIDDeviceGetReport(dev->device_handle, kIOHIDReportTypeFeature, data[0], /* Report ID */ data, &len); if (res == kIOReturnSuccess) return len; else return -1; } void HID_API_EXPORT hid_close(hid_device *dev) { if (!dev) return; /* Disconnect the report callback before close. */ if (!dev->disconnected) { IOHIDDeviceRegisterInputReportCallback( dev->device_handle, dev->input_report_buf, dev->max_input_report_len, NULL, dev); IOHIDManagerRegisterDeviceRemovalCallback(hid_mgr, NULL, dev); IOHIDDeviceUnscheduleFromRunLoop(dev->device_handle, dev->run_loop, dev->run_loop_mode); IOHIDDeviceScheduleWithRunLoop(dev->device_handle, CFRunLoopGetMain(), kCFRunLoopDefaultMode); } /* Cause read_thread() to stop. */ dev->shutdown_thread = 1; /* Wake up the run thread's event loop so that the thread can exit. */ CFRunLoopSourceSignal(dev->source); CFRunLoopWakeUp(dev->run_loop); /* Notify the read thread that it can shut down now. */ pthread_barrier_wait(&dev->shutdown_barrier); /* Wait for read_thread() to end. */ pthread_join(dev->thread, NULL); /* Close the OS handle to the device, but only if it's not been unplugged. If it's been unplugged, then calling IOHIDDeviceClose() will crash. */ if (!dev->disconnected) { IOHIDDeviceClose(dev->device_handle, kIOHIDOptionsTypeSeizeDevice); } /* Clear out the queue of received reports. */ pthread_mutex_lock(&dev->mutex); while (dev->input_reports) { return_data(dev, NULL, 0); } pthread_mutex_unlock(&dev->mutex); CFRelease(dev->device_handle); free_hid_device(dev); } int HID_API_EXPORT_CALL hid_get_manufacturer_string(hid_device *dev, wchar_t *string, size_t maxlen) { return get_manufacturer_string(dev->device_handle, string, maxlen); } int HID_API_EXPORT_CALL hid_get_product_string(hid_device *dev, wchar_t *string, size_t maxlen) { return get_product_string(dev->device_handle, string, maxlen); } int HID_API_EXPORT_CALL hid_get_serial_number_string(hid_device *dev, wchar_t *string, size_t maxlen) { return get_serial_number(dev->device_handle, string, maxlen); } int HID_API_EXPORT_CALL hid_get_indexed_string(hid_device *dev, int string_index, wchar_t *string, size_t maxlen) { /* TODO: */ return 0; } HID_API_EXPORT const wchar_t * HID_API_CALL hid_error(hid_device *dev) { /* TODO: */ return NULL; } #if 0 static int32_t get_usage(IOHIDDeviceRef device) { int32_t res; res = get_int_property(device, CFSTR(kIOHIDDeviceUsageKey)); if (!res) res = get_int_property(device, CFSTR(kIOHIDPrimaryUsageKey)); return res; } static int32_t get_usage_page(IOHIDDeviceRef device) { int32_t res; res = get_int_property(device, CFSTR(kIOHIDDeviceUsagePageKey)); if (!res) res = get_int_property(device, CFSTR(kIOHIDPrimaryUsagePageKey)); return res; } static int get_transport(IOHIDDeviceRef device, wchar_t *buf, size_t len) { return get_string_property(device, CFSTR(kIOHIDTransportKey), buf, len); } int main(void) { IOHIDManagerRef mgr; int i; mgr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); IOHIDManagerSetDeviceMatching(mgr, NULL); IOHIDManagerOpen(mgr, kIOHIDOptionsTypeNone); CFSetRef device_set = IOHIDManagerCopyDevices(mgr); CFIndex num_devices = CFSetGetCount(device_set); IOHIDDeviceRef *device_array = calloc(num_devices, sizeof(IOHIDDeviceRef)); CFSetGetValues(device_set, (const void **) device_array); for (i = 0; i < num_devices; i++) { IOHIDDeviceRef dev = device_array[i]; printf("Device: %p\n", dev); printf(" %04hx %04hx\n", get_vendor_id(dev), get_product_id(dev)); wchar_t serial[256], buf[256]; char cbuf[256]; get_serial_number(dev, serial, 256); printf(" Serial: %ls\n", serial); printf(" Loc: %ld\n", get_location_id(dev)); get_transport(dev, buf, 256); printf(" Trans: %ls\n", buf); make_path(dev, cbuf, 256); printf(" Path: %s\n", cbuf); } return 0; } #endif open-zwave-1.5/cpp/hidapi/pc/000077500000000000000000000000001264474202400161015ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/pc/hidapi-hidraw.pc.in000066400000000000000000000005051264474202400215440ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: hidapi-hidraw Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the hidraw implementation. Version: @VERSION@ Libs: -L${libdir} -lhidapi-hidraw Cflags: -I${includedir}/hidapi open-zwave-1.5/cpp/hidapi/pc/hidapi-libusb.pc.in000066400000000000000000000004731264474202400215520ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: hidapi-libusb Description: C Library for USB HID device access from Linux, Mac OS X, FreeBSD, and Windows. This is the libusb implementation. Version: @VERSION@ Libs: -L${libdir} -lhidapi-libusb Cflags: -I${includedir}/hidapi open-zwave-1.5/cpp/hidapi/pc/hidapi.pc.in000066400000000000000000000004241264474202400202700ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: hidapi Description: C Library for USB/Bluetooth HID device access from Linux, Mac OS X, FreeBSD, and Windows. Version: @VERSION@ Libs: -L${libdir} -lhidapi Cflags: -I${includedir}/hidapi open-zwave-1.5/cpp/hidapi/udev/000077500000000000000000000000001264474202400164425ustar00rootroot00000000000000open-zwave-1.5/cpp/hidapi/udev/99-hid.rules000066400000000000000000000027641264474202400205320ustar00rootroot00000000000000# This is a sample udev file for HIDAPI devices which changes the permissions # to 0666 (world readable/writable) for a specified device on Linux systems. # If you are using the libusb implementation of hidapi (hid-libusb.c), then # use something like the following line, substituting the VID and PID with # those of your device. Note that for kernels before 2.6.24, you will need # to substitute "usb" with "usb_device". It shouldn't hurt to use two lines # (one each way) for compatibility with older systems. # HIDAPI/libusb SUBSYSTEM=="usb", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", MODE="0666" # If you are using the hidraw implementation, then do something like the # following, substituting the VID and PID with your device. Busnum 1 is USB. # HIDAPI/hidraw KERNEL=="hidraw*", ATTRS{busnum}=="1", ATTRS{idVendor}=="04d8", ATTRS{idProduct}=="003f", MODE="0666" # Once done, optionally rename this file for your device, and drop it into # /etc/udev/rules.d and unplug and re-plug your device. This is all that is # necessary to see the new permissions. Udev does not have to be restarted. # Note that the hexadecimal values for VID and PID are case sensitive and # must be lower case. # If you think permissions of 0666 are too loose, then see: # http://reactivated.net/writing_udev_rules.html for more information on finer # grained permission setting. For example, it might be sufficient to just # set the group or user owner for specific devices (for example the plugdev # group on some systems). open-zwave-1.5/cpp/src/000077500000000000000000000000001264474202400150305ustar00rootroot00000000000000open-zwave-1.5/cpp/src/Bitfield.h000066400000000000000000000067021264474202400167300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Bitfield.h // // Variable length bitfield implementation // // Copyright (c) 2011 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 . // //----------------------------------------------------------------------------- #ifndef _Bitfield_H #define _Bitfield_H #include #include "Defs.h" namespace OpenZWave { class OPENZWAVE_EXPORT Bitfield { friend class Iterator; public: Bitfield():m_numSetBits(0){} ~Bitfield(){} void Set( uint32 _idx ) { 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; } } void Clear( uint32 _idx ) { if( IsSet(_idx) ) { m_bits[_idx>>5] &= ~(1<<(_idx&0x1f)); --m_numSetBits; } } bool IsSet( uint32 _idx )const { if( (_idx>>5) < m_bits.size() ) { return( ( m_bits[_idx>>5] & (1<<(_idx&0x1f)) ) !=0 ); } return false; } uint32 GetNumSetBits()const{ return m_numSetBits; } class Iterator { friend class Bitfield; public: uint32 operator *() const { return m_idx; } Iterator& operator++() { // Search forward to next set bit NextSetBit(); return *this; } Iterator operator++(int) { Iterator tmp = *this; ++tmp; return tmp; } bool operator ==(const Iterator &rhs) { return m_idx == rhs.m_idx; } bool operator !=(const Iterator &rhs) { return m_idx != rhs.m_idx; } private: 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 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; } } } } uint32 m_idx; Bitfield const* m_bitfield; }; Iterator Begin()const{ return Iterator( this, 0 ); } Iterator End()const{ return Iterator( this, (uint32) m_bits.size()<<5 ); } private: OPENZWAVE_EXPORT_WARNINGS_OFF vector m_bits; OPENZWAVE_EXPORT_WARNINGS_ON uint32 m_numSetBits; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/Defs.h000066400000000000000000000365301264474202400160710ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Defs.h // // Basic types and preprocessor directives // // 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 . // //----------------------------------------------------------------------------- #ifndef _Defs_H #define _Defs_H #include #include #include #include // Compilation export flags #if (defined _WINDOWS || defined WIN32 || defined _MSC_VER) && !defined MINGW # if defined OPENZWAVE_MAKEDLL // Create the dynamic library. # define OPENZWAVE_EXPORT __declspec(dllexport) # elif defined OPENZWAVE_USEDLL // Use the dynamic library # define OPENZWAVE_EXPORT __declspec(dllimport) # 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__ #define DEPRECATED __attribute__((deprecated)) #elif defined(_MSC_VER) #define DEPRECATED __declspec(deprecated) #else #pragma message("WARNING: You need to implement DEPRECATED for this compiler") #define DEPRECATED #endif #ifdef NULL #undef NULL #endif #define NULL 0 // Basic types typedef signed char int8; typedef unsigned char uint8; typedef signed short int16; typedef unsigned short uint16; typedef signed int int32; typedef unsigned int uint32; #ifdef _MSC_VER typedef signed __int64 int64; typedef unsigned __int64 uint64; #endif #ifdef __GNUC__ typedef signed long long int64; typedef unsigned long long uint64; #endif typedef float float32; typedef double float64; typedef struct ozwversion { uint32_t _v; /* major << 16 | minor */ } ozwversion; /** * \brief version_major - return the major version of the given struct * \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) { return (v._v & 0xFFFF0000) >> 16; } /** * \brief version_minor - return the minor version of the given struct * \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) { return v._v & 0xFFFF; } /** * \brief version - create a new version number * \param major: major version number * \param minor: minor version number * \return the Version Number Struct */ static inline struct ozwversion version(uint16_t major, uint16_t minor) { struct ozwversion v; v._v = (uint32_t)(major << 16) | (uint32_t)minor; return v; } /** * \brief version_cmp - compare two versions * \param a: the first version number * \param b: the second version number * \return a number greater, equal, or less than 0 if a is greater, equal or * less than b, respectively * * Example: * struct version a = version(1, 0); * struct version b = version(1, 3); * if (version_cmp(a, b) < 0) * printf("b is smaller than b\n"); */ static inline int version_cmp(struct ozwversion a, struct ozwversion b) { return (a._v == b._v) ? 0 : (a._v > b._v) ? 1 : - 1; } #include "OZWException.h" #define OPENZWAVE_DISABLE_EXCEPTIONS #if defined(_MSC_VER) # define __MYFUNCTION__ __FUNCTION__ #else # define __MYFUNCTION__ __FILE__ #endif // Exceptions : define OPENZWAVE_DISABLE_EXCEPTIONS in compiler flags to enable exceptions instead of exit function #ifndef OPENZWAVE_DISABLE_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 OpenZWave { // Include the STL namespace using namespace std; } // Modifications for Microsoft compilers #ifdef _MSC_VER // Fix for namespace-related compiler bug namespace OpenZWave { } // Rename safe versions of sprintf etc #define snprintf sprintf_s #define strcasecmp _stricmp #define sscanf sscanf_s #endif // Modifications for MiNGW32 compiler #ifdef MINGW // Replace "safe" versions of sprintf #define sprintf_s snprintf // seems some MINGW versions don't have a errno_t #ifndef errno_t #define errno_t int #endif #define fopen_s fopen #endif //#define MAX_TRIES 3 // Retry sends up to 3 times #define MAX_TRIES 1 // set this to one, as I believe now that a ACK failure is indication that the device is offline, hence additional attempts will not work. #define MAX_MAX_TRIES 7 // Don't exceed this retry limit #define ACK_TIMEOUT 1000 // How long to wait for an ACK #define BYTE_TIMEOUT 150 //#define RETRY_TIMEOUT 40000 // Retry send after 40 seconds #define RETRY_TIMEOUT 10000 // Retry send after 10 seconds (we might need to keep this below 10 for Security CC to function correctly) #define SOF 0x01 #define ACK 0x06 #define NAK 0x15 #define CAN 0x18 #define NUM_NODE_BITFIELD_BYTES 29 // 29 bytes = 232 bits, one for each possible node in the network. #define REQUEST 0x00 #define RESPONSE 0x01 #define ZW_CLOCK_SET 0x30 #define TRANSMIT_OPTION_ACK 0x01 #define TRANSMIT_OPTION_LOW_POWER 0x02 #define TRANSMIT_OPTION_AUTO_ROUTE 0x04 #define TRANSMIT_OPTION_NO_ROUTE 0x10 #define TRANSMIT_OPTION_EXPLORE 0x20 #define TRANSMIT_COMPLETE_OK 0x00 #define TRANSMIT_COMPLETE_NO_ACK 0x01 #define TRANSMIT_COMPLETE_FAIL 0x02 #define TRANSMIT_COMPLETE_NOT_IDLE 0x03 #define TRANSMIT_COMPLETE_NOROUTE 0x04 #define RECEIVE_STATUS_ROUTED_BUSY 0x01 #define RECEIVE_STATUS_TYPE_BROAD 0x04 #define FUNC_ID_SERIAL_API_GET_INIT_DATA 0x02 #define FUNC_ID_SERIAL_API_APPL_NODE_INFORMATION 0x03 #define FUNC_ID_APPLICATION_COMMAND_HANDLER 0x04 #define FUNC_ID_ZW_GET_CONTROLLER_CAPABILITIES 0x05 #define FUNC_ID_SERIAL_API_SET_TIMEOUTS 0x06 #define FUNC_ID_SERIAL_API_GET_CAPABILITIES 0x07 #define FUNC_ID_SERIAL_API_SOFT_RESET 0x08 #define FUNC_ID_ZW_SEND_NODE_INFORMATION 0x12 #define FUNC_ID_ZW_SEND_DATA 0x13 #define FUNC_ID_ZW_GET_VERSION 0x15 #define FUNC_ID_ZW_R_F_POWER_LEVEL_SET 0x17 #define FUNC_ID_ZW_GET_RANDOM 0x1c #define FUNC_ID_ZW_MEMORY_GET_ID 0x20 #define FUNC_ID_MEMORY_GET_BYTE 0x21 #define FUNC_ID_ZW_READ_MEMORY 0x23 #define FUNC_ID_ZW_SET_LEARN_NODE_STATE 0x40 // Not implemented #define FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO 0x41 // Get protocol info (baud rate, listening, etc.) for a given node #define FUNC_ID_ZW_SET_DEFAULT 0x42 // Reset controller and node info to default (original) values #define FUNC_ID_ZW_NEW_CONTROLLER 0x43 // Not implemented #define FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE 0x44 // Replication send data complete #define FUNC_ID_ZW_REPLICATION_SEND_DATA 0x45 // Replication send data #define FUNC_ID_ZW_ASSIGN_RETURN_ROUTE 0x46 // Assign a return route from the specified node to the controller #define FUNC_ID_ZW_DELETE_RETURN_ROUTE 0x47 // Delete all return routes from the specified node #define FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE 0x48 // Ask the specified node to update its neighbors (then read them from the controller) #define FUNC_ID_ZW_APPLICATION_UPDATE 0x49 // Get a list of supported (and controller) command classes #define FUNC_ID_ZW_ADD_NODE_TO_NETWORK 0x4a // Control the addnode (or addcontroller) process...start, stop, etc. #define FUNC_ID_ZW_REMOVE_NODE_FROM_NETWORK 0x4b // Control the removenode (or removecontroller) process...start, stop, etc. #define FUNC_ID_ZW_CREATE_NEW_PRIMARY 0x4c // Control the createnewprimary process...start, stop, etc. #define FUNC_ID_ZW_CONTROLLER_CHANGE 0x4d // Control the transferprimary process...start, stop, etc. #define FUNC_ID_ZW_SET_LEARN_MODE 0x50 // Put a controller into learn mode for replication/ receipt of configuration info #define FUNC_ID_ZW_ASSIGN_SUC_RETURN_ROUTE 0x51 // Assign a return route to the SUC #define FUNC_ID_ZW_ENABLE_SUC 0x52 // Make a controller a Static Update Controller #define FUNC_ID_ZW_REQUEST_NETWORK_UPDATE 0x53 // Network update for a SUC(?) #define FUNC_ID_ZW_SET_SUC_NODE_ID 0x54 // Identify a Static Update Controller node id #define FUNC_ID_ZW_DELETE_SUC_RETURN_ROUTE 0x55 // Remove return routes to the SUC #define FUNC_ID_ZW_GET_SUC_NODE_ID 0x56 // Try to retrieve a Static Update Controller node id (zero if no SUC present) #define FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS 0x5a // Allow options for request node neighbor update #define FUNC_ID_ZW_EXPLORE_REQUEST_INCLUSION 0x5e // supports NWI #define FUNC_ID_ZW_REQUEST_NODE_INFO 0x60 // Get info (supported command classes) for the specified node #define FUNC_ID_ZW_REMOVE_FAILED_NODE_ID 0x61 // Mark a specified node id as failed #define FUNC_ID_ZW_IS_FAILED_NODE_ID 0x62 // Check to see if a specified node has failed #define FUNC_ID_ZW_REPLACE_FAILED_NODE 0x63 // Remove a failed node from the controller's list (?) #define FUNC_ID_ZW_GET_ROUTING_INFO 0x80 // Get a specified node's neighbor information from the controller #define FUNC_ID_SERIAL_API_SLAVE_NODE_INFO 0xA0 // Set application virtual slave node information #define FUNC_ID_APPLICATION_SLAVE_COMMAND_HANDLER 0xA1 // Slave command handler #define FUNC_ID_ZW_SEND_SLAVE_NODE_INFO 0xA2 // Send a slave node information frame #define FUNC_ID_ZW_SEND_SLAVE_DATA 0xA3 // Send data from slave #define FUNC_ID_ZW_SET_SLAVE_LEARN_MODE 0xA4 // Enter slave learn mode #define FUNC_ID_ZW_GET_VIRTUAL_NODES 0xA5 // Return all virtual nodes #define FUNC_ID_ZW_IS_VIRTUAL_NODE 0xA6 // Virtual node test #define FUNC_ID_ZW_SET_PROMISCUOUS_MODE 0xD0 // Set controller into promiscuous mode to listen to all frames #define FUNC_ID_PROMISCUOUS_APPLICATION_COMMAND_HANDLER 0xD1 #define ADD_NODE_ANY 0x01 #define ADD_NODE_CONTROLLER 0x02 #define ADD_NODE_SLAVE 0x03 #define ADD_NODE_EXISTING 0x04 #define ADD_NODE_STOP 0x05 #define ADD_NODE_STOP_FAILED 0x06 #define ADD_NODE_STATUS_LEARN_READY 0x01 #define ADD_NODE_STATUS_NODE_FOUND 0x02 #define ADD_NODE_STATUS_ADDING_SLAVE 0x03 #define ADD_NODE_STATUS_ADDING_CONTROLLER 0x04 #define ADD_NODE_STATUS_PROTOCOL_DONE 0x05 #define ADD_NODE_STATUS_DONE 0x06 #define ADD_NODE_STATUS_FAILED 0x07 #define REMOVE_NODE_ANY 0x01 #define REMOVE_NODE_CONTROLLER 0x02 #define REMOVE_NODE_SLAVE 0x03 #define REMOVE_NODE_STOP 0x05 #define REMOVE_NODE_STATUS_LEARN_READY 0x01 #define REMOVE_NODE_STATUS_NODE_FOUND 0x02 #define REMOVE_NODE_STATUS_REMOVING_SLAVE 0x03 #define REMOVE_NODE_STATUS_REMOVING_CONTROLLER 0x04 #define REMOVE_NODE_STATUS_DONE 0x06 #define REMOVE_NODE_STATUS_FAILED 0x07 #define CREATE_PRIMARY_START 0x02 #define CREATE_PRIMARY_STOP 0x05 #define CREATE_PRIMARY_STOP_FAILED 0x06 #define CONTROLLER_CHANGE_START 0x02 #define CONTROLLER_CHANGE_STOP 0x05 #define CONTROLLER_CHANGE_STOP_FAILED 0x06 #define LEARN_MODE_STARTED 0x01 #define LEARN_MODE_DONE 0x06 #define LEARN_MODE_FAILED 0x07 #define LEARN_MODE_DELETED 0x80 #define REQUEST_NEIGHBOR_UPDATE_STARTED 0x21 #define REQUEST_NEIGHBOR_UPDATE_DONE 0x22 #define REQUEST_NEIGHBOR_UPDATE_FAILED 0x23 #define FAILED_NODE_OK 0x00 #define FAILED_NODE_REMOVED 0x01 #define FAILED_NODE_NOT_REMOVED 0x02 #define FAILED_NODE_REPLACE_WAITING 0x03 #define FAILED_NODE_REPLACE_DONE 0x04 #define FAILED_NODE_REPLACE_FAILED 0x05 #define FAILED_NODE_REMOVE_STARTED 0x00 #define FAILED_NODE_NOT_PRIMARY_CONTROLLER 0x02 #define FAILED_NODE_NO_CALLBACK_FUNCTION 0x04 #define FAILED_NODE_NOT_FOUND 0x08 #define FAILED_NODE_REMOVE_PROCESS_BUSY 0x10 #define FAILED_NODE_REMOVE_FAIL 0x20 #define SUC_UPDATE_DONE 0x00 #define SUC_UPDATE_ABORT 0x01 #define SUC_UPDATE_WAIT 0x02 #define SUC_UPDATE_DISABLED 0x03 #define SUC_UPDATE_OVERFLOW 0x04 #define SUC_FUNC_BASIC_SUC 0x00 #define SUC_FUNC_NODEID_SERVER 0x01 #define UPDATE_STATE_NODE_INFO_RECEIVED 0x84 #define UPDATE_STATE_NODE_INFO_REQ_DONE 0x82 #define UPDATE_STATE_NODE_INFO_REQ_FAILED 0x81 #define UPDATE_STATE_ROUTING_PENDING 0x80 #define UPDATE_STATE_NEW_ID_ASSIGNED 0x40 #define UPDATE_STATE_DELETE_DONE 0x20 #define UPDATE_STATE_SUC_ID 0x10 #define APPLICATION_NODEINFO_LISTENING 0x01 #define APPLICATION_NODEINFO_OPTIONAL_FUNCTIONALITY 0x02 #define SLAVE_ASSIGN_COMPLETE 0x00 #define SLAVE_ASSIGN_NODEID_DONE 0x01 // Node ID has been assigned #define SLAVE_ASSIGN_RANGE_INFO_UPDATE 0x02 // Node is doing neighbor discovery #define SLAVE_LEARN_MODE_DISABLE 0x00 // disable add/remove virtual slave nodes #define SLAVE_LEARN_MODE_ENABLE 0x01 // enable ability to include/exclude virtual slave nodes #define SLAVE_LEARN_MODE_ADD 0x02 // add node directly but only if primary/inclusion controller #define SLAVE_LEARN_MODE_REMOVE 0x03 // remove node directly but only if primary/inclusion controller #define OPTION_HIGH_POWER 0x80 #define OPTION_NWI 0x40 // NWI Inclusion //Device request related #define BASIC_SET 0x01 #define BASIC_REPORT 0x03 #define COMMAND_CLASS_BASIC 0x20 #define COMMAND_CLASS_CONTROLLER_REPLICATION 0x21 #define COMMAND_CLASS_APPLICATION_STATUS 0x22 #define COMMAND_CLASS_HAIL 0x82 #endif // _Defs_H open-zwave-1.5/cpp/src/DoxygenMain.h000066400000000000000000000166311264474202400174320ustar00rootroot00000000000000 /** * \mainpage OpenZWave * \section Introduction Introduction to OpenZWave * OpenZWave is an open-source, cross-platform library designed to enable * anyone to add support for Z-Wave home-automation devices to their * applications, without requiring any in depth knowledge of the Z-Wave * protocol. *

* Z-Wave employs a proprietary protocol which the owners, Sigma Designs, * have chosen not to release into the public domain. There is also no * official free or low-cost SDK that can be used to develop applications * (The ControlThink SDK is now tied exclusively to their own Z-Wave PC * interface). The only way to obtain the protocol documentation and sample * code is to purchase an expensive development kit, and sign a non-disclosure * agreement (NDA) preventing the release of that knowledge. *

* OpenZWave was created to fill that gap. We do not have the official * documentation, have signed no NDA, and are free to develop the library as * we see fit. Our knowledge comes from existing bodies of open-source code * (principally the Z-Wave parts of LinuxMCE), and through examining the * messages sent by Z-Wave devices. *

* 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. It is NOT * our aim to publish alternative documentation of the Z-Wave protocol, or * to attempt to "punish" Sigma Designs for their decision to keep the * protocol closed. * \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 * 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 * across the mesh. *

* 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. * 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. *

* 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 * interfaces. The switches, dimmers, movement sensors etc are all slaves. * Controllers and Devices * Replication * Command Classes * Values *


* \section Library The OpenZWave Library * \subsection Overview Overview * \subsection Manager The Manager * All Z-Wave functionality is accessed via the Manager class. While this * does not make for the most efficient code structure, it does enable * the library to handle potentially complex and hard-to-debug issues * such as multi-threading and object lifespans behind the scenes. * Application development is therefore simplified and less prone to bugs. *

* \subsection Notifications Notifications * Communication between the PC and devices on the the Z-Wave network occurs * asynchronously. Some devices, notably movement sensors, sleep most of the * time to save battery power, and can only receive commands when awake. * Therefore a command to change a value in a device may not occur immediately. * It may take several seconds or minutes, or even never arrive at all. * For this reason, many OpenZWave methods, even those that request * information, do not return that information directly. A request will be * sent to the network, and the response sent to the application some time * later via a system of notification callbacks. The notification handler * will be at the core of any application using OpenZWave. It is here that * all information regarding device configurations and states will be reported. *

* A Z-Wave network is a dynamic entity. Controllers and devices can be * added or removed at any time. Once a network has been set up, this * probably won't happen very often, but OpenZWave, and any application * built upon it, must cope all the same. The notification callback system * is used to inform the application of any changes to the structure of the * network. * \subsection Values Working with Values * * \subsection Guidelines Application Development Guidelines * The main considerations when designing an application based upon * OpenZWave are: * * - Communication with Z-Wave devices is asynchronous and not guaranteed * 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 * 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 * with the addition and removal of devices. * * Some users will have more than one Z-Wave controller, to allow for remote * locations or to work around the 232 device limit. OpenZWave is designed * for use with multiple controllers, and all applications should be written * to support this. * * - There is no need to save the state of the network and restore it on * the next run. OpenZWave does this automatically, and is designed to cope * with any changes that occur to the network while the application is not * running. * *


* \section Structure Source Code Structure * *
* \section Samples Samples * The SDK package includes skeleton code for creating xPL-enabled * applications. Code is provided for three types of application - a Windows * service, a Windowed application, and a console application. The Windows * service is quite flexible - it will run as a console application if no * command line parameters are passed to it. This makes it possible to * ship one application that will run on all versions of Windows, whether or * not there is support for services. It is also useful for debugging. *

* The full source code for the W800RF32 service is also provided as a real * life example of using the SDK to build a complete xPL application. *


* \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 . *


* \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) *

*/ open-zwave-1.5/cpp/src/Driver.cpp000066400000000000000000006351501264474202400170010ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Driver.cpp // // Communicates with a Z-Wave network // // 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 . // //----------------------------------------------------------------------------- #include "Defs.h" #include "Driver.h" #include "Options.h" #include "Manager.h" #include "Node.h" #include "Msg.h" #include "Notification.h" #include "Scene.h" #include "ZWSecurity.h" #include "platform/Event.h" #include "platform/Mutex.h" #include "platform/SerialController.h" #ifdef WINRT #include "platform/winRT/HidControllerWinRT.h" #else #include "platform/HidController.h" #endif #include "platform/Thread.h" #include "platform/Log.h" #include "platform/TimeStamp.h" #include "command_classes/CommandClasses.h" #include "command_classes/ApplicationStatus.h" #include "command_classes/ControllerReplication.h" #include "command_classes/Security.h" #include "command_classes/WakeUp.h" #include "command_classes/SwitchAll.h" #include "command_classes/ManufacturerSpecific.h" #include "command_classes/NoOperation.h" #include "value_classes/ValueID.h" #include "value_classes/Value.h" #include "value_classes/ValueStore.h" #include "tinyxml.h" #include "Utils.h" #if defined(__unix__) || (defined(__APPLE__) && defined(__MACH__)) # include #elif defined _WIN32 # include #define sleep(x) Sleep(1000 * x) #endif #include #include using namespace OpenZWave; // Version numbering for saved configurations. Any change that will invalidate // previously saved configurations must be accompanied by an increment to the // version number, and a comment explaining the date of, and reason for, the change. // // 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; static char const* c_libraryTypeNames[] = { "Unknown", // library type 0 "Static Controller", // library type 1 "Controller", // library type 2 "Enhanced Slave", // library type 3 "Slave", // library type 4 "Installer", // library type 5 "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" }; static char const* c_sendQueueNames[] = { "Command", "Security", "NoOp", "Controller", "WakeUp", "Send", "Query", "Poll" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Driver::Driver ( string const& _controllerPath, ControllerInterface const& _interface ): m_driverThread( new Thread( "driver" ) ), m_initMutex(new Mutex()), m_exit( false ), m_init( false ), m_awakeNodesQueried( false ), m_allNodesQueried( false ), m_notifytransactions( false ), 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_nondelivery( 0 ), m_routedbusy( 0 ), m_broadcastReadCnt( 0 ), m_broadcastWriteCnt( 0 ), m_nonceReportSent( 0 ), m_nonceReportSentAttempt( 0 ) { // set a timestamp to indicate when this driver started TimeStamp m_startTime; // Create the message queue events for( int32 i=0; iSetSignalThreshold( 1 ); Options::Get()->GetOptionAsBool( "NotifyTransactions", &m_notifytransactions ); Options::Get()->GetOptionAsInt( "PollInterval", &m_pollInterval ); Options::Get()->GetOptionAsBool( "IntervalBetweenPolls", &m_bIntervalBetweenPolls ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 ); 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( save ) { WriteConfig(); Scene::WriteXML( "zwscene.xml" ); } } // The order of the statements below has been achieved by mitigating freed memory //references using a memory allocator checker. Do not rearrange unless you are //certain memory won't be referenced out of order. --Greg Satz, April 2010 m_initMutex->Lock(); m_exit = true; m_initMutex->Unlock(); m_pollThread->Stop(); m_pollThread->Release(); m_driverThread->Stop(); m_driverThread->Release(); m_sendMutex->Release(); m_controller->Close(); m_controller->Release(); m_initMutex->Release(); if( m_currentMsg != NULL ) { RemoveCurrentMsg(); } // Clear the node data { LockGuard LG(m_nodeMutex); for( int i=0; i<256; ++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 ); } } } // Don't release until all nodes have removed their poll values m_pollMutex->Release(); // Clear the send Queue for( int32 i=0; iRelease(); } /* Doing our Notification Call back here in the destructor is just asking for trouble * as there is a good chance that the application will do some sort of GetDriver() supported * method on the Manager Class, which by this time, most of the OZW Classes associated with the * Driver class is 99% destructed. (mainly nodes, which cascade to CC, which cascade to ValueID * classes etc). We might need a flag around the Manager::GetDriver() class that stops applications * from getting a half destructed Driver Reference, but still retain a Internal GetDriver() method * that can return half destructed Driver references for internal classes (as per Greg's note above) */ bool notify; if( Options::Get()->GetOptionAsBool( "NotifyOnDriverUnload", ¬ify) ) { if( notify ) { NotifyWatchers(); } } if (m_controllerReplication) delete m_controllerReplication; m_notificationsEvent->Release(); m_nodeMutex->Release(); } //----------------------------------------------------------------------------- // // Start the driver thread //----------------------------------------------------------------------------- void Driver::Start ( ) { // Start the thread that will handle communications with the Z-Wave network m_driverThread->Start( Driver::DriverThreadEntryPoint, this ); } //----------------------------------------------------------------------------- // // Entry point of the thread for creating and managing the worker threads //----------------------------------------------------------------------------- void Driver::DriverThreadEntryPoint ( Event* _exitEvent, void* _context ) { Driver* driver = (Driver*)_context; if( driver ) { driver->DriverThreadProc( _exitEvent ); } } //----------------------------------------------------------------------------- // // Create and manage the worker threads //----------------------------------------------------------------------------- void Driver::DriverThreadProc ( Event* _exitEvent ) { uint32 attempts = 0; while( true ) { if( Init( attempts ) ) { // Driver has been initialised Wait* waitObjects[11]; waitObjects[0] = _exitEvent; // Thread must exit. waitObjects[1] = m_notificationsEvent; // Notifications waiting to be sent. waitObjects[2] = m_controller; // Controller has received data. waitObjects[3] = m_queueEvent[MsgQueue_Command]; // A controller command is in progress. waitObjects[4] = m_queueEvent[MsgQueue_Security]; // Security Related Commands (As they have a timeout) waitObjects[5] = m_queueEvent[MsgQueue_NoOp]; // Send device probes and diagnostics messages waitObjects[6] = m_queueEvent[MsgQueue_Controller]; // A multi-part controller command is in progress waitObjects[7] = m_queueEvent[MsgQueue_WakeUp]; // A node has woken. Pending messages should be sent. waitObjects[8] = m_queueEvent[MsgQueue_Send]; // Ordinary requests to be sent. waitObjects[9] = m_queueEvent[MsgQueue_Query]; // Node queries are pending. waitObjects[10] = m_queueEvent[MsgQueue_Poll]; // Poll request is waiting. TimeStamp retryTimeStamp; int retryTimeout = RETRY_TIMEOUT; Options::Get()->GetOptionAsInt( "RetryTimeout", &retryTimeout ); //retryTimeout = RETRY_TIMEOUT * 10; while( true ) { Log::Write( LogLevel_StreamDetail, " Top of DriverThreadProc loop." ); uint32 count = 11; int32 timeout = Wait::Timeout_Infinite; // If we're waiting for a message to complete, we can only // handle incoming data, notifications and exit events. if( m_waitingForAck || m_expectedCallbackId || m_expectedReply ) { count = 3; timeout = m_waitingForAck ? ACK_TIMEOUT : retryTimeStamp.TimeRemaining(); if( timeout < 0 ) { timeout = 0; } } else if( m_currentControllerCommand != NULL ) { count = 7; } else { Log::QueueClear(); // clear the log queue when starting a new message } // Wait for something to do int32 res = Wait::Multiple( waitObjects, count, timeout ); switch( res ) { case -1: { // 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; } case 0: { // Exit has been signalled return; } case 1: { // Notifications are waiting to be sent NotifyWatchers(); break; } case 2: { // Data has been received ReadMsg(); break; } default: { // All the other events are sending message queue items if( WriteNextMsg( (MsgQueue)(res-3) ) ) { retryTimeStamp.SetTime( retryTimeout ); } break; } } } } ++attempts; uint32 maxAttempts = 0; Options::Get()->GetOptionAsInt("DriverMaxAttempts", (int32 *)&maxAttempts); if( maxAttempts && (attempts >= maxAttempts) ) { Manager::Get()->Manager::SetDriverReady(this, false); NotifyWatchers(); break; } if( attempts < 25 ) { // Retry every 5 seconds for the first two minutes if( Wait::Single( _exitEvent, 5000 ) == 0 ) { // Exit signalled. return; } } else { // Retry every 30 seconds after that if( Wait::Single( _exitEvent, 30000 ) == 0 ) { // Exit signalled. return; } } } } //----------------------------------------------------------------------------- // // Initialize the controller //----------------------------------------------------------------------------- bool Driver::Init ( uint32 _attempts ) { m_initMutex->Lock(); if (m_exit) { m_initMutex->Unlock(); return false; } m_Controller_nodeId = -1; m_waitingForAck = false; // Open the controller Log::Write( LogLevel_Info, " Opening controller %s", m_controllerPath.c_str() ); if( !m_controller->Open( m_controllerPath ) ) { 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 ); // Send a NAK to the ZWave device uint8 nak = NAK; m_controller->Write( &nak, 1 ); // Get/set ZWave controller information in its preferred initialization order 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 ); //msg->Append( 0xff ); //SendMsg( msg ); m_initMutex->Unlock(); // Init successful return true; } //----------------------------------------------------------------------------- // // Clean up any messages to a node //----------------------------------------------------------------------------- void Driver::RemoveQueues ( uint8 const _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() ) { bool remove = false; MsgQueueItem const& item = *it; 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 ) { remove = true; } else if( MsgQueueCmd_Controller == item.m_command && _nodeId == item.m_cci->m_controllerCommandNode && m_currentControllerCommand != item.m_cci ) { delete item.m_cci; remove = true; } if( remove ) { it = m_msgQueue[i].erase( it ); } else { ++it; } } if( m_msgQueue[i].empty() ) { m_queueEvent[i]->Reset(); } } } //----------------------------------------------------------------------------- // Configuration //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Read our configuration from an XML document //----------------------------------------------------------------------------- bool Driver::ReadConfig ( ) { char str[32]; int32 intVal; // Load the XML document that contains the driver configuration string userPath; Options::Get()->GetOptionAsString( "UserPath", &userPath ); 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 ) ) { return false; } TiXmlElement const* driverElement = doc.RootElement(); // Version if( TIXML_SUCCESS != driverElement->QueryIntAttribute( "version", &intVal ) || (uint32)intVal != c_configVersion ) { Log::Write( LogLevel_Warning, "WARNING: Driver::ReadConfig - %s is from an older version of OpenZWave and cannot be loaded.", filename.c_str() ); return false; } // Home ID char const* homeIdStr = driverElement->Attribute( "home_id" ); if( homeIdStr ) { char* p; uint32 homeId = (uint32)strtoul( homeIdStr, &p, 0 ); if( homeId != m_homeId ) { Log::Write( LogLevel_Warning, "WARNING: Driver::ReadConfig - Home ID in file %s is incorrect", filename.c_str() ); return false; } } else { Log::Write( LogLevel_Warning, "WARNING: Driver::ReadConfig - Home ID is missing from file %s", filename.c_str() ); return false; } // Node ID if( TIXML_SUCCESS == driverElement->QueryIntAttribute( "node_id", &intVal ) ) { if( (uint8)intVal != m_Controller_nodeId ) { Log::Write( LogLevel_Warning, "WARNING: Driver::ReadConfig - Controller Node ID in file %s is incorrect", filename.c_str() ); return false; } } else { Log::Write( LogLevel_Warning, "WARNING: Driver::ReadConfig - Node ID is missing from file %s", filename.c_str() ); return false; } // Capabilities if( TIXML_SUCCESS == driverElement->QueryIntAttribute( "api_capabilities", &intVal ) ) { m_initCaps = (uint8)intVal; } if( TIXML_SUCCESS == driverElement->QueryIntAttribute( "controller_capabilities", &intVal ) ) { m_controllerCaps = (uint8)intVal; } // Poll Interval 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 ) { m_bIntervalBetweenPolls = !strcmp( str, "true" ); } // Read the nodes LockGuard LG(m_nodeMutex); TiXmlElement const* nodeElement = driverElement->FirstChildElement(); while( nodeElement ) { char const* str = nodeElement->Value(); if( str && !strcmp( str, "Node" ) ) { // Get the node Id from the XML if( TIXML_SUCCESS == nodeElement->QueryIntAttribute( "id", &intVal ) ) { 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 ); // Read the rest of the node configuration from the XML node->ReadXML( nodeElement ); } } nodeElement = nodeElement->NextSiblingElement(); } LG.Unlock(); // restore the previous state (for now, polling) for the nodes/values just retrieved for( int i=0; i<256; i++ ) { if( m_nodes[i] != NULL ) { ValueStore* vs = m_nodes[i]->m_values; for( ValueStore::Iterator it = vs->Begin(); it != vs->End(); ++it ) { Value* value = it->second; if( value->m_pollIntensity != 0 ) EnablePoll( value->GetID(), value->m_pollIntensity ); } } } return true; } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- void Driver::WriteConfig ( ) { char str[32]; if (!m_homeId) { Log::Write( LogLevel_Warning, "WARNING: Tried to write driver config with no home ID set"); return; } // 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 ); driverElement->SetAttribute( "xmlns", "http://code.google.com/p/open-zwave/" ); snprintf( str, sizeof(str), "%d", c_configVersion ); driverElement->SetAttribute( "version", 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_initCaps ); driverElement->SetAttribute( "api_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), "%s", m_bIntervalBetweenPolls ? "true" : "false" ); driverElement->SetAttribute( "poll_interval_between", str ); { LockGuard LG(m_nodeMutex); for( int i=0; i<256; ++i ) { if( m_nodes[i] ) { m_nodes[i]->WriteXML( driverElement ); } } } string userPath; Options::Get()->GetOptionAsString( "UserPath", &userPath ); snprintf( str, sizeof(str), "ozwcache_0x%08x.xml", m_homeId ); string filename = userPath + string(str); doc.SaveFile( filename.c_str() ); } //----------------------------------------------------------------------------- // Controller //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Returns a pointer to the requested node without locking. // Only to be used by main thread code. //----------------------------------------------------------------------------- Node* Driver::GetNodeUnsafe ( uint8 _nodeId ) { if( Node* node = m_nodes[_nodeId] ) { return node; } return NULL; } //----------------------------------------------------------------------------- // // Locks the nodes and returns a pointer to the requested one //----------------------------------------------------------------------------- Node* Driver::GetNode ( uint8 _nodeId ) { 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] ) { return node; } return NULL; } //----------------------------------------------------------------------------- // Sending Z-Wave messages //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Queue an item on the query queue that indicates a stage is complete //----------------------------------------------------------------------------- void Driver::SendQueryStageComplete ( uint8 const _nodeId, Node::QueryStage const _stage ) { MsgQueueItem item; item.m_command = MsgQueueCmd_QueryStageComplete; item.m_nodeId = _nodeId; item.m_queryStage = _stage; item.m_retry = false; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { if( !node->IsListeningDevice() ) { if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) { 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 ); 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() ); m_sendMutex->Lock(); m_msgQueue[MsgQueue_Query].push_back( item ); m_queueEvent[MsgQueue_Query]->Set(); m_sendMutex->Unlock(); } } //----------------------------------------------------------------------------- // // Request the current stage will be repeated //----------------------------------------------------------------------------- void Driver::RetryQueryStageComplete ( uint8 const _nodeId, Node::QueryStage const _stage ) { MsgQueueItem item; item.m_command = MsgQueueCmd_QueryStageComplete; item.m_nodeId = _nodeId; item.m_queryStage = _stage; m_sendMutex->Lock(); for( list::iterator it = m_msgQueue[MsgQueue_Query].begin(); it != m_msgQueue[MsgQueue_Query].end(); ++it ) { if( *it == item ) { (*it).m_retry = true; break; } } m_sendMutex->Unlock(); } //----------------------------------------------------------------------------- // // Queue a message to be sent to the Z-Wave PC Interface //----------------------------------------------------------------------------- void Driver::SendMsg ( Msg* _msg, MsgQueue const _queue ) { MsgQueueItem item; item.m_command = MsgQueueCmd_SendMsg; item.m_msg = _msg; /* make sure the HomeId is Set on this message */ _msg->SetHomeId(m_homeId); _msg->Finalize(); { 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() ) ) { 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()); item.m_msg->setEncrypted(); } } // If the message is for a sleeping node, we queue it in the node itself. if( !node->IsListeningDevice() ) { if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) { if( !wakeUp->IsAwake() ) { Log::Write( LogLevel_Detail, "" ); // Handle saving multi-step controller commands if( m_currentControllerCommand != NULL ) { 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_msg = NULL; UpdateControllerState( ControllerState_Sleeping ); } else { Log::Write( LogLevel_Detail, GetNodeNumber( _msg ), "Queuing (%s) %s", c_sendQueueNames[MsgQueue_WakeUp], _msg->GetAsString().c_str() ); } wakeUp->QueueMsg( item ); return; } } } } } 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_queueEvent[_queue]->Set(); m_sendMutex->Unlock(); } //----------------------------------------------------------------------------- // // Transmit a queued message to the Z-Wave controller //----------------------------------------------------------------------------- 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 ) { // Send a message m_currentMsg = item.m_msg; m_currentMsgQueueSource = _queue; m_msgQueue[_queue].pop_front(); if( m_msgQueue[_queue].empty() ) { m_queueEvent[_queue]->Reset(); } m_sendMutex->Unlock(); return WriteMsg( "WriteNextMsg" ); } 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() ) { m_queueEvent[_queue]->Reset(); } m_sendMutex->Unlock(); 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 ) { node->QueryStageComplete( stage ); } node->AdvanceQueries(); return true; } } 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 ) { m_sendMutex->Lock(); m_msgQueue[_queue].pop_front(); if( m_msgQueue[_queue].empty() ) { m_queueEvent[_queue]->Reset(); } m_sendMutex->Unlock(); if( m_currentControllerCommand->m_controllerCallback ) { 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 ) { DoControllerCommand(); } else if( m_currentControllerCommand->m_controllerStateChanged ) { if( m_currentControllerCommand->m_controllerCallback ) { 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" ); m_sendMutex->Lock(); m_queueEvent[_queue]->Reset(); m_sendMutex->Unlock(); } return true; } return false; } //----------------------------------------------------------------------------- // // Transmit the current message to the Z-Wave controller //----------------------------------------------------------------------------- bool Driver::WriteMsg ( string const &msg ) { if( !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; m_expectedNodeId = 0; m_expectedReply = 0; m_waitingForAck = false; return false; } /* if this is called with m_nonceReportSent > 0 it means that we have * tried to send a NONCE report and it timed out or was NAK'd * */ uint8 attempts; uint8 nodeId; if (m_nonceReportSent > 0) { attempts = m_nonceReportSentAttempt++; nodeId = m_nonceReportSent; } 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() ) ) { if( node != NULL && !node->IsNodeAlive() ) { 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() ); } if( m_currentControllerCommand != NULL ) { /* its a ControllerCommand that is failed */ UpdateControllerState( ControllerState_Error, ControllerError_Failed); } RemoveCurrentMsg(); m_dropped++; return false; } if (( attempts != 0) && (m_nonceReportSent == 0)) { // this is not the first attempt, so increment the callback id before sending m_currentMsg->UpdateCallbackId(); } /* XXX TODO: Minor Bug - Due to the post increament of the SendAttempts, it means our final NONCE_GET will go though * but the subsequent MSG send will fail (as the counter is incremented only upon a successful NONCE_GET, and Not a Send * */ 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(); m_expectedNodeId = m_currentMsg->GetTargetNodeId(); m_expectedReply = m_currentMsg->GetExpectedReply(); m_waitingForAck = true; } string attemptsstr = ""; if( attempts > 1 ) { char buf[15]; snprintf( buf, sizeof(buf), "Attempt %d, ", attempts ); attemptsstr = buf; m_retries++; if( node != NULL ) { node->m_retries++; } } Log::Write( LogLevel_Detail, "" ); if (m_nonceReportSent > 0) { /* 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() ); 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); 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() ); uint32 bytesWritten = m_controller->Write(m_currentMsg->GetBuffer(), m_currentMsg->GetLength()); if (bytesWritten == 0) { //0 will be returned when the port is closed or something bad happened //so send notification Notification* notification = new Notification(Notification::Type_DriverFailed); notification->SetHomeAndNodeIds(m_homeId, m_currentMsg->GetTargetNodeId()); QueueNotification(notification); NotifyWatchers(); m_driverThread->Stop(); return false; } } m_writeCnt++; if( nodeId == 0xff ) { m_broadcastWriteCnt++; // not accurate since library uses 0xff for the controller too } else { if( node != NULL ) { node->m_sentCnt++; node->m_sentTS.SetTime(); if( m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER ) { CommandClass *cc = node->GetCommandClass(m_expectedCommandClassId); if( cc != NULL ) { cc->SentCntIncr(); } } } } return true; } //----------------------------------------------------------------------------- // // Delete the current message //----------------------------------------------------------------------------- void Driver::RemoveCurrentMsg ( ) { Log::Write( LogLevel_Detail, GetNodeNumber( m_currentMsg ), "Removing current message" ); if( m_currentMsg != NULL) { delete m_currentMsg; m_currentMsg = NULL; } m_expectedCallbackId = 0; m_expectedCommandClassId = 0; m_expectedNodeId = 0; m_expectedReply = 0; m_waitingForAck = false; m_nonceReportSent = 0; m_nonceReportSentAttempt = 0; } //----------------------------------------------------------------------------- // // Move messages for a sleeping device to its wake-up queue //----------------------------------------------------------------------------- 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->IsListeningDevice() && !node->IsFrequentListeningDevice() && _targetNodeId != m_Controller_nodeId ) { if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) { // Mark the node as asleep wakeUp->SetAwake( false ); // If we need to save the messages 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 ) { // Don't save controller message as it will be recreated RemoveCurrentMsg(); } // Then try the current message first if( m_currentMsg ) { 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() ) { 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 ); } else { delete m_currentMsg; } m_currentMsg = NULL; m_expectedCallbackId = 0; m_expectedCommandClassId = 0; m_expectedNodeId = 0; m_expectedReply = 0; m_waitingForAck = false; } } // Now the message queues for( int i=0; i::iterator it = m_msgQueue[i].begin(); while( it != m_msgQueue[i].end() ) { bool remove = false; MsgQueueItem const& item = *it; if( MsgQueueCmd_SendMsg == item.m_command ) { 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() ) { 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 ); } else { delete item.m_msg; } remove = true; } } if( MsgQueueCmd_QueryStageComplete == item.m_command ) { if( _targetNodeId == item.m_nodeId ) { Log::Write( LogLevel_Info, _targetNodeId, "Node not responding - moving QueryStageComplete command to Wake-Up queue" ); wakeUp->QueueMsg( item ); remove = true; } } if( MsgQueueCmd_Controller == item.m_command ) { 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] ); wakeUp->QueueMsg( item ); remove = true; } } if( remove ) { it = m_msgQueue[i].erase( it ); } else { ++it; } } // If the queue is now empty, we need to clear its event if( m_msgQueue[i].empty() ) { m_queueEvent[i]->Reset(); } } if( m_currentControllerCommand ) { // Put command back on queue so it will be cleaned up UpdateControllerState( ControllerState_Sleeping ); MsgQueueItem item; item.m_command = MsgQueueCmd_Controller; item.m_cci = new ControllerCommandItem( *m_currentControllerCommand ); m_currentControllerCommand = item.m_cci; m_msgQueue[MsgQueue_Controller].push_back( item ); m_queueEvent[MsgQueue_Controller]->Set(); } m_sendMutex->Unlock(); // Move completed successfully return true; } } } } // Failed to move messages return false; } //----------------------------------------------------------------------------- // // 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 ) { // Only called with a ZW_SEND_DATA error response. We count and output the message here. if( _error == TRANSMIT_COMPLETE_NOROUTE ) { m_badroutes++; Log::Write( LogLevel_Info, _nodeId, "ERROR: %s failed. No route available.", _funcStr ); } 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 ) { // 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 ) ) { return true; } Log::Write( LogLevel_Warning, _nodeId, "WARNING: Device is not a sleeping node." ); } } else if( _error == TRANSMIT_COMPLETE_FAIL ) { m_netbusy++; Log::Write( LogLevel_Info, _nodeId, "ERROR: %s failed. Network is busy.", _funcStr ); } else if( _error == TRANSMIT_COMPLETE_NOT_IDLE ) { m_notidle++; Log::Write( LogLevel_Info, _nodeId, "ERROR: %s failed. Network is busy.", _funcStr ); } if( Node* node = GetNodeUnsafe( _nodeId ) ) { if( ++node->m_errors >= 3 ) { node->SetNodeAlive( false ); } } return false; } //----------------------------------------------------------------------------- // // Identify controller (as opposed to node) commands...especially blocking ones //----------------------------------------------------------------------------- void Driver::CheckCompletedNodeQueries ( ) { 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 ) { if( m_nodes[i] ) { if( m_nodes[i]->GetCurrentQueryStage() != Node::QueryStage_Complete ) { if ( !m_nodes[i]->IsNodeAlive() ) { deadFound = true; continue; } all = false; if( m_nodes[i]->IsListeningDevice() ) { sleepingOnly = false; } } } } LG.Unlock(); Log::Write( LogLevel_Warning, "CheckCompletedNodeQueries all=%d, deadFound=%d sleepingOnly=%d", all, deadFound, sleepingOnly ); if( all ) { 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 ); } 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 ); } m_awakeNodesQueried = true; m_allNodesQueried = true; } else if( sleepingOnly ) { 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 ); m_awakeNodesQueried = true; } } } } //----------------------------------------------------------------------------- // // Determine if the reply is from the node we are expecting. //----------------------------------------------------------------------------- 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 ) { 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 ) { return true; } // Accept if source message contains node info and it is from the one we are expecting if( m_expectedNodeId == _nodeId ) { return true; } Log::Write( LogLevel_Detail, "IsExpectedReply: m_expectedNodeId = %d m_expectedReply = %02x", m_expectedNodeId, m_expectedReply ); return false; } //----------------------------------------------------------------------------- // Receiving Z-Wave messages //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Read data from the serial port //----------------------------------------------------------------------------- bool Driver::ReadMsg ( ) { uint8 buffer[1024] = {0}; if( !m_controller->Read( buffer, 1 ) ) { // Nothing to read return false; } switch( buffer[0] ) { case SOF: { 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; } 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[2], buffer[1] ); m_controller->SetSignalThreshold( 1 ); uint32 length = buffer[1] + 2; // Log the data string str = ""; for( uint32 i=0; iWrite( &ack, 1 ); m_readCnt++; // Process the received message ProcessMsg( &buffer[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; } 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 { Log::Write( LogLevel_Warning, "m_currentMsg was NULL when trying to set MaxSendAttempts" ); Log::QueueDump(); } 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 ) { 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; } 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; } //----------------------------------------------------------------------------- // // Process data received from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::ProcessMsg ( uint8* _data ) { bool handleCallback = true; bool wasencrypted = false; //uint8 nodeId = GetNodeNumber( m_currentMsg ); if ((REQUEST == _data[0]) && (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] ); // No Need to triger a WriteMsg here - It should be handled automatically m_currentMsg->setNonce(&_data[7]); this->SendEncryptedMessage(); 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] ); { uint8 *nonce = NULL; LockGuard LG(m_nodeMutex); Node* node = GetNode( _data[3] ); if( node ) { nonce = node->GenerateNonceKey(); } else { Log::Write(LogLevel_Warning, _data[3], "Couldn't Generate Nonce Key for Node %d", _data[3]); return; } SendNonceKey(_data[3], nonce); } /* don't continue processing */ return; /* if this message is encrypted, decrypt it first */ } else if ((SecurityCmd_MessageEncap == _data[6]) || (SecurityCmd_MessageEncapNonceGet == _data[6])) { uint8 _newdata[256]; uint8 *_nonce; /* clear out NONCE Report tracking */ m_nonceReportSent = 0; m_nonceReportSentAttempt = 0; /* 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) { Log::Write(LogLevel_Warning, _data[3], "Could Not Retrieve Nonce for Node %d", _data[3]); return; } } 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])) { /* 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*/ _data[4] = _data[4] - 8 - 8 - 2 - 2; /* now copy the decrypted packet */ memcpy(&_data[5], &_newdata[1], _data[4]); //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 == _data[6]) { 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 ) { _nonce = node->GenerateNonceKey(); } else { Log::Write(LogLevel_Warning, _data[3], "Couldn't Generate Nonce Key for Node %d", _data[3]); return; } SendNonceKey(_data[3], _nonce); } wasencrypted = true; } else { /* it failed for some reason, lets just move on */ m_expectedReply = 0; m_expectedNodeId = 0; RemoveCurrentMsg(); return; } } } 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_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: { 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: { Log::Write( LogLevel_Detail, "" ); if( _data[2] ) { Log::Write( LogLevel_Info, _data[3], "FUNC_ID_ZW_REQUEST_NODE_INFO Request successful." ); } else { Log::Write( LogLevel_Info, _data[3], "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; } 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] ) { 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, 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, 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; } 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 ) { if( ( m_expectedCallbackId || m_expectedReply ) ) { if( m_expectedCallbackId ) { if( m_expectedCallbackId == _data[2] ) { Log::Write( LogLevel_Detail, _data[3], " Expected callbackId was received" ); m_expectedCallbackId = 0; } else if (_data[2] == 0x02 || _data[2] == 0x01) { /* it was a NONCE request/reply. Drop it */ return; } } if( m_expectedReply ) { if( m_expectedReply == _data[1] ) { if( m_expectedCommandClassId && ( m_expectedReply == FUNC_ID_APPLICATION_COMMAND_HANDLER ) ) { 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" ); m_waitingForAck = false; m_expectedReply = 0; m_expectedCommandClassId = 0; m_expectedNodeId = 0; } } else { if( IsExpectedReply( _data[3] ) ) { Log::Write( LogLevel_Detail, _data[3], " Expected reply was received" ); m_expectedReply = 0; m_expectedNodeId = 0; } } } } if( !( m_expectedCallbackId || m_expectedReply ) ) { Log::Write( LogLevel_Detail, _data[3], " Message transaction complete" ); Log::Write( LogLevel_Detail, "" ); if( m_notifytransactions ) { Notification* notification = new Notification( Notification::Type_Notification ); notification->SetHomeAndNodeIds( m_homeId, _data[3] ); notification->SetNotification( Notification::Code_MsgComplete ); QueueNotification( notification ); } RemoveCurrentMsg(); } } } } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleGetVersionResponse ( uint8* _data ) { m_libraryVersion = (char*)&_data[2]; 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() ); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleGetRandomResponse ( uint8* _data ) { Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to FUNC_ID_ZW_GET_RANDOM: %s", _data[2] ? "true" : "false" ); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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:" ); char str[256]; 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 ); } 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 ); } } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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] ); // _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 ) ); if( IsBridgeController() ) { SendMsg( new Msg( "FUNC_ID_ZW_GET_VIRTUAL_NODES", 0xff, REQUEST, FUNC_ID_ZW_GET_VIRTUAL_NODES, false ), MsgQueue_Command); } else 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 ); } SendMsg( new 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 ); } 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 msg->Append( 0x00 ); // Length SendMsg( msg, MsgQueue_Command ); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleSerialAPISoftResetResponse ( uint8* _data ) { 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 ) { Log::Write( LogLevel_Info, GetNodeNumber( m_currentMsg ), "Received reply to complete Controller Reset." ); if( m_controllerResetEvent != NULL ) { m_controllerResetEvent->Set(); m_controllerResetEvent = NULL; } } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleEnableSUCResponse ( uint8* _data ) { 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 res = true; ControllerState state = ControllerState_InProgress; if( _data[2] ) { 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" ); state = ControllerState_Failed; res = false; } UpdateControllerState( state ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleSetSUCNodeIdResponse ( uint8* _data ) { 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 ) { 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) { 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"); } } else { Log::Write( LogLevel_Info, " No SUC, not becoming SUC as option is disabled" ); } } } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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] ); m_Controller_nodeId = _data[6]; m_controllerReplication = static_cast(ControllerReplication::Create( m_homeId, m_Controller_nodeId )); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleSerialAPIGetInitDataResponse ( uint8* _data ) { int32 i; 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 ); // Read the config file first, to get the last known state ReadConfig(); } else { // 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 ); } 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 ) { for( i=0; iSetQueryStage( 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 ); // Create the node and request its info InitNode( nodeId ); } } } else { 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 ); delete m_nodes[nodeId]; m_nodes[nodeId] = NULL; Notification* notification = new Notification( Notification::Type_NodeRemoved ); notification->SetHomeAndNodeIds( m_homeId, nodeId ); QueueNotification( notification ); } } } } } m_init = true; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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 ) { 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" ); // Update the node with the protocol info if( Node* node = GetNodeUnsafe( nodeId ) ) { node->UpdateProtocolInfo( &_data[2] ); } } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- bool Driver::HandleAssignReturnRouteResponse ( uint8* _data ) { bool res = true; ControllerState state = ControllerState_InProgress; if( _data[2] ) { 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" ); state = ControllerState_Failed; res = false; } UpdateControllerState( state ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- bool Driver::HandleDeleteReturnRouteResponse ( uint8* _data ) { bool res = true; ControllerState state = ControllerState_InProgress; if( _data[2] ) { 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" ); state = ControllerState_Failed; res = false; } UpdateControllerState( state ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- bool Driver::HandleRemoveFailedNodeResponse ( uint8* _data ) { bool res = true; ControllerState state = ControllerState_InProgress; ControllerError error = ControllerError_None; 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: { 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() ); 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" ); } UpdateControllerState( state, error ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleIsFailedNodeResponse ( uint8* _data ) { ControllerState state; 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 ); state = ControllerState_NodeFailed; if( Node* node = GetNodeUnsafe( nodeId ) ) { 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 ); state = ControllerState_Completed; } 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 ) ) { node->SetNodeAlive( true ); } state = ControllerState_NodeOK; } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- bool Driver::HandleReplaceFailedNodeResponse ( uint8* _data ) { bool res = true; ControllerState state = ControllerState_InProgress; if( _data[2] ) { // 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" ); } UpdateControllerState( state ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleSendDataResponse ( uint8* _data, bool _replication ) { if( _data[2] ) { 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" ); m_nondelivery++; if( Node* node = GetNodeUnsafe( GetNodeNumber( m_currentMsg ) ) ) { node->m_sentFailed++; } } } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleGetRoutingInfoResponse ( uint8* _data ) { 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 ) ) ) { // 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:" ); bool bNeighbors = false; for( int by=0; by<29; by++ ) { 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, 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 ); /* Callback ID's below 10 are reserved for NONCE messages */ 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 ) { if( _data[3] != 0 ) { node->m_sentFailed++; } else { node->m_lastRequestRTT = -node->m_sentTS.TimeRemaining(); 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; } 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 ); } } // We do this here since HandleErrorResponse/MoveMessagesToWakeUpQueue can delete m_currentMsg 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 ); } // Callback ID matches our expectation if( _data[3] != 0 ) { 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 ) ) { node->QueryStageRetry( node->GetCurrentQueryStage(), 3 ); } } } else if( node != NULL ) { // If WakeUpNoMoreInformation request succeeds, update our status if( m_currentMsg && m_currentMsg->IsWakeUpNoMoreInformationCommand() ) { if( WakeUp* wakeUp = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) { // Mark the node as asleep wakeUp->SetAwake( false ); } } // If node is not alive, mark it alive now if( !node->IsNodeAlive() ) { node->SetNodeAlive( true ); } } // Command reception acknowledged by node, error or not, but ignore any NONCE messages // // m_expectedCallbackId = 0; } } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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: { 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 ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- 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 ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleRemoveNodeFromNetworkRequest ( uint8* _data ) { //uint8 nodeId = GetNodeNumber( m_currentMsg ); if( m_currentControllerCommand == NULL ) { return; } ControllerState state = m_currentControllerCommand->m_controllerState; 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: { 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) { 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: { 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 { if( _data[5] >= 3 ) { LockGuard LG(m_nodeMutex); for( int i=0; i<256; i++ ) { if( m_nodes[i] == NULL ) { continue; } // Ignore primary controller if( m_nodes[i]->m_nodeId == m_Controller_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." ); } } 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 ) { // 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 { 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 ) { LockGuard LG(m_nodeMutex); delete m_nodes[m_currentControllerCommand->m_controllerCommandNode]; m_nodes[m_currentControllerCommand->m_controllerCommandNode] = NULL; LG.Unlock(); 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; } } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleControllerChangeRequest ( uint8* _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 ) { 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 ) { 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:" ); switch( _data[3] ) { 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 ); // 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 ); // 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; } } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleRemoveFailedNodeRequest ( uint8* _data ) { ControllerState state = ControllerState_Completed; uint8 nodeId = GetNodeNumber( m_currentMsg ); switch( _data[3] ) { case FAILED_NODE_OK: { 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; LockGuard LG(m_nodeMutex); delete m_nodes[m_currentControllerCommand->m_controllerCommandNode]; m_nodes[m_currentControllerCommand->m_controllerCommandNode] = NULL; LG.Unlock(); 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; } } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- 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: { 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 ) { InitNode( m_currentControllerCommand->m_controllerCommandNode, true ); } 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 ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleApplicationCommandHandlerRequest ( uint8* _data, bool encrypted ) { uint8 status = _data[2]; uint8 nodeId = _data[3]; uint8 classId = _data[5]; Node* node = GetNodeUnsafe( nodeId ); if( ( status & RECEIVE_STATUS_ROUTED_BUSY ) != 0 ) { m_routedbusy++; } if( ( status & RECEIVE_STATUS_TYPE_BROAD ) != 0 ) { m_broadcastReadCnt++; } 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 ) { // if the exact same sequence of bytes are received within 500ms node->m_receivedDups++; } else { memcpy( node->m_lastReceivedMessage, _data, sizeof(node->m_lastReceivedMessage) ); } node->m_receivedTS.SetTime(); 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 the average has been established, update by averaging the average and the last RTT 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 ); } else { node->m_receivedUnsolicited++; } if ( !node->IsNodeAlive() ) { node->SetNodeAlive( true ); } } if( ApplicationStatus::StaticGetCommandClassId() == classId ) { //TODO: Test this class function or implement } else if( ControllerReplication::StaticGetCommandClassId() == classId ) { if( m_controllerReplication && m_currentControllerCommand && ( ControllerCommand_ReceiveConfiguration == m_currentControllerCommand->m_controllerCommand ) ) { m_controllerReplication->HandleMsg( &_data[6], _data[4] ); UpdateControllerState( ControllerState_InProgress ); } } else { // Allow the node to handle the message itself if( node != NULL ) { node->ApplicationCommandHandler( _data, encrypted ); } } } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface when in promiscuous mode. //----------------------------------------------------------------------------- void Driver::HandlePromiscuousApplicationCommandHandlerRequest ( uint8* _data ) { //uint8 nodeId = _data[3]; //uint8 len = _data[4]; //uint8 classId = _data[5]; //uint8 destNodeId = _data[5+len]; } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleAssignReturnRouteRequest ( uint8* _data ) { ControllerState state; uint8 nodeId = GetNodeNumber( m_currentMsg ); if( m_currentControllerCommand == NULL ) { return; } if( _data[3] ) { // Failed 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 ); state = ControllerState_Completed; } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleDeleteReturnRouteRequest ( uint8* _data ) { ControllerState state; uint8 nodeId = GetNodeNumber( m_currentMsg ); if( m_currentControllerCommand == NULL ) { return; } if( _data[3] ) { // Failed 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 ); state = ControllerState_Completed; } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleSendNodeInformationRequest ( uint8* _data ) { ControllerState state; uint8 nodeId = GetNodeNumber( m_currentMsg ); if( m_currentControllerCommand == NULL ) { return; } if( _data[3] ) { // Failed 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" ); state = ControllerState_Completed; } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleNodeNeighborUpdateRequest ( uint8* _data ) { uint8 nodeId = GetNodeNumber( m_currentMsg ); ControllerState state = ControllerState_Normal; switch( _data[3] ) { 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 ) { RequestNodeNeighbors( m_currentControllerCommand->m_controllerCommandNode, 0 ); } break; } case REQUEST_NEIGHBOR_UPDATE_FAILED: { Log::Write( LogLevel_Warning, nodeId, "WARNING: REQUEST_NEIGHBOR_UPDATE_FAILED" ); state = ControllerState_Failed; break; } default: { break; } } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- bool Driver::HandleApplicationUpdateRequest ( uint8* _data ) { bool messageRemoved = false; uint8 nodeId = _data[3]; Node* node = GetNodeUnsafe( nodeId ); // If node is not alive, mark it alive now if( node != NULL && !node->IsNodeAlive() ) { node->SetNodeAlive( true ); } switch( _data[2] ) { case UPDATE_STATE_SUC_ID: { 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: { Log::Write( LogLevel_Info, nodeId, "** Network change **: Z-Wave node %d was removed", nodeId ); LockGuard LG(m_nodeMutex); delete m_nodes[nodeId]; m_nodes[nodeId] = NULL; LG.Unlock(); 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 ); // Request the node protocol info (also removes any existing node and creates a new one) InitNode( nodeId ); 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 ) { Node* tnode = GetNodeUnsafe( m_currentMsg->GetTargetNodeId() ); if( tnode ) { // 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; } 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 ) { node->UpdateNodeInfo( &_data[8], _data[4] - 3 ); } break; } } if( messageRemoved ) { m_waitingForAck = false; m_expectedCallbackId = 0; m_expectedReply = 0; m_expectedCommandClassId = 0; m_expectedNodeId = 0; } return messageRemoved; } //----------------------------------------------------------------------------- // // Handle common AddNode processing for many similar commands //----------------------------------------------------------------------------- void Driver::CommonAddNodeStatusRequestHandler ( uint8 _funcId, uint8* _data ) { uint8 nodeId = GetNodeNumber( m_currentMsg ); ControllerState state = ControllerState_Normal; 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: { 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: { 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; 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; } 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(); // Get the controller out of add mode to avoid accidentally adding other devices. AddNodeStop( _funcId ); break; } default: { break; } } UpdateControllerState( state ); } //----------------------------------------------------------------------------- // Polling Z-Wave devices //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Enable polling of a value //----------------------------------------------------------------------------- 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 ) { // confirm that this value is in the node's value store if( Value* value = node->GetValue( _valueId ) ) { // update the value's pollIntensity 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 ) { 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)" ); value->Release(); m_pollMutex->Unlock(); return true; } } // Not in the list, so we add it PollEntry pe; pe.m_id = _valueId; pe.m_pollCounter = value->GetPollIntensity(); 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() ); 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 ); return false; } // allow the poll thread to continue m_pollMutex->Unlock(); Log::Write( LogLevel_Info, "EnablePoll failed - node %d not found", nodeId ); return false; } //----------------------------------------------------------------------------- // // Disable polling of a node //----------------------------------------------------------------------------- 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) { // See if the value is already in the poll list. for( list::iterator it = m_pollList.begin(); it != m_pollList.end(); ++it ) { if( (*it).m_id == _valueId ) { // Found it // remove it from the poll list m_pollList.erase( it ); // get the value object and reset pollIntensity to zero (indicating no polling) Value* value = GetValue( _valueId ); if (!value) continue; 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() ); return true; } } // Not in the list m_pollMutex->Unlock(); 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 ); return false; } //----------------------------------------------------------------------------- // // Check polling status of a value //----------------------------------------------------------------------------- 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 ) { bPolled = true; } else { bPolled = false; } if (value) value->Release(); /* * This code is retained for the moment as a belt-and-suspenders test to confirm that * the pollIntensity member of each value and the pollList contents do not get out * of sync. */ // confirm that this node exists uint8 nodeId = _valueId.GetNodeId(); 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 ) { if( (*it).m_id == _valueId ) { // Found it 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() ); } } } // Not in the list 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() ); } } // 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" ); return false; } //----------------------------------------------------------------------------- // // Set the intensity with which this value is polled //----------------------------------------------------------------------------- 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 ); if (!value) return; value->SetPollIntensity( _intensity ); value->Release(); m_pollMutex->Unlock(); } //----------------------------------------------------------------------------- // // Entry point of the thread for poll Z-Wave devices //----------------------------------------------------------------------------- void Driver::PollThreadEntryPoint ( Event* _exitEvent, void* _context ) { Driver* driver = (Driver*)_context; if( driver ) { driver->PollThreadProc( _exitEvent ); } } //----------------------------------------------------------------------------- // // Thread for poll Z-Wave devices //----------------------------------------------------------------------------- void Driver::PollThreadProc ( Event* _exitEvent ) { while( 1 ) { int32 pollInterval = m_pollInterval; if( m_awakeNodesQueried && !m_pollList.empty() ) { // We only bother getting the lock if the pollList is not empty m_pollMutex->Lock(); // Get the next value to be polled PollEntry pe = m_pollList.front(); m_pollList.pop_front(); 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) { pe.m_pollCounter--; m_pollList.push_back( pe ); m_pollMutex->Unlock(); continue; } // 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 ); if (!value) continue; pe.m_pollCounter = value->GetPollIntensity(); 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( 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 ); pollInterval *= 1000; } pollInterval /= (int32) m_pollList.size(); } { LockGuard LG(m_nodeMutex); // Request the state of the value from the node to which it belongs if( Node* node = GetNode( valueId.GetNodeId() ) ) { bool requestState = true; 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( !wakeUp->IsAwake() ) { wakeUp->SetPollRequired(); requestState = false; } } } if( requestState ) { // Request an update of the value CommandClass* cc = node->GetCommandClass( valueId.GetCommandClassId() ); if (cc) { uint8 index = valueId.GetIndex(); uint8 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 ); } } } } m_pollMutex->Unlock(); // Polling messages are only sent when there are no other messages waiting to be sent // While this makes the polls much more variable and uncertain if some other activity dominates // a send queue, that may be appropriate // TODO we can have a debate about whether to test all four queues or just the Poll queue // 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 ) { // Exit has been called return; } loopCount++; 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::QueueDump(); // assert( 0 ); } } // ready for next poll...insert the pollInterval delay i32 = Wait::Single( _exitEvent, pollInterval ); if( i32 == 0 ) { // Exit has been called return; } } 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 ) { // Exit has been called return; } } } } //----------------------------------------------------------------------------- // Retrieving Node information //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Delete all nodes and fetch new node data from the Z-Wave network //----------------------------------------------------------------------------- void Driver::InitAllNodes ( ) { // Delete all the node data LockGuard LG(m_nodeMutex); for( int i=0; i<256; ++i ) { if( m_nodes[i] ) { delete m_nodes[i]; m_nodes[i] = NULL; } } LG.Unlock(); // Fetch new node data from the Z-Wave network 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 ) { // Delete any existing node and replace it with a new one { 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 ); } // Add the new node 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 ); if (_length == 0) { // Request the node info m_nodes[_nodeId]->SetQueryStage( Node::QueryStage_ProtocolInfo ); } else { if (isNetworkKeySet()) m_nodes[_nodeId]->SetSecured(secure); else Log::Write(LogLevel_Info, _nodeId, "Network Key Not Set - Secure Option is %s", secure ? "required" : "not required"); m_nodes[_nodeId]->SetProtocolInfo(_protocolInfo, _length); } Log::Write(LogLevel_Info, _nodeId, "Initilizing Node. New Node: %s (%s)", static_cast(m_nodes[_nodeId])->IsAddingNode() ? "true" : "false", newNode ? "true" : "false"); } //----------------------------------------------------------------------------- // // Get whether the node is a listening device that does not go to sleep //----------------------------------------------------------------------------- bool Driver::IsNodeListeningDevice ( uint8 const _nodeId ) { bool res = false; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { res = node->IsListeningDevice(); } return res; } //----------------------------------------------------------------------------- // // Get whether the node is a listening device that does not go to sleep //----------------------------------------------------------------------------- bool Driver::IsNodeFrequentListeningDevice ( uint8 const _nodeId ) { bool res = false; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { res = node->IsFrequentListeningDevice(); } return res; } //----------------------------------------------------------------------------- // // Get whether the node is a beam capable device. //----------------------------------------------------------------------------- bool Driver::IsNodeBeamingDevice ( uint8 const _nodeId ) { bool res = false; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { res = node->IsBeamingDevice(); } return res; } //----------------------------------------------------------------------------- // // Get whether the node is a routing device that passes messages to other nodes //----------------------------------------------------------------------------- bool Driver::IsNodeRoutingDevice ( uint8 const _nodeId ) { bool res = false; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { res = node->IsRoutingDevice(); } return res; } //----------------------------------------------------------------------------- // // Get the security attribute for a node //----------------------------------------------------------------------------- bool Driver::IsNodeSecurityDevice ( uint8 const _nodeId ) { bool security = false; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { security = node->IsSecurityDevice(); } return security; } //----------------------------------------------------------------------------- // // Get the maximum baud rate of a node's communications //----------------------------------------------------------------------------- uint32 Driver::GetNodeMaxBaudRate ( uint8 const _nodeId ) { uint32 baud = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { baud = node->GetMaxBaudRate(); } return baud; } //----------------------------------------------------------------------------- // // Get the version number of a node //----------------------------------------------------------------------------- uint8 Driver::GetNodeVersion ( uint8 const _nodeId ) { uint8 version = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { version = node->GetVersion(); } return version; } //----------------------------------------------------------------------------- // // Get the security byte of a node //----------------------------------------------------------------------------- uint8 Driver::GetNodeSecurity ( uint8 const _nodeId ) { uint8 security = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { security = node->GetSecurity(); } return security; } //----------------------------------------------------------------------------- // // Get the basic type of a node //----------------------------------------------------------------------------- uint8 Driver::GetNodeBasic ( uint8 const _nodeId ) { uint8 basic = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { basic = node->GetBasic(); } return basic; } //----------------------------------------------------------------------------- // // Get the generic type of a node //----------------------------------------------------------------------------- uint8 Driver::GetNodeGeneric ( uint8 const _nodeId ) { uint8 genericType = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { genericType = node->GetGeneric(); } return genericType; } //----------------------------------------------------------------------------- // // Get the specific type of a node //----------------------------------------------------------------------------- uint8 Driver::GetNodeSpecific ( uint8 const _nodeId ) { uint8 specific = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { specific = node->GetSpecific(); } return specific; } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetType(); } return "Unknown"; } bool Driver::IsNodeZWavePlus ( uint8 const _nodeId ) { 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 numNeighbors = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { numNeighbors = node->GetNeighbors( o_neighbors ); } return numNeighbors; } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetManufacturerName(); } return ""; } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetProductName(); } return ""; } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetNodeName(); } return ""; } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetLocation(); } return ""; } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetManufacturerId(); } return 0; } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetProductType(); } return 0; } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetProductId(); } return 0; } //----------------------------------------------------------------------------- // // Get the node device type as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- uint16 Driver::GetNodeDeviceType ( uint8 const _nodeId ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetDeviceType(); } return 0x00; // unknown } //----------------------------------------------------------------------------- // // Get the node DeviceType as a string as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- string Driver::GetNodeDeviceTypeString ( uint8 const _nodeId ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetDeviceTypeString(); } return ""; // unknown } //----------------------------------------------------------------------------- // // Get the node role as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- uint8 Driver::GetNodeRole ( uint8 const _nodeId ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetRoleType(); } return 0x00; // unknown } //----------------------------------------------------------------------------- // // Get the node role as a string as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- string Driver::GetNodeRoleString ( uint8 const _nodeId ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetRoleTypeString(); } return ""; // unknown } //----------------------------------------------------------------------------- // // Get the node role as a string as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- uint8 Driver::GetNodePlusType ( uint8 const _nodeId ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->GetNodeType(); } return 0x00; // unknown } //----------------------------------------------------------------------------- // // Get the node role as a string as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- string Driver::GetNodePlusTypeString ( uint8 const _nodeId ) { 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->SetManufacturerName( _manufacturerName ); } } //----------------------------------------------------------------------------- // // Set the product name string value with the specified ID //----------------------------------------------------------------------------- void Driver::SetNodeProductName ( uint8 const _nodeId, string const& _productName ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->SetProductName( _productName ); } } //----------------------------------------------------------------------------- // // Set the node name string value with the specified ID //----------------------------------------------------------------------------- void Driver::SetNodeName ( uint8 const _nodeId, string const& _nodeName ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->SetNodeName( _nodeName ); } } //----------------------------------------------------------------------------- // // Set the location string value with the specified ID //----------------------------------------------------------------------------- void Driver::SetNodeLocation ( uint8 const _nodeId, string const& _location ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->SetLocation( _location ); } } //----------------------------------------------------------------------------- // // Helper to set the node level through the basic command class //----------------------------------------------------------------------------- void Driver::SetNodeLevel ( uint8 const _nodeId, uint8 const _level ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->SetLevel( _level ); } } //----------------------------------------------------------------------------- // // Helper to set the node on through the basic command class //----------------------------------------------------------------------------- void Driver::SetNodeOn ( uint8 const _nodeId ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->SetNodeOn(); } } //----------------------------------------------------------------------------- // // Helper to set the node off through the basic command class //----------------------------------------------------------------------------- void Driver::SetNodeOff ( uint8 const _nodeId ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->SetNodeOff(); } } //----------------------------------------------------------------------------- // // Get a pointer to a Value object for the specified ValueID //----------------------------------------------------------------------------- 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()] ) { return node->GetValue( _id ); } return NULL; } //----------------------------------------------------------------------------- // Controller commands //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Reset controller and erase all node information //----------------------------------------------------------------------------- void Driver::ResetController ( 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 ); } //----------------------------------------------------------------------------- // // Soft-reset the Z-Wave controller chip //----------------------------------------------------------------------------- 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 ); } //----------------------------------------------------------------------------- // // Get the neighbour information for a node from the controller //----------------------------------------------------------------------------- void Driver::RequestNodeNeighbors ( uint8 const _nodeId, uint32 const _requestFlags ) { 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 ); } } //----------------------------------------------------------------------------- // // 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 ) { ControllerCommandItem* cci; MsgQueueItem item; if( _command == ControllerCommand_None ) { return false; } 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; cci->m_controllerCallbackContext = _context; cci->m_highPower = _highPower; cci->m_controllerCommandNode = _nodeId; cci->m_controllerCommandArg = _arg; cci->m_controllerState = ControllerState_Normal; cci->m_controllerStateChanged = false; cci->m_controllerCommandDone = false; item.m_command = MsgQueueCmd_Controller; item.m_cci = cci; m_sendMutex->Lock(); m_msgQueue[MsgQueue_Controller].push_back( item ); m_queueEvent[MsgQueue_Controller]->Set(); m_sendMutex->Unlock(); return true; } //----------------------------------------------------------------------------- // // Start the controller performing one of its network management functions //----------------------------------------------------------------------------- void Driver::DoControllerCommand ( ) { UpdateControllerState( ControllerState_Starting ); switch( m_currentControllerCommand->m_controllerCommand ) { case ControllerCommand_AddDevice: { if( !IsPrimaryController() ) { UpdateControllerState( ControllerState_Error, ControllerError_NotPrimary ); } else { 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 ); } break; } 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" ); Msg* msg = new 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, "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() ) { UpdateControllerState( ControllerState_Error, ControllerError_NotPrimary ); } else { 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 ); } 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() ) { UpdateControllerState( ControllerState_Error, ControllerError_NotPrimary ); } else { 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 ); } break; } case ControllerCommand_RequestNetworkUpdate: { if( !IsStaticUpdateController() ) { UpdateControllerState( ControllerState_Error, ControllerError_NotSUC ); } else { 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 ); } break; } case ControllerCommand_RequestNodeNeighborUpdate: { 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 ); Msg* msg; if( opts ) { msg = new Msg( "ControllerCommand_RequestNodeNeighborUpdate", m_currentControllerCommand->m_controllerCommandNode, REQUEST, FUNC_ID_ZW_REQUEST_NODE_NEIGHBOR_UPDATE_OPTIONS, true ); } else { msg = new 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; } 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; } case ControllerCommand_CreateButton: { if( IsBridgeController() ) { Node* node = GetNodeUnsafe( m_currentControllerCommand->m_controllerCommandNode ); if( node != NULL ) { if( node->m_buttonMap.find( m_currentControllerCommand->m_controllerCommandArg ) == node->m_buttonMap.end() && m_virtualNeighborsReceived ) { bool found = false; for( uint8 n = 1; n <= 232 && !found; n++ ) { 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( !found ) // create a new virtual node { 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 ); } } else { UpdateControllerState( ControllerState_Error, ControllerError_ButtonNotFound ); } } else { UpdateControllerState( ControllerState_Error, ControllerError_NodeNotFound ); } } else { UpdateControllerState( ControllerState_Error, ControllerError_NotBridge ); } break; } case ControllerCommand_DeleteButton: { if( IsBridgeController() ) { 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() ) msg->Append( SLAVE_LEARN_MODE_REMOVE ); else msg->Append( SLAVE_LEARN_MODE_ENABLE ); SendMsg( msg ); #endif 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 ); } else { UpdateControllerState( ControllerState_Error, ControllerError_ButtonNotFound ); } } else { UpdateControllerState( ControllerState_Error, ControllerError_NodeNotFound ); } } else { UpdateControllerState( ControllerState_Error, ControllerError_NotBridge ); } break; } case ControllerCommand_None: { // To keep gcc quiet break; } } } //----------------------------------------------------------------------------- // // Stop the current controller function //----------------------------------------------------------------------------- void Driver::UpdateControllerState( ControllerState const _state, ControllerError const _error ) { if( m_currentControllerCommand != NULL ) { 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: { break; } } } Notification* notification = new Notification( Notification::Type_ControllerCommand ); notification->SetHomeAndNodeIds(m_homeId, 0); notification->SetEvent(_state); if( _error != ControllerError_None ) { m_currentControllerCommand->m_controllerReturnError = _error; /* Create a new Notification Callback */ notification->SetNotification(_error); } QueueNotification( notification ); } } //----------------------------------------------------------------------------- // // Stop the current controller function //----------------------------------------------------------------------------- bool Driver::CancelControllerCommand ( ) { 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: { 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; } } UpdateControllerState( ControllerState_Cancel ); return true; } //----------------------------------------------------------------------------- // // Stop the Add Node mode based on API of controller //----------------------------------------------------------------------------- void Driver::AddNodeStop ( uint8 const _funcId ) { if( m_currentControllerCommand == NULL ) { // Controller is not doing anything return; } 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 ); } else { Msg* msg = new Msg( "Add Node Stop", 0xff, REQUEST, _funcId, false, true ); msg->Append( ADD_NODE_STOP ); SendMsg( msg, Driver::MsgQueue_Command ); } } //----------------------------------------------------------------------------- // // Run a series of messages to a single node or every node on the network. //----------------------------------------------------------------------------- void Driver::TestNetwork ( uint8 const _nodeId, uint32 const _count ) { LockGuard LG(m_nodeMutex); if( _nodeId == 0 ) // send _count messages to every node { for( int i=0; i<256; ++i ) { if( i == m_Controller_nodeId ) // ignore sending to ourself { continue; } if( m_nodes[i] != NULL ) { NoOperation *noop = static_cast( m_nodes[i]->GetCommandClass( NoOperation::StaticGetCommandClassId() ) ); for( int j=0; j < (int)_count; j++ ) { noop->Set( true ); } } } } 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++ ) { noop->Set( true ); } } } //----------------------------------------------------------------------------- // SwitchAll //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // All devices that support the SwitchAll command class will be turned on //----------------------------------------------------------------------------- void Driver::SwitchAllOn ( ) { SwitchAll::On( this, 0xff ); LockGuard LG(m_nodeMutex); for( int i=0; i<256; ++i ) { if( GetNodeUnsafe( i ) ) { if( m_nodes[i]->GetCommandClass( SwitchAll::StaticGetCommandClassId() ) ) { SwitchAll::On( this, (uint8)i ); } } } } //----------------------------------------------------------------------------- // // All devices that support the SwitchAll command class will be turned off //----------------------------------------------------------------------------- void Driver::SwitchAllOff ( ) { SwitchAll::Off( this, 0xff ); LockGuard LG(m_nodeMutex); for( int i=0; i<256; ++i ) { if( GetNodeUnsafe( i ) ) { if( m_nodes[i]->GetCommandClass( SwitchAll::StaticGetCommandClassId() ) ) { SwitchAll::Off( this, (uint8)i ); } } } } //----------------------------------------------------------------------------- // // 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 ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { return node->SetConfigParam( _param, _value, _size ); } return false; } //----------------------------------------------------------------------------- // // Request the value of one of the configuration parameters of a device //----------------------------------------------------------------------------- void Driver::RequestConfigParam ( uint8 const _nodeId, uint8 const _param ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->RequestConfigParam( _param ); } } //----------------------------------------------------------------------------- // // Gets the number of association groups reported by this node //----------------------------------------------------------------------------- uint8 Driver::GetNumGroups ( uint8 const _nodeId ) { uint8 numGroups = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { numGroups = node->GetNumGroups(); } return numGroups; } //----------------------------------------------------------------------------- // // Gets the associations for a group //----------------------------------------------------------------------------- uint32 Driver::GetAssociations ( uint8 const _nodeId, uint8 const _groupIdx, uint8** o_associations ) { uint32 numAssociations = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { numAssociations = node->GetAssociations( _groupIdx, o_associations ); } return numAssociations; } //----------------------------------------------------------------------------- // // Gets the associations for a group //----------------------------------------------------------------------------- uint32 Driver::GetAssociations ( uint8 const _nodeId, uint8 const _groupIdx, InstanceAssociation** o_associations ) { uint32 numAssociations = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { numAssociations = node->GetAssociations( _groupIdx, o_associations ); } return numAssociations; } //----------------------------------------------------------------------------- // // Gets the maximum number of associations for a group //----------------------------------------------------------------------------- uint8 Driver::GetMaxAssociations ( uint8 const _nodeId, uint8 const _groupIdx ) { uint8 maxAssociations = 0; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { maxAssociations = node->GetMaxAssociations( _groupIdx ); } return maxAssociations; } //----------------------------------------------------------------------------- // // Gets the label for a particular group //----------------------------------------------------------------------------- string Driver::GetGroupLabel ( uint8 const _nodeId, uint8 const _groupIdx ) { string label = ""; LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { label = node->GetGroupLabel( _groupIdx ); } return label; } //----------------------------------------------------------------------------- // // Adds a node to an association group //----------------------------------------------------------------------------- void Driver::AddAssociation ( uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->AddAssociation( _groupIdx, _targetNodeId, _instance ); } } //----------------------------------------------------------------------------- // // Removes a node from an association group //----------------------------------------------------------------------------- void Driver::RemoveAssociation ( uint8 const _nodeId, uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance ) { LockGuard LG(m_nodeMutex); if( Node* node = GetNode( _nodeId ) ) { node->RemoveAssociation( _groupIdx, _targetNodeId, _instance ); } } //----------------------------------------------------------------------------- // // Add a notification to the queue to be sent at a later, safe time. //----------------------------------------------------------------------------- void Driver::QueueNotification ( Notification* _notification ) { m_notifications.push_back( _notification ); m_notificationsEvent->Set(); } //----------------------------------------------------------------------------- // // Notify any watching objects of a value change //----------------------------------------------------------------------------- void Driver::NotifyWatchers ( ) { list::iterator nit = m_notifications.begin(); 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: if (!GetValue(notification->GetValueID())) { Log::Write(LogLevel_Info, notification->GetNodeId(), "Dropping Notification as ValueID does not exist"); nit = m_notifications.begin(); delete notification; continue; } break; default: break; } Log::Write(LogLevel_Detail, notification->GetNodeId(), "Notification: %s", notification->GetAsString().c_str()); Manager::Get()->NotifyWatchers( notification ); delete notification; nit = m_notifications.begin(); } m_notificationsEvent->Reset(); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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" ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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" ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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] ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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" ); return res; } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- 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 ); m_virtualNeighborsReceived = true; bool bNeighbors = false; for( int by=0; by<29; by++ ) { 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 ) { int i; uint32 numNeighbors = 0; if( !m_virtualNeighborsReceived ) { *o_neighbors = NULL; return 0; } for( i = 0; i < 29; i++ ) { 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 ) { *o_neighbors = NULL; return 0; } // 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 bi=0; bi<8; bi++ ) { if( (m_virtualNeighbors[by] & (0x01< // Get the virtual neighbour information from the controller //----------------------------------------------------------------------------- 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 ); } //----------------------------------------------------------------------------- // // Send node info frame on behalf of a virtual node. //----------------------------------------------------------------------------- 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 ); } //----------------------------------------------------------------------------- // // Disable Slave Learn Mode. //----------------------------------------------------------------------------- void Driver::SendSlaveLearnModeOff ( ) { 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 ); } } //----------------------------------------------------------------------------- // // Save button info into file. //----------------------------------------------------------------------------- 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 ); 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++ ) { if( m_nodes[i] == NULL || m_nodes[i]->m_buttonMap.empty() ) { continue; } TiXmlElement* nodeElement = new TiXmlElement( "Node" ); 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 ) { TiXmlElement* valueElement = new TiXmlElement( "Button" ); 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 ); nodeElement->LinkEndChild( valueElement ); } nodesElement->LinkEndChild( nodeElement ); } string userPath; Options::Get()->GetOptionAsString( "UserPath", &userPath ); string filename = userPath + "zwbutton.xml"; doc.SaveFile( filename.c_str() ); } //----------------------------------------------------------------------------- // // Read button info per node from file. //----------------------------------------------------------------------------- void Driver::ReadButtons ( uint8 const _nodeId ) { int32 intVal; int32 nodeId; int32 buttonId; char const* str; // Load the XML document that contains the driver configuration string userPath; Options::Get()->GetOptionAsString( "UserPath", &userPath ); string filename = userPath + "zwbutton.xml"; TiXmlDocument doc; if( !doc.LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) { Log::Write( LogLevel_Debug, "Driver::ReadButtons - zwbutton.xml file not found."); return; } TiXmlElement const* nodesElement = doc.RootElement(); str = nodesElement->Value(); if( str && strcmp( str, "Nodes" )) { Log::Write( LogLevel_Warning, "WARNING: Driver::ReadButtons - zwbutton.xml is malformed"); return; } // Version if( TIXML_SUCCESS == nodesElement->QueryIntAttribute( "version", &intVal ) ) { if( (uint32)intVal != 1 ) { 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." ); return; } TiXmlElement const* nodeElement = nodesElement->FirstChildElement(); while( nodeElement ) { str = nodeElement->Value(); if( str && !strcmp( str, "Node" )) { Node* node = NULL; if( TIXML_SUCCESS == nodeElement->QueryIntAttribute( "id", &intVal ) ) { if( _nodeId == intVal ) { node = GetNodeUnsafe( intVal ); } } if( node != NULL ) { TiXmlElement const* buttonElement = nodeElement->FirstChildElement(); while( buttonElement ) { str = buttonElement->Value(); if( str && !strcmp( str, "Button")) { if (TIXML_SUCCESS != buttonElement->QueryIntAttribute( "id", &buttonId ) ) { Log::Write( LogLevel_Warning, "WARNING: Driver::ReadButtons - cannot find Button Id for node %d", _nodeId ); return; } str = buttonElement->GetText(); if( str ) { char *p; 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 ); return; } node->m_buttonMap[buttonId] = nodeId; Notification* notification = new Notification( Notification::Type_CreateButton ); notification->SetHomeAndNodeIds( m_homeId, nodeId ); notification->SetButtonId( buttonId ); QueueNotification( notification ); } buttonElement = buttonElement->NextSiblingElement(); } } } nodeElement = nodeElement->NextSiblingElement(); } } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- bool Driver::HandleSetSlaveLearnModeResponse ( uint8* _data ) { bool res = true; ControllerState state = ControllerState_InProgress; 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" ); } else { // 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 ); return res; } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleSetSlaveLearnModeRequest ( uint8* _data ) { ControllerState state = ControllerState_Waiting; uint8 nodeId = GetNodeNumber( m_currentMsg ); if( m_currentControllerCommand == NULL ) { return; } SendSlaveLearnModeOff(); 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 { 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 ) { 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 { 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 ) { 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; } } m_currentControllerCommand->m_controllerAdded = false; UpdateControllerState( state ); } //----------------------------------------------------------------------------- // // Process a response from the Z-Wave PC interface //----------------------------------------------------------------------------- bool Driver::HandleSendSlaveNodeInfoResponse ( uint8* _data ) { bool res = true; ControllerState state = ControllerState_InProgress; uint8 nodeId = GetNodeNumber( m_currentMsg ); if( m_currentControllerCommand == NULL ) { return false; } if( _data[2] ) { 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" ); state = ControllerState_Failed; // Undo button map settings Node* node = GetNodeUnsafe( m_currentControllerCommand->m_controllerCommandNode ); if( node != NULL ) { node->m_buttonMap.erase( m_currentControllerCommand->m_controllerCommandArg ); } res = false; } UpdateControllerState( state ); return res; } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- void Driver::HandleSendSlaveNodeInfoRequest ( uint8* _data ) { if( m_currentControllerCommand == NULL ) { return; } if( _data[3] == 0 ) // finish up { 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 ); 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) { SendVirtualNodeInfo( node->m_buttonMap[m_currentControllerCommand->m_controllerCommandArg], m_currentControllerCommand->m_controllerCommandNode ); } } } //----------------------------------------------------------------------------- // // Process a request from the Z-Wave PC interface //----------------------------------------------------------------------------- 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 { map::iterator it = node->m_buttonMap.begin(); for( ; it != node->m_buttonMap.end(); ++it ) { if( it->second == _data[3] ) break; } if( it != node->m_buttonMap.end() ) { Notification *notification; if( _data[8] == 0 ) { notification = new Notification( Notification::Type_ButtonOff ); } else { notification = new Notification( Notification::Type_ButtonOn ); } notification->SetHomeAndNodeIds( m_homeId, _data[4] ); notification->SetButtonId( it->first ); QueueNotification( notification ); } } } //----------------------------------------------------------------------------- // // See if we can get node from incoming message data //----------------------------------------------------------------------------- uint8 Driver::NodeFromMessage ( uint8 const* buffer ) { uint8 nodeId = 0; if( buffer[1] >= 5 ) { switch( buffer[3] ) { case FUNC_ID_APPLICATION_COMMAND_HANDLER: nodeId = buffer[5]; break; case FUNC_ID_ZW_APPLICATION_UPDATE: nodeId = buffer[5]; break; } } return nodeId; } //----------------------------------------------------------------------------- // // Update a node's routing information //----------------------------------------------------------------------------- void Driver::UpdateNodeRoutes ( uint8 const _nodeId, bool _doUpdate // = false ) { // Only for routing slaves Node* node = GetNodeUnsafe( _nodeId ); if( node != NULL && node->GetBasic() == 0x04 ) { uint8 numGroups = GetNumGroups( _nodeId ); uint8 numNodes = 0; uint8 nodes[5]; InstanceAssociation* associations; uint8 i; // Determine up to 5 destinations 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++ ) { 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++ ) { if( nodes[k] == associations[j].m_nodeId ) { break; } } if( k >= numNodes && numNodes < sizeof(nodes) ) // not in list so add it { nodes[numNodes++] = associations[j].m_nodeId; } } if( associations != NULL ) { delete [] associations; } } 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_AssignReturnRoute, NULL, NULL, true, _nodeId, nodes[i] ); } node->m_numRouteNodes = numNodes; memcpy( node->m_routeNodes, nodes, sizeof(nodes) ); } } } //----------------------------------------------------------------------------- // // Return driver statistics //----------------------------------------------------------------------------- void Driver::GetDriverStatistics ( DriverData* _data ) { _data->m_SOFCnt = m_SOFCnt; _data->m_ACKWaiting = m_ACKWaiting; _data->m_readAborts = m_readAborts; _data->m_badChecksum = m_badChecksum; _data->m_readCnt = m_readCnt; _data->m_writeCnt = m_writeCnt; _data->m_CANCnt = m_CANCnt; _data->m_NAKCnt = m_NAKCnt; _data->m_ACKCnt = m_ACKCnt; _data->m_OOFCnt = m_OOFCnt; _data->m_dropped = m_dropped; _data->m_retries = m_retries; _data->m_callbacks = m_callbacks; _data->m_badroutes = m_badroutes; _data->m_noack = m_noack; _data->m_netbusy = m_netbusy; _data->m_notidle = m_notidle; _data->m_nondelivery = m_nondelivery; _data->m_routedbusy = m_routedbusy; _data->m_broadcastReadCnt = m_broadcastReadCnt; _data->m_broadcastWriteCnt = m_broadcastWriteCnt; } //----------------------------------------------------------------------------- // // Return per node statistics //----------------------------------------------------------------------------- void Driver::GetNodeStatistics ( uint8 const _nodeId, Node::NodeData* _data ) { LockGuard LG(m_nodeMutex); Node* node = GetNode( _nodeId ); if( node != NULL ) { node->GetNodeStatistics( _data ); } } //----------------------------------------------------------------------------- // // Report driver statistics to the driver's log //----------------------------------------------------------------------------- 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 ); // 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, "***************************************************************************" ); } //----------------------------------------------------------------------------- // // Get the Network Key we will use for Security Command Class //----------------------------------------------------------------------------- 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 bool keySet = false; if (keySet == false) { Options::Get()->GetOptionAsString("NetworkKey", &networkKey ); OpenZWave::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:"); int i = 0; for (std::vector::iterator it = elems.begin(); it != elems.end(); it++) Log::Write(LogLevel_Warning, "%d) - %s", ++i, (*it).c_str()); 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])) { 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 { keybytes[i] = (tempkey[i] & 0xFF); } i++; } keySet = true; } return keybytes; } //----------------------------------------------------------------------------- // // Send either a NONCE request, or the actual encrypted message, depending what state the Message Currently is in. //----------------------------------------------------------------------------- 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_currentMsg->clearNonce(); return true; } bool Driver::SendNonceRequest(string logmsg) { uint8 m_buffer[11]; /* construct a standard NONCE_GET message */ m_buffer[0] = SOF; m_buffer[1] = 9; // Length of the entire message m_buffer[2] = REQUEST; 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[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 */ //m_buffer[9] = m_expectedCallbackId; m_buffer[9] = 2; // Calculate the checksum m_buffer[10] = 0xff; 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], m_expectedCallbackId, m_expectedReply, logmsg.c_str(), PktToString(m_buffer, 10).c_str()); m_controller->Write(m_buffer, 11); return true; } 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 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()) { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed - Network Key Not Set"); return false; } 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) { 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) { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to Set Initial Network Key for Authentication"); return false; } uint8 tmpEncKey[32]; uint8 tmpAuthKey[32]; aes_mode_reset(this->EncryptKey); aes_mode_reset(this->AuthKey); 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) { 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) { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to set Encrypted Network Key for Encryption"); return false; } if (aes_encrypt_key128(tmpAuthKey, this->AuthKey) == EXIT_FAILURE) { Log::Write(LogLevel_Warning, GetControllerNodeId(), "Failed to set Encrypted Network Key for Authentication"); return false; } aes_mode_reset(this->EncryptKey); aes_mode_reset(this->AuthKey); return true; } void Driver::SendNonceKey(uint8 nodeId, uint8 *nonce) { uint8 m_buffer[19]; /* construct a standard NONCE_GET message */ m_buffer[0] = SOF; m_buffer[1] = 17; // Length of the entire message m_buffer[2] = REQUEST; 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[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 ) { 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()); m_controller->Write(m_buffer, 19); m_nonceReportSent = nodeId; } aes_encrypt_ctx *Driver::GetAuthKey ( ) { 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) { 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 ) { /* we are adding a Node, so our EncryptKey is different from normal comms */ initNetworkKeys(true); } else if (m_inclusionkeySet) { initNetworkKeys(false); } return this->EncryptKey; }; bool Driver::isNetworkKeySet() { std::string networkKey; if (!Options::Get()->GetOptionAsString("NetworkKey", &networkKey )) { return false; } else { return networkKey.length() <= 0 ? false : true; } } open-zwave-1.5/cpp/src/Driver.h000066400000000000000000001163551264474202400164470ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Driver.h // // Communicates with a Z-Wave network // // 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 . // //----------------------------------------------------------------------------- #ifndef _Driver_H #define _Driver_H #include #include #include #include "Defs.h" #include "Group.h" #include "value_classes/ValueID.h" #include "Node.h" #include "platform/Event.h" #include "platform/Mutex.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; /** \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 Value; friend class ValueStore; friend class ValueButton; friend class Association; friend class Basic; friend class ManufacturerSpecific; friend class NodeNaming; friend class NoOperation; friend class SceneActivation; friend class WakeUp; friend class Security; friend class Msg; //----------------------------------------------------------------------------- // 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 capabilties * - [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. */ 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 ReadConfig(); // Read the configuration from a file void WriteConfig(); // Save the configuration to a file //----------------------------------------------------------------------------- // 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); } 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 * 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, 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 ) { 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 cancelled. */ 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_Security, 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 mext wakes up. 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 interupted 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 diagostics. // // 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 }; class MsgQueueItem { public: MsgQueueItem() : m_msg(NULL), m_nodeId(0), m_queryStage(Node::QueryStage_None), m_retry(false), m_cci(NULL) {} bool operator == ( MsgQueueItem const& _other )const { 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) ); } } return false; } 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 signalled 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 ); 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 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; 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 unsolcited 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_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; }; } // namespace OpenZWave #endif // _Driver_H open-zwave-1.5/cpp/src/Group.cpp000066400000000000000000000373601264474202400166410ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Group.cpp // // A set of associations in a Z-Wave device. // // 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 . // //----------------------------------------------------------------------------- #include #include "Group.h" #include "Manager.h" #include "Driver.h" #include "Node.h" #include "Notification.h" #include "Options.h" #include "command_classes/Association.h" #include "command_classes/AssociationCommandConfiguration.h" #include "command_classes/MultiInstanceAssociation.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 ) { char str[16]; snprintf( str, sizeof(str), "Group %d", m_groupIdx ); m_label = str; CheckAuto(); } //----------------------------------------------------------------------------- // // 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 ) { int intVal; char const* str; vector pending; if( TIXML_SUCCESS == _groupElement->QueryIntAttribute( "index", &intVal ) ) { m_groupIdx = (uint8)intVal; } /* call this so the config can override if necessary */ CheckAuto(); if( TIXML_SUCCESS == _groupElement->QueryIntAttribute( "max_associations", &intVal ) ) { m_maxAssociations = (uint8)intVal; } str = _groupElement->Attribute( "auto" ); if( str ) { m_auto = !strcmp( str, "true" ); } str = _groupElement->Attribute( "label" ); if( str ) { m_label = str; } str = _groupElement->Attribute( "multiInstance" ); if( str ) { m_multiInstance = !strcmp( str, "true" ); } // Read the associations for this group TiXmlElement const* associationElement = _groupElement->FirstChildElement(); while( associationElement ) { char const* elementName = associationElement->Value(); if( elementName && !strcmp( elementName, "Node" ) ) { 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; else association.m_instance = 0x00; pending.push_back( association ); } } associationElement = associationElement->NextSiblingElement(); } // Group must be added before OnGroupChanged is called so UpdateNodeRoutes can find it. // 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 ); } //----------------------------------------------------------------------------- // // Check if we should AutoAssociate for this group //----------------------------------------------------------------------------- void Group::CheckAuto ( ) { // Auto-association by default is with group 1 or 255, with group 1 taking precedence. // 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 ) { m_auto = true; } 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( Node* node = driver->GetNodeUnsafe( m_nodeId ) ) { if( Group* group = node->GetGroup( 255 ) ) { group->SetAuto( false ); } } } } } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- void Group::WriteXML ( TiXmlElement* _groupElement ) { char str[16]; snprintf( str, 16, "%d", m_groupIdx ); _groupElement->SetAttribute( "index", 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( "multiInstance", m_multiInstance ? "true" : "false" ); } 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 ); if (it->first.m_instance != 0) { snprintf( str, 16, "%d", it->first.m_instance ); associationElement->SetAttribute( "instance", str ); } _groupElement->LinkEndChild( associationElement ); } } //----------------------------------------------------------------------------- // // Whether a group contains a particular node //----------------------------------------------------------------------------- bool Group::Contains ( uint8 const _nodeId, uint8 const _instance ) { for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) { if ((it->first.m_nodeId == _nodeId) && (it->first.m_instance == _instance)) { return true; } } return false; } //----------------------------------------------------------------------------- // // Associate a node with this group //----------------------------------------------------------------------------- void Group::AddAssociation ( uint8 const _nodeId, uint8 const _instance ) { if( Driver* driver = Manager::Get()->GetDriver( m_homeId ) ) { if( Node* node = driver->GetNodeUnsafe( m_nodeId ) ) { MultiInstanceAssociation* cc = static_cast( node->GetCommandClass( MultiInstanceAssociation::StaticGetCommandClassId() )); if( cc && IsMultiInstance() ) { cc->Set( m_groupIdx, _nodeId, _instance ); cc->QueryGroup( m_groupIdx, 0 ); } else if( Association* cc = static_cast( node->GetCommandClass( Association::StaticGetCommandClassId() ) ) ) { cc->Set( m_groupIdx, _nodeId ); cc->QueryGroup( m_groupIdx, 0 ); } else { Log::Write( LogLevel_Info, m_nodeId, "No supported Association CC found" ); } } } } //----------------------------------------------------------------------------- // // Remove a node from this group //----------------------------------------------------------------------------- void Group::RemoveAssociation ( uint8 const _nodeId, uint8 const _instance ) { if( Driver* driver = Manager::Get()->GetDriver( m_homeId ) ) { if( Node* node = driver->GetNodeUnsafe( m_nodeId ) ) { MultiInstanceAssociation* cc = static_cast( node->GetCommandClass( MultiInstanceAssociation::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 ); cc->QueryGroup( m_groupIdx, 0 ); } else { Log::Write( LogLevel_Info, m_nodeId, "No supported Association CC found" ); } } } } //----------------------------------------------------------------------------- // // Change the group contents and notify the watchers //----------------------------------------------------------------------------- void Group::OnGroupChanged ( vector const& _associations ) { vector instanceAssociations; uint8 i; for( i=0; i<_associations.size(); ++i ) { InstanceAssociation association; association.m_nodeId = _associations[i]; association.m_instance = 0x00; instanceAssociations.push_back( association ); } OnGroupChanged(instanceAssociations); instanceAssociations.clear(); } //----------------------------------------------------------------------------- // // Change the group contents and notify the watchers //----------------------------------------------------------------------------- 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() ) { m_associations.clear(); notify = true; } else { // Handle initial group creation case if ( _associations.size() == 0 && m_associations.size() == 0 ) { notify = true; } } // Add the new associations. uint8 oldSize = (uint8)m_associations.size(); uint8 i; for( i=0; i<_associations.size(); ++i ) { m_associations[_associations[i]] = AssociationCommandVec(); } 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 ) { m_associations[_associations[i]] = AssociationCommandVec(); } notify = true; } 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( Node* node = driver->GetNodeUnsafe( m_nodeId ) ) { if( AssociationCommandConfiguration* cc = static_cast( node->GetCommandClass( AssociationCommandConfiguration::StaticGetCommandClassId() ) ) ) { for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) { 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 ); // Update routes on remote node if necessary bool update = false; Options::Get()->GetOptionAsBool( "PerformReturnRoutes", &update ); if( update ) { Driver *drv = Manager::Get()->GetDriver( m_homeId ); if (drv) drv->UpdateNodeRoutes( m_nodeId ); } } } //----------------------------------------------------------------------------- // // Get a list of associations for this group //----------------------------------------------------------------------------- uint32 Group::GetAssociations ( uint8** o_associations ) { size_t numNodes = m_associations.size(); if( !numNodes ) { *o_associations = NULL; return 0; } 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 ) { if ( it->first.m_instance == 0x00) { associations[i++] = it->first.m_nodeId; } } *o_associations = associations; return (uint32) i; } //----------------------------------------------------------------------------- // // Get a list of associations for this group //----------------------------------------------------------------------------- uint32 Group::GetAssociations ( InstanceAssociation** o_associations ) { size_t numNodes = m_associations.size(); if( !numNodes ) { *o_associations = NULL; return 0; } InstanceAssociation* associations = new InstanceAssociation[numNodes]; uint32 i = 0; for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) { associations[i++] = it->first; } *o_associations = associations; return (uint32) numNodes; } //----------------------------------------------------------------------------- // Command methods (COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION) //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // 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 ) { if( (it->first.m_nodeId == _nodeId) && (it->first.m_instance == _instance) ) { it->second.clear(); return true; } } return false; } //----------------------------------------------------------------------------- // // 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 ) { for( map::iterator it = m_associations.begin(); it != m_associations.end(); ++it ) { if( (it->first.m_nodeId == _nodeId) && (it->first.m_instance == _instance) ) { it->second.push_back( AssociationCommand( _length, _data ) ); return true; } } return false; } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Group::AssociationCommand::AssociationCommand ( uint8 const _length, uint8 const* _data ): m_length( _length ) { m_data = new uint8[_length]; memcpy( m_data, _data, _length ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Group::AssociationCommand::~AssociationCommand ( ) { delete [] m_data; } open-zwave-1.5/cpp/src/Group.h000066400000000000000000000107621264474202400163030ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Group.h // // A set of associations in a Z-Wave device. // // 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 . // //----------------------------------------------------------------------------- #ifndef _Group_H #define _Group_H #include #include #include #include "Defs.h" class TiXmlElement; namespace OpenZWave { class Node; typedef struct InstanceAssociation { uint8 m_nodeId; uint8 m_instance; } InstanceAssociation; /** \brief Manages a group of devices (various nodes associated with each other). */ class Group { friend class Node; friend class Association; friend class MultiInstanceAssociation; //----------------------------------------------------------------------------- // 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 ); private: bool IsAuto()const{ return m_auto; } void SetAuto( bool const _state ){ m_auto = _state; } void CheckAuto(); bool IsMultiInstance()const{ return m_multiInstance; } 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 { public: AssociationCommand( uint8 const _length, uint8 const* _data ); ~AssociationCommand(); private: uint8 m_length; 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; }; } //namespace OpenZWave #endif //_Group_H open-zwave-1.5/cpp/src/Manager.cpp000066400000000000000000003734611264474202400171240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Manager.cpp // // The main public interface to OpenZWave. // // 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 . // //----------------------------------------------------------------------------- #include #include #include #include #include "Defs.h" #include "Manager.h" #include "Driver.h" #include "Node.h" #include "Notification.h" #include "Options.h" #include "Scene.h" #include "Utils.h" #include "platform/Mutex.h" #include "platform/Event.h" #include "platform/Log.h" #include "command_classes/CommandClasses.h" #include "command_classes/CommandClass.h" #include "command_classes/WakeUp.h" #include "value_classes/ValueID.h" #include "value_classes/ValueBool.h" #include "value_classes/ValueButton.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueDecimal.h" #include "value_classes/ValueInt.h" #include "value_classes/ValueList.h" #include "value_classes/ValueRaw.h" #include "value_classes/ValueSchedule.h" #include "value_classes/ValueShort.h" #include "value_classes/ValueString.h" using namespace OpenZWave; Manager* Manager::s_instance = NULL; extern uint16_t ozw_vers_major; extern uint16_t ozw_vers_minor; extern uint16_t ozw_vers_revision; extern char ozw_version_string[]; //----------------------------------------------------------------------------- // Construction //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Static creation of the singleton //----------------------------------------------------------------------------- Manager* Manager::Create ( ) { if( Options::Get() && Options::Get()->AreLocked() ) { if( NULL == s_instance ) { s_instance = new Manager(); } return s_instance; } // 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..." ); OZW_FATAL_ERROR(OZWException::OZWEXCEPTION_OPTIONS, "Options Not Created and Locked"); return NULL; } //----------------------------------------------------------------------------- // // Static method to destroy the singleton. //----------------------------------------------------------------------------- void Manager::Destroy ( ) { delete s_instance; s_instance = NULL; } //----------------------------------------------------------------------------- // // Static method to get the Version of OZW as a string. //----------------------------------------------------------------------------- std::string Manager::getVersionAsString() { std::ostringstream versionstream; versionstream << ozw_vers_major << "." << ozw_vers_minor << "." << ozw_vers_revision; return versionstream.str(); } //----------------------------------------------------------------------------- // // 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(); } //----------------------------------------------------------------------------- // // Static method to get the Version of OZW. //----------------------------------------------------------------------------- ozwversion Manager::getVersion() { return version(ozw_vers_major, ozw_vers_minor); } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Manager::Manager ( ): m_notificationMutex( new Mutex() ) { // Ensure the singleton instance is set s_instance = this; // Create the log file (if enabled) bool logging = false; Options::Get()->GetOptionAsBool( "Logging", &logging ); string userPath = ""; Options::Get()->GetOptionAsString( "UserPath", &userPath ); string logFileNameBase = "OZW_Log.txt"; Options::Get()->GetOptionAsString( "LogFileName", &logFileNameBase ); bool bAppend = false; Options::Get()->GetOptionAsBool( "AppendLogFile", &bAppend ); bool bConsoleOutput = true; Options::Get()->GetOptionAsBool( "ConsoleOutput", &bConsoleOutput ); int nSaveLogLevel = (int) LogLevel_Detail; 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)) { Log::Write(LogLevel_Warning, "Invalid LogLevel Specified for QueueLogLevel in Options.xml"); nSaveLogLevel = (int) LogLevel_Debug; } int nDumpTrigger = (int) LogLevel_Warning; Options::Get()->GetOptionAsInt( "DumpTriggerLevel", &nDumpTrigger ); string logFilename = userPath + logFileNameBase; Log::Create( logFilename, bAppend, bConsoleOutput, (LogLevel) nSaveLogLevel, (LogLevel) nQueueLogLevel, (LogLevel) nDumpTrigger ); Log::SetLoggingState( logging ); CommandClasses::RegisterCommandClasses(); Scene::ReadScenes(); Log::Write(LogLevel_Always, "OpenZwave Version %s Starting Up", getVersionAsString().c_str()); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Manager::~Manager ( ) { // Clear the pending list while( !m_pendingDrivers.empty() ) { list::iterator it = m_pendingDrivers.begin(); delete *it; m_pendingDrivers.erase( it ); } // Clear the ready map while( !m_readyDrivers.empty() ) { map::iterator it = m_readyDrivers.begin(); delete it->second; m_readyDrivers.erase( it ); } m_notificationMutex->Release(); // Clear the watchers list while( !m_watchers.empty() ) { list::iterator it = m_watchers.begin(); delete *it; m_watchers.erase( it ); } // Clear the generic device class list while( !Node::s_genericDeviceClasses.empty() ) { map::iterator git = Node::s_genericDeviceClasses.begin(); delete git->second; Node::s_genericDeviceClasses.erase( git ); } Log::Destroy(); } //----------------------------------------------------------------------------- // Configuration //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Save the configuration of a driver to a file //----------------------------------------------------------------------------- void Manager::WriteConfig ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->WriteConfig(); 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 ); } Scene::WriteXML( "zwscene.xml" ); } //----------------------------------------------------------------------------- // Drivers //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Add a new Z-Wave PC 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 ) { if( _controllerPath == (*pit)->GetControllerPath() ) { 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 ) { if( _controllerPath == rit->second->GetControllerPath() ) { 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->Start(); Log::Write( LogLevel_Info, "mgr, Added driver for controller %s", _controllerPath.c_str() ); return true; } //----------------------------------------------------------------------------- // // Remove a Z-Wave PC Interface //----------------------------------------------------------------------------- bool Manager::RemoveDriver ( string const& _controllerPath ) { // Search the pending list for( list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit ) { if( _controllerPath == (*pit)->GetControllerPath() ) { delete *pit; 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 ) { 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: * 1) Driver::~Driver destructor starts deleting everything.... * 2) This Triggers Notifications such as ValueDeleted etc * 3) Notifications are delivered to applications, and applications start calling * Manager Functions which require the Driver (such as IsPolled(valueid)) * 4) Manager looks up the Driver in the m_readyDriver and returns a pointer to the Driver Class * which is currently being destructed. * 5) All Hell Breaks loose and we crash and burn. * * 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() ); delete rit->second; 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() ); return false; } //----------------------------------------------------------------------------- // // Get a pointer to the driver for a Z-Wave PC Interface //----------------------------------------------------------------------------- Driver* Manager::GetDriver ( uint32 const _homeId ) { 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 ); 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; } //----------------------------------------------------------------------------- // // Move a driver from pending to ready, and notify any watchers //----------------------------------------------------------------------------- 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 ) { if( (*it) == _driver ) { // Remove the driver from the pending list m_pendingDrivers.erase( it ); found = true; break; } } 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, "" ); } // 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() ); _driver->QueueNotification( notification ); } } //----------------------------------------------------------------------------- // // //----------------------------------------------------------------------------- uint8 Manager::GetControllerNodeId ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetControllerNodeId(); } Log::Write( LogLevel_Info, "mgr, GetControllerNodeId() failed - _homeId %d not found", _homeId ); return 0xff; } //----------------------------------------------------------------------------- // // //----------------------------------------------------------------------------- uint8 Manager::GetSUCNodeId ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetSUCNodeId(); } Log::Write( LogLevel_Info, "mgr, GetSUCNodeId() failed - _homeId %d not found", _homeId ); return 0xff; } //----------------------------------------------------------------------------- // // //----------------------------------------------------------------------------- bool Manager::IsPrimaryController ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->IsPrimaryController(); } Log::Write( LogLevel_Info, "mgr, IsPrimaryController() failed - _homeId %d not found", _homeId ); return false; } //----------------------------------------------------------------------------- // // //----------------------------------------------------------------------------- bool Manager::IsStaticUpdateController ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->IsStaticUpdateController(); } Log::Write( LogLevel_Info, "mgr, IsStaticUpdateController() failed - _homeId %d not found", _homeId ); return false; } //----------------------------------------------------------------------------- // // //----------------------------------------------------------------------------- bool Manager::IsBridgeController ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->IsBridgeController(); } Log::Write( LogLevel_Info, "mgr, IsBridgeController() failed - _homeId %d not found", _homeId ); return false; } //----------------------------------------------------------------------------- // // //----------------------------------------------------------------------------- string Manager::GetLibraryVersion ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetLibraryVersion(); } Log::Write( LogLevel_Info, "mgr, GetLibraryVersion() failed - _homeId %d not found", _homeId ); return ""; } //----------------------------------------------------------------------------- // // //----------------------------------------------------------------------------- string Manager::GetLibraryTypeName ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetLibraryTypeName(); } Log::Write( LogLevel_Info, "mgr, GetLibraryTypeName() failed - _homeId %d not found", _homeId ); return ""; } //----------------------------------------------------------------------------- // // //----------------------------------------------------------------------------- int32 Manager::GetSendQueueCount ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetSendQueueCount(); } Log::Write( LogLevel_Info, "mgr, GetSendQueueCount() failed - _homeId %d not found", _homeId ); return -1; } //----------------------------------------------------------------------------- // // Send driver statistics to the log file //----------------------------------------------------------------------------- void Manager::LogDriverStatistics ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->LogDriverStatistics(); } 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 ifType = Driver::ControllerInterface_Unknown; if( Driver* driver = GetDriver( _homeId ) ) { ifType = driver->GetControllerInterfaceType(); } return ifType; } //----------------------------------------------------------------------------- // // Retrieve controller interface path //----------------------------------------------------------------------------- string Manager::GetControllerPath ( uint32 const _homeId ) { string path = ""; if( Driver* driver = GetDriver( _homeId ) ) { path = driver->GetControllerPath(); } return path; } //----------------------------------------------------------------------------- // Polling Z-Wave values //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Return the polling interval //----------------------------------------------------------------------------- int32 Manager::GetPollInterval ( ) { 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 ) { return (*pit)->GetPollInterval(); } return 0; } //----------------------------------------------------------------------------- // // Set the polling interval on all drivers //----------------------------------------------------------------------------- void Manager::SetPollInterval ( int32 _milliseconds, bool _bIntervalBetweenPolls ) { for( list::iterator pit = m_pendingDrivers.begin(); pit != m_pendingDrivers.end(); ++pit ) { (*pit)->SetPollInterval( _milliseconds, _bIntervalBetweenPolls ); } for( map::iterator rit = m_readyDrivers.begin(); rit != m_readyDrivers.end(); ++rit ) { rit->second->SetPollInterval( _milliseconds, _bIntervalBetweenPolls ); } } //----------------------------------------------------------------------------- // // Enable polling of a value //----------------------------------------------------------------------------- bool Manager::EnablePoll ( ValueID const &_valueId, uint8 const _intensity ) { if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) { return( driver->EnablePoll( _valueId, _intensity ) ); } Log::Write( LogLevel_Info, "mgr, EnablePoll failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId() ); return false; } //----------------------------------------------------------------------------- // // Disable polling of a value //----------------------------------------------------------------------------- bool Manager::DisablePoll ( ValueID const &_valueId ) { if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) { return( driver->DisablePoll( _valueId ) ); } Log::Write( LogLevel_Info, "mgr, DisablePoll failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId() ); return false; } //----------------------------------------------------------------------------- // // Check polling status of a value //----------------------------------------------------------------------------- bool Manager::isPolled ( ValueID const &_valueId ) { if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) { return( driver->isPolled( _valueId ) ); } Log::Write( LogLevel_Info, "mgr, isPolled failed - Driver with Home ID 0x%.8x is not available", _valueId.GetHomeId() ); return false; } //----------------------------------------------------------------------------- // // Change the intensity with which this value is polled //----------------------------------------------------------------------------- void Manager::SetPollIntensity ( ValueID const &_valueId, uint8 const _intensity ) { if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) { return( driver->SetPollIntensity( _valueId, _intensity ) ); } 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 intensity = 0; if( Driver* driver = GetDriver( _valueId.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _valueId ) ) { intensity = value->GetPollIntensity(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetPollIntensity"); } } return intensity; } //----------------------------------------------------------------------------- // Retrieving Node information //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Fetch the data for a node from the Z-Wave network //----------------------------------------------------------------------------- bool Manager::RefreshNodeInfo ( uint32 const _homeId, uint8 const _nodeId ) { 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); Node* node = driver->GetNode( _nodeId ); if( node ) { node->SetQueryStage( Node::QueryStage_ProtocolInfo ); return true; } } return false; } //----------------------------------------------------------------------------- // // Fetch the command class data for a node from the Z-Wave network //----------------------------------------------------------------------------- bool Manager::RequestNodeState ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { LockGuard LG(driver->m_nodeMutex); // Retreive the Node's session and dynamic data Node* node = driver->GetNode( _nodeId ); if( node ) { node->SetQueryStage( Node::QueryStage_Associations ); return true; } } return false; } //----------------------------------------------------------------------------- // // Fetch only the dynamic command class data for a node from the Z-Wave network //----------------------------------------------------------------------------- bool Manager::RequestNodeDynamic ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { LockGuard LG(driver->m_nodeMutex); // Retreive the Node's dynamic data Node* node = driver->GetNode( _nodeId ); if( node ) { node->SetQueryStage( Node::QueryStage_Dynamic ); return true; } } return false; } //----------------------------------------------------------------------------- // // Get whether the node is a listening device that does not go to sleep //----------------------------------------------------------------------------- bool Manager::IsNodeListeningDevice ( uint32 const _homeId, uint8 const _nodeId ) { bool res = false; if( Driver* driver = GetDriver( _homeId ) ) { res = driver->IsNodeListeningDevice( _nodeId ); } return res; } //----------------------------------------------------------------------------- // // Get whether the node is a listening device that does not go to sleep //----------------------------------------------------------------------------- bool Manager::IsNodeFrequentListeningDevice ( uint32 const _homeId, uint8 const _nodeId ) { bool res = false; if( Driver* driver = GetDriver( _homeId ) ) { res = driver->IsNodeFrequentListeningDevice( _nodeId ); } return res; } //----------------------------------------------------------------------------- // // Get whether the node is a beam capable device. //----------------------------------------------------------------------------- bool Manager::IsNodeBeamingDevice ( uint32 const _homeId, uint8 const _nodeId ) { bool res = false; if( Driver* driver = GetDriver( _homeId ) ) { res = driver->IsNodeBeamingDevice( _nodeId ); } return res; } //----------------------------------------------------------------------------- // // Get whether the node is a routing device that passes messages to other nodes //----------------------------------------------------------------------------- bool Manager::IsNodeRoutingDevice ( uint32 const _homeId, uint8 const _nodeId ) { bool res = false; if( Driver* driver = GetDriver( _homeId ) ) { res = driver->IsNodeRoutingDevice( _nodeId ); } return res; } //----------------------------------------------------------------------------- // // Get the security attribute for a node. //----------------------------------------------------------------------------- bool Manager::IsNodeSecurityDevice ( uint32 const _homeId, uint8 const _nodeId ) { bool security = 0; if( Driver* driver = GetDriver( _homeId ) ) { security = driver->IsNodeSecurityDevice( _nodeId ); } return security; } //----------------------------------------------------------------------------- // // Get the maximum baud rate of a node's communications //----------------------------------------------------------------------------- uint32 Manager::GetNodeMaxBaudRate ( uint32 const _homeId, uint8 const _nodeId ) { uint32 baud = 0; if( Driver* driver = GetDriver( _homeId ) ) { baud = driver->GetNodeMaxBaudRate( _nodeId ); } return baud; } //----------------------------------------------------------------------------- // // Get the version number of a node //----------------------------------------------------------------------------- uint8 Manager::GetNodeVersion ( uint32 const _homeId, uint8 const _nodeId ) { uint8 version = 0; if( Driver* driver = GetDriver( _homeId ) ) { version = driver->GetNodeVersion( _nodeId ); } return version; } //----------------------------------------------------------------------------- // // Get the security byte of a node //----------------------------------------------------------------------------- uint8 Manager::GetNodeSecurity ( uint32 const _homeId, uint8 const _nodeId ) { uint8 version = 0; if( Driver* driver = GetDriver( _homeId ) ) { 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 version = false; if( Driver* driver = GetDriver( _homeId ) ) { version = driver->IsNodeZWavePlus( _nodeId ); } return version; } //----------------------------------------------------------------------------- // // Get the basic type of a node //----------------------------------------------------------------------------- uint8 Manager::GetNodeBasic ( uint32 const _homeId, uint8 const _nodeId ) { uint8 basic = 0; if( Driver* driver = GetDriver( _homeId ) ) { basic = driver->GetNodeBasic( _nodeId ); } return basic; } //----------------------------------------------------------------------------- // // Get the generic type of a node //----------------------------------------------------------------------------- uint8 Manager::GetNodeGeneric ( uint32 const _homeId, uint8 const _nodeId ) { uint8 genericType = 0; if( Driver* driver = GetDriver( _homeId ) ) { genericType = driver->GetNodeGeneric( _nodeId ); } return genericType; } //----------------------------------------------------------------------------- // // Get the specific type of a node //----------------------------------------------------------------------------- uint8 Manager::GetNodeSpecific ( uint32 const _homeId, uint8 const _nodeId ) { uint8 specific = 0; if( Driver* driver = GetDriver( _homeId ) ) { specific = driver->GetNodeSpecific( _nodeId ); } return specific; } //----------------------------------------------------------------------------- // // Get a string describing the type of a node //----------------------------------------------------------------------------- string Manager::GetNodeType ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { if (driver->IsNodeZWavePlus(_nodeId)) return driver->GetNodeDeviceTypeString(_nodeId); else return driver->GetNodeType( _nodeId ); } return "Unknown"; } //----------------------------------------------------------------------------- // // Get the bitmap of this node's neighbors //----------------------------------------------------------------------------- uint32 Manager::GetNodeNeighbors ( uint32 const _homeId, uint8 const _nodeId, uint8** o_neighbors ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodeNeighbors( _nodeId, o_neighbors ); } return 0; } //----------------------------------------------------------------------------- // // Get the manufacturer name of a node //----------------------------------------------------------------------------- string Manager::GetNodeManufacturerName ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodeManufacturerName( _nodeId ); } return "Unknown"; } //----------------------------------------------------------------------------- // // Get the product name of a node //----------------------------------------------------------------------------- string Manager::GetNodeProductName ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodeProductName( _nodeId ); } return "Unknown"; } //----------------------------------------------------------------------------- // // Get the user-editable name of a node //----------------------------------------------------------------------------- string Manager::GetNodeName ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodeName( _nodeId ); } return "Unknown"; } //----------------------------------------------------------------------------- // // Get the location of a node //----------------------------------------------------------------------------- string Manager::GetNodeLocation ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodeLocation( _nodeId ); } return "Unknown"; } //----------------------------------------------------------------------------- // // Set the manufacturer name a node //----------------------------------------------------------------------------- void Manager::SetNodeManufacturerName ( uint32 const _homeId, uint8 const _nodeId, string const& _manufacturerName ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->SetNodeManufacturerName( _nodeId, _manufacturerName ); } } //----------------------------------------------------------------------------- // // Set the product name of a node //----------------------------------------------------------------------------- void Manager::SetNodeProductName ( uint32 const _homeId, uint8 const _nodeId, string const& _productName ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->SetNodeProductName( _nodeId, _productName ); } } //----------------------------------------------------------------------------- // // Set the node name value with the specified ID //----------------------------------------------------------------------------- void Manager::SetNodeName ( uint32 const _homeId, uint8 const _nodeId, string const& _nodeName ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->SetNodeName( _nodeId, _nodeName ); } } //----------------------------------------------------------------------------- // // Set a string describing the location of a node //----------------------------------------------------------------------------- void Manager::SetNodeLocation ( uint32 const _homeId, uint8 const _nodeId, string const& _location ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->SetNodeLocation( _nodeId, _location ); } } //----------------------------------------------------------------------------- // // Get the manufacturer ID value of a node //----------------------------------------------------------------------------- string Manager::GetNodeManufacturerId ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { uint16 mid = driver->GetNodeManufacturerId( _nodeId ); std::stringstream ss; ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << mid; return ss.str(); } return "Unknown"; } //----------------------------------------------------------------------------- // // Get the product type value of a node //----------------------------------------------------------------------------- string Manager::GetNodeProductType ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { uint16 mid = driver->GetNodeProductType( _nodeId ); std::stringstream ss; ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << mid; return ss.str(); } return "Unknown"; } //----------------------------------------------------------------------------- // // Get the node device type as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- uint16 Manager::GetNodeDeviceType ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodeDeviceType( _nodeId ); } return 0x00; // unknown } //----------------------------------------------------------------------------- // // Get the node device type as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- string Manager::GetNodeDeviceTypeString ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { 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 ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodeRole( _nodeId ); } return 0x00; // unknown } //----------------------------------------------------------------------------- // // Get the node role as reported in the Z-Wave+ Info report. //----------------------------------------------------------------------------- string Manager::GetNodeRoleString ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodeRoleString( _nodeId ); } return ""; // unknown } uint8 Manager::GetNodePlusType ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodePlusType( _nodeId ); } return 0x00; // unknown } string Manager::GetNodePlusTypeString ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNodePlusTypeString( _nodeId ); } return ""; // unknown } //----------------------------------------------------------------------------- // // Get the product Id value with the specified ID //----------------------------------------------------------------------------- string Manager::GetNodeProductId ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { uint16 mid = driver->GetNodeProductId( _nodeId ); std::stringstream ss; ss << "0x" << std::hex << std::setw(4) << std::setfill('0') << mid; return ss.str(); } return "Unknown"; } //----------------------------------------------------------------------------- // // Helper method to turn a node on //----------------------------------------------------------------------------- void Manager::SetNodeOn ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->SetNodeOn( _nodeId ); } } //----------------------------------------------------------------------------- // // Helper method to turn a node off //----------------------------------------------------------------------------- void Manager::SetNodeOff ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->SetNodeOff( _nodeId ); } } //----------------------------------------------------------------------------- // // Helper method to return whether a particular class is available in a node //----------------------------------------------------------------------------- bool Manager::IsNodeInfoReceived ( uint32 const _homeId, uint8 const _nodeId ) { bool result = false; if( Driver* driver = GetDriver( _homeId ) ) { Node *node; // Need to lock and unlock nodes to check this information LockGuard LG(driver->m_nodeMutex); if( (node = driver->GetNode( _nodeId ) ) != NULL) { result = node->NodeInfoReceived(); } } return result; } //----------------------------------------------------------------------------- // // 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 result = false; if( Driver* driver = GetDriver( _homeId ) ) { Node *node; // Need to lock and unlock nodes to check this information LockGuard LG(driver->m_nodeMutex); if( ( node = driver->GetNode( _nodeId ) ) != NULL ) { CommandClass *cc; if( node->NodeInfoReceived() && ( ( cc = node->GetCommandClass( _commandClassId ) ) != NULL ) ) { if( _className ) { *_className = cc->GetCommandClassName(); } if( _classVersion ) { *_classVersion = cc->GetVersion(); } // Positive result result = true; } } } return result; } //----------------------------------------------------------------------------- // // Helper method to return whether a node is awake or sleeping //----------------------------------------------------------------------------- bool Manager::IsNodeAwake ( uint32 const _homeId, uint8 const _nodeId ) { if( IsNodeListeningDevice( _homeId, _nodeId ) ) { return true; // if listening then always awake } bool result = true; if( Driver* driver = GetDriver( _homeId ) ) { // Need to lock and unlock nodes to check this information LockGuard LG(driver->m_nodeMutex); if( Node* node = driver->GetNode( _nodeId ) ) { if( WakeUp* wcc = static_cast( node->GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) { result = wcc->IsAwake(); } } } return result; } //----------------------------------------------------------------------------- // // Helper method to return whether a node is on the network or not //----------------------------------------------------------------------------- bool Manager::IsNodeFailed ( uint32 const _homeId, uint8 const _nodeId ) { bool result = false; if( Driver* driver = GetDriver( _homeId ) ) { LockGuard LG(driver->m_nodeMutex); if( Node* node = driver->GetNode( _nodeId ) ) { result = !node->IsNodeAlive(); } } return result; } //----------------------------------------------------------------------------- // // Helper method to return whether a node's query stage //----------------------------------------------------------------------------- string Manager::GetNodeQueryStage ( uint32 const _homeId, uint8 const _nodeId ) { string result = "Unknown"; if( Driver* driver = GetDriver( _homeId ) ) { LockGuard LG(driver->m_nodeMutex); if( Node* node = driver->GetNode( _nodeId ) ) { result = node->GetQueryStageName( node->GetCurrentQueryStage() ); } } return result; } //----------------------------------------------------------------------------- // // Helper method to set the basic level of a node //----------------------------------------------------------------------------- void Manager::SetNodeLevel ( uint32 const _homeId, uint8 const _nodeId, uint8 const _level ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->SetNodeLevel( _nodeId, _level ); } } //----------------------------------------------------------------------------- // Values //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Gets the user-friendly label for the value //----------------------------------------------------------------------------- string Manager::GetValueLabel ( ValueID const& _id ) { string label; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { label = value->GetLabel(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueLabel"); } } return label; } //----------------------------------------------------------------------------- // // Sets the user-friendly label for the value //----------------------------------------------------------------------------- void Manager::SetValueLabel ( ValueID const& _id, string const& _value ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { value->SetLabel( _value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValueLabel"); } } } //----------------------------------------------------------------------------- // // Gets the units that the value is measured in //----------------------------------------------------------------------------- string Manager::GetValueUnits ( ValueID const& _id ) { string units; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { units = value->GetUnits(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueUnits"); } } return units; } //----------------------------------------------------------------------------- // // Sets the units that the value is measured in //----------------------------------------------------------------------------- void Manager::SetValueUnits ( ValueID const& _id, string const& _value ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { value->SetUnits( _value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValueUnits"); } } } //----------------------------------------------------------------------------- // // Gets a help string describing the value's purpose and usage //----------------------------------------------------------------------------- string Manager::GetValueHelp ( ValueID const& _id ) { string help; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { help = value->GetHelp(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueHelp"); } } return help; } //----------------------------------------------------------------------------- // // Sets a help string describing the value's purpose and usage //----------------------------------------------------------------------------- void Manager::SetValueHelp ( ValueID const& _id, string const& _value ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { value->SetHelp( _value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValueHelp"); } } } //----------------------------------------------------------------------------- // // Gets the minimum for a value //----------------------------------------------------------------------------- int32 Manager::GetValueMin ( ValueID const& _id ) { int32 limit = 0; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { limit = value->GetMin(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueMin"); } } return limit; } //----------------------------------------------------------------------------- // // Gets the maximum for a value //----------------------------------------------------------------------------- int32 Manager::GetValueMax ( ValueID const& _id ) { int32 limit = 0; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { limit = value->GetMax(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueMax"); } } return limit; } //----------------------------------------------------------------------------- // // Test whether the value is read-only //----------------------------------------------------------------------------- bool Manager::IsValueReadOnly ( ValueID const& _id ) { bool res = false; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { res = value->IsReadOnly(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to IsValueReadOnly"); } } return res; } //----------------------------------------------------------------------------- // // Test whether the value is write-only //----------------------------------------------------------------------------- bool Manager::IsValueWriteOnly ( ValueID const& _id ) { bool res = false; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { res = value->IsWriteOnly(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to IsValueWriteOnly"); } } return res; } //----------------------------------------------------------------------------- // // Test whether the value has been set by a status message from the device //----------------------------------------------------------------------------- bool Manager::IsValueSet ( ValueID const& _id ) { bool res = false; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { res = value->IsSet(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to IsValueSet"); } } return res; } //----------------------------------------------------------------------------- // // Test whether the value is currently being polled //----------------------------------------------------------------------------- bool Manager::IsValuePolled ( ValueID const& _id ) { bool res = false; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { res = value->IsPolled(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to IsValuePolled"); } } return res; } //----------------------------------------------------------------------------- // // Gets a value as a bool //----------------------------------------------------------------------------- bool Manager::GetValueAsBool ( ValueID const& _id, bool* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_Bool == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueBool* value = static_cast( driver->GetValue( _id ) ) ) { *o_value = value->GetValue(); value->Release(); res = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsBool"); } } } else if( ValueID::ValueType_Button == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueButton* value = static_cast( driver->GetValue( _id ) ) ) { *o_value = value->IsPressed(); value->Release(); res = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsBool"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsBool is not a Bool or Button Value"); } } return res; } //----------------------------------------------------------------------------- // // Gets a value as an 8-bit unsigned integer //----------------------------------------------------------------------------- bool Manager::GetValueAsByte ( ValueID const& _id, uint8* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_Byte == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueByte* value = static_cast( driver->GetValue( _id ) ) ) { *o_value = value->GetValue(); value->Release(); res = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsByte"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsByte is not a Byte Value"); } } return res; } //----------------------------------------------------------------------------- // // Gets a value as a floating point number //----------------------------------------------------------------------------- bool Manager::GetValueAsFloat ( ValueID const& _id, float* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_Decimal == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueDecimal* value = static_cast( driver->GetValue( _id ) ) ) { string str = value->GetValue(); *o_value = (float)atof( str.c_str() ); value->Release(); res = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsFloat"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsFloat is not a Float Value"); } } return res; } //----------------------------------------------------------------------------- // // Gets a value as a 32-bit signed integer //----------------------------------------------------------------------------- bool Manager::GetValueAsInt ( ValueID const& _id, int32* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_Int == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueInt* value = static_cast( driver->GetValue( _id ) ) ) { *o_value = value->GetValue(); value->Release(); res = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsInt"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsInt is not a Int Value"); } } return res; } //----------------------------------------------------------------------------- // // Gets a value as a collection of bytes //----------------------------------------------------------------------------- bool Manager::GetValueAsRaw ( ValueID const& _id, uint8** o_value, uint8* o_length ) { bool res = false; if( o_value && o_length ) { if( ValueID::ValueType_Raw == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueRaw* value = static_cast( driver->GetValue( _id ) ) ) { *o_length = value->GetLength(); *o_value = new uint8[*o_length]; memcpy( *o_value, value->GetValue(), *o_length ); value->Release(); res = true; } 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"); } } return res; } //----------------------------------------------------------------------------- // // Gets a value as a 16-bit signed integer //----------------------------------------------------------------------------- bool Manager::GetValueAsShort ( ValueID const& _id, int16* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_Short == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueShort* value = static_cast( driver->GetValue( _id ) ) ) { *o_value = value->GetValue(); value->Release(); res = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsShort"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueAsShort is not a Short Value"); } } return res; } //----------------------------------------------------------------------------- // // Creates a string representation of the value, regardless of type //----------------------------------------------------------------------------- bool Manager::GetValueAsString ( ValueID const& _id, string* o_value ) { bool res = false; char str[256] = {0}; if( o_value ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); switch( _id.GetType() ) { case ValueID::ValueType_Bool: { if( ValueBool* value = static_cast( driver->GetValue( _id ) ) ) { *o_value = value->GetValue() ? "True" : "False"; value->Release(); res = true; } 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 ) ) ) { snprintf( str, sizeof(str), "%u", value->GetValue() ); *o_value = str; value->Release(); res = true; } 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 ) ) ) { *o_value = value->GetValue(); value->Release(); res = true; } 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 ) ) ) { snprintf( str, sizeof(str), "%d", value->GetValue() ); *o_value = str; value->Release(); res = true; } 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 ) ) ) { ValueList::Item const *item = value->GetItem(); if (item == NULL) { o_value = NULL; res = false; } else { *o_value = item->m_label; res = true; } value->Release(); } 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 ) ) ) { *o_value = value->GetAsString(); value->Release(); res = true; } 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 ) ) ) { snprintf( str, sizeof(str), "%d", value->GetValue() ); *o_value = str; value->Release(); res = true; } 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 ) ) ) { *o_value = value->GetValue(); value->Release(); res = true; } 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 ) ) ) { *o_value = value->IsPressed() ? "True" : "False"; value->Release(); res = true; } 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 ) ) ) { *o_value = value->GetAsString(); value->Release(); res = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueAsString"); } break; } #if 0 /* comment this out so if we miss a ValueID, GCC warns us loudly! */ default: { // To keep GCC happy break; } #endif } } } return res; } //----------------------------------------------------------------------------- // // Gets the selected item from a list value (returning a string) //----------------------------------------------------------------------------- bool Manager::GetValueListSelection ( ValueID const& _id, string* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_List == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) { ValueList::Item const *item = value->GetItem(); if( item != NULL && item->m_label.length() > 0) { *o_value = item->m_label; res = true; } else { o_value = NULL; Log::Write(LogLevel_Warning, "ValueList returned a NULL value for GetValueListSelection: %s", value->GetLabel().c_str()); } value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueListSelection"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueListSelection is not a List Value"); } } return res; } //----------------------------------------------------------------------------- // // Gets the selected item from a list value (returning the index) //----------------------------------------------------------------------------- bool Manager::GetValueListSelection ( ValueID const& _id, int32* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_List == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) { ValueList::Item const *item = value->GetItem(); if (item == NULL) { res = false; } else { *o_value = item->m_value; res = true; } value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueListSelection"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueListSelection is not a List Value"); } } return res; } //----------------------------------------------------------------------------- // // Gets the list of items from a list value //----------------------------------------------------------------------------- bool Manager::GetValueListItems ( ValueID const& _id, vector* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_List == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) { o_value->clear(); res = value->GetItemLabels( o_value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueListItems"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueListItems is not a List Value"); } } return res; } //----------------------------------------------------------------------------- // // Gets the list of values from a list value //----------------------------------------------------------------------------- bool Manager::GetValueListValues ( ValueID const& _id, vector* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_List == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) { o_value->clear(); res = value->GetItemValues( o_value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueListValues"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueListValues is not a List Value"); } } return res; } //----------------------------------------------------------------------------- // // Gets a value's scale as a uint8 //----------------------------------------------------------------------------- bool Manager::GetValueFloatPrecision ( ValueID const& _id, uint8* o_value ) { bool res = false; if( o_value ) { if( ValueID::ValueType_Decimal == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueDecimal* value = static_cast( driver->GetValue( _id ) ) ) { *o_value = value->GetPrecision(); value->Release(); res = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetValueFloatPrecision"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueFloatPrecision is not a Decimal Value"); } } return res; } //----------------------------------------------------------------------------- // // Sets the value from a bool //----------------------------------------------------------------------------- bool Manager::SetValue ( ValueID const& _id, bool const _value ) { bool res = false; if( ValueID::ValueType_Bool == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { if( _id.GetNodeId() != driver->GetControllerNodeId() ) { LockGuard LG(driver->m_nodeMutex); if( ValueBool* value = static_cast( driver->GetValue( _id ) ) ) { res = value->Set( _value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a bool Value"); } return res; } //----------------------------------------------------------------------------- // // Sets the value from a byte //----------------------------------------------------------------------------- bool Manager::SetValue ( ValueID const& _id, uint8 const _value ) { bool res = false; if( ValueID::ValueType_Byte == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { if( _id.GetNodeId() != driver->GetControllerNodeId() ) { LockGuard LG(driver->m_nodeMutex); if( ValueByte* value = static_cast( driver->GetValue( _id ) ) ) { res = value->Set( _value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Byte Value"); } return res; } //----------------------------------------------------------------------------- // // Sets the value from a floating point number //----------------------------------------------------------------------------- bool Manager::SetValue ( ValueID const& _id, float const _value ) { bool res = false; if( ValueID::ValueType_Decimal == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { if( _id.GetNodeId() != driver->GetControllerNodeId() ) { LockGuard LG(driver->m_nodeMutex); if( ValueDecimal* value = static_cast( driver->GetValue( _id ) ) ) { char str[256]; 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 ) ) { for( nLen = strlen( str ) - 1; nLen > 0; nLen-- ) { if( str[nLen] == '0' ) str[nLen] = 0; else break; } if( (str[nLen] == '.') || (str[nLen] == ',') ) str[nLen] = 0; } // now set the value res = value->Set( str ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Decimal Value"); } return res; } //----------------------------------------------------------------------------- // // Sets the value from a 32-bit signed integer //----------------------------------------------------------------------------- bool Manager::SetValue ( ValueID const& _id, int32 const _value ) { bool res = false; if( ValueID::ValueType_Int == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { if( _id.GetNodeId() != driver->GetControllerNodeId() ) { LockGuard LG(driver->m_nodeMutex); if( ValueInt* value = static_cast( driver->GetValue( _id ) ) ) { res = value->Set( _value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Int Value"); } return res; } //----------------------------------------------------------------------------- // // Sets the value from a collection of bytes //----------------------------------------------------------------------------- bool Manager::SetValue ( ValueID const& _id, uint8 const* _value, uint8 const _length ) { bool res = false; if( ValueID::ValueType_Raw == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { if( _id.GetNodeId() != driver->GetControllerNodeId() ) { LockGuard LG(driver->m_nodeMutex); if( ValueRaw* value = static_cast( driver->GetValue( _id ) ) ) { res = value->Set( _value, _length ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Raw Value"); } return res; } //----------------------------------------------------------------------------- // // Sets the value from a 16-bit signed integer //----------------------------------------------------------------------------- bool Manager::SetValue ( ValueID const& _id, int16 const _value ) { bool res = false; if( ValueID::ValueType_Short == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { if( _id.GetNodeId() != driver->GetControllerNodeId() ) { LockGuard LG(driver->m_nodeMutex); if( ValueShort* value = static_cast( driver->GetValue( _id ) ) ) { res = value->Set( _value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValue is not a Short Value"); } return res; } //----------------------------------------------------------------------------- // // Sets the selected item in a list by value //----------------------------------------------------------------------------- bool Manager::SetValueListSelection ( ValueID const& _id, string const& _selectedItem ) { bool res = false; if( ValueID::ValueType_List == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { if( _id.GetNodeId() != driver->GetControllerNodeId() ) { LockGuard LG(driver->m_nodeMutex); if( ValueList* value = static_cast( driver->GetValue( _id ) ) ) { res = value->SetByLabel( _selectedItem ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValueListSelection"); } } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetValueListSelection is not a List Value"); } return res; } //----------------------------------------------------------------------------- // // Sets the value from a string //----------------------------------------------------------------------------- bool Manager::SetValue ( ValueID const& _id, string const& _value ) { bool res = false; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { if( _id.GetNodeId() != driver->GetControllerNodeId() ) { LockGuard LG(driver->m_nodeMutex); switch( _id.GetType() ) { case ValueID::ValueType_Bool: { if( ValueBool* value = static_cast( driver->GetValue( _id ) ) ) { if( !strcasecmp( "true", _value.c_str() ) ) { res = value->Set( true ); } else if( !strcasecmp( "false", _value.c_str() ) ) { res = value->Set( false ); } value->Release(); } 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 ) ) ) { uint32 val = (uint32)atoi( _value.c_str() ); if( val < 256 ) { res = value->Set( (uint8)val ); } value->Release(); } 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 ) ) ) { res = value->Set( _value ); value->Release(); } 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 ) ) ) { int32 val = atoi( _value.c_str() ); res = value->Set( val ); value->Release(); } 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 ) ) ) { res = value->SetByLabel( _value ); value->Release(); } 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 ) ) ) { int32 val = (uint32)atoi( _value.c_str() ); if( ( val < 32768 ) && ( val >= -32768 ) ) { res = value->Set( (int16)val ); } value->Release(); } 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 ) ) ) { res = value->Set( _value ); value->Release(); } 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 ) ) ) { res = value->SetFromString( _value ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetValue"); } break; } case ValueID::ValueType_Schedule: case ValueID::ValueType_Button: { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetValueFloatPrecision is not a Decimal Value"); break; } } } } return res; } //----------------------------------------------------------------------------- // // Instruct the driver to refresh this value by sending a message to the device //----------------------------------------------------------------------------- bool Manager::RefreshValue ( ValueID const& _id ) { bool bRet = false; // return value if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { Node *node; // Need to lock and unlock nodes to check this information LockGuard LG(driver->m_nodeMutex); if( (node = driver->GetNode( _id.GetNodeId() ) ) != NULL) { CommandClass* cc = node->GetCommandClass( _id.GetCommandClassId() ); if (cc) { uint8 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 ); bRet = true; } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to RefreshValue"); bRet = false; } } } return bRet; } //----------------------------------------------------------------------------- // // Set the verify changes flag for the specified value //----------------------------------------------------------------------------- void Manager::SetChangeVerified ( ValueID const& _id, bool _verify ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { value->SetChangeVerified( _verify ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetChangeVerified"); } } } //----------------------------------------------------------------------------- // // Get the verify changes flag for the specified value //----------------------------------------------------------------------------- bool Manager::GetChangeVerified ( ValueID const& _id ) { bool res = false; if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( Value* value = driver->GetValue( _id ) ) { res = value->GetChangeVerified(); value->Release(); } 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 res = false; if( ValueID::ValueType_Button == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueButton* value = static_cast( driver->GetValue( _id ) ) ) { res = value->PressButton(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to PressButton"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to PressButton is not a Button Value"); } return res; } //----------------------------------------------------------------------------- // // Stops an activity in a device. //----------------------------------------------------------------------------- bool Manager::ReleaseButton ( ValueID const& _id ) { bool res = false; if( ValueID::ValueType_Button == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueButton* value = static_cast( driver->GetValue( _id ) ) ) { res = value->ReleaseButton(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to ReleaseButton"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to ReleaseButton is not a Button Value"); } return res; } //----------------------------------------------------------------------------- // Climate Control Schedules //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Get the number of switch points defined in a schedule //----------------------------------------------------------------------------- uint8 Manager::GetNumSwitchPoints ( ValueID const& _id ) { // bool res = false; uint8 numSwitchPoints = 0; if( ValueID::ValueType_Schedule == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) { numSwitchPoints = value->GetNumSwitchPoints(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetNumSwitchPoints"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetNumSwitchPoints is not a Schedule Value"); } return numSwitchPoints; } //----------------------------------------------------------------------------- // // Set a switch point in the schedule //----------------------------------------------------------------------------- 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( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) { res = value->SetSwitchPoint( _hours, _minutes, _setback ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to SetSwitchPoint"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to SetSwitchPoint is not a Schedule Value"); } return res; } //----------------------------------------------------------------------------- // // Remove a switch point from the schedule //----------------------------------------------------------------------------- bool Manager::RemoveSwitchPoint ( ValueID const& _id, uint8 const _hours, uint8 const _minutes ) { bool res = false; if( ValueID::ValueType_Schedule == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) { uint8 idx; res = value->FindSwitchPoint( _hours, _minutes, &idx ); if( res ) { res = value->RemoveSwitchPoint( idx ); } value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to RemoveSwitchPoint"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to RemoveSwitchPoint is not a Schedule Value"); } return res; } //----------------------------------------------------------------------------- // // Clears all switch points from the schedule //----------------------------------------------------------------------------- void Manager::ClearSwitchPoints ( ValueID const& _id ) { if( ValueID::ValueType_Schedule == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) { value->ClearSwitchPoints(); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to ClearSwitchPoints"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to ClearSwitchPoints is not a Schedule Value"); } } //----------------------------------------------------------------------------- // // 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 res = false; if( ValueID::ValueType_Schedule == _id.GetType() ) { if( Driver* driver = GetDriver( _id.GetHomeId() ) ) { LockGuard LG(driver->m_nodeMutex); if( ValueSchedule* value = static_cast( driver->GetValue( _id ) ) ) { res = value->GetSwitchPoint( _idx, o_hours, o_minutes, o_setback ); value->Release(); } else { OZW_ERROR(OZWException::OZWEXCEPTION_INVALID_VALUEID, "Invalid ValueID passed to GetSwitchPoint"); } } } else { OZW_ERROR(OZWException::OZWEXCEPTION_CANNOT_CONVERT_VALUEID, "ValueID passed to GetSwitchPoint is not a Schedule Value"); } return res; } //----------------------------------------------------------------------------- // SwitchAll //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // All devices that support the SwitchAll command class will be turned on //----------------------------------------------------------------------------- void Manager::SwitchAllOn ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->SwitchAllOn(); } } //----------------------------------------------------------------------------- // // All devices that support the SwitchAll command class will be turned off //----------------------------------------------------------------------------- void Manager::SwitchAllOff ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->SwitchAllOff(); } } //----------------------------------------------------------------------------- // Configuration Parameters //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // 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 ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->SetConfigParam( _nodeId, _param, _value, _size ); } return false; } //----------------------------------------------------------------------------- // // Request the value of one of the configuration parameters of a device //----------------------------------------------------------------------------- void Manager::RequestConfigParam ( uint32 const _homeId, uint8 const _nodeId, uint8 const _param ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->RequestConfigParam( _nodeId, _param ); } } //----------------------------------------------------------------------------- // // Request the values of all of the known configuration parameters of a device //----------------------------------------------------------------------------- void Manager::RequestAllConfigParams ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { LockGuard LG(driver->m_nodeMutex); Node* node = driver->GetNode( _nodeId ); if( node ) { node->SetQueryStage( Node::QueryStage_Configuration ); } } } //----------------------------------------------------------------------------- // Groups //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Gets the number of association groups reported by this node //----------------------------------------------------------------------------- uint8 Manager::GetNumGroups ( uint32 const _homeId, uint8 const _nodeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetNumGroups( _nodeId ); } return 0; } //----------------------------------------------------------------------------- // // Gets the associations for a group //----------------------------------------------------------------------------- uint32 Manager::GetAssociations ( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, uint8** o_associations ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetAssociations( _nodeId, _groupIdx, o_associations ); } return 0; } //----------------------------------------------------------------------------- // // Gets the associations for a group //----------------------------------------------------------------------------- uint32 Manager::GetAssociations ( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx, InstanceAssociation** o_associations ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetAssociations( _nodeId, _groupIdx, o_associations ); } return 0; } //----------------------------------------------------------------------------- // // Gets the maximum number of associations for a group //----------------------------------------------------------------------------- uint8 Manager::GetMaxAssociations ( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetMaxAssociations( _nodeId, _groupIdx ); } return 0; } //----------------------------------------------------------------------------- // // Gets the label for a particular group //----------------------------------------------------------------------------- string Manager::GetGroupLabel ( uint32 const _homeId, uint8 const _nodeId, uint8 const _groupIdx ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->GetGroupLabel( _nodeId, _groupIdx ); } return ""; } //----------------------------------------------------------------------------- // // 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 ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->AddAssociation( _nodeId, _groupIdx, _targetNodeId, _instance ); } } //----------------------------------------------------------------------------- // // 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 ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->RemoveAssociation( _nodeId, _groupIdx, _targetNodeId, _instance ); } } //----------------------------------------------------------------------------- // Notifications //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Add a watcher to the list //----------------------------------------------------------------------------- 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 ) { if( ((*it)->m_callback == _watcher ) && ( (*it)->m_context == _context ) ) { // Already in the list m_notificationMutex->Unlock(); return false; } } m_watchers.push_back( new Watcher( _watcher, _context ) ); m_notificationMutex->Unlock(); return true; } //----------------------------------------------------------------------------- // // Remove a watcher from the list //----------------------------------------------------------------------------- bool Manager::RemoveWatcher ( pfnOnNotification_t _watcher, void* _context ) { m_notificationMutex->Lock(); list::iterator it = m_watchers.begin(); while( it != m_watchers.end() ) { if( ((*it)->m_callback == _watcher ) && ( (*it)->m_context == _context ) ) { delete (*it); m_watchers.erase( it ); m_notificationMutex->Unlock(); return true; } ++it; } m_notificationMutex->Unlock(); return false; } //----------------------------------------------------------------------------- // // Notify any watching objects of a value change //----------------------------------------------------------------------------- void Manager::NotifyWatchers ( Notification* _notification ) { m_notificationMutex->Lock(); for( list::iterator it = m_watchers.begin(); it != m_watchers.end(); ++it ) { Watcher* pWatcher = *it; pWatcher->m_callback( _notification, pWatcher->m_context ); } m_notificationMutex->Unlock(); } //----------------------------------------------------------------------------- // Controller commands //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Reset controller and erase all node information //----------------------------------------------------------------------------- void Manager::ResetController ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { Event *event = new Event(); driver->ResetController( event ); Wait::Single( event ); event->Release(); string path = driver->GetControllerPath(); Driver::ControllerInterface intf = driver->GetControllerInterfaceType(); RemoveDriver( path ); AddDriver( path, intf ); Wait::Multiple( NULL, 0, 500 ); } RemoveAllScenes( _homeId ); } //----------------------------------------------------------------------------- // // Soft-reset the Z-Wave controller chip //----------------------------------------------------------------------------- void Manager::SoftReset ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->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 void* _context, // = NULL bool _highPower, // = false uint8 _nodeId, // = 0xff uint8 _arg // = 0 ) { if( Driver* driver = GetDriver( _homeId ) ) { return driver->BeginControllerCommand( _command, _callback, _context, _highPower, _nodeId, _arg ); } return false; } //----------------------------------------------------------------------------- // // Stop the current controller function //----------------------------------------------------------------------------- bool Manager::CancelControllerCommand ( uint32 const _homeId ) { if( Driver* driver = GetDriver( _homeId ) ) { return( driver->CancelControllerCommand() ); } return false; } //----------------------------------------------------------------------------- // // Send a number of test messages to a node and record results. //----------------------------------------------------------------------------- void Manager::TestNetworkNode ( uint32 const _homeId, uint8 const _nodeId, uint32 const _count ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->TestNetwork( _nodeId, _count ); } } //----------------------------------------------------------------------------- // // Send a number of test messages to every node and record results. //----------------------------------------------------------------------------- void Manager::TestNetwork ( uint32 const _homeId, uint32 const _count ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->TestNetwork( 0, _count ); } } //----------------------------------------------------------------------------- // // Heal a single node in the network //----------------------------------------------------------------------------- void Manager::HealNetworkNode ( uint32 const _homeId, uint8 const _nodeId, bool _doRR ) { if( Driver* driver = GetDriver( _homeId ) ) { 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->UpdateNodeRoutes( _nodeId, true ); } } } } //----------------------------------------------------------------------------- // // Heal the Z-Wave network one node at a time. //----------------------------------------------------------------------------- void Manager::HealNetwork ( uint32 const _homeId, bool _doRR ) { if( Driver* driver = GetDriver( _homeId ) ) { LockGuard LG(driver->m_nodeMutex); for( uint8 i=0; i<255; i++ ) { if( driver->m_nodes[i] != NULL ) { driver->BeginControllerCommand( Driver::ControllerCommand_RequestNodeNeighborUpdate, NULL, NULL, true, i, 0 ); if( _doRR ) { driver->UpdateNodeRoutes( i, true ); } } } } } //----------------------------------------------------------------------------- // // Add a Device to the Network. //----------------------------------------------------------------------------- bool Manager::AddNode ( uint32 const _homeId, bool _doSecurity ) { if (Driver *driver = GetDriver( _homeId ) ) { 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 false; } //----------------------------------------------------------------------------- // // Remove a Device from the Network. //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Remove a Specific Device from the network if its non-responsive. //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Test if the Controller Believes the Node has Failed. //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Ask a Node to update its Return Route to the Controller //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Ask a Node to update its Neighbor Table. //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Ask a Node to delete all its Return Routes //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Send a NIF frame from the Controller to the Node //----------------------------------------------------------------------------- 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); } return false; } //----------------------------------------------------------------------------- // // Return the number of defined scenes. //----------------------------------------------------------------------------- uint8 Manager::GetNumScenes ( ) { return Scene::s_sceneCnt; } //----------------------------------------------------------------------------- // // Return an array of all Scene Ids //----------------------------------------------------------------------------- uint8 Manager::GetAllScenes ( uint8** _sceneIds ) { *_sceneIds = NULL; return Scene::GetAllScenes( _sceneIds ); } //----------------------------------------------------------------------------- // // Remove every scene id //----------------------------------------------------------------------------- void Manager::RemoveAllScenes ( uint32 const _homeId ) { for( int i = 1; i < 256; i++ ) { if( _homeId == 0 ) // remove every device from every scene { RemoveScene( i ); } else { Scene *scene = Scene::Get( i ); if( scene != NULL ) { scene->RemoveValues( _homeId ); } } } } //----------------------------------------------------------------------------- // // Create a new scene and return new Scene ID. //----------------------------------------------------------------------------- uint8 Manager::CreateScene ( ) { for( int i = 1; i < 256; i++ ) { Scene* scene = Scene::Get( i ); if( scene != NULL ) { continue; } new Scene( i ); return i; } return 0; } //----------------------------------------------------------------------------- // // Remove scene and delete its contents //----------------------------------------------------------------------------- bool Manager::RemoveScene ( uint8 const _sceneId ) { Scene *scene = 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 ) { Scene *scene = 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 ) { Scene *scene = 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 ) { Scene *scene = 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 ) { Scene *scene = 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 ) { Scene *scene = 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 ) { Scene *scene = 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 ) { Scene *scene = 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 ) { Scene *scene = 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 ) { Scene *scene = 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 ) { o_value->clear(); Scene *scene = 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 ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { string str; if( scene->GetValue( _valueId, &str ) ) { *o_value = !strcasecmp( "true", str.c_str() ); return true; } } return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID byte value //----------------------------------------------------------------------------- bool Manager::SceneGetValueAsByte ( uint8 const _sceneId, ValueID const& _valueId, uint8* o_value ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { string str; if( scene->GetValue( _valueId, &str ) ) { *o_value = (uint8)atoi( str.c_str() ); return true; } } return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID float value //----------------------------------------------------------------------------- bool Manager::SceneGetValueAsFloat ( uint8 const _sceneId, ValueID const& _valueId, float* o_value ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { string str; if( scene->GetValue( _valueId, &str ) ) { *o_value = (float)atof( str.c_str() ); return true; } } return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID integer value //----------------------------------------------------------------------------- bool Manager::SceneGetValueAsInt ( uint8 const _sceneId, ValueID const& _valueId, int32* o_value ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { string str; if( scene->GetValue( _valueId, &str ) ) { *o_value = (int32)atoi( str.c_str() ); return true; } } return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID short value //----------------------------------------------------------------------------- bool Manager::SceneGetValueAsShort ( uint8 const _sceneId, ValueID const& _valueId, int16* o_value ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { string str; if( scene->GetValue( _valueId, &str ) ) { *o_value = (int16)atoi( str.c_str() ); return true; } } return false; } //----------------------------------------------------------------------------- // // Return a scene's Value ID string value //----------------------------------------------------------------------------- bool Manager::SceneGetValueAsString ( uint8 const _sceneId, ValueID const& _valueId, string* o_value ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { if( scene->GetValue( _valueId, o_value ) ) { return true; } } 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 ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { if( scene->GetValue( _valueId, o_value ) ) { return true; } } 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 ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { string str; if( scene->GetValue( _valueId, &str ) ) { *o_value = (int32)atoi( str.c_str() ); return true; } } return false; } //----------------------------------------------------------------------------- // // Set a scene's ValueID bool 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; } //----------------------------------------------------------------------------- // // Set a scene's ValueID byte 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; } //----------------------------------------------------------------------------- // // Set a scene's ValueID float 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; } //----------------------------------------------------------------------------- // // Set a scene's ValueID integer 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; } //----------------------------------------------------------------------------- // // Set a scene's ValueID short 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; } //----------------------------------------------------------------------------- // // Set a scene's ValueID string 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; } //----------------------------------------------------------------------------- // // Set a scene's ValueID list item value (as string). //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // Set a scene's ValueID list item value (as integer). //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // Return a scene's label //----------------------------------------------------------------------------- string Manager::GetSceneLabel ( uint8 const _sceneId ) { Scene *scene = 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 ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { scene->SetLabel( _value ); } } //----------------------------------------------------------------------------- // // Check if a Scene ID exists //----------------------------------------------------------------------------- bool Manager::SceneExists ( uint8 const _sceneId ) { return Scene::Get( _sceneId ) != NULL; } //----------------------------------------------------------------------------- // // Perform all the settings for the given Scene ID //----------------------------------------------------------------------------- bool Manager::ActivateScene ( uint8 const _sceneId ) { Scene *scene = Scene::Get( _sceneId ); if( scene != NULL ) { return scene->Activate(); } return false; } //----------------------------------------------------------------------------- // // Retrieve driver based counters. //----------------------------------------------------------------------------- void Manager::GetDriverStatistics ( uint32 const _homeId, Driver::DriverData* _data ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->GetDriverStatistics( _data ); } } //----------------------------------------------------------------------------- // // Retrieve driver based counters. //----------------------------------------------------------------------------- void Manager::GetNodeStatistics ( uint32 const _homeId, uint8 const _nodeId, Node::NodeData* _data ) { if( Driver* driver = GetDriver( _homeId ) ) { driver->GetNodeStatistics( _nodeId, _data ); } } open-zwave-1.5/cpp/src/Manager.h000066400000000000000000004031661264474202400165650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Manager.h // // The main public interface to OpenZWave. // // 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 . // //----------------------------------------------------------------------------- #ifndef _Manager_H #define _Manager_H #include #include #include #include #include #include #include "Defs.h" #include "Driver.h" #include "Group.h" #include "value_classes/ValueID.h" namespace OpenZWave { class Options; class Node; class Msg; class Value; class Event; class Mutex; class SerialPort; class Thread; class Notification; class ValueBool; class ValueByte; class ValueDecimal; class ValueInt; class ValueList; class ValueShort; class ValueString; class ValueRaw; /** \brief * The main public interface to OpenZWave. * * \nosubgrouping * A singleton class providing the main public interface to OpenZWave. * The Manager class exposes all the functionality required to add * Z-Wave support to an application. It handles the sending and receiving * of Z-Wave messages as well as the configuration of a Z-Wave network * and its devices, freeing the library user from the burden of learning * the low-level details of the Z-Wave protocol. *

* All Z-Wave functionality is accessed via the Manager class. While this * does not make for the most efficient code structure, it does enable * the library to handle potentially complex and hard-to-debug issues * such as multi-threading and object lifespans behind the scenes. * Application development is therefore simplified and less prone to bugs. *

* There can be only one instance of the Manager class, and all applications * will start by calling Manager::Create static method to create that instance. * From then on, a call to the Manager::Get static method will return the * pointer to the Manager object. On application exit, Manager::Destroy * should be called to allow OpenZWave to clean up and delete any other * objects it has created. *

* Once the Manager has been created, a call should be made to Manager::AddWatcher * 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 * will read any previously saved configuration and then query the Z-Wave controller * for any missing information. Once that process is complete, a DriverReady * notification callback will be sent containing the Home ID of the controller, * which is required by most of the other Manager class methods. *

* [After the DriverReady notification is sent, the Driver will poll each node on * the network to update information about each node. After all "awake" nodes * have been polled, an "AllAwakeNodesQueried" notification is sent. This is when * a client application can expect all of the node information (both static * information, like the physical device's capabilities, session information * (like [associations and/or names] and dynamic information (like temperature or * on/off state) to be available. Finally, after all nodes (whether listening or * sleeping) have been polled, an "AllNodesQueried" notification is sent.] */ 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(); /** * \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 Deletes the Manager and cleans up any associated objects. * \see Create, Get */ static void Destroy(); /** * \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 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 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 the configuration 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 'zwcfg_'. * 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. * \param _homeId The Home ID of the Z-Wave controller to save. */ void WriteConfig( uint32 const _homeId ); /** * \brief Gets a pointer to the locked Options object. * \return pointer to the Options object. * \see Create */ Options* GetOptions()const{ return m_options; } /*@}*/ private: Options* m_options; // Pointer to the locked Options object that was passed in during creation. //----------------------------------------------------------------------------- // 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 recieved 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 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 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 promary 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 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 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 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 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 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 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 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 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 ); /*@}*/ //----------------------------------------------------------------------------- // Node information //----------------------------------------------------------------------------- /** \name Node information * Methods for accessing information on indivdual nodes. */ /*@{*/ public: /** * \brief Trigger the fetching of fixed data about a node. * Causes the node's data to be obtained from the Z-Wave network in the same way as if it had just been added. * This method would normally be called automatically by OpenZWave, but if you know that a node has been * changed, calling this method will force a refresh of all of the data held by the library. This can be especially * useful for devices that were asleep when the application was first run. This is the * same as the query state starting from the beginning. * \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 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 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 ); /** * \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 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 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 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 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 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 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 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 commmand 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 commmand 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 commmand 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 * commmand 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 commmand 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 manufactuer * specific command class is not supported by the device. * \see GetNodeProductType, GetNodeProductId, GetNodeManufacturerName, GetNodeProductName * \todo Change the return to uint16 in 2.0 timeframe */ 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 * commmand 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 manufactuer * specific command class is not supported by the device. * \see GetNodeManufacturerId, GetNodeProductId, GetNodeManufacturerName, GetNodeProductName * \todo Change the return to uint16 in 2.0 timeframe */ 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 * commmand 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 manufactuer * specific command class is not supported by the device. * \see GetNodeManufacturerId, GetNodeProductType, GetNodeManufacturerName, GetNodeProductName * \todo Change the return to uint16 in 2.0 timeframe */ 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 commmand 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 commmand 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 commmand 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 * commmand 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. * \see SetNodeOff, SetNodeLevel */ 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. * \see SetNodeOn, SetNodeLevel */ 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). * \see SetNodeOn, SetNodeOff */ 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 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 ); /*@}*/ //----------------------------------------------------------------------------- // 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. * \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 ); /** * \brief Sets the user-friendly label for the value. * \param _id The unique identifier of the value. * \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 ); /** * \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. * \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 ); /** * \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. * \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 ); /** * \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 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, 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, GetValueAsBool, GetValueAsByte, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems */ bool GetValueFloatPrecision( ValueID const& _id, uint8* o_value ); /** * \brief Sets the state of a bool. * Due to the possibility of a device being asleep, the command is assumed to suceed, 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 suceed, 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 suceed, 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 suceed, 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 suceed, 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 suceed, 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 suceed, 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 ); /*@}*/ //----------------------------------------------------------------------------- // 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. */ void SwitchAllOn( uint32 const _homeId ); /** * \brief Switch all devices off. * All devices that support the SwitchAll command class will be turned off. */ 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 behaviour. * 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 paramter _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 behaviour. * 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. * 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 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 suceed, 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 suceed, 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 ) { } }; OPENZWAVE_EXPORT_WARNINGS_OFF list m_watchers; // List of all the registered 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 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 * * \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 succcesfully 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 AddNode 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 succesfully 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 AddNode 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 succesfully 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 AddNode 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 succesfully 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 AddNode 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 succesfully 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 AddNode 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 succesfully 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 AddNode 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 succesfully 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 * * Results of the AddNode 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 NodeID of the Node to recieve the NIF * \return if the sendNIF Command was send succesfully 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 succesfully 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 recieve 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 succesfully 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 succesfully 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 succesfully 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 succesfully 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 succesfully 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 succesfully 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 succesfully to the Controller * \sa CancelControllerCommand */ bool DeleteButton(uint32 const _homeId, uint8 const _nodeId, uint8 const _buttonid); /*@}*/ //----------------------------------------------------------------------------- // Scene commands //----------------------------------------------------------------------------- /** \name Scene Commands * Commands for Z-Wave scene interface. */ /*@{*/ public: /** * \brief Gets the number of scenes that have been defined. * \return The number of scenes. * \see GetAllScenes, RemoveAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ uint8 GetAllScenes( uint8** _sceneIds ); /** * \brief Remove all the SceneIds. * \param _homeId The Home ID of the Z-Wave controller. 0 for all devices from all scenes. * \see GetAllScenes, GetNumScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, SetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SceneExists, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, ActivateScene */ 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists */ 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 ); }; /*@}*/ } // namespace OpenZWave #endif // _Manager_H open-zwave-1.5/cpp/src/Msg.cpp000066400000000000000000000201141264474202400162600ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Msg.cpp // // Represents a Z-Wave message // // 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 . // //----------------------------------------------------------------------------- #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Manager.h" #include "Utils.h" #include "ZWSecurity.h" #include "platform/Log.h" #include "command_classes/MultiInstance.h" #include "command_classes/Security.h" #include "aes/aescpp.h" using namespace OpenZWave; /* Callback for normal messages start at 10. Special Messages using a Callback prior to 10 */ uint8 Msg::s_nextCallbackId = 10; #define DEBUG 1 //----------------------------------------------------------------------------- // // 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; } 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 ) { 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 = 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; } //----------------------------------------------------------------------------- // // 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(); } // Add the callback id if( m_bCallbackRequired ) { // Set the length byte m_buffer[1] = m_length; // Length of following data if( 0 == s_nextCallbackId ) { s_nextCallbackId = 10; } 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 } // 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 ) { s_nextCallbackId = 10; } // 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; char byteStr[16]; if( m_targetNodeId != 0xff ) { snprintf( byteStr, sizeof(byteStr), " (Node=%d)", m_targetNodeId ); str += byteStr; } 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 ) { m_buffer[i+4] = m_buffer[i]; } 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]; } 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), "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() { 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 Encyrpt Packet"); return NULL; } } open-zwave-1.5/cpp/src/Msg.h000066400000000000000000000147521264474202400157400ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Msg.h // // Represents a Z-Wave message // // 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 . // //----------------------------------------------------------------------------- #ifndef _Msg_H #define _Msg_H #include #include #include #include "Defs.h" //#include "Driver.h" 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 { public: enum MessageFlags { m_MultiChannel = 0x01, // Indicate MultiChannel encapsulation m_MultiInstance = 0x02, // Indicate MultiInstance encapsulation }; 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 SetInstance( CommandClass* _cc, uint8 const _instance ); // Used to enable wrapping with MultiInstance/MultiChannel during finalize. void Append( uint8 const _data ); void Finalize(); void UpdateCallbackId(); /** * \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 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 expected Command Class ID (if any) for this message. * \return Expected command class ID for this message. */ uint8 GetExpectedCommandClassId()const{ return m_expectedCommandClassId; } /** * \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 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; } uint32 GetLength()const{ return m_encrypted == true ? m_length + 20 + 6 : m_length; } uint8* GetBuffer(); string GetAsString(); uint8 GetSendAttempts()const{ return m_sendAttempts; } void SetSendAttempts( uint8 _count ){ m_sendAttempts = _count; } uint8 GetMaxSendAttempts()const{ return m_maxSendAttempts; } void SetMaxSendAttempts( uint8 _count ){ if( _count < MAX_MAX_TRIES ) m_maxSendAttempts = _count; } 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 ) ); } 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; }; /** Returns a pointer to the driver (interface with a Z-Wave controller) * associated with this node. */ Driver* GetDriver()const; private: void MultiEncap(); // Encapsulate the data inside a MultiInstance/Multicommand message string m_logText; bool m_bFinal; bool m_bCallbackRequired; uint8 m_callbackId; uint8 m_expectedReply; uint8 m_expectedCommandClassId; uint8 m_length; uint8 m_buffer[256]; uint8 e_buffer[256]; uint8 m_targetNodeId; uint8 m_sendAttempts; uint8 m_maxSendAttempts; 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 OpenZWave #endif //_Msg_H open-zwave-1.5/cpp/src/Node.cpp000066400000000000000000003211461264474202400164300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Node.cpp // // A node in the Z-Wave network. // // Copyright (c) 2009 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 . // //----------------------------------------------------------------------------- #include #include "Node.h" #include "Defs.h" #include "Group.h" #include "Options.h" #include "Manager.h" #include "Driver.h" #include "Notification.h" #include "Msg.h" #include "ZWSecurity.h" #include "platform/Log.h" #include "platform/Mutex.h" #include "Utils.h" #include "tinyxml.h" #include "command_classes/CommandClasses.h" #include "command_classes/CommandClass.h" #include "command_classes/Association.h" #include "command_classes/Basic.h" #include "command_classes/Configuration.h" #include "command_classes/ControllerReplication.h" #include "command_classes/ManufacturerSpecific.h" #include "command_classes/MultiInstance.h" #include "command_classes/MultiInstanceAssociation.h" #include "command_classes/Security.h" #include "command_classes/WakeUp.h" #include "command_classes/NodeNaming.h" #include "command_classes/NoOperation.h" #include "command_classes/Version.h" #include "command_classes/SwitchAll.h" #include "command_classes/ZWavePlusInfo.h" #include "command_classes/DeviceResetLocally.h" #include "Scene.h" #include "value_classes/ValueID.h" #include "value_classes/Value.h" #include "value_classes/ValueBool.h" #include "value_classes/ValueButton.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueDecimal.h" #include "value_classes/ValueInt.h" #include "value_classes/ValueRaw.h" #include "value_classes/ValueList.h" #include "value_classes/ValueSchedule.h" #include "value_classes/ValueShort.h" #include "value_classes/ValueString.h" #include "value_classes/ValueStore.h" 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; static char const* c_queryStageNames[] = { "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_numRouteNodes( 0 ), 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_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_lastnonce ( 0 ) { memset( m_neighbors, 0, sizeof(m_neighbors) ); memset( m_routeNodes, 0, sizeof(m_routeNodes) ); memset( m_nonces, 0, sizeof(m_nonces) ); AddCommandClass( 0 ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Node::~Node ( ) { // Remove any messages from queues GetDriver()->RemoveQueues( m_nodeId ); // Remove the values from the poll list for( ValueStore::Iterator it = m_values->Begin(); it != m_values->End(); ++it ) { ValueID const& valueId = it->second->GetID(); if( GetDriver()->isPolled( valueId ) ) { GetDriver()->DisablePoll( valueId ); } } Scene::RemoveValues( m_homeId, m_nodeId ); // Delete the values delete m_values; // Delete the command classes while( !m_commandClassMap.empty() ) { map::iterator it = m_commandClassMap.begin(); delete it->second; m_commandClassMap.erase( it ); } // Delete the groups while( !m_groups.empty() ) { map::iterator it = m_groups.begin(); delete it->second; m_groups.erase( it ); } // Delete the button map while( !m_buttonMap.empty() ) { map::iterator it = m_buttonMap.begin(); m_buttonMap.erase( it ); } } //----------------------------------------------------------------------------- // // Proceed through the initialisation process //----------------------------------------------------------------------------- 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 // in the next stage. The stage is saved with the node data, so that any incomplete // queries can be restarted the next time the application runs. // The individual command classes also store some state as to whether they have // had a response to certain queries. This state is initilized by the SetStaticRequests // call in QueryStage_None. It is also saved, so we do not need to request state // from every command class if some have previously responded. // // Each stage must generate all the messages for its particular stage as // 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 ); bool addQSC = false; // We only want to add a query stage complete if we did some work. while( !m_queryPending && m_nodeAlive ) { switch( m_queryStage ) { case QueryStage_None: { // Init the node query process m_queryStage = QueryStage_ProtocolInfo; m_queryRetries = 0; break; } case QueryStage_ProtocolInfo: { // determines, among other things, whether this node is a listener, its maximum baud rate and its device classes 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 ); m_queryPending = true; addQSC = true; } else { // This stage has been done already, so move to the Neighbours stage m_queryStage = QueryStage_Probe; m_queryRetries = 0; } break; } case 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() ) ); /* don't Probe the Controller */ if( GetDriver()->GetControllerNodeId() != m_nodeId ) { noop->Set( true ); m_queryPending = true; addQSC = true; } else { m_queryStage = QueryStage_WakeUp; m_queryRetries = 0; } break; } case QueryStage_WakeUp: { // 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" ); WakeUp* wakeUp = static_cast( GetCommandClass( 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() ) { // start the process of requesting node state from this sleeping device wakeUp->Init(); m_queryPending = true; addQSC = true; } else { // this is not a sleeping device, so move to the ManufacturerSpecific1 stage m_queryStage = QueryStage_ManufacturerSpecific1; m_queryRetries = 0; } break; } case QueryStage_ManufacturerSpecific1: { // 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" ); /* if its the Controller, then we can just load up the XML straight away */ if( GetDriver()->GetControllerNodeId() == m_nodeId ) { Log::Write( LogLevel_Detail, m_nodeId, "Load Controller Manufacturer Specific Config"); string configPath = ManufacturerSpecific::SetProductDetails( this, GetDriver()->GetManufacturerId(), GetDriver()->GetProductType(), GetDriver()->GetProductId() ); if( configPath.length() > 0 ) { ManufacturerSpecific::LoadConfigXML( this, configPath ); } m_queryStage = QueryStage_NodeInfo; m_queryRetries = 0; } else { 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 ) { m_queryPending = cc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query ); addQSC = m_queryPending; } if( !m_queryPending ) { m_queryStage = QueryStage_NodeInfo; m_queryRetries = 0; } } break; } case QueryStage_NodeInfo: { 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 ); m_queryPending = true; addQSC = true; } else { // This stage has been done already, so move to the Manufacturer Specific stage m_queryStage = QueryStage_NodePlusInfo; m_queryRetries = 0; } break; } case QueryStage_NodePlusInfo: { Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_NodePlusInfo" ); ZWavePlusInfo* pluscc = static_cast( GetCommandClass( ZWavePlusInfo::StaticGetCommandClassId() ) ); if ( pluscc ) { m_queryPending = pluscc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query ); } if (m_queryPending) { addQSC = m_queryPending; } else { // this is not a Zwave+ node, so move onto the next querystage m_queryStage = QueryStage_SecurityReport; m_queryRetries = 0; } break; } case QueryStage_SecurityReport: { /* 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" ); Security* seccc = static_cast( GetCommandClass( Security::StaticGetCommandClassId() ) ); if( seccc ) { // start the process setting up the Security CommandClass m_queryPending = seccc->Init(); /* Dont add a QueryStageComplete flag here, as this is a multipacket exchange. * the Security Command Class will automatically advance the Query Stage * when we recieve a SecurityCmd_SupportedReport */ addQSC = true; } else { // this is not a Security Device, so move onto the next querystage m_queryStage = QueryStage_ManufacturerSpecific2; m_queryRetries = 0; } break; } case QueryStage_ManufacturerSpecific2: { 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() ) ); if( cc ) { m_queryPending = cc->RequestState( CommandClass::RequestFlag_Static, 1, Driver::MsgQueue_Query ); addQSC = m_queryPending; } if( !m_queryPending ) { m_queryStage = QueryStage_Versions; m_queryRetries = 0; } } else { ManufacturerSpecific* cc = static_cast( GetCommandClass( ManufacturerSpecific::StaticGetCommandClassId() ) ); if( cc ) { cc->ReLoadConfigXML(); } m_queryStage = QueryStage_Versions; m_queryRetries = 0; } break; } 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_Info, m_nodeId, "Requesting Versions"); for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) { CommandClass* cc = it->second; Log::Write(LogLevel_Info, m_nodeId, "Requesting Versions for %s", cc->GetCommandClassName().c_str()); if( cc->GetMaxVersion() > 1 ) { Log::Write(LogLevel_Info, m_nodeId, " ok"); // Get the version for each supported command class that // we have implemented at greater than version one. m_queryPending |= vcc->RequestCommandClassVersion( it->second ); } } addQSC = m_queryPending; } // advance to Instances stage when finished if( !m_queryPending ) { m_queryStage = QueryStage_Instances; m_queryRetries = 0; } break; } 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 ) { m_queryPending = micc->RequestInstances(); addQSC = m_queryPending; } // when done, advance to the Static stage 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 ); } break; } case QueryStage_Static: { // 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" ); for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) { if( !it->second->IsAfterMark() ) { 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 ); } } addQSC = 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 // have already queried it at the discovery phase in Probe. m_queryStage = QueryStage_Associations; m_queryRetries = 0; } break; } /* 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(), "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() ) ); /* Don't do this if its to the Controller */ if( GetDriver()->GetControllerNodeId() != m_nodeId ) { noop->Set( true ); m_queryPending = true; addQSC = true; } else { m_queryStage = QueryStage_Associations; m_queryRetries = 0; } break; } 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" ); MultiInstanceAssociation* macc = static_cast( GetCommandClass( MultiInstanceAssociation::StaticGetCommandClassId() ) ); if( macc ) { macc->RequestAllGroups( 0 ); m_queryPending = true; addQSC = true; } else { Association* acc = static_cast( GetCommandClass( Association::StaticGetCommandClassId() ) ); if( acc ) { acc->RequestAllGroups( 0 ); m_queryPending = true; addQSC = true; } else { // if this device doesn't support Associations, move to retrieve Session information m_queryStage = QueryStage_Neighbors; m_queryRetries = 0; } } break; } 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 ); m_queryPending = true; addQSC = true; break; } case QueryStage_Session: { // 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 ) { if( !it->second->IsAfterMark() ) { m_queryPending |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_Session, Driver::MsgQueue_Query ); } } addQSC = m_queryPending; if( !m_queryPending ) { m_queryStage = QueryStage_Dynamic; m_queryRetries = 0; } break; } case QueryStage_Dynamic: { // 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" ); m_queryPending = RequestDynamicValues(); addQSC = m_queryPending; if( !m_queryPending ) { m_queryStage = QueryStage_Configuration; m_queryRetries = 0; } break; } case QueryStage_Configuration: { // Request the configurable parameter values from the node. Log::Write( LogLevel_Detail, m_nodeId, "QueryStage_Configuration" ); if( m_queryConfiguration ) { if( RequestAllConfigParams( 0 ) ) { m_queryPending = true; addQSC = true; } m_queryConfiguration = false; } if( !m_queryPending ) { m_queryStage = QueryStage_Complete; m_queryRetries = 0; } break; } case QueryStage_Complete: { 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 ); // Check whether all nodes are now complete GetDriver()->CheckCompletedNodeQueries(); return; } default: { break; } } } 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 ); } } //----------------------------------------------------------------------------- // // We are done with a stage in the query process //----------------------------------------------------------------------------- void Node::QueryStageComplete ( QueryStage const _stage ) { // Check that we are actually on the specified stage if( _stage != m_queryStage ) { return; } 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 ); } m_queryRetries = 0; } } //----------------------------------------------------------------------------- // // Retry a stage up to the specified maximum //----------------------------------------------------------------------------- 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); // Check that we are actually on the specified stage if( _stage != m_queryStage ) { return; } m_queryPending = false; 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 ) { m_queryStage = (Node::QueryStage)( (uint32)(m_queryStage + 1) ); } } // Repeat the current query stage 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 ) { if( (int)_stage < (int)m_queryStage ) { m_queryStage = _stage; m_queryPending = false; if( QueryStage_Configuration == _stage ) { m_queryConfiguration = true; } } if( _advance ) { AdvanceQueries(); } } //----------------------------------------------------------------------------- // // Gets the query stage name //----------------------------------------------------------------------------- string Node::GetQueryStageName ( QueryStage const _stage ) { return c_queryStageNames[_stage]; } //----------------------------------------------------------------------------- // // Gets the neighbors of a node //----------------------------------------------------------------------------- uint32 Node::GetNeighbors ( uint8** o_neighbors ) { // determine how many neighbors there are int i; uint32 numNeighbors = 0; if( m_queryStage < QueryStage_Session ) { *o_neighbors = NULL; return 0; } for( i = 0; i < 29; i++ ) { 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 ) { *o_neighbors = NULL; return 0; } // 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 bi=0; bi<8; bi++ ) { if( (m_neighbors[by] & ( 0x01< // Read the node config from XML //----------------------------------------------------------------------------- void Node::ReadXML ( TiXmlElement const* _node ) { char const* str; int intVal; 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 ) { if( !strcmp( str, c_queryStageNames[i] ) ) { queryStage = (QueryStage)i; break; } } /* we cant use the SetQueryStage method here, as it only allows us to * go to a lower QueryStage, and not a higher QueryStage. As QueryStage_Complete is higher than * QueryStage_None (the default) we manually set it here. Note - in Driver::HandleSerialAPIGetInitDataResponse the * QueryStage is set to CacheLoad (which is less than QueryStage_Associations) if this is a existing node read in via the zw state file. * */ m_queryStage = queryStage; m_queryPending = false; if( QueryStage_Configuration == queryStage ) { m_queryConfiguration = true; } } if( m_queryStage != QueryStage_None ) { 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 ); } if( m_queryStage > QueryStage_NodeInfo ) { m_nodeInfoReceived = true; } if( m_queryStage > QueryStage_Instances ) { Notification* notification = new Notification( Notification::Type_EssentialNodeQueriesComplete ); notification->SetHomeAndNodeIds( m_homeId, m_nodeId ); GetDriver()->QueueNotification( notification ); } } str = _node->Attribute( "name" ); if( str ) { m_nodeName = str; } str = _node->Attribute( "location" ); if( str ) { m_location = str; } if( TIXML_SUCCESS == _node->QueryIntAttribute( "basic", &intVal ) ) { m_basic = (uint8)intVal; } if( TIXML_SUCCESS == _node->QueryIntAttribute( "generic", &intVal ) ) { m_generic = (uint8)intVal; } if( TIXML_SUCCESS == _node->QueryIntAttribute( "specific", &intVal ) ) { m_specific = (uint8)intVal; } if( TIXML_SUCCESS == _node->QueryIntAttribute( "roletype", &intVal ) ) { m_role = (uint8)intVal; m_nodePlusInfoReceived = true; } if( TIXML_SUCCESS == _node->QueryIntAttribute( "devicetype", &intVal ) ) { m_deviceType = (uint16)intVal; m_nodePlusInfoReceived = true; } if (TIXML_SUCCESS == _node->QueryIntAttribute ( "nodetype", &intVal ) ) { m_nodeType = (uint8)intVal; m_nodePlusInfoReceived = true; } str = _node->Attribute( "type" ); if( str ) { m_type = str; } m_listening = true; str = _node->Attribute( "listening" ); if( str ) { m_listening = !strcmp( str, "true" ); } m_frequentListening = false; str = _node->Attribute( "frequentListening" ); if( str ) { m_frequentListening = !strcmp( str, "true" ); } m_beaming = false; str = _node->Attribute( "beaming" ); if( str ) { m_beaming = !strcmp( str, "true" ); } m_routing = true; str = _node->Attribute( "routing" ); if( str ) { m_routing = !strcmp( str, "true" ); } m_maxBaudRate = 0; if( TIXML_SUCCESS == _node->QueryIntAttribute( "max_baud_rate", &intVal ) ) { m_maxBaudRate = (uint32)intVal; } m_version = 0; if( TIXML_SUCCESS == _node->QueryIntAttribute( "version", &intVal ) ) { m_version = (uint8)intVal; } m_security = false; str = _node->Attribute( "security" ); if( str ) { m_security = !strcmp( str, "true" ); } m_secured = false; str = _node->Attribute( "secured" ); if( str ) { m_secured = !strcmp( str, "true" ); } m_nodeInfoSupported = true; str = _node->Attribute( "nodeinfosupported" ); if( str ) { m_nodeInfoSupported = !strcmp( str, "true" ); } m_refreshonNodeInfoFrame = true; str = _node->Attribute( "refreshonnodeinfoframe" ); if ( str ) m_refreshonNodeInfoFrame = !strcmp (str, "true" ); // Read the manufacturer info and create the command classes TiXmlElement const* child = _node->FirstChildElement(); while( child ) { str = child->Value(); if( str ) { if( !strcmp( str, "CommandClasses" ) ) { ReadCommandClassesXML( child ); } else if( !strcmp( str, "Manufacturer" ) ) { str = child->Attribute( "id" ); if( str ) { m_manufacturerId = strtol(str, NULL, 16); } str = child->Attribute( "name" ); if( str ) { m_manufacturerName = str; } TiXmlElement const* product = child->FirstChildElement(); if( !strcmp( product->Value(), "Product" ) ) { str = product->Attribute( "type" ); if( str ) { m_productType = strtol(str, NULL, 16); } str = product->Attribute( "id" ); if( str ) { m_productId = strtol(str, NULL, 16); } str = product->Attribute( "name" ); if( str ) { m_productName = str; } } } } // Move to the next child node child = child->NextSiblingElement(); } 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 ); } } //----------------------------------------------------------------------------- // // Read the device's protocol configuration from XML //----------------------------------------------------------------------------- void Node::ReadDeviceProtocolXML ( TiXmlElement const* _ccsElement ) { TiXmlElement const* ccElement = _ccsElement->FirstChildElement(); while( ccElement ) { char const* str = ccElement->Value(); if( str && !strcmp( str, "Protocol" ) ) { str = ccElement->Attribute( "nodeinfosupported" ); if( str ) { m_nodeInfoSupported = !strcmp( str, "true" ); } str = ccElement->Attribute( "refreshonnodeinfoframe" ); if ( str ) { 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 ) { str = childElement->Value(); if( str && !strcmp( str, "APIcall" ) ) { char const* funcStr = childElement->Attribute( "function" ); char *p; uint8 func = (uint8)strtol( funcStr, &p, 16 ); if( p != funcStr ) { char const* presStr = ccElement->Attribute( "present" ); GetDriver()->SetAPICall( func, !strcmp( presStr, "true" ) ); } } childElement = childElement->NextSiblingElement(); } return; } ccElement = ccElement->NextSiblingElement(); } } //----------------------------------------------------------------------------- // // Read the command classes from XML //----------------------------------------------------------------------------- void Node::ReadCommandClassesXML ( TiXmlElement const* _ccsElement ) { char const* str; int32 intVal; TiXmlElement const* ccElement = _ccsElement->FirstChildElement(); while( ccElement ) { str = ccElement->Value(); if( str && !strcmp( str, "CommandClass" ) ) { if( TIXML_SUCCESS == ccElement->QueryIntAttribute( "id", &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" ) ) { remove = true; } CommandClass* cc = GetCommandClass( id ); if( remove ) { // Remove support for the command class RemoveCommandClass( id ); } else { if( NULL == cc ) { if (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 ); } if( NULL != cc ) { cc->ReadXML( ccElement ); } } } } ccElement = ccElement->NextSiblingElement(); } } //----------------------------------------------------------------------------- // // Save the static node configuration data //----------------------------------------------------------------------------- void Node::WriteXML ( TiXmlElement* _driverElement ) { char str[32]; TiXmlElement* nodeElement = new TiXmlElement( "Node" ); _driverElement->LinkEndChild( nodeElement ); snprintf( str, 32, "%d", m_nodeId ); nodeElement->SetAttribute( "id", 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_generic ); nodeElement->SetAttribute( "generic", str ); snprintf( str, 32, "%d", m_specific ); nodeElement->SetAttribute( "specific", str ); if( m_nodePlusInfoReceived ) { 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_nodeType ); nodeElement->SetAttribute ( "nodetype", 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" ); snprintf( str, 32, "%d", m_maxBaudRate ); nodeElement->SetAttribute( "max_baud_rate", str ); snprintf( str, 32, "%d", m_version ); nodeElement->SetAttribute( "version", str ); if( m_security ) { nodeElement->SetAttribute( "security", "true" ); } if( m_secured ) { nodeElement->SetAttribute( "secured", "true" ); } if( !m_nodeInfoSupported ) { nodeElement->SetAttribute( "nodeinfosupported", "false" ); } if (!m_refreshonNodeInfoFrame) { nodeElement->SetAttribute( "refreshonnodeinfoframe", "false" ); } nodeElement->SetAttribute( "query_stage", c_queryStageNames[m_queryStage] ); // 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 ); /* 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( "name", m_manufacturerName.c_str() ); 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() ); } /* 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( "name", m_productName.c_str() ); // Write the command classes TiXmlElement* ccsElement = new TiXmlElement( "CommandClasses" ); nodeElement->LinkEndChild( ccsElement ); for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) { if( it->second->GetCommandClassId() == NoOperation::StaticGetCommandClassId() ) // don't output NoOperation { continue; } TiXmlElement* ccElement = new TiXmlElement( "CommandClass" ); ccsElement->LinkEndChild( ccElement ); it->second->WriteXML( ccElement ); } } //----------------------------------------------------------------------------- // // Handle the FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO response //----------------------------------------------------------------------------- void Node::UpdateProtocolInfo ( uint8 const* _data ) { if( ProtocolInfoReceived() ) { // We already have this info return; } 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 ); return; } // Capabilities m_listening = ( ( _data[0] & 0x80 ) != 0 ); m_routing = ( ( _data[0] & 0x40 ) != 0 ); m_maxBaudRate = 9600; if( ( _data[0] & 0x38 ) == 0x10 ) { m_maxBaudRate = 40000; } m_version = ( _data[0] & 0x07 ) + 1; m_frequentListening = ( ( _data[1] & ( SecurityFlag_Sensor250ms | SecurityFlag_Sensor1000ms ) ) != 0 ); m_beaming = ( ( _data[1] & SecurityFlag_BeamCapability ) != 0 ); // Security 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()) { // 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" ); 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, " 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) { // 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 ); // Set up the device class based data for the node, including mandatory command classes 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() ) { GetDriver()->ReadButtons( m_nodeId ); } m_basicprotocolInfoReceived = true; } 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()) { // 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() ) ) { pCommandClass->SetInstance( 1 ); } } } m_protocolInfoReceived = true; } void Node::SetProtocolInfo ( uint8 const* _protocolInfo, uint8 const _length ) { if( ProtocolInfoReceived() || m_basicprotocolInfoReceived == true ) { // We already have this info return; } 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 ); 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 ); // Set up the device class based data for the node, including mandatory command classes 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()))) { /* Security CC has already been loaded, most likely via the SetDeviceClasses Function above */ if (!GetDriver()->isNetworkKeySet()) { Log::Write(LogLevel_Warning, m_nodeId, "Security Command Class Disabled. NetworkKey is not Set"); } else { pCommandClass->ExchangeNetworkKeys(); } } 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()) { Log::Write(LogLevel_Warning, m_nodeId, "Security Command Class Disabled. NetworkKey is not Set"); } else { pCommandClass->ExchangeNetworkKeys(); } } } } } UpdateNodeInfo(&_protocolInfo[3], _length-3); m_basicprotocolInfoReceived = true; } void Node::SetSecured(bool secure) { m_secured = secure; } void Node::SetSecuredClasses ( uint8 const* _data, uint8 const _length ) { uint32 i; m_secured = true; Log::Write( LogLevel_Info, m_nodeId, " Secured command classes for node %d:", m_nodeId ); if (!GetDriver()->isNetworkKeySet()) { Log::Write (LogLevel_Warning, m_nodeId, " Secured Command Classes cannot be enabled as Network Key is not set"); return; } bool afterMark = false; for( i=0; i<_length; ++i ) { 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; continue; } /* Check if this is a CC that is already registered with the node */ if (CommandClass *pCommandClass = GetCommandClass(_data[i])) { /* if it was specified int 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 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 )) { pCommandClass->SetSecured(); 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()) { pCommandClass->SetSecured(); Log::Write( LogLevel_Info, m_nodeId, " %s (Secured) - %s", pCommandClass->GetCommandClassName().c_str(), pCommandClass->IsInNIF() ? "InNIF": "NotInNIF"); } } } /* 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] ) ) { if( CommandClass* pCommandClass = AddCommandClass( _data[i] ) ) { // If this class came after the COMMAND_CLASS_MARK, then we do not create values. if( afterMark ) { pCommandClass->SetAfterMark(); } if (pCommandClass->IsSecureSupported()) { pCommandClass->SetSecured(); 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. pCommandClass->SetInstance( 1 ); /* set our Static Request Flags */ uint8 request = 0; if( GetCommandClass( MultiInstance::StaticGetCommandClassId() ) ) { // Request instances request |= (uint8)CommandClass::StaticRequest_Instances; } if( GetCommandClass( Version::StaticGetCommandClassId() ) ) { // Request versions request |= (uint8)CommandClass::StaticRequest_Version; } if( 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, " UnSecured command classes for node %d:", m_nodeId ); 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" ); } } //----------------------------------------------------------------------------- // // Set up the command classes from the node info frame //----------------------------------------------------------------------------- void Node::UpdateNodeInfo ( uint8 const* _data, uint8 const _length ) { if( !NodeInfoReceived() ) { // Add the command classes specified by the device Log::Write( LogLevel_Info, m_nodeId, " Optional command classes for node %d:", m_nodeId ); bool newCommandClasses = false; uint32 i; bool afterMark = false; for( i=0; i<_length; ++i ) { 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; if( !newCommandClasses ) { Log::Write( LogLevel_Info, m_nodeId, " None" ); } Log::Write( LogLevel_Info, m_nodeId, " Optional command classes controlled by node %d:", m_nodeId ); newCommandClasses = false; continue; } if( 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()); continue; } if( 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 ) { pCommandClass->SetAfterMark(); } // 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 ); 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 { Log::Write( LogLevel_Info, m_nodeId, " CommandClass 0x%.2x - NOT REQUIRED", _data[i] ); } } if( !newCommandClasses ) { // No additional command classes over the mandatory ones. Log::Write( LogLevel_Info, m_nodeId, " None" ); } SetStaticRequests(); m_nodeInfoReceived = true; } else { /* Only Refresh if the Device Config Specifies it - Only the dynamic stuff */ if (m_refreshonNodeInfoFrame) SetQueryStage( QueryStage_Dynamic ); } // Treat the node info frame as a sign that the node is awake if( WakeUp* wakeUp = static_cast( GetCommandClass( WakeUp::StaticGetCommandClassId() ) ) ) { wakeUp->SetAwake( true ); } } //----------------------------------------------------------------------------- // // Track alive state of a node for dead node detection. //----------------------------------------------------------------------------- void Node::SetNodeAlive ( bool const _isAlive ) { Notification* notification; if( _isAlive ) { Log::Write( LogLevel_Error, m_nodeId, "WARNING: node revived" ); m_nodeAlive = true; m_errors = 0; 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 ); } else { Log::Write( LogLevel_Error, m_nodeId, "ERROR: node presumed dead" ); m_nodeAlive = false; 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 ); } GetDriver()->QueueNotification( notification ); } //----------------------------------------------------------------------------- // // The first time we hear from a node, we set flags to indicate the // 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 ( ) { uint8 request = 0; if( GetCommandClass( MultiInstance::StaticGetCommandClassId() ) ) { // Request instances request |= (uint8)CommandClass::StaticRequest_Instances; } if( GetCommandClass( Version::StaticGetCommandClassId() ) ) { // Request versions request |= (uint8)CommandClass::StaticRequest_Version; } if( request ) { for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) { it->second->SetStaticRequest( request ); } SetQueryStage( QueryStage_ManufacturerSpecific2 ); } } //----------------------------------------------------------------------------- // // Set the name of the node //----------------------------------------------------------------------------- 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() ) ) ) { // The node supports naming, so we try to write the name into the device cc->SetName( _nodeName ); } } //----------------------------------------------------------------------------- // // Set the location of the node //----------------------------------------------------------------------------- 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() ) ) ) { // The node supports naming, so we try to write the location into the device cc->SetLocation( _location ); } } //----------------------------------------------------------------------------- // // Handle a command class message //----------------------------------------------------------------------------- void Node::ApplicationCommandHandler ( uint8 const* _data, bool encrypted ) { if( CommandClass* pCommandClass = GetCommandClass( _data[5] ) ) { if (pCommandClass->IsSecured() && !encrypted) { Log::Write( LogLevel_Warning, m_nodeId, "Recieved 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"); return; } else { Log::Write( LogLevel_Warning, m_nodeId, " Allowing Message (EnforceSecureReception is not set)"); } } pCommandClass->ReceivedCntIncr(); pCommandClass->HandleMsg( &_data[6], _data[4] ); } else { if( _data[5] == 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" ); Msg* msg = new Msg( "Replication Command Complete", m_nodeId, REQUEST, FUNC_ID_ZW_REPLICATION_COMMAND_COMPLETE, false ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Command ); } else { Log::Write( LogLevel_Info, m_nodeId, "ApplicationCommandHandler - Unhandled Command Class 0x%.2x", _data[5] ); } } } //----------------------------------------------------------------------------- // // Get the specified command class object if supported, otherwise NULL //----------------------------------------------------------------------------- CommandClass* Node::GetCommandClass ( uint8 const _commandClassId )const { map::const_iterator it = m_commandClassMap.find( _commandClassId ); if( it != m_commandClassMap.end() ) { return it->second; } // Not found return NULL; } //----------------------------------------------------------------------------- // // Add a command class to the node //----------------------------------------------------------------------------- CommandClass* Node::AddCommandClass ( uint8 const _commandClassId ) { 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 ) ) { m_commandClassMap[_commandClassId] = pCommandClass; return pCommandClass; } else { Log::Write( LogLevel_Info, m_nodeId, "AddCommandClass - Unsupported Command Class 0x%.2x", _commandClassId ); } return NULL; } //----------------------------------------------------------------------------- // // Remove a command class from the node //----------------------------------------------------------------------------- void Node::RemoveCommandClass ( uint8 const _commandClassId ) { 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() ) { 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() ); delete it->second; m_commandClassMap.erase( it ); } //----------------------------------------------------------------------------- // // Set a configuration parameter in a device //----------------------------------------------------------------------------- bool Node::SetConfigParam ( uint8 const _param, int32 _value, uint8 const _size ) { if( Configuration* cc = static_cast( GetCommandClass( Configuration::StaticGetCommandClassId() ) ) ) { // First try to find an existing value representing the parameter, and set that. if( Value* value = cc->GetValue( 1, _param ) ) { switch( value->GetID().GetType() ) { case ValueID::ValueType_Bool: { ValueBool* valueBool = static_cast( value ); valueBool->Set( _value != 0 ); break; } case ValueID::ValueType_Byte: { ValueByte* valueByte = static_cast( value ); valueByte->Set( (uint8)_value ); break; } case ValueID::ValueType_Short: { ValueShort* valueShort = static_cast( value ); valueShort->Set( (uint16)_value ); break; } case ValueID::ValueType_Int: { ValueInt* valueInt = static_cast( value ); valueInt->Set( _value ); break; } case ValueID::ValueType_List: { ValueList* valueList = static_cast( value ); valueList->SetByValue( _value ); break; } default: { } } return true; } // 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 ); return true; } return false; } //----------------------------------------------------------------------------- // // Request the value of a configuration parameter from the device //----------------------------------------------------------------------------- void Node::RequestConfigParam ( uint8 const _param ) { if( Configuration* cc = static_cast( GetCommandClass( Configuration::StaticGetCommandClassId() ) ) ) { cc->RequestValue( 0, _param, 1, Driver::MsgQueue_Send ); } } //----------------------------------------------------------------------------- // // Request the values of all known configuration parameters from the device //----------------------------------------------------------------------------- bool Node::RequestAllConfigParams ( uint32 const _requestFlags ) { bool res = false; if( Configuration* cc = static_cast( GetCommandClass( 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 ) { Value* value = it->second; if( value->GetID().GetCommandClassId() == 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 ); } } } return res; } //----------------------------------------------------------------------------- // // Request an update of all known dynamic values from the device //----------------------------------------------------------------------------- bool Node::RequestDynamicValues ( ) { bool res = false; for( map::const_iterator it = m_commandClassMap.begin(); it != m_commandClassMap.end(); ++it ) { if( !it->second->IsAfterMark() ) { res |= it->second->RequestStateForAllInstances( CommandClass::RequestFlag_Dynamic, Driver::MsgQueue_Send ); } } return res; } //----------------------------------------------------------------------------- // // Helper method to set a device's basic 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 ) ) { adjustedLevel = 99; } if( Basic* cc = static_cast( GetCommandClass( Basic::StaticGetCommandClassId() ) ) ) { cc->Set( adjustedLevel ); } } //----------------------------------------------------------------------------- // // Helper method to set a device to be on //----------------------------------------------------------------------------- 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() ) ) ) { cc->Set( 255 ); } } //----------------------------------------------------------------------------- // // Helper method to set a device to be off //----------------------------------------------------------------------------- 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() ) ) ) { cc->Set( 0 ); } } //----------------------------------------------------------------------------- // // Helper to create a ValueID //----------------------------------------------------------------------------- ValueID Node::CreateValueID ( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex, ValueID::ValueType const _type ) { return ValueID( m_homeId, m_nodeId, _genre, _commandClassId, _instance, _valueIndex, _type ); } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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(); if( store->AddValue( value ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // 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, uint8 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 ) ) { value->Release(); return true; } value->Release(); return false; } //----------------------------------------------------------------------------- // // Helper to remove an existing list value from the value store //----------------------------------------------------------------------------- void Node::RemoveValueList ( ValueList* _value ) { 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 ) { Value* value = NULL; // Create the value ValueID::ValueType type = Value::GetTypeEnumFromName( _valueElement->Attribute( "type" ) ); switch( type ) { 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; } default: { Log::Write( LogLevel_Info, m_nodeId, "Unknown ValueType in XML: %s", _valueElement->Attribute( "type" ) ); break; } } if( value ) { value->ReadXML( m_homeId, m_nodeId, _commandClassId, _valueElement ); ValueStore* store = GetValueStore(); if( store->AddValue( value ) ) { value->Release(); return true; } value->Release(); } return false; } //----------------------------------------------------------------------------- // // Apply XML differences to a value //----------------------------------------------------------------------------- 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" ) ); uint8 instance = 0; if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "instance", &intVal ) ) { instance = (uint8)intVal; } uint8 index = 0; if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "index", &intVal ) ) { index = (uint8)intVal; } 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( Value* value = store->GetValue( id.GetValueStoreKey() ) ) { value->ReadXML( m_homeId, m_nodeId, _commandClassId, _valueElement ); value->Release(); } else { CreateValueFromXML( _commandClassId, _valueElement ); } } } //----------------------------------------------------------------------------- // // Get the value object with the specified ID //----------------------------------------------------------------------------- Value* Node::GetValue ( ValueID const& _id ) { // This increments the value's reference count return GetValueStore()->GetValue( _id.GetValueStoreKey() ); } //----------------------------------------------------------------------------- // // Get the value object with the specified settings //----------------------------------------------------------------------------- Value* Node::GetValue ( uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex ) { Value* value = NULL; ValueStore* store = GetValueStore(); // This increments the value's reference count value = store->GetValue( ValueID::GetValueStoreKey( _commandClassId, _instance, _valueIndex ) ); return value; } //----------------------------------------------------------------------------- // // Remove the value object with the specified settings //----------------------------------------------------------------------------- bool Node::RemoveValue ( uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex ) { 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 ) { map::iterator it = m_groups.find( _groupIdx ); if( it == m_groups.end() ) { return NULL; } return it->second; } //----------------------------------------------------------------------------- // // Add a group into the node's map //----------------------------------------------------------------------------- void Node::AddGroup ( Group* _group ) { 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[_group->GetIdx()] = _group; } //----------------------------------------------------------------------------- // // Save the group data //----------------------------------------------------------------------------- void Node::WriteGroups ( TiXmlElement* _associationsElement ) { 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 ); } } //----------------------------------------------------------------------------- // // Gets the number of association groups reported by this node //----------------------------------------------------------------------------- uint8 Node::GetNumGroups ( ) { return (uint8) m_groups.size(); } //----------------------------------------------------------------------------- // // Gets the associations for a group //----------------------------------------------------------------------------- uint32 Node::GetAssociations ( uint8 const _groupIdx, uint8** o_associations ) { uint32 numAssociations = 0; if( Group* group = GetGroup( _groupIdx ) ) { numAssociations = group->GetAssociations( o_associations ); } return numAssociations; } //----------------------------------------------------------------------------- // // Gets the associations for a group //----------------------------------------------------------------------------- uint32 Node::GetAssociations ( uint8 const _groupIdx, InstanceAssociation** o_associations ) { uint32 numAssociations = 0; if( Group* group = GetGroup( _groupIdx ) ) { numAssociations = group->GetAssociations( o_associations ); } return numAssociations; } //----------------------------------------------------------------------------- // // Gets the maximum number of associations for a group //----------------------------------------------------------------------------- uint8 Node::GetMaxAssociations ( uint8 const _groupIdx ) { uint8 maxAssociations = 0; if( Group* group = GetGroup( _groupIdx ) ) { maxAssociations = group->GetMaxAssociations(); } return maxAssociations; } //----------------------------------------------------------------------------- // // Gets the label for a particular group //----------------------------------------------------------------------------- string Node::GetGroupLabel ( uint8 const _groupIdx ) { string label = ""; if( Group* group = GetGroup( _groupIdx ) ) { label = group->GetLabel(); } return label; } //----------------------------------------------------------------------------- // // Adds a node to an association group //----------------------------------------------------------------------------- void Node::AddAssociation ( uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance ) { if( Group* group = GetGroup( _groupIdx ) ) { group->AddAssociation( _targetNodeId, _instance ); } } //----------------------------------------------------------------------------- // // Removes a node from an association group //----------------------------------------------------------------------------- void Node::RemoveAssociation ( uint8 const _groupIdx, uint8 const _targetNodeId, uint8 const _instance ) { if( Group* group = GetGroup( _groupIdx ) ) { group->RemoveAssociation( _targetNodeId, _instance ); } } //----------------------------------------------------------------------------- // // Automatically associate the controller with certain groups //----------------------------------------------------------------------------- void Node::AutoAssociate ( ) { bool autoAssociate = false; 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 ) { Group* group = it->second; 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 ); } } } } //----------------------------------------------------------------------------- // // Get a pointer to our driver //----------------------------------------------------------------------------- Driver* Node::GetDriver ( )const { return( Manager::Get()->GetDriver( m_homeId ) ); } //----------------------------------------------------------------------------- // Device Classes //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // // Use the device class data to get a label for a MultiChannel EndPoint. //----------------------------------------------------------------------------- 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 ); 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 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 ) ) { label = specificDeviceClass->GetLabel(); } } return label; } //----------------------------------------------------------------------------- // // Set the device class data for the node //----------------------------------------------------------------------------- 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 ) { ReadDeviceClasses(); } // Get the basic device class label 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() ); } else { 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() ) { 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() ); // Add the mandatory command classes for this generic class type 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 ) ) { m_type = specificDeviceClass->GetLabel(); 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() ); if( specificDeviceClass->GetBasicMapping() ) { // Override the generic device class basic mapping with the specific device class one. basicMapping = specificDeviceClass->GetBasicMapping(); } } else { 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" ); } // Deal with sleeping devices 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() ) ) { pCommandClass->SetInstance( 1 ); } } // Apply any COMMAND_CLASS_BASIC remapping if( Basic* cc = static_cast( GetCommandClass( Basic::StaticGetCommandClassId() ) ) ) { cc->SetMapping( basicMapping ); } // Write the mandatory command classes to the log if( !m_commandClassMap.empty() ) { map::const_iterator cit; 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 ) { if( !cit->second->IsAfterMark() && cit->second->GetCommandClassId() != NoOperation::StaticGetCommandClassId() ) { Log::Write( LogLevel_Info, m_nodeId, " %s", cit->second->GetCommandClassName().c_str() ); reportedClasses = true; } } if( !reportedClasses ) { Log::Write( LogLevel_Info, m_nodeId, " None" ); } 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 ) { if( cit->second->IsAfterMark() ) { Log::Write( LogLevel_Info, m_nodeId, " %s", cit->second->GetCommandClassName().c_str() ); reportedClasses = true; } } if( !reportedClasses ) { Log::Write( LogLevel_Info, m_nodeId, " None" ); } } return true; } //----------------------------------------------------------------------------- // // 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 ) { if ( m_nodePlusInfoReceived ) { return false; // already set } if( !s_deviceClassesLoaded ) { ReadDeviceClasses(); } m_nodePlusInfoReceived = true; m_role = _role; 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 ); 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() ); uint8 const *_commandClasses = deviceClass->GetMandatoryCommandClasses(); /* no CommandClasses to add */ if (_commandClasses != NULL) { int i = 0; while (uint8 ccid = _commandClasses[i++]) { if( CommandClasses::IsSupported( ccid ) ) { Log::Write( LogLevel_Info, m_nodeId, " %s", CommandClasses::GetName(ccid).c_str()); } else { Log::Write( LogLevel_Info, m_nodeId, " 0x%.2x (Not Supported)", ccid); } } // Add the mandatory command classes for this Roletype AddMandatoryCommandClasses( deviceClass->GetMandatoryCommandClasses() ); } else { 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); } // Apply any Zwave+ device class data 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() ); uint8 const *_commandClasses = deviceClass->GetMandatoryCommandClasses(); /* no CommandClasses to add */ if (_commandClasses != NULL) { int i = 0; while (uint8 ccid = _commandClasses[i++]) { if( CommandClasses::IsSupported( ccid ) ) { Log::Write( LogLevel_Info, m_nodeId, " %s", CommandClasses::GetName(ccid).c_str()); } else { Log::Write( LogLevel_Info, m_nodeId, " 0x%.2x (Not Supported)", ccid); } } // Add the mandatory command classes for this device class type AddMandatoryCommandClasses( deviceClass->GetMandatoryCommandClasses() ); } else { 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); } // Apply any Role device class data 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() ); uint8 const *_commandClasses = roleDeviceClass->GetMandatoryCommandClasses(); /* no CommandClasses to add */ if (_commandClasses != NULL) { int i = 0; while (uint8 ccid = _commandClasses[i++]) { if( CommandClasses::IsSupported( ccid ) ) { Log::Write( LogLevel_Info, m_nodeId, " %s", CommandClasses::GetName(ccid).c_str()); } else { Log::Write( LogLevel_Info, m_nodeId, " 0x%.2x (Not Supported)", ccid); } } // Add the mandatory command classes for this role class type AddMandatoryCommandClasses( roleDeviceClass->GetMandatoryCommandClasses() ); } else { 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); } return true; } //----------------------------------------------------------------------------- // // Add mandatory command classes to the node //----------------------------------------------------------------------------- bool Node::AddMandatoryCommandClasses ( uint8 const* _commandClasses ) { if( NULL == _commandClasses ) { // No command classes to add return false; } int i=0; bool afterMark = false; while( uint8 cc = _commandClasses[i++] ) { if( cc == 0xef ) { // COMMAND_CLASS_MARK. // Marks the end of the list of supported command classes. The remaining classes // are those that can be controlled by this device, which we can ignore. afterMark = true; continue; } if( CommandClasses::IsSupported( cc ) ) { if (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 this class came after the COMMAND_CLASS_MARK, then we do not create values. 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 ); } } } return true; } //----------------------------------------------------------------------------- // // Read the static device class data from the device_classes.xml file //----------------------------------------------------------------------------- void Node::ReadDeviceClasses ( ) { // Load the XML document that contains the device class information string configPath; Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); string filename = configPath + string("device_classes.xml"); TiXmlDocument doc; 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." ); return; } TiXmlElement const* deviceClassesElement = doc.RootElement(); // Read the basic and generic device classes TiXmlElement const* child = deviceClassesElement->FirstChildElement(); while( child ) { char const* str = child->Value(); if( str ) { char const* keyStr = child->Attribute( "key" ); if( keyStr ) { char* pStop; uint16 key = (uint16)strtol( keyStr, &pStop, 16 ); if( !strcmp( str, "Generic" ) ) { s_genericDeviceClasses[key] = new GenericDeviceClass( child ); } else if( !strcmp( str, "Basic" ) ) { char const* label = child->Attribute( "label" ); if( label ) { s_basicDeviceClasses[key] = label; } } else if( !strcmp( str, "Role" ) ) { s_roleDeviceClasses[key] = new DeviceClass( child ); } else if( !strcmp( str, "DeviceType" ) ) { s_deviceTypeClasses[key] = new DeviceClass( child ); } else if (!strcmp( str, "NodeType" ) ) { s_nodeTypes[key] = new DeviceClass( child ); } } } child = child->NextSiblingElement(); } s_deviceClassesLoaded = true; } //----------------------------------------------------------------------------- // // Return driver statistics //----------------------------------------------------------------------------- void Node::GetNodeStatistics ( NodeData* _data ) { _data->m_sentCnt = m_sentCnt; _data->m_sentFailed = m_sentFailed; _data->m_retries = m_retries; _data->m_receivedCnt = m_receivedCnt; _data->m_receivedDups = m_receivedDups; _data->m_receivedUnsolicited = m_receivedUnsolicited; _data->m_lastRequestRTT = m_lastRequestRTT; _data->m_lastResponseRTT = m_lastResponseRTT; _data->m_sentTS = m_sentTS.GetAsString(); _data->m_receivedTS = m_receivedTS.GetAsString(); _data->m_averageRequestRTT = m_averageRequestRTT; _data->m_averageResponseRTT = m_averageResponseRTT; _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 ) { 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 ); } } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Node::DeviceClass::DeviceClass ( TiXmlElement const* _el ): m_mandatoryCommandClasses(NULL), m_basicMapping(0) { char const* str = _el->Attribute( "label" ); if( str ) { m_label = 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 ) { ccs.push_back( (uint8)strtol( pos, &pos, 16 ) ); if( (*pos) == ',' ) { ++pos; } } // Copy the vector contents into an array. size_t numCCs = ccs.size(); m_mandatoryCommandClasses = new uint8[numCCs+1]; m_mandatoryCommandClasses[numCCs] = 0; // Zero terminator for( uint32 i=0; iAttribute( "basic" ); if( str ) { char* pStop; m_basicMapping = (uint8)strtol( str, &pStop, 16 ); } } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Node::GenericDeviceClass::GenericDeviceClass ( TiXmlElement const* _el ): DeviceClass( _el ) { // Add any specific device classes TiXmlElement const* child = _el->FirstChildElement(); while( child ) { char const* str = child->Value(); if( str && !strcmp( str, "Specific" ) ) { char const* keyStr = child->Attribute( "key" ); if( keyStr ) { char* pStop; uint8 key = (uint8)strtol( keyStr, &pStop, 16 ); m_specificDeviceClasses[key] = new DeviceClass( child ); } } child = child->NextSiblingElement(); } } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Node::GenericDeviceClass::~GenericDeviceClass ( ) { while( !m_specificDeviceClasses.empty() ) { map::iterator it = m_specificDeviceClasses.begin(); delete it->second; m_specificDeviceClasses.erase( it ); } } //----------------------------------------------------------------------------- // // Get a specific device class object //----------------------------------------------------------------------------- Node::DeviceClass* Node::GenericDeviceClass::GetSpecificDeviceClass ( uint8 const& _specific ) { map::iterator it = m_specificDeviceClasses.find( _specific ); if( it != m_specificDeviceClasses.end() ) { return it->second; } return NULL; } //----------------------------------------------------------------------------- // // Generate a NONCE key for this node //----------------------------------------------------------------------------- uint8 *Node::GenerateNonceKey() { uint8 idx = this->m_lastnonce; for (int i = 0; i < 8; i++) { this->m_nonces[idx][i] = (rand()%0xFF)+1; } 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); } return &this->m_nonces[idx][0]; } //----------------------------------------------------------------------------- // // Get a NONCE key for this node that matches the nonceid. //----------------------------------------------------------------------------- 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]) { 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); } return NULL; } //----------------------------------------------------------------------------- // // Get the ZWave+ DeviceType as a String //----------------------------------------------------------------------------- string Node::GetDeviceTypeString() { if( !s_deviceClassesLoaded ) { ReadDeviceClasses(); } map::iterator nit = s_deviceTypeClasses.find( m_deviceType ); if (nit != s_deviceTypeClasses.end()) { DeviceClass* deviceClass = nit->second; return deviceClass->GetLabel(); } return ""; } //----------------------------------------------------------------------------- // // Get the ZWave+ RoleType as a String //----------------------------------------------------------------------------- string Node::GetRoleTypeString() { if( !s_deviceClassesLoaded ) { ReadDeviceClasses(); } map::iterator nit = s_roleDeviceClasses.find( m_role ); if (nit != s_roleDeviceClasses.end()) { DeviceClass* deviceClass = nit->second; return deviceClass->GetLabel(); } return ""; } //----------------------------------------------------------------------------- // // Get the ZWave+ NodeType as a String //----------------------------------------------------------------------------- string Node::GetNodeTypeString() { if( !s_deviceClassesLoaded ) { ReadDeviceClasses(); } map::iterator nit = s_nodeTypes.find( m_nodeType ); if (nit != s_nodeTypes.end()) { DeviceClass* deviceClass = nit->second; return deviceClass->GetLabel(); } return ""; } //----------------------------------------------------------------------------- // // Get the ZWave+ NodeType as a String //----------------------------------------------------------------------------- bool Node::IsNodeReset() { DeviceResetLocally *drl = static_cast(GetCommandClass(DeviceResetLocally::StaticGetCommandClassId())); if (drl) return drl->IsDeviceReset(); else return false; } open-zwave-1.5/cpp/src/Node.h000066400000000000000000000711741264474202400161000ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Node.h // // A node in the Z-Wave network // // 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 . // //----------------------------------------------------------------------------- #ifndef _Node_H #define _Node_H #include #include #include #include #include "Defs.h" #include "value_classes/ValueID.h" #include "value_classes/ValueList.h" #include "Msg.h" #include "platform/TimeStamp.h" #include "Group.h" class TiXmlElement; namespace OpenZWave { class CommandClass; 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; /** \brief The Node class describes a Z-Wave node object...typically a device on the * Z-Wave network. */ class Node { friend class Manager; friend class Driver; friend class Group; friend class 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 Meter; friend class MeterPulse; friend class MultiInstance; friend class MultiInstanceAssociation; 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; //----------------------------------------------------------------------------- // Construction //----------------------------------------------------------------------------- public: /** Constructor initializes the node object, associating it with a specific * network (_homeId) and network node (_nodeId). * \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 ); /** Destructor cleans up memory allocated to node and its child objects. */ virtual ~Node(); private: /** Returns a pointer to the driver (interface with a Z-Wave controller) * associated with this node. */ Driver* GetDriver()const; //----------------------------------------------------------------------------- // Initialization //----------------------------------------------------------------------------- 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, /**< Retrive 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. * * \remark * 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 * in the next stage. The stage is saved with the node data, so that any incomplete * queries can be restarted the next time the application runs. *

* The individual command classes also store some state information as to whether * they have had a response to certain queries. This state information is * initilized by the SetStaticRequests call in QueryStage_None. It is also saved, * so we do not need to request state from every command class if some have previously * responded. */ void AdvanceQueries(); /** * Signal that a specific query stage has been completed for this node. This will * only work if the query process for this node is indeed at the specified stage. * Otherwise, the function returns with no action. * \param _stage The current stage of the query process. */ void QueryStageComplete( QueryStage const _stage ); /** * Retry the specified query stage (up to _maxAttempts retries). This will * only work if the query process for this node is indeed at the specified stage. * Otherwise, the function returns with no action. * \param _stage The query stage to retry. * \param _maxAttempts */ 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). * If a later stage is specified than the current one, it is ignored. * \param _stage The desired query stage. * \see m_queryStage, m_queryPending */ 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; } /** * Returns the specified query stage string. * \param _stage The query stage. * \return Specified query stage string. * \see m_queryStage, m_queryPending */ 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; } /** * This function handles a response to the FUNC_ID_ZW_GET_NODE_PROTOCOL_INFO * command for this node. If protocol information has already been retrieved * for the node, the function simply returns. Otherwise, it populates several * member variables about the device at this node: * - m_routing (whether it is a routing node (capable of passing commands along to other nodes in the network) or not * - m_maxBaudRate (the maximum baud rate at which this device can communicate) * - m_version (TODO) * - m_security (whether device supports security features) * - m_listening (device is powered and listening constantly) * - m_frequentListening (device can be woken up with a beam) * - m_beaming (device is beam capable) */ 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 * info. * @param _protocolInfo Byte 0 - Basic Device Class Byte 1 - Generic Device Class, Byte 2 - Specific Device Classes Remaining Bytes - Supported Command Classes * @param _length lenght of the _protocolInfo field. */ void SetProtocolInfo(uint8 const* _protocolInfo, 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 AllQueriesCompleted()const{ return( QueryStage_Complete == m_queryStage ); } 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 ); 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; //----------------------------------------------------------------------------- // Capabilities //----------------------------------------------------------------------------- public: // 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 }; // Node Ids enum { 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 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 neighbouring 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 //----------------------------------------------------------------------------- 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 GetManufacturerId()const{ return std::to_string(m_manufacturerId); } uint16 GetManufacturerId()const{ return m_manufacturerId; } // string GetProductType()const{ return string(m_productType); } uint16 GetProductType()const{ return m_productType; } // string GetProductId()const{ return string(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 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; uint16 m_manufacturerId; uint16 m_productType; uint16 m_productId; // zwave+ info uint16 GetDeviceType() const { return m_deviceType; } string GetDeviceTypeString(); uint8 GetRoleType() const { return m_role; } string GetRoleTypeString(); uint8 GetNodeType() const { return m_nodeType; } string GetNodeTypeString(); uint16 m_deviceType; uint8 m_role; uint8 m_nodeType; //----------------------------------------------------------------------------- // Command Classes //----------------------------------------------------------------------------- public: /** * This function retrieves a pointer to the requested command class object (if supported by this node). * \param _commandClassId Class ID (a single byte value) identifying the command class requested. * \return Pointer to the requested CommandClass object if supported, otherwise NULL. * \see CommandClass, m_commandClassMap */ 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 * as Secured if they exist, and if they don't, it creates new Command Classes and sets them up as Secured * @param _data a list of Command Classes that are Secured by the Device * @param _length the length of the _data string */ void SetSecuredClasses( uint8 const* _data, uint8 const _length ); void SetSecured(bool secure); 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. * \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 ); /** * 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 ); map m_commandClassMap; /**< Map of command class ids and pointers to associated command class objects */ bool m_secured; /**< Is this Node added Securely */ //----------------------------------------------------------------------------- // Basic commands (helpers that go through the basic command class) //----------------------------------------------------------------------------- public: void SetLevel( uint8 const _level ); //----------------------------------------------------------------------------- // On/Off commands (helpers that go through the basic or switchall command class) //----------------------------------------------------------------------------- public: void SetNodeOn(); void SetNodeOff(); //----------------------------------------------------------------------------- // Values (handled by the command classes) //----------------------------------------------------------------------------- public: ValueID CreateValueID( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex, ValueID::ValueType const _type ); Value* GetValue( ValueID const& _id ); Value* GetValue( uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex ); bool RemoveValue( uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex ); // Helpers for creating values bool CreateValueBool( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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, uint8 const _valueIndex, string const& _label, uint8 const _pollIntensity ); bool CreateValueByte( ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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, uint8 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, uint8 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, uint8 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, uint8 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, uint8 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, uint8 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, uint8 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 ReadValueFromXML( uint8 const _commandClassId, TiXmlElement const* _valueElement ); bool CreateValueFromXML( uint8 const _commandClassId, TiXmlElement const* _valueElement ); private: ValueStore* GetValueStore()const{ return m_values; } 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 ); //----------------------------------------------------------------------------- // Dynamic Values (used by query and other command classes for updating) //----------------------------------------------------------------------------- private: bool RequestDynamicValues(); //----------------------------------------------------------------------------- // Groups //----------------------------------------------------------------------------- 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 ); 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 map m_groups; // Maps group indices to Group objects. //----------------------------------------------------------------------------- // Device Classes (static data read from the device_classes.xml file) //----------------------------------------------------------------------------- private: // Container for device class info 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; } 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. }; // Container for generic device class info class GenericDeviceClass : public DeviceClass { public: GenericDeviceClass( TiXmlElement const* _el ); ~GenericDeviceClass(); DeviceClass* GetSpecificDeviceClass( uint8 const& _specific ); private: 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. 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 alreayd 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: struct CommandClassData { uint8 m_commandClassId; uint32 m_sentCnt; uint32 m_receivedCnt; }; struct NodeData { uint32 m_sentCnt; uint32 m_sentFailed; uint32 m_retries; uint32 m_receivedCnt; uint32 m_receivedDups; uint32 m_receivedUnsolicited; string m_sentTS; string m_receivedTS; uint32 m_lastRequestRTT; uint32 m_averageRequestRTT; // ms uint32 m_lastResponseRTT; uint32 m_averageResponseRTT; uint8 m_quality; // Node quality measure uint8 m_lastReceivedMessage[254]; list m_ccData; }; private: void GetNodeStatistics( NodeData* _data ); uint32 m_sentCnt; // Number of messages sent from this node. uint32 m_sentFailed; // Number of sent messages failed uint32 m_retries; // Number of message retries uint32 m_receivedCnt; // Number of messages received from this node. uint32 m_receivedDups; // Number of duplicated messages received; 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 uint32 m_averageRequestRTT; // Average Request round trip time. uint32 m_averageResponseRTT; // Average Reponse round trip time. uint8 m_quality; // Node quality measure uint8 m_lastReceivedMessage[254]; // Place to hold last received message uint8 m_errors; // Count errors for dead node detection //----------------------------------------------------------------------------- // Encryption Related //----------------------------------------------------------------------------- public: uint8 *GenerateNonceKey(); uint8 *GetNonceKey(uint32 nonceid); private: uint8 m_lastnonce; uint8 m_nonces[8][8]; }; } //namespace OpenZWave #endif //_Node_H open-zwave-1.5/cpp/src/Notification.cpp000066400000000000000000000143311264474202400201640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Security.cpp // // Common Security/Encryption Routines // // Copyright (c) 2015 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 "Defs.h" #include "Notification.h" #include "Driver.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Return a string representation of OZW //----------------------------------------------------------------------------- string Notification::GetAsString() const { string str; switch (m_type) { case Type_ValueAdded: str = "ValueAdded"; break; case Type_ValueRemoved: str = "ValueRemoved"; break; case Type_ValueChanged: str = "ValueChanged"; break; case Type_ValueRefreshed: str = "ValueRefreshed"; break; case Type_Group: str = "Group"; break; case Type_NodeNew: str = "NodeNew"; break; case Type_NodeAdded: str = "NodeAdded"; break; case Type_NodeRemoved: str = "NodeRemoved"; break; case Type_NodeProtocolInfo: str = "NodeProtocolInfo"; break; case Type_NodeNaming: str = "NodeNaming"; break; case Type_NodeEvent: str = "NodeEvent"; break; case Type_PollingDisabled: str = "PollingDisabled"; break; case Type_PollingEnabled: str = "PollingEnabled"; break; case Type_SceneEvent: str = "SceneEvent"; break; case Type_CreateButton: str = "CreateButton"; break; case Type_DeleteButton: str = "DeleteButton"; break; case Type_ButtonOn: str = "ButtonOn"; break; case Type_ButtonOff: str = "ButtonOff"; break; case Type_DriverReady: str = "DriverReady"; break; case Type_DriverFailed: str = "DriverFailed"; break; case Type_DriverReset: str = "DriverReset"; break; case Type_EssentialNodeQueriesComplete: str = "EssentialNodeQueriesComplete"; break; case Type_NodeQueriesComplete: str = "NodeQueriesComplete"; break; case Type_AwakeNodesQueried: str = "AwakeNodesQueried"; break; case Type_AllNodesQueriedSomeDead: str = "AllNodesQueriedSomeDead"; break; case Type_AllNodesQueried: str = "AllNodesQueried"; break; case Type_Notification: switch (m_byte) { case Code_MsgComplete: str = "Notification - MsgComplete"; break; case Code_Timeout: str = "Notification - TimeOut"; break; case Code_NoOperation: str = "Notification - NoOperation"; break; case Code_Awake: str = "Notification - Node Awake"; break; case Code_Sleep: str = "Notification - Node Asleep"; break; case Code_Dead: str = "Notification - Node Dead"; break; case Code_Alive: str = "Notification - Node Alive"; break; } break; case Type_DriverRemoved: str = "DriverRemoved"; break; case Type_ControllerCommand: switch (m_event) { case Driver::ControllerState_Normal: str = "ControlerCommand - Normal"; break; case Driver::ControllerState_Starting: str = "ControllerComand - Starting"; break; case Driver::ControllerState_Cancel: str = "ControllerCommand - Canceled"; break; case Driver::ControllerState_Error: switch (m_byte) { case Driver::ControllerError_None: str = "ControllerCommand - Error - None"; break; case Driver::ControllerError_ButtonNotFound: str = "ControllerCommand - Error - ButtonNotFound"; break; case Driver::ControllerError_NodeNotFound: str = "ControllerCommand - Error - NodeNotFound"; break; case Driver::ControllerError_NotBridge: str = "ControllerCommand - Error - NotBridge"; break; case Driver::ControllerError_NotSUC: str = "ControllerCommand - Error - NotSUC"; break; case Driver::ControllerError_NotSecondary: str = "ControllerCommand - Error - NotSecondary"; break; case Driver::ControllerError_NotPrimary: str = "ControllerCommand - Error - NotPrimary"; break; case Driver::ControllerError_IsPrimary: str = "ControllerCommand - Error - IsPrimary"; break; case Driver::ControllerError_NotFound: str = "ControllerCommand - Error - NotFound"; break; case Driver::ControllerError_Busy: str = "ControllerCommand - Error - Busy"; break; case Driver::ControllerError_Failed: str = "ControllerCommand - Error - Failed"; break; case Driver::ControllerError_Disabled: str = "ControllerCommand - Error - Disabled"; break; case Driver::ControllerError_Overflow: str = "ControllerCommand - Error - OverFlow"; break; } break; case Driver::ControllerState_Waiting: str = "ControllerCommand - Waiting"; break; case Driver::ControllerState_Sleeping: str = "ControllerCommand - Sleeping"; break; case Driver::ControllerState_InProgress: str = "ControllerCommand - InProgress"; break; case Driver::ControllerState_Completed: str = "ControllerCommand - Completed"; break; case Driver::ControllerState_Failed: str = "ControllerCommand - Failed"; break; case Driver::ControllerState_NodeOK: str = "ControllerCommand - NodeOK"; break; case Driver::ControllerState_NodeFailed: str = "ControllerCommand - NodeFailed"; break; } break; case Type_NodeReset: str = "Node Reset"; break; } return str; } open-zwave-1.5/cpp/src/Notification.h000066400000000000000000000246741264474202400176440ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Notification.h // // Contains details of a Z-Wave event reported to the user // // 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 . // //----------------------------------------------------------------------------- #ifndef _Notification_H #define _Notification_H #include "Defs.h" #include "value_classes/ValueID.h" namespace OpenZWave { /** \brief Provides a container for data sent via the notification callback * handler installed by a call to Manager::AddWatcher. * * A notification object is only ever created or deleted internally by * 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; 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 receievd, 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 */ 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 initialisation 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 occured 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 recieving 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 */ }; /** * 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 */ }; /** * 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 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 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 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. * \return the event value. */ 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; } /** * 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 Notification as a String * \return A string representation of this Notification */ string GetAsString()const; private: Notification( NotificationType _type ): m_type( _type ), m_byte(0), m_event(0) {} ~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; } NotificationType m_type; ValueID m_valueId; uint8 m_byte; uint8 m_event; }; } //namespace OpenZWave #endif //_Notification_H open-zwave-1.5/cpp/src/OZWException.h000066400000000000000000000076021264474202400175440ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FatalErrorException.h // // Exception Handling Code // // Copyright (c) 2014 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 _FatalErrorException_H #define _FatalErrorException_H #include #include #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 */ OPENZWAVE_EXPORT_WARNINGS_OFF class OPENZWAVE_EXPORT OZWException : public std::runtime_error { public: enum ExceptionType { OZWEXCEPTION_OPTIONS, OZWEXCEPTION_CONFIG, OZWEXCEPTION_INVALID_HOMEID = 100, OZWEXCEPTION_INVALID_VALUEID, OZWEXCEPTION_CANNOT_CONVERT_VALUEID, OZWEXCEPTION_SECURITY_FAILED }; //----------------------------------------------------------------------------- // 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() 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 Initilization Failed (" << 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 } #endif // _FatalErrorException_H open-zwave-1.5/cpp/src/Options.cpp000066400000000000000000000445751264474202400172060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Options.h // // Program options read from XML files or the command line. // // 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 . // //----------------------------------------------------------------------------- #include #include #include "Defs.h" #include "Options.h" #include "Utils.h" #include "Manager.h" #include "platform/Log.h" #include "platform/FileOps.h" #include "tinyxml.h" using namespace OpenZWave; Options* Options::s_instance = NULL; //----------------------------------------------------------------------------- // // Static method to create an Options object //----------------------------------------------------------------------------- Options* Options::Create ( string const& _configPath, string const& _userPath, string const& _commandLine ) { 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] != '/' ) { configPath += "/"; } if( userPath.size() > 0 && userPath[userPath.size() - 1] != '/' ) { userPath += "/"; } FileOps::Create(); if( !FileOps::FolderExists( configPath ) ) { Log::Create( "", false, true, LogLevel_Debug, LogLevel_Debug, LogLevel_None ); /* Try some default directories */ if ( FileOps::FolderExists( "config/" ) ) { 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/" ) ) { 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 ) ) { 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() ); OZW_FATAL_ERROR(OZWException::OZWEXCEPTION_CONFIG, "Cannot Find Configuration Files"); return NULL; } } 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", true ); // 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 #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 #endif } return s_instance; } //----------------------------------------------------------------------------- // // Static method to destroy an Options object //----------------------------------------------------------------------------- bool Options::Destroy ( ) { 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"); return false; } delete s_instance; s_instance = NULL; return true; } //----------------------------------------------------------------------------- // // 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 ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Options::~Options ( ) { // Clear the options map while( !m_options.empty() ) { map::iterator it = m_options.begin(); delete it->second; m_options.erase( it ); } } //----------------------------------------------------------------------------- // // Add a boolean option. //----------------------------------------------------------------------------- bool Options::AddOptionBool ( string const& _name, bool const _value ) { // get (or create) option Option* option = AddOption( _name ); 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 ); m_options[lowerName] = option; return true; } //----------------------------------------------------------------------------- // // Add an integer option. //----------------------------------------------------------------------------- bool Options::AddOptionInt ( string const& _name, int32 const _value ) { // get (or create) option Option* option = AddOption( _name ); 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 ); m_options[lowerName] = option; return true; } //----------------------------------------------------------------------------- // // Add a string option. //----------------------------------------------------------------------------- bool Options::AddOptionString ( string const& _name, string const& _value, bool const _append ) { // get (or create) option Option* option = AddOption( _name ); if (option == NULL) return false; // set unique option members option->m_type = Options::OptionType_String; option->m_valueString = _value; option->m_append = _append; // save in m_options map string lowerName = ToLower( _name ); m_options[lowerName] = option; return true; } //----------------------------------------------------------------------------- // // Get the value of a boolean option. //----------------------------------------------------------------------------- bool Options::GetOptionAsBool ( string const& _name, bool* o_value ) { 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() ); return false; } //----------------------------------------------------------------------------- // // Get the value of an integer option. //----------------------------------------------------------------------------- bool Options::GetOptionAsInt ( string const& _name, int32* o_value ) { 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() ); return false; } //----------------------------------------------------------------------------- // // Get the value of a string option. //----------------------------------------------------------------------------- bool Options::GetOptionAsString ( string const& _name, string* o_value ) { 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() ); return false; } //----------------------------------------------------------------------------- // // Get the type of value stored in an option. //----------------------------------------------------------------------------- Options::OptionType Options::GetOptionType ( string const& _name ) { 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() ); return OptionType_Invalid; } //----------------------------------------------------------------------------- // // Read all the option XMLs and Command Lines, and lock their values. //----------------------------------------------------------------------------- bool Options::Lock ( ) { if( m_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 ); m_locked = true; return true; } //----------------------------------------------------------------------------- // // Parse a string containing program options, such as a command line //----------------------------------------------------------------------------- bool Options::ParseOptionsString ( string const& _commandLine ) { bool res = true; size_t pos = 0; size_t start = 0; while( 1 ) { // find start of first option name pos = _commandLine.find_first_of( "--", start ); if( string::npos == pos ) { break; } start = pos + 2; // found an option. Get the name. string optionName; pos = _commandLine.find( " ", start ); if( string::npos == pos ) { optionName = _commandLine.substr( start ); start = pos; } else { optionName = _commandLine.substr( start, pos-start ); start = pos + 1; } // Find the matching option object Option* option = Find( optionName ); if( option ) { // Read the values int numValues = 0; bool parsing = true; while( parsing ) { string value; size_t back = start; pos = _commandLine.find( " ", start ); if( string::npos == pos ) { // Last value in string value = _commandLine.substr( start ); parsing = false; start = pos; } else { value = _commandLine.substr( start, pos-start ); start = pos+1; } if( !value.compare( 0, 2, "--" ) ) { // Value is actually the next option. 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 ) { option->m_valueBool = true; } else { res = false; } } start = back; // back up to the beginning of the next option break; } else if( value.size() > 0 ) { // Set the value option->SetValueFromString( value ); numValues++; } } } } return res; } //----------------------------------------------------------------------------- // // Parse an XML file containing program options //----------------------------------------------------------------------------- bool Options::ParseOptionsXML ( string const& _filename ) { TiXmlDocument doc; 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; } 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 ) { char const* str = optionElement->Value(); if( str && !strcmp( str, "Option" ) ) { char const* name = optionElement->Attribute( "name" ); if( name ) { Option* option = Find( name ); if( option ) { char const* value = optionElement->Attribute( "value" ); if( value ) { // Set the value option->SetValueFromString( value ); } } } } optionElement = optionElement->NextSiblingElement(); } return true; } //----------------------------------------------------------------------------- // // General setup for adding a specific option //----------------------------------------------------------------------------- Options::Option* Options::AddOption ( string const& _name ) { if( m_locked ) { 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 = new Option( _name ); } return option; } //----------------------------------------------------------------------------- // // Find an option by name //----------------------------------------------------------------------------- Options::Option* Options::Find ( string const& _name ) { string lowername = ToLower( _name ); map::iterator it = m_options.find( lowername ); if( it != m_options.end() ) { return it->second; } return NULL; } //----------------------------------------------------------------------------- // // Find an option by name //----------------------------------------------------------------------------- bool Options::Option::SetValueFromString ( string const& _value ) { if( OptionType_Bool == m_type ) { string lowerValue = ToLower( _value ); if( ( lowerValue == "true" ) || ( lowerValue == "1" ) ) { m_valueBool = true; return true; } if( ( lowerValue == "false" ) || ( lowerValue == "0" ) ) { m_valueBool = false; return true; } return false; } if( OptionType_Int == m_type ) { m_valueInt = (int32)atol( _value.c_str() ); return true; } if( OptionType_String == m_type ) { if( m_append && ( m_valueString.size() > 0 ) ) { m_valueString += ( string(",") + _value ); } else { m_valueString = _value; } return true; } return false; } open-zwave-1.5/cpp/src/Options.h000066400000000000000000000253371264474202400166460ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Options.h // // Program options read from XML files or the command line. // // 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 . // //----------------------------------------------------------------------------- #ifndef _Options_H #define _Options_H #include #include #include #include "Defs.h" namespace OpenZWave { /** \brief Manages library options read from XML files or the command line. * * A class that manages program options read from XML files or the command line. * The OpenZWave Manager class requires a complete and locked Options * object when created. The Options are therefore one of the first things that * any OpenZWave application must deal with. * Options are first read from an XML file called options.xml located in the * User data folder (the path to which is supplied to the Options::Create method). * This is the same folder that will be used by the Manager to save the state of * each controller in the Z-Wave network, to avoid querying them for their entire * state every time the application starts up. * The second source of program options is a string, which will normally be the * command line used to launch the application. * In this way, common options can be specified in the XML, but over-ridden if * necessary by the command line. * The Options process is as follows: * 1) Create an Options object, providing paths to the OpenZWave config folder, * the User data folder and any command line string containing program options. * 2) Call Options::AddOptionBool, Options::AddOptionInt or Options::AddOptionString * to add any application-specific configurable options. In this way, the Options * class can be used for non-OpenZWave options as well. (OpenZWave options must * be specified in step #1 above (either via xml file or a command line string). * 3) Call Options::Lock. This will cause the option values to be read from * the options.xml file and the command line string, and will lock the options * so that no more calls aside from GetOptionAs may be made. * 4) Create the OpenZWave Manager object. */ 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; }; } // namespace OpenZWave #endif // _Options_H open-zwave-1.5/cpp/src/Scene.cpp000066400000000000000000000305641264474202400166010ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Scene.cpp // // A collection of ValueIDs to be used together. // // Copyright (c) 2011 Greg Satz // // 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 #include "Manager.h" #include "platform/Log.h" #include "value_classes/Value.h" #include "value_classes/ValueID.h" #include "Scene.h" #include "Options.h" #include "tinyxml.h" using namespace OpenZWave; uint32 const c_sceneVersion = 1; //----------------------------------------------------------------------------- // Statics //----------------------------------------------------------------------------- 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++; } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Scene::~Scene ( ) { while( !m_values.empty() ) { SceneStorage* ss = m_values.back(); m_values.pop_back(); delete ss; } s_sceneCnt--; s_scenes[m_sceneId] = NULL; } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- 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 ); scenesElement->SetAttribute( "xmlns", "http://code.google.com/p/open-zwave/" ); snprintf( str, sizeof(str), "%d", c_sceneVersion ); scenesElement->SetAttribute( "version", str); for( int i = 1; i < 256; i++ ) { if( s_scenes[i] == NULL ) { continue; } 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() ); 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), "%d", (*vt)->m_id.GetNodeId() ); valueElement->SetAttribute( "nodeId", str ); valueElement->SetAttribute( "genre", 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.GetInstance() ); valueElement->SetAttribute( "instance", str ); snprintf( str, sizeof(str), "%d", (*vt)->m_id.GetIndex() ); valueElement->SetAttribute( "index", str ); valueElement->SetAttribute( "type", Value::GetTypeNameFromEnum((*vt)->m_id.GetType()) ); TiXmlText* textElement = new TiXmlText( (*vt)->m_value.c_str() ); valueElement->LinkEndChild( textElement ); sceneElement->LinkEndChild( valueElement ); } scenesElement->LinkEndChild( sceneElement ); } string userPath; Options::Get()->GetOptionAsString( "UserPath", &userPath ); string filename = userPath + _name; 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 ) { 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; } TiXmlElement const* sceneElement = scenesElement->FirstChildElement(); while( sceneElement ) { Scene* scene = NULL; if( TIXML_SUCCESS == sceneElement->QueryIntAttribute( "id", &intVal ) ) { scene = new Scene( (uint8)intVal ); } if( scene == NULL ) { continue; } str = sceneElement->Attribute( "label" ); if( str ) { scene->m_label = str; } // Read the ValueId for this scene TiXmlElement const* valueElement = sceneElement->FirstChildElement(); while( valueElement ) { 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 = 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 = 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(); } 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; } //----------------------------------------------------------------------------- // // 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++ ) { if (s_scenes[i] != NULL) { (*_sceneIds)[j++] = s_scenes[i]->m_sceneId; } } } 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; } //----------------------------------------------------------------------------- // // 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 ) { delete *it; m_values.erase( it ); return true; } } 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 ) { delete *it; m_values.erase( it ); goto again; } } // 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 ) { 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; } } } } //----------------------------------------------------------------------------- // // 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 ) { o_value->push_back( (*it)->m_id ); } } 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 ) { *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 ) { (*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 ) ) { res = false; } } return res; } open-zwave-1.5/cpp/src/Scene.h000066400000000000000000000062511264474202400162420ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Scene.h // // A collection of ValueIDs to be used together. // // Copyright (c) 2011 Greg Satz // // 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 _Scene_H #define _Scene_H #include #include #include "Defs.h" class TiXmlElement; namespace OpenZWave { class ValueID; /** \brief Collection of ValueIDs to be treated as a unit. */ class Scene { friend class Manager; friend class Driver; friend class Node; //----------------------------------------------------------------------------- // Construction //----------------------------------------------------------------------------- private: Scene( uint8 const _sceneId ); ~Scene(); static void WriteXML( string const& _name ); static bool ReadScenes(); //----------------------------------------------------------------------------- // Scene functions //----------------------------------------------------------------------------- private: static Scene* Get( uint8 const _sceneId ); static uint8 GetAllScenes( uint8** _sceneIds ); string const& GetLabel()const{ return m_label; } void SetLabel( string const &_label ){ m_label = _label; } 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 OpenZWave #endif //_Scene_H open-zwave-1.5/cpp/src/Utils.cpp000066400000000000000000000071551264474202400166440ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Utils.h // // Miscellaneous helper functions // // 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 . // //----------------------------------------------------------------------------- #include "Defs.h" #include "Utils.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // Remove WhiteSpaces from the begining and end of a string //----------------------------------------------------------------------------- std::string &OpenZWave::trim ( 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])) { s[val] = s[cur]; val++; } } s.resize(val); return 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 { 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 // // 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 _Utils_H #define _Utils_H #include "platform/Mutex.h" #include "platform/Log.h" #include #include #include #include #include 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, seperated by seperators * \param lst the vector to store the results in * \param input the input string to split * \param seperators a string containing a list of valid seperators * \param remove_empty if after spliting a string, the any of the results are a empty string, should we preseve 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 { LockGuard(Mutex* mutex) : _ref(mutex) { //std::cout << "Locking" << std::endl; _ref->Lock(); }; ~LockGuard() { #if 0 if (_ref->IsSignalled()) std::cout << "Already Unlocked" << std::endl; else std::cout << "Unlocking" << std::endl; #endif if (!_ref->IsSignalled()) _ref->Unlock(); } void Unlock() { // std::cout << "Unlocking" << std::endl; _ref->Unlock(); } private: LockGuard(const LockGuard&); LockGuard& operator = ( LockGuard const& ); Mutex* _ref; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/ZWSecurity.cpp000066400000000000000000000277451264474202400176430ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Security.cpp // // Common Security/Encryption Routines // // Copyright (c) 2015 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 "Defs.h" #include "ZWSecurity.h" #include "Node.h" #include "Driver.h" #include "Manager.h" #include "Options.h" #include "Utils.h" #include "platform/Log.h" #include "command_classes/MultiInstance.h" #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 ) { // 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); #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; } /* 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; } /* 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 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 */ #ifdef DEBUG PrintHex("Computed Auth", tmpauth, 8); #endif /* 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 ) { #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; #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] = (rand()%0xFF)+1; initializationVector[i] = 0xAA; 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]; /* now encrypt */ uint8 encryptedpayload[30]; aes_mode_reset(driver->GetEncKey()); #ifdef DEBUG 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; } #ifdef DEBUG 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]; /* regenerate the IV */ for (int i = 0; i < 8; i++) { //initializationVector[i] = (rand()%0xFF)+1; initializationVector[i] = 0xAA; } /* 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]; } /* now calculate the MAC and append it */ uint8 mac[8]; GenerateAuthentication(&e_buffer[7], e_buffer[5], driver, _sendingNode, _receivingNode, initializationVector, 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; 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); #endif 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); #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()); #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); 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 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); char* pos = const_cast(customsecurecc.c_str()); while( *pos ) { if (CommandClass == (uint8)strtol( pos, &pos, 16 )) { return SecurityStrategy_Supported; } if( (*pos) == ',' ) { ++pos; } } } return SecurityStrategy_Essential; } } open-zwave-1.5/cpp/src/ZWSecurity.h000066400000000000000000000016441264474202400172760ustar00rootroot00000000000000/* * Security.h * * Created on: Mar 20, 2015 * Author: justinhammond */ #ifndef SECURITY_H_ #define SECURITY_H_ #include #include #include #include "Defs.h" #include "Driver.h" 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); } #endif /* SECURITY_H_ */ open-zwave-1.5/cpp/src/aes/000077500000000000000000000000001264474202400156005ustar00rootroot00000000000000open-zwave-1.5/cpp/src/aes/aes.h000066400000000000000000000163031264474202400165240ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 This file contains the definitions required to use AES in C. See aesopt.h for optimisation details. */ #ifndef _AES_H #define _AES_H #include /* This include is used to find 8 & 32 bit unsigned integer types */ #include "brg_types.h" #if defined(__cplusplus) extern "C" { #endif #define AES_128 /* if a fast 128 bit key scheduler is needed */ #define AES_192 /* if a fast 192 bit key scheduler is needed */ #define AES_256 /* if a fast 256 bit key scheduler is needed */ #define AES_VAR /* if variable key size scheduler is needed */ #define AES_MODES /* if support is needed for modes */ /* The following must also be set in assembler files if being used */ #define AES_ENCRYPT /* if support for encryption is needed */ #define AES_DECRYPT /* if support for decryption is needed */ #define AES_BLOCK_SIZE 16 /* the AES block size in bytes */ #define N_COLS 4 /* the number of columns in the state */ /* The key schedule length is 11, 13 or 15 16-byte blocks for 128, */ /* 192 or 256-bit keys respectively. That is 176, 208 or 240 bytes */ /* or 44, 52 or 60 32-bit words. */ #if defined( AES_VAR ) || defined( AES_256 ) #define KS_LENGTH 60 #elif defined( AES_192 ) #define KS_LENGTH 52 #else #define KS_LENGTH 44 #endif #define AES_RETURN INT_RETURN /* the character array 'inf' in the following structures is used */ /* to hold AES context information. This AES code uses cx->inf.b[0] */ /* to hold the number of rounds multiplied by 16. The other three */ /* elements can be used by code that implements additional modes */ typedef union { uint32_t l; uint8_t b[4]; } aes_inf; #pragma warning( disable : 4324 ) #ifdef _WIN64 __declspec(align(16)) #endif typedef struct { uint32_t ks[KS_LENGTH]; aes_inf inf; } aes_encrypt_ctx; #ifdef _WIN64 __declspec(align(16)) #endif typedef struct { uint32_t ks[KS_LENGTH]; aes_inf inf; } aes_decrypt_ctx; #pragma warning( default : 4324 ) /* This routine must be called before first use if non-static */ /* tables are being used */ AES_RETURN aes_init(void); /* Key lengths in the range 16 <= key_len <= 32 are given in bytes, */ /* those in the range 128 <= key_len <= 256 are given in bits */ #if defined( AES_ENCRYPT ) #if defined( AES_128 ) || defined( AES_VAR) AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); #endif #if defined( AES_192 ) || defined( AES_VAR) AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); #endif #if defined( AES_256 ) || defined( AES_VAR) AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); #endif #if defined( AES_VAR ) AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]); #endif AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); #endif #if defined( AES_DECRYPT ) #if defined( AES_128 ) || defined( AES_VAR) AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); #endif #if defined( AES_192 ) || defined( AES_VAR) AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); #endif #if defined( AES_256 ) || defined( AES_VAR) AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); #endif #if defined( AES_VAR ) AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]); #endif AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); #endif #if defined( AES_MODES ) /* Multiple calls to the following subroutines for multiple block */ /* ECB, CBC, CFB, OFB and CTR mode encryption can be used to handle */ /* long messages incrementally provided that the context AND the iv */ /* are preserved between all such calls. For the ECB and CBC modes */ /* each individual call within a series of incremental calls must */ /* process only full blocks (i.e. len must be a multiple of 16) but */ /* the CFB, OFB and CTR mode calls can handle multiple incremental */ /* calls of any length. Each mode is reset when a new AES key is */ /* set but ECB and CBC operations can be reset without setting a */ /* new key by setting a new IV value. To reset CFB, OFB and CTR */ /* without setting the key, aes_mode_reset() must be called and the */ /* IV must be set. NOTE: All these calls update the IV on exit so */ /* this has to be reset if a new operation with the same IV as the */ /* previous one is required (or decryption follows encryption with */ /* the same IV array). */ AES_RETURN aes_test_alignment_detection(unsigned int n); AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, const aes_encrypt_ctx cx[1]); AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, const aes_decrypt_ctx cx[1]); AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, const aes_encrypt_ctx cx[1]); AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, const aes_decrypt_ctx cx[1]); AES_RETURN aes_mode_reset(aes_encrypt_ctx cx[1]); AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx cx[1]); AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx cx[1]); #define aes_ofb_encrypt aes_ofb_crypt #define aes_ofb_decrypt aes_ofb_crypt AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx cx[1]); typedef void cbuf_inc(unsigned char *cbuf); #define aes_ctr_encrypt aes_ctr_crypt #define aes_ctr_decrypt aes_ctr_crypt AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]); #endif #if defined(__cplusplus) } #endif #endif open-zwave-1.5/cpp/src/aes/aes.txt000066400000000000000000000575011264474202400171210ustar00rootroot00000000000000 An AES (Rijndael) Implementation in C/C++ (as specified in FIPS-197) ==================================================================== Changes in this Version (14/11/2013) ==================================== 1. Added the ability to use Intel's hardware support for AES on Windows using Microsoft Visual Studio. 2. Added the include 'stdint.h' and used the uint_t instead of the old uint_t (e.g. uint_32t is now uint32_t). 3. Added a missing .text directive in aes_x86_v2.asm that caused runtime errors in one build configuration. Changes in this Version (16/04/2007) ==================================== These changes remove errors in the VC++ build files and add some improvements in file naming consitency and portability. There are no changes to overcome reported bugs in the code. 1. gen_tabs() has been renamed to aes_init() to better decribe its function to those not familiar with AES internals. 2. via_ace.h has been renamed to aes_via_ace.h. 3. Minor changes have been made to aestab.h and aestab.c to enable all the code to be compiled in either C or C++. 4. The code for detecting memory alignment in aesmdoes.c has been simplified and a new routine has been added: aes_test_alignment_detection() to check that the aligment test is likely to be correct. 5. The addition of support for Structured Exception Handling (SEH) to YASM (well done Peter and Michael!) has allowed the AMD64 x64 assembler code to be changed to comply with SEH requriements. 6. Corrections to build files (for win32 debug build). Overview ======== This code implements AES for both 32 and 64 bit systems with optional assembler support for x86 and AMD64/EM64T (but optimised for AMD64). The basic AES source code files are as follows: aes.h the header file needed to use AES in C aescpp.h the header file required with to use AES in C++ aesopt.h the header file for setting options (and some common code) aestab.h the header file for the AES table declaration aescrypt.c the main C source code file for encryption and decryption aeskey.c the main C source code file for the key schedule aestab.c the main file for the AES tables brg_types.h a header defining some standard types and DLL defines brg_endian.h a header containing code to detect or define endianness aes_x86_v1.asm x86 assembler (YASM) alternative to aescrypt.c using large tables aes_x86_v2.asm x86 assembler (YASM) alternative to aescrypt.c using compressed tables aes_amd64.asm AMD64 assembler (YASM) alternative to aescrypt.c using compressed tables In addition AES modes are implemented in the files: aes_modes.c AES modes with optional support for VIA ACE detection and use aes_via_ace.h the header file for VIA ACE support and Intel hardware support for AES (AES_NI) is implemented in the files aes_ni.h defines for AES_NI implementation aes_ni.c the AES_NI implementation Other associated files for testing and support are: aesaux.h header for auxilliary routines for testsing aesaux.c auxilliary routines for testsingt aestst.h header file for setting the testing environment rdtsc.h a header file that provides access to the Time Stamp Counter aestst.c a simple test program for quick tests of the AES code aesgav.c a program to generate and verify the test vector files aesrav.c a program to verify output against the test vector files aestmr.c a program to time the code on x86 systems modetest.c a program to test the AES modes support vbxam.doc a demonstration of AES DLL use from Visual Basic in Microsoft Word vb.txt Visual Basic code from the above example (win32 only) aesxam.c an example of AES use tablegen.c a program to generate a simplified 'aestab.c' file for use with compilers that find aestab.c too complex yasm.rules the YASM build rules file for Microsoft Visual Studio 2005 via_ace.txt describes support for the VIA ACE cryptography engine aes.txt this file Building The AES Libraries -------------------------- A. Versions ----------- The code can be used to build static and dynamic libraries, each in five versions: Key scheduling code in C, encrypt/decrypt in: C C source code (win32 and x64) ASM_X86_V1C large table x86 assembler code (win32) ASM_X86_V2C compressed table x86 assembler code (win32) ASM_AMD64 compressed table x64 assembler code (x64) Key scheduling and encrypt/decrypt code in assembler: ASM_X86_V2 compressed table x86 assembler (win32) The C version can be compiled for Win32 or x64 whereas the x86 and x64 assembler versions are for Win32 and x64 respectively. If Intel's hardware support for AES (AES_NI) is available, it can be used with either the C or the ASM_AMD64 version. If ASM_AMD64 is to be used, it is important that the define USE_INTEL_AES_IF_PRESENT in asm_amd64.asm is set to the same value as it has in aesopt.h B. YASM ------- If you wish to use the x86 assembler files you will also need the YASM open source x86 assembler (r1331 or later) for Windows which can be obtained from: http://www.tortall.net/projects/yasm/ This assembler should be placed in the bin directory used by VC++, which, for Visual Stduio 2005, is typically: C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin You will also need to move the yasm.rules file from this distribution into the directory where Visual Studio 2005 expects to find it, which is typically: C:\Program Files (x86)\Microsoft Visual Studio 8\VC\VCProjectDefaults Alternatively you can configure the path for rules files within Visual Studio. C. Configuration ---------------- The following configurations are available as projects for Visual Studio but the following descriptions should allow them to be built in other x86 environments lib_generic_c Win32 and x64 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h (+ aes_ni.h for AES_NI) C source: aescrypt.c, aeskey.c, aestab.c, aes_modes.c (+ aes_ni.c for AES_NI) defines dll_generic_c Win32 and x64 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h (+ aes_ni.h for AES_NI) C source: aescrypt.c, aeskey.c, aestab.c, aes_modes.c (+ aes_ni.c for AES_NI) defines DLL_EXPORT lib_asm_x86_v1c Win32 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h C source: aeskey.c, aestab.c, aes_modes.c x86 assembler: aes_x86_v1.asm defines ASM_X86_V1C (set for C and assembler files) dll_asm_x86_v1c Win32 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h C source: aeskey.c, aestab.c, aes_modes.c x86 assembler: aes_x86_v1.asm defines DLL_EXPORT, ASM_X86_V1C (set for C and assembler files) lib_asm_x86_v2c Win32 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h C source: aeskey.c, aestab.c, aes_modes.c x86 assembler: aes_x86_v2.asm defines ASM_X86_V2C (set for C and assembler files) dll_asm_x86_v2c Win32 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h C source: aeskey.c, aestab.c, aes_modes.c x86 assembler: aes_x86_v1.asm defines DLL_EXPORT, ASM_X86_V2C (set for C and assembler files) lib_asm_x86_v2 Win32 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h C source: aes_modes.c x86 assembler: aes_x86_v1.asm defines ASM_X86_V2 (set for C and assembler files) dll_asm_x86_v2 Win32 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h C source: aes_modes.c x86 assembler: aes_x86_v1.asm defines DLL_EXPORT, ASM_AMD64_C (set for C and assembler files) lib_asm_amd64_c x64 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h (+ aes_ni.h for AES_NI) C source: aes_modes.c (+ aes_ni.c for AES_NI) x86 assembler: aes_amd64.asm defines ASM_X86_V2 (set for C and assembler files) dll_asm_amd64_c x64 headers: aes.h, aesopt.h, aestab.h, brg_endian.h, tdefs.h (+ aes_ni.h for AES_NI) C source: aes_modes.c (+ aes_ni.c for AES_NI) x86 assembler: aes_amd64.asm defines DLL_EXPORT, ASM_AMD64_C (set for C and assembler files) Notes: ASM_X86_V1C is defined if using the version 1 assembler code (aescrypt1.asm). The defines in the assember file must match those in aes.h and aesopt.h). Also remember to include/exclude the right assembler and C files in the build to avoid undefined or multiply defined symbols - include aes_x86_v1.asm and exclude aescrypt.c ASM_X86_V2 is defined if using the version 2 assembler code (aes_x86_v2.asm). This version provides a full, self contained assembler version and does not use any C source code files except for the mutiple block encryption modes that are provided by aes_modes.c. The define ASM_X86_V2 must be set on the YASM command line (or in aes_x86_v2.asm) to use this version and all C files except aec_modes.c and, for the DLL build, aestab.c must be excluded from the build. ASM_X86_V2C is defined when using the version 2 assembler code (aes_x86_v2.asm) with faster key scheduling provided by the in C code (the options in the assember file must match those in aes.h and aesopt.h). In this case aeskey.c and aestab.c are needed with aes_x86_v2.asm and the define ASM_X86_V2C must be set for both the C files and for aes_x86_v2.asm in the build commands(or in aesopt.h and aes_x86_v2.asm). Include aes_x86_v2.asm, aeskey.c and aestab.c, exclude aescrypt.c for this option. ASM_AMD64_C is defined when using the AMD64 assembly code because the C key scheduling is used in this case. DLL_EXPORT must be defined to generate the DLL version of the code and to run tests on it DLL_IMPORT must be defined to use the DLL version of the code in an application program Directories the paths for the various directories for test vector input and output have to be set in aestst.h VIA ACE see the via_ace.txt for this item Static The static libraries are named: Libraries aes_lib_generic_c.lib aes_lib_asm_x86_v1c.lib aes_lib_asm_x86_v2.lib aes_lib_asm_x86_v2c.lib aes_lib_asm_amd64_c.lib and placed in one of the the directories: lib\win32\release\ lib\win32\debug\ lib\x64\release\ lib\x64\debug\ in the aes root directory depending on the platform(win32 or x64) and the build (release or debug). After any of these is built it is then copied into the aes\lib directory, which is the library location that is subsequently used for testing. Hence testing is always for the last static library built. Dynamic These libraries are named: Libraries aes_lib_generic_c.dll aes_lib_asm_x86_v1c.dll aes_lib_asm_x86_v2.dll aes_lib_asm_x86_v2c.dll aes_lib_asm_amd64_c.dll and placed in one of the the directories: dll\win32\release\ dll\win32\debug\ dll\x64\release\ dll\x64\debug\ in the aes root directory depending on the platform(win32 or x64) and the build (release or debug). Each DLL library: aes_.dll has three associated files: aes_dll_.lib the library file for implicit linking aes_dll_.exp the exports file aes_dll_.pdb the symbol file After any DLL is built it and its three related files are then copied to the aes\dll directory, which is the library location used in subsequent testing. Hence testing is always for the last DLL built. D. Testing ---------- These tests require that the test vector files are placed in the 'testvals' subdirectory. If the AES Algorithm Validation Suite tests are used then the *.fax files need to be put in the 'testvals\fax' subdirectory. This is covered in more detail below. The projects test_lib and time_lib are used to test and time the last static library built. They use the files: test_lib: Win32 (x64 for the C and AMD64 versions) headers: aes.h, aescpp.h, brg_types.h, aesaux.h and aestst.h C source: aesaux.c, aesrav.c defines: time_lib: Win32 (x64 for the C and AMD64 versions) headers: aes.h, aescpp.h, brg_types.h, aesaux.h, aestst.h and rdtsc.h C source: aesaux.c, aestmr.c defines: The projects test_dll and time_dll are used to test and time the last DLL built. These use the files: test_dll: Win32 (x64 for the C and AMD64 versions) headers: aes.h, aescpp.h, brg_types.h, aesaux.h and aestst.h C source: aesaux.c, aesrav.c defines: DLL_IMPORT time_dll: Win32 (x64 for the C and AMD64 versions) headers: aes.h, aescpp.h, brg_types.h, aesaux.h aestst.h and rdtsc.h C source: aesaux.c, aestmr.c defines: DLL_IMPORT and link to the DLL using dynamic (run-time) linking. However, if the lib file associated with the DLL is linked into this project and the symbol DYNAMIC_LINK in aestst.h is left undefined, then implicit linking will be used The above tests take command line arguments that determine which test are run as follows: test_lib /t:[knec] /k:[468] test_dll /t:[knec] /k:[468] where the symbols in square brackets can be used in any combination (without the brackets) and have the following meanings: /t:[knec] selects which tests are used /k:[468] selects the key lengths used /c compares output with reference (see later) k: generate ECB Known Answer Test files n: generate ECB Known Answer Test files (new) e: generate ECB Monte Carlo Test files c: generate CBC Monte Carlo Test files and the characters giving the lengths are digits representing the key lengths in 32-bit units (4, 6, 8 for lengths of 128, 192 or 256 bits respectively). The project test_modes tests the AES modes. It uses the files: test_modes: Win32 or x64 headers: aes.h, aescpp.h, brg_types.h, aesaux,h and aestst.h C source: aesaux.c, modetest.c defines: none for static library test, DLL_IMPORT for DLL test which again links to the last library built. E. Other Applications --------------------- These are: gen_tests builds the test_vector files. The commad line is gen_tests /t:knec /k:468 /c as described earlier test_aes_avs run the AES Algorithm Validation Suite tests for ECB, CBC, CFB and OFB modes gen_tables builds a simple version of aes_tab.c (in aestab2.c) for compilers that cannot handle the normal version aes_example provides an example of AES use These applications are linked to the last static library built or, if DLL_IMPORT is defined during compilation, to the last DLL built. F. Use of the VIA ACE Cryptography Engine (x86 only) ---------------------------------------------------- The use of the code with the VIA ACE cryptography engine in described in the file via_ace.txt. In outline aes_modes.c is used and USE_VIA_ACE_IF_PRESENT is defined either in section 2 of aesopt.h or as a compilation option in Visual Studio. If in addition ASSUME_VIA_ACE_PRESENT is also defined then all normal AES code will be removed if not needed to support VIA ACE use. If VIA ACE support is needed and AES assembler is being used only the ASM_X86_V1C and ASM_X86_V2C versions should be used since ASM_X86_V2 and ASM_AMD64 do not support the VIA ACE engine. G. The AES Test Vector Files ---------------------------- These files fall in the following groups (where is a two digit number): 1. ecbvk.txt ECB vectors with variable key 2. ecbvt.txt ECB vectors with variable text 3. ecbnk.txt new ECB vectors with variable key 4. ecbnt.txt new ECB vectors with variable text 5. ecbme.txt ECB monte carlo encryption test vectors 6. ecbmd.txt ECB monte carlo decryption test vectors 7. cbcme.txt CBC monte carlo encryption test vectors 8. cbcmd.txt CBC monte carlo decryption test vectors The first digit of the numeric suffix on the filename gives the block size in 32 bit units and the second numeric digit gives the key size. For example, the file ecbvk44.txt provides the test vectors for ECB encryption with a 128 bit block size and a 128 bit key size. The test routines expect to find these files in the 'testvals' subdirectory within the aes root directory. The 'outvals' subdirectory is used for outputs that are compared with the files in 'testvals'. Note that the monte carlo test vectors are the result of applying AES iteratively 10000 times, not just once. The AES Algorithm Validation Suite tests can be run for ECB, CBC, CFB and OFB modes (CFB1 and CFB8 are not implemented). The test routine uses the *.fax test files, which should be placed in the 'testvals\fax' subdirectory. H. The Basic AES Calling Interface ---------------------------------- The basic AES code keeps its state in a context, there being different contexts for encryption and decryption: aes_encrypt_ctx aes_decrypt_ctx The AES code is initialised with the call aes_init(void) although this is only essential if the option to generate the AES tables at run-time has been set in the options (i.e.fixed tables are not being used). The AES encryption key is set by one of the calls: aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]) aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]) aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]) or by: aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]) where the key length is set by 'key_len', which can be the length in bits or bytes. Similarly, the AES decryption key is set by one of: aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]) aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]) aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]) or by: aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) Encryption and decryption for a single 16 byte block is then achieved using: aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]) aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]) The above subroutines return a value of EXIT_SUCCESS or EXIT_FAILURE depending on whether the operation succeeded or failed. I. The Calling Interface for the AES Modes ------------------------------------------ The subroutines for the AES modes, ECB, CBC, CFB, OFB and CTR, each process blocks of variable length and can also be called several times to complete single mode operations incrementally on long messages (or those messages, not all of which are available at the same time). The calls: aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, const aes_encrypt_ctx cx[1]) aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, const aes_decrypt_ctx cx[1]) for ECB operations and those for CBC: aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, const aes_encrypt_ctx cx[1]) aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, const aes_decrypt_ctx cx[1]) can only process blocks whose lengths are multiples of 16 bytes but the calls for CFB, OFB and CTR mode operations: aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx cx[1]) aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx cx[1]) aes_ofb_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx cx[1]) aes_ofb_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx cx[1]) aes_ctr_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]) aes_ctr_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx cx[1]) can process blocks of any length. Note also that CFB, OFB and CTR mode calls only use AES encryption contexts even during decryption operations. The calls CTR mode operations use a buffer (cbuf) which holds the counter value together with a function parameter: void cbuf_inc(unsigned char *cbuf); that is ued to update the counter value after each 16 byte AES operation. The counter buffer is updated appropriately to allow for incremental operations. Please note the following IMPORTANT points about the AES mode subroutines: 1. All modes are reset when a new AES key is set. 2. Incremental calls to the different modes cannot be mixed. If a change of mode is needed a new key must be set or a reset must be issued (see below). 3. For modes with IVs, the IV value is an input AND an ouTput since it is updated after each call to the value needed for any subsequent incremental call(s). If the mode is reset, the IV hence has to be set (or reset) as well. 4. ECB operations must be multiples of 16 bytes but do not need to be reset for new operations. 5. CBC operations must also be multiples of 16 bytes and are reset for a new operation by setting the IV. 6. CFB, OFB and CTR mode must be reset by setting a new IV value AND by calling: aes_mode_reset(aes_encrypt_ctx cx[1]) For CTR mode the cbuf value also has to be reset. 7. CFB, OFB and CTR modes only use AES encryption operations and contexts and do not need AES decrytpion operations. 8. AES keys remain valid across resets and changes of mode (but encryption and decryption keys must both be set if they are needed). Brian Gladman 14/11/2013 open-zwave-1.5/cpp/src/aes/aes_modes.c000066400000000000000000000753001264474202400177100ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 These subroutines implement multiple block AES modes for ECB, CBC, CFB, OFB and CTR encryption, The code provides support for the VIA Advanced Cryptography Engine (ACE). NOTE: In the following subroutines, the AES contexts (ctx) must be 16 byte aligned if VIA ACE is being used */ #include #include #include #include "aesopt.h" #if defined( AES_MODES ) #if defined(__cplusplus) extern "C" { #endif #if defined( _MSC_VER ) && ( _MSC_VER > 800 ) #pragma intrinsic(memcpy) #endif #define BFR_BLOCKS 8 /* These values are used to detect long word alignment in order to */ /* speed up some buffer operations. This facility may not work on */ /* some machines so this define can be commented out if necessary */ #define FAST_BUFFER_OPERATIONS #define lp32(x) ((uint32_t*)(x)) #if defined( USE_VIA_ACE_IF_PRESENT ) #include "aes_via_ace.h" #pragma pack(16) aligned_array(unsigned long, enc_gen_table, 12, 16) = NEH_ENC_GEN_DATA; aligned_array(unsigned long, enc_load_table, 12, 16) = NEH_ENC_LOAD_DATA; aligned_array(unsigned long, enc_hybrid_table, 12, 16) = NEH_ENC_HYBRID_DATA; aligned_array(unsigned long, dec_gen_table, 12, 16) = NEH_DEC_GEN_DATA; aligned_array(unsigned long, dec_load_table, 12, 16) = NEH_DEC_LOAD_DATA; aligned_array(unsigned long, dec_hybrid_table, 12, 16) = NEH_DEC_HYBRID_DATA; /* NOTE: These control word macros must only be used after */ /* a key has been set up because they depend on key size */ /* See the VIA ACE documentation for key type information */ /* and aes_via_ace.h for non-default NEH_KEY_TYPE values */ #ifndef NEH_KEY_TYPE # define NEH_KEY_TYPE NEH_HYBRID #endif #if NEH_KEY_TYPE == NEH_LOAD #define kd_adr(c) ((uint8_t*)(c)->ks) #elif NEH_KEY_TYPE == NEH_GENERATE #define kd_adr(c) ((uint8_t*)(c)->ks + (c)->inf.b[0]) #elif NEH_KEY_TYPE == NEH_HYBRID #define kd_adr(c) ((uint8_t*)(c)->ks + ((c)->inf.b[0] == 160 ? 160 : 0)) #else #error no key type defined for VIA ACE #endif #else #define aligned_array(type, name, no, stride) type name[no] #define aligned_auto(type, name, no, stride) type name[no] #endif #if defined( _MSC_VER ) && _MSC_VER > 1200 #define via_cwd(cwd, ty, dir, len) \ unsigned long* cwd = (dir##_##ty##_table + ((len - 128) >> 4)) #else #define via_cwd(cwd, ty, dir, len) \ aligned_auto(unsigned long, cwd, 4, 16); \ cwd[1] = cwd[2] = cwd[3] = 0; \ cwd[0] = neh_##dir##_##ty##_key(len) #endif /* test the code for detecting and setting pointer alignment */ AES_RETURN aes_test_alignment_detection(unsigned int n) /* 4 <= n <= 16 */ { uint8_t p[16]; uint32_t i, count_eq = 0, count_neq = 0; if(n < 4 || n > 16) return EXIT_FAILURE; for(i = 0; i < n; ++i) { uint8_t *qf = ALIGN_FLOOR(p + i, n), *qh = ALIGN_CEIL(p + i, n); if(qh == qf) ++count_eq; else if(qh == qf + n) ++count_neq; else return EXIT_FAILURE; } return (count_eq != 1 || count_neq != n - 1 ? EXIT_FAILURE : EXIT_SUCCESS); } AES_RETURN aes_mode_reset(aes_encrypt_ctx ctx[1]) { ctx->inf.b[2] = 0; return EXIT_SUCCESS; } AES_RETURN aes_ecb_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, const aes_encrypt_ctx ctx[1]) { int nb = len >> 4; if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE; #if defined( USE_VIA_ACE_IF_PRESENT ) if(ctx->inf.b[1] == 0xff) { uint8_t *ksp = (uint8_t*)(ctx->ks); via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); if(ALIGN_OFFSET( ctx, 16 )) return EXIT_FAILURE; if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) { via_ecb_op5(ksp, cwd, ibuf, obuf, nb); } else { aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); uint8_t *ip, *op; while(nb) { int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb); ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE); via_ecb_op5(ksp, cwd, ip, op, m); if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE); ibuf += m * AES_BLOCK_SIZE; obuf += m * AES_BLOCK_SIZE; nb -= m; } } return EXIT_SUCCESS; } #endif #if !defined( ASSUME_VIA_ACE_PRESENT ) while(nb--) { if(aes_encrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; } #endif return EXIT_SUCCESS; } AES_RETURN aes_ecb_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, const aes_decrypt_ctx ctx[1]) { int nb = len >> 4; if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE; #if defined( USE_VIA_ACE_IF_PRESENT ) if(ctx->inf.b[1] == 0xff) { uint8_t *ksp = kd_adr(ctx); via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192); if(ALIGN_OFFSET( ctx, 16 )) return EXIT_FAILURE; if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) { via_ecb_op5(ksp, cwd, ibuf, obuf, nb); } else { aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); uint8_t *ip, *op; while(nb) { int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb); ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE); via_ecb_op5(ksp, cwd, ip, op, m); if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE); ibuf += m * AES_BLOCK_SIZE; obuf += m * AES_BLOCK_SIZE; nb -= m; } } return EXIT_SUCCESS; } #endif #if !defined( ASSUME_VIA_ACE_PRESENT ) while(nb--) { if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; } #endif return EXIT_SUCCESS; } AES_RETURN aes_cbc_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, const aes_encrypt_ctx ctx[1]) { int nb = len >> 4; if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE; #if defined( USE_VIA_ACE_IF_PRESENT ) if(ctx->inf.b[1] == 0xff) { uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv; aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16); via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); if(ALIGN_OFFSET( ctx, 16 )) return EXIT_FAILURE; if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ { ivp = liv; memcpy(liv, iv, AES_BLOCK_SIZE); } if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 )) { via_cbc_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp); } else { aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); uint8_t *ip, *op; while(nb) { int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb); ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE); via_cbc_op7(ksp, cwd, ip, op, m, ivp, ivp); if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE); ibuf += m * AES_BLOCK_SIZE; obuf += m * AES_BLOCK_SIZE; nb -= m; } } if(iv != ivp) memcpy(iv, ivp, AES_BLOCK_SIZE); return EXIT_SUCCESS; } #endif #if !defined( ASSUME_VIA_ACE_PRESENT ) # ifdef FAST_BUFFER_OPERATIONS if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( iv, 4 )) while(nb--) { lp32(iv)[0] ^= lp32(ibuf)[0]; lp32(iv)[1] ^= lp32(ibuf)[1]; lp32(iv)[2] ^= lp32(ibuf)[2]; lp32(iv)[3] ^= lp32(ibuf)[3]; if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; memcpy(obuf, iv, AES_BLOCK_SIZE); ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; } else # endif while(nb--) { iv[ 0] ^= ibuf[ 0]; iv[ 1] ^= ibuf[ 1]; iv[ 2] ^= ibuf[ 2]; iv[ 3] ^= ibuf[ 3]; iv[ 4] ^= ibuf[ 4]; iv[ 5] ^= ibuf[ 5]; iv[ 6] ^= ibuf[ 6]; iv[ 7] ^= ibuf[ 7]; iv[ 8] ^= ibuf[ 8]; iv[ 9] ^= ibuf[ 9]; iv[10] ^= ibuf[10]; iv[11] ^= ibuf[11]; iv[12] ^= ibuf[12]; iv[13] ^= ibuf[13]; iv[14] ^= ibuf[14]; iv[15] ^= ibuf[15]; if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; memcpy(obuf, iv, AES_BLOCK_SIZE); ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; } #endif return EXIT_SUCCESS; } AES_RETURN aes_cbc_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, const aes_decrypt_ctx ctx[1]) { unsigned char tmp[AES_BLOCK_SIZE]; int nb = len >> 4; if(len & (AES_BLOCK_SIZE - 1)) return EXIT_FAILURE; #if defined( USE_VIA_ACE_IF_PRESENT ) if(ctx->inf.b[1] == 0xff) { uint8_t *ksp = kd_adr(ctx), *ivp = iv; aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16); via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192); if(ALIGN_OFFSET( ctx, 16 )) return EXIT_FAILURE; if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ { ivp = liv; memcpy(liv, iv, AES_BLOCK_SIZE); } if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 ) && !ALIGN_OFFSET( iv, 16 )) { via_cbc_op6(ksp, cwd, ibuf, obuf, nb, ivp); } else { aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); uint8_t *ip, *op; while(nb) { int m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb); ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE); via_cbc_op6(ksp, cwd, ip, op, m, ivp); if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE); ibuf += m * AES_BLOCK_SIZE; obuf += m * AES_BLOCK_SIZE; nb -= m; } } if(iv != ivp) memcpy(iv, ivp, AES_BLOCK_SIZE); return EXIT_SUCCESS; } #endif #if !defined( ASSUME_VIA_ACE_PRESENT ) # ifdef FAST_BUFFER_OPERATIONS if(!ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 )) while(nb--) { memcpy(tmp, ibuf, AES_BLOCK_SIZE); if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; lp32(obuf)[0] ^= lp32(iv)[0]; lp32(obuf)[1] ^= lp32(iv)[1]; lp32(obuf)[2] ^= lp32(iv)[2]; lp32(obuf)[3] ^= lp32(iv)[3]; memcpy(iv, tmp, AES_BLOCK_SIZE); ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; } else # endif while(nb--) { memcpy(tmp, ibuf, AES_BLOCK_SIZE); if(aes_decrypt(ibuf, obuf, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; obuf[ 0] ^= iv[ 0]; obuf[ 1] ^= iv[ 1]; obuf[ 2] ^= iv[ 2]; obuf[ 3] ^= iv[ 3]; obuf[ 4] ^= iv[ 4]; obuf[ 5] ^= iv[ 5]; obuf[ 6] ^= iv[ 6]; obuf[ 7] ^= iv[ 7]; obuf[ 8] ^= iv[ 8]; obuf[ 9] ^= iv[ 9]; obuf[10] ^= iv[10]; obuf[11] ^= iv[11]; obuf[12] ^= iv[12]; obuf[13] ^= iv[13]; obuf[14] ^= iv[14]; obuf[15] ^= iv[15]; memcpy(iv, tmp, AES_BLOCK_SIZE); ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; } #endif return EXIT_SUCCESS; } AES_RETURN aes_cfb_encrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx ctx[1]) { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb; if(b_pos) /* complete any partial block */ { while(b_pos < AES_BLOCK_SIZE && cnt < len) { *obuf++ = (iv[b_pos++] ^= *ibuf++); cnt++; } b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); } if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */ { #if defined( USE_VIA_ACE_IF_PRESENT ) if(ctx->inf.b[1] == 0xff) { int m; uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv; aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16); via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); if(ALIGN_OFFSET( ctx, 16 )) return EXIT_FAILURE; if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ { ivp = liv; memcpy(liv, iv, AES_BLOCK_SIZE); } if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) { via_cfb_op7(ksp, cwd, ibuf, obuf, nb, ivp, ivp); ibuf += nb * AES_BLOCK_SIZE; obuf += nb * AES_BLOCK_SIZE; cnt += nb * AES_BLOCK_SIZE; } else /* input, output or both are unaligned */ { aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); uint8_t *ip, *op; while(nb) { m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m; ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE); via_cfb_op7(ksp, cwd, ip, op, m, ivp, ivp); if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE); ibuf += m * AES_BLOCK_SIZE; obuf += m * AES_BLOCK_SIZE; cnt += m * AES_BLOCK_SIZE; } } if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE); } #else # ifdef FAST_BUFFER_OPERATIONS if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 )) while(cnt + AES_BLOCK_SIZE <= len) { assert(b_pos == 0); if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; lp32(obuf)[0] = lp32(iv)[0] ^= lp32(ibuf)[0]; lp32(obuf)[1] = lp32(iv)[1] ^= lp32(ibuf)[1]; lp32(obuf)[2] = lp32(iv)[2] ^= lp32(ibuf)[2]; lp32(obuf)[3] = lp32(iv)[3] ^= lp32(ibuf)[3]; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; cnt += AES_BLOCK_SIZE; } else # endif while(cnt + AES_BLOCK_SIZE <= len) { assert(b_pos == 0); if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; obuf[ 0] = iv[ 0] ^= ibuf[ 0]; obuf[ 1] = iv[ 1] ^= ibuf[ 1]; obuf[ 2] = iv[ 2] ^= ibuf[ 2]; obuf[ 3] = iv[ 3] ^= ibuf[ 3]; obuf[ 4] = iv[ 4] ^= ibuf[ 4]; obuf[ 5] = iv[ 5] ^= ibuf[ 5]; obuf[ 6] = iv[ 6] ^= ibuf[ 6]; obuf[ 7] = iv[ 7] ^= ibuf[ 7]; obuf[ 8] = iv[ 8] ^= ibuf[ 8]; obuf[ 9] = iv[ 9] ^= ibuf[ 9]; obuf[10] = iv[10] ^= ibuf[10]; obuf[11] = iv[11] ^= ibuf[11]; obuf[12] = iv[12] ^= ibuf[12]; obuf[13] = iv[13] ^= ibuf[13]; obuf[14] = iv[14] ^= ibuf[14]; obuf[15] = iv[15] ^= ibuf[15]; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; cnt += AES_BLOCK_SIZE; } #endif } while(cnt < len) { if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; while(cnt < len && b_pos < AES_BLOCK_SIZE) { *obuf++ = (iv[b_pos++] ^= *ibuf++); cnt++; } b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); } ctx->inf.b[2] = (uint8_t)b_pos; return EXIT_SUCCESS; } AES_RETURN aes_cfb_decrypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx ctx[1]) { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb; if(b_pos) /* complete any partial block */ { uint8_t t; while(b_pos < AES_BLOCK_SIZE && cnt < len) { t = *ibuf++; *obuf++ = t ^ iv[b_pos]; iv[b_pos++] = t; cnt++; } b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); } if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */ { #if defined( USE_VIA_ACE_IF_PRESENT ) if(ctx->inf.b[1] == 0xff) { int m; uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv; aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16); via_cwd(cwd, hybrid, dec, 2 * ctx->inf.b[0] - 192); if(ALIGN_OFFSET( ctx, 16 )) return EXIT_FAILURE; if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ { ivp = liv; memcpy(liv, iv, AES_BLOCK_SIZE); } if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) { via_cfb_op6(ksp, cwd, ibuf, obuf, nb, ivp); ibuf += nb * AES_BLOCK_SIZE; obuf += nb * AES_BLOCK_SIZE; cnt += nb * AES_BLOCK_SIZE; } else /* input, output or both are unaligned */ { aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); uint8_t *ip, *op; while(nb) { m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m; ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); if(ip != ibuf) /* input buffer is not aligned */ memcpy(buf, ibuf, m * AES_BLOCK_SIZE); via_cfb_op6(ksp, cwd, ip, op, m, ivp); if(op != obuf) /* output buffer is not aligned */ memcpy(obuf, buf, m * AES_BLOCK_SIZE); ibuf += m * AES_BLOCK_SIZE; obuf += m * AES_BLOCK_SIZE; cnt += m * AES_BLOCK_SIZE; } } if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE); } #else # ifdef FAST_BUFFER_OPERATIONS if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) &&!ALIGN_OFFSET( iv, 4 )) while(cnt + AES_BLOCK_SIZE <= len) { uint32_t t; assert(b_pos == 0); if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; t = lp32(ibuf)[0], lp32(obuf)[0] = t ^ lp32(iv)[0], lp32(iv)[0] = t; t = lp32(ibuf)[1], lp32(obuf)[1] = t ^ lp32(iv)[1], lp32(iv)[1] = t; t = lp32(ibuf)[2], lp32(obuf)[2] = t ^ lp32(iv)[2], lp32(iv)[2] = t; t = lp32(ibuf)[3], lp32(obuf)[3] = t ^ lp32(iv)[3], lp32(iv)[3] = t; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; cnt += AES_BLOCK_SIZE; } else # endif while(cnt + AES_BLOCK_SIZE <= len) { uint8_t t; assert(b_pos == 0); if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; t = ibuf[ 0], obuf[ 0] = t ^ iv[ 0], iv[ 0] = t; t = ibuf[ 1], obuf[ 1] = t ^ iv[ 1], iv[ 1] = t; t = ibuf[ 2], obuf[ 2] = t ^ iv[ 2], iv[ 2] = t; t = ibuf[ 3], obuf[ 3] = t ^ iv[ 3], iv[ 3] = t; t = ibuf[ 4], obuf[ 4] = t ^ iv[ 4], iv[ 4] = t; t = ibuf[ 5], obuf[ 5] = t ^ iv[ 5], iv[ 5] = t; t = ibuf[ 6], obuf[ 6] = t ^ iv[ 6], iv[ 6] = t; t = ibuf[ 7], obuf[ 7] = t ^ iv[ 7], iv[ 7] = t; t = ibuf[ 8], obuf[ 8] = t ^ iv[ 8], iv[ 8] = t; t = ibuf[ 9], obuf[ 9] = t ^ iv[ 9], iv[ 9] = t; t = ibuf[10], obuf[10] = t ^ iv[10], iv[10] = t; t = ibuf[11], obuf[11] = t ^ iv[11], iv[11] = t; t = ibuf[12], obuf[12] = t ^ iv[12], iv[12] = t; t = ibuf[13], obuf[13] = t ^ iv[13], iv[13] = t; t = ibuf[14], obuf[14] = t ^ iv[14], iv[14] = t; t = ibuf[15], obuf[15] = t ^ iv[15], iv[15] = t; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; cnt += AES_BLOCK_SIZE; } #endif } while(cnt < len) { uint8_t t; if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; while(cnt < len && b_pos < AES_BLOCK_SIZE) { t = *ibuf++; *obuf++ = t ^ iv[b_pos]; iv[b_pos++] = t; cnt++; } b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); } ctx->inf.b[2] = (uint8_t)b_pos; return EXIT_SUCCESS; } AES_RETURN aes_ofb_crypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *iv, aes_encrypt_ctx ctx[1]) { int cnt = 0, b_pos = (int)ctx->inf.b[2], nb; if(b_pos) /* complete any partial block */ { while(b_pos < AES_BLOCK_SIZE && cnt < len) { *obuf++ = iv[b_pos++] ^ *ibuf++; cnt++; } b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); } if((nb = (len - cnt) >> 4) != 0) /* process whole blocks */ { #if defined( USE_VIA_ACE_IF_PRESENT ) if(ctx->inf.b[1] == 0xff) { int m; uint8_t *ksp = (uint8_t*)(ctx->ks), *ivp = iv; aligned_auto(uint8_t, liv, AES_BLOCK_SIZE, 16); via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); if(ALIGN_OFFSET( ctx, 16 )) return EXIT_FAILURE; if(ALIGN_OFFSET( iv, 16 )) /* ensure an aligned iv */ { ivp = liv; memcpy(liv, iv, AES_BLOCK_SIZE); } if(!ALIGN_OFFSET( ibuf, 16 ) && !ALIGN_OFFSET( obuf, 16 )) { via_ofb_op6(ksp, cwd, ibuf, obuf, nb, ivp); ibuf += nb * AES_BLOCK_SIZE; obuf += nb * AES_BLOCK_SIZE; cnt += nb * AES_BLOCK_SIZE; } else /* input, output or both are unaligned */ { aligned_auto(uint8_t, buf, BFR_BLOCKS * AES_BLOCK_SIZE, 16); uint8_t *ip, *op; while(nb) { m = (nb > BFR_BLOCKS ? BFR_BLOCKS : nb), nb -= m; ip = (ALIGN_OFFSET( ibuf, 16 ) ? buf : ibuf); op = (ALIGN_OFFSET( obuf, 16 ) ? buf : obuf); if(ip != ibuf) memcpy(buf, ibuf, m * AES_BLOCK_SIZE); via_ofb_op6(ksp, cwd, ip, op, m, ivp); if(op != obuf) memcpy(obuf, buf, m * AES_BLOCK_SIZE); ibuf += m * AES_BLOCK_SIZE; obuf += m * AES_BLOCK_SIZE; cnt += m * AES_BLOCK_SIZE; } } if(ivp != iv) memcpy(iv, ivp, AES_BLOCK_SIZE); } #else # ifdef FAST_BUFFER_OPERATIONS if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( iv, 4 )) while(cnt + AES_BLOCK_SIZE <= len) { assert(b_pos == 0); if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; lp32(obuf)[0] = lp32(iv)[0] ^ lp32(ibuf)[0]; lp32(obuf)[1] = lp32(iv)[1] ^ lp32(ibuf)[1]; lp32(obuf)[2] = lp32(iv)[2] ^ lp32(ibuf)[2]; lp32(obuf)[3] = lp32(iv)[3] ^ lp32(ibuf)[3]; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; cnt += AES_BLOCK_SIZE; } else # endif while(cnt + AES_BLOCK_SIZE <= len) { assert(b_pos == 0); if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; obuf[ 0] = iv[ 0] ^ ibuf[ 0]; obuf[ 1] = iv[ 1] ^ ibuf[ 1]; obuf[ 2] = iv[ 2] ^ ibuf[ 2]; obuf[ 3] = iv[ 3] ^ ibuf[ 3]; obuf[ 4] = iv[ 4] ^ ibuf[ 4]; obuf[ 5] = iv[ 5] ^ ibuf[ 5]; obuf[ 6] = iv[ 6] ^ ibuf[ 6]; obuf[ 7] = iv[ 7] ^ ibuf[ 7]; obuf[ 8] = iv[ 8] ^ ibuf[ 8]; obuf[ 9] = iv[ 9] ^ ibuf[ 9]; obuf[10] = iv[10] ^ ibuf[10]; obuf[11] = iv[11] ^ ibuf[11]; obuf[12] = iv[12] ^ ibuf[12]; obuf[13] = iv[13] ^ ibuf[13]; obuf[14] = iv[14] ^ ibuf[14]; obuf[15] = iv[15] ^ ibuf[15]; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; cnt += AES_BLOCK_SIZE; } #endif } while(cnt < len) { if(!b_pos && aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; while(cnt < len && b_pos < AES_BLOCK_SIZE) { *obuf++ = iv[b_pos++] ^ *ibuf++; cnt++; } b_pos = (b_pos == AES_BLOCK_SIZE ? 0 : b_pos); } ctx->inf.b[2] = (uint8_t)b_pos; return EXIT_SUCCESS; } #define BFR_LENGTH (BFR_BLOCKS * AES_BLOCK_SIZE) AES_RETURN aes_ctr_crypt(const unsigned char *ibuf, unsigned char *obuf, int len, unsigned char *cbuf, cbuf_inc ctr_inc, aes_encrypt_ctx ctx[1]) { unsigned char *ip; int i, blen, b_pos = (int)(ctx->inf.b[2]); #if defined( USE_VIA_ACE_IF_PRESENT ) aligned_auto(uint8_t, buf, BFR_LENGTH, 16); if(ctx->inf.b[1] == 0xff && ALIGN_OFFSET( ctx, 16 )) return EXIT_FAILURE; #else uint8_t buf[BFR_LENGTH]; #endif if(b_pos) { memcpy(buf, cbuf, AES_BLOCK_SIZE); if(aes_ecb_encrypt(buf, buf, AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; while(b_pos < AES_BLOCK_SIZE && len) { *obuf++ = *ibuf++ ^ buf[b_pos++]; --len; } if(len) ctr_inc(cbuf), b_pos = 0; } while(len) { blen = (len > BFR_LENGTH ? BFR_LENGTH : len), len -= blen; for(i = 0, ip = buf; i < (blen >> 4); ++i) { memcpy(ip, cbuf, AES_BLOCK_SIZE); ctr_inc(cbuf); ip += AES_BLOCK_SIZE; } if(blen & (AES_BLOCK_SIZE - 1)) memcpy(ip, cbuf, AES_BLOCK_SIZE), i++; #if defined( USE_VIA_ACE_IF_PRESENT ) if(ctx->inf.b[1] == 0xff) { via_cwd(cwd, hybrid, enc, 2 * ctx->inf.b[0] - 192); via_ecb_op5((ctx->ks), cwd, buf, buf, i); } else #endif if(aes_ecb_encrypt(buf, buf, i * AES_BLOCK_SIZE, ctx) != EXIT_SUCCESS) return EXIT_FAILURE; i = 0; ip = buf; # ifdef FAST_BUFFER_OPERATIONS if(!ALIGN_OFFSET( ibuf, 4 ) && !ALIGN_OFFSET( obuf, 4 ) && !ALIGN_OFFSET( ip, 4 )) while(i + AES_BLOCK_SIZE <= blen) { lp32(obuf)[0] = lp32(ibuf)[0] ^ lp32(ip)[0]; lp32(obuf)[1] = lp32(ibuf)[1] ^ lp32(ip)[1]; lp32(obuf)[2] = lp32(ibuf)[2] ^ lp32(ip)[2]; lp32(obuf)[3] = lp32(ibuf)[3] ^ lp32(ip)[3]; i += AES_BLOCK_SIZE; ip += AES_BLOCK_SIZE; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; } else #endif while(i + AES_BLOCK_SIZE <= blen) { obuf[ 0] = ibuf[ 0] ^ ip[ 0]; obuf[ 1] = ibuf[ 1] ^ ip[ 1]; obuf[ 2] = ibuf[ 2] ^ ip[ 2]; obuf[ 3] = ibuf[ 3] ^ ip[ 3]; obuf[ 4] = ibuf[ 4] ^ ip[ 4]; obuf[ 5] = ibuf[ 5] ^ ip[ 5]; obuf[ 6] = ibuf[ 6] ^ ip[ 6]; obuf[ 7] = ibuf[ 7] ^ ip[ 7]; obuf[ 8] = ibuf[ 8] ^ ip[ 8]; obuf[ 9] = ibuf[ 9] ^ ip[ 9]; obuf[10] = ibuf[10] ^ ip[10]; obuf[11] = ibuf[11] ^ ip[11]; obuf[12] = ibuf[12] ^ ip[12]; obuf[13] = ibuf[13] ^ ip[13]; obuf[14] = ibuf[14] ^ ip[14]; obuf[15] = ibuf[15] ^ ip[15]; i += AES_BLOCK_SIZE; ip += AES_BLOCK_SIZE; ibuf += AES_BLOCK_SIZE; obuf += AES_BLOCK_SIZE; } while(i++ < blen) *obuf++ = *ibuf++ ^ ip[b_pos++]; } ctx->inf.b[2] = (uint8_t)b_pos; return EXIT_SUCCESS; } #if defined(__cplusplus) } #endif #endif open-zwave-1.5/cpp/src/aes/aescpp.h000066400000000000000000000115671264474202400172360ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 This file contains the definitions required to use AES (Rijndael) in C++. */ #ifndef _AESCPP_H #define _AESCPP_H #include "aes.h" #if defined( AES_ENCRYPT ) class AESencrypt { public: aes_encrypt_ctx cx[1]; AESencrypt(void) { aes_init(); }; #if defined(AES_128) AESencrypt(const unsigned char key[]) { aes_encrypt_key128(key, cx); } AES_RETURN key128(const unsigned char key[]) { return aes_encrypt_key128(key, cx); } #endif #if defined(AES_192) AES_RETURN key192(const unsigned char key[]) { return aes_encrypt_key192(key, cx); } #endif #if defined(AES_256) AES_RETURN key256(const unsigned char key[]) { return aes_encrypt_key256(key, cx); } #endif #if defined(AES_VAR) AES_RETURN key(const unsigned char key[], int key_len) { return aes_encrypt_key(key, key_len, cx); } #endif AES_RETURN encrypt(const unsigned char in[], unsigned char out[]) const { return aes_encrypt(in, out, cx); } #ifndef AES_MODES AES_RETURN ecb_encrypt(const unsigned char in[], unsigned char out[], int nb) const { while(nb--) { aes_encrypt(in, out, cx), in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE; } } #endif #ifdef AES_MODES AES_RETURN mode_reset(void) { return aes_mode_reset(cx); } AES_RETURN ecb_encrypt(const unsigned char in[], unsigned char out[], int nb) const { return aes_ecb_encrypt(in, out, nb, cx); } AES_RETURN cbc_encrypt(const unsigned char in[], unsigned char out[], int nb, unsigned char iv[]) const { return aes_cbc_encrypt(in, out, nb, iv, cx); } AES_RETURN cfb_encrypt(const unsigned char in[], unsigned char out[], int nb, unsigned char iv[]) { return aes_cfb_encrypt(in, out, nb, iv, cx); } AES_RETURN cfb_decrypt(const unsigned char in[], unsigned char out[], int nb, unsigned char iv[]) { return aes_cfb_decrypt(in, out, nb, iv, cx); } AES_RETURN ofb_crypt(const unsigned char in[], unsigned char out[], int nb, unsigned char iv[]) { return aes_ofb_crypt(in, out, nb, iv, cx); } typedef void ctr_fn(unsigned char ctr[]); AES_RETURN ctr_crypt(const unsigned char in[], unsigned char out[], int nb, unsigned char iv[], ctr_fn cf) { return aes_ctr_crypt(in, out, nb, iv, cf, cx); } #endif }; #endif #if defined( AES_DECRYPT ) class AESdecrypt { public: aes_decrypt_ctx cx[1]; AESdecrypt(void) { aes_init(); }; #if defined(AES_128) AESdecrypt(const unsigned char key[]) { aes_decrypt_key128(key, cx); } AES_RETURN key128(const unsigned char key[]) { return aes_decrypt_key128(key, cx); } #endif #if defined(AES_192) AES_RETURN key192(const unsigned char key[]) { return aes_decrypt_key192(key, cx); } #endif #if defined(AES_256) AES_RETURN key256(const unsigned char key[]) { return aes_decrypt_key256(key, cx); } #endif #if defined(AES_VAR) AES_RETURN key(const unsigned char key[], int key_len) { return aes_decrypt_key(key, key_len, cx); } #endif AES_RETURN decrypt(const unsigned char in[], unsigned char out[]) const { return aes_decrypt(in, out, cx); } #ifndef AES_MODES AES_RETURN ecb_decrypt(const unsigned char in[], unsigned char out[], int nb) const { while(nb--) { aes_decrypt(in, out, cx), in += AES_BLOCK_SIZE, out += AES_BLOCK_SIZE; } } #endif #ifdef AES_MODES AES_RETURN ecb_decrypt(const unsigned char in[], unsigned char out[], int nb) const { return aes_ecb_decrypt(in, out, nb, cx); } AES_RETURN cbc_decrypt(const unsigned char in[], unsigned char out[], int nb, unsigned char iv[]) const { return aes_cbc_decrypt(in, out, nb, iv, cx); } #endif }; #endif #endif open-zwave-1.5/cpp/src/aes/aescrypt.c000066400000000000000000000241101264474202400175740ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 */ #include "aesopt.h" #include "aestab.h" #if defined( USE_INTEL_AES_IF_PRESENT ) #include #else /* map names here to provide the external API ('name' -> 'aes_name') */ # define aes_xi(x) aes_ ## x #endif #if defined(__cplusplus) extern "C" { #endif #define si(y,x,k,c) (s(y,c) = word_in(x, c) ^ (k)[c]) #define so(y,x,c) word_out(y, c, s(x,c)) #if defined(ARRAYS) #define locals(y,x) x[4],y[4] #else #define locals(y,x) x##0,x##1,x##2,x##3,y##0,y##1,y##2,y##3 #endif #define l_copy(y, x) s(y,0) = s(x,0); s(y,1) = s(x,1); \ s(y,2) = s(x,2); s(y,3) = s(x,3); #define state_in(y,x,k) si(y,x,k,0); si(y,x,k,1); si(y,x,k,2); si(y,x,k,3) #define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3) #define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3) #if ( FUNCS_IN_C & ENCRYPTION_IN_C ) /* Visual C++ .Net v7.1 provides the fastest encryption code when using Pentium optimiation with small code but this is poor for decryption so we need to control this with the following VC++ pragmas */ #if defined( _MSC_VER ) && !defined( _WIN64 ) #pragma optimize( "s", on ) #endif /* Given the column (c) of the output state variable, the following macros give the input state variables which are needed in its computation for each row (r) of the state. All the alternative macros give the same end values but expand into different ways of calculating these values. In particular the complex macro used for dynamically variable block sizes is designed to expand to a compile time constant whenever possible but will expand to conditional clauses on some branches (I am grateful to Frank Yellin for this construction) */ #define fwd_var(x,r,c)\ ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ : r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\ : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ : ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))) #if defined(FT4_SET) #undef dec_fmvars #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c)) #elif defined(FT1_SET) #undef dec_fmvars #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(f,n),fwd_var,rf1,c)) #else #define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ fwd_mcol(no_table(x,t_use(s,box),fwd_var,rf1,c))) #endif #if defined(FL4_SET) #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,l),fwd_var,rf1,c)) #elif defined(FL1_SET) #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(f,l),fwd_var,rf1,c)) #else #define fwd_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(s,box),fwd_var,rf1,c)) #endif AES_RETURN aes_xi(encrypt)(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]) { uint32_t locals(b0, b1); const uint32_t *kp; #if defined( dec_fmvars ) dec_fmvars; /* declare variables for fwd_mcol() if needed */ #endif if(cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16) return EXIT_FAILURE; kp = cx->ks; state_in(b0, in, kp); #if (ENC_UNROLL == FULL) switch(cx->inf.b[0]) { case 14 * 16: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); round(fwd_rnd, b0, b1, kp + 2 * N_COLS); kp += 2 * N_COLS; case 12 * 16: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); round(fwd_rnd, b0, b1, kp + 2 * N_COLS); kp += 2 * N_COLS; case 10 * 16: round(fwd_rnd, b1, b0, kp + 1 * N_COLS); round(fwd_rnd, b0, b1, kp + 2 * N_COLS); round(fwd_rnd, b1, b0, kp + 3 * N_COLS); round(fwd_rnd, b0, b1, kp + 4 * N_COLS); round(fwd_rnd, b1, b0, kp + 5 * N_COLS); round(fwd_rnd, b0, b1, kp + 6 * N_COLS); round(fwd_rnd, b1, b0, kp + 7 * N_COLS); round(fwd_rnd, b0, b1, kp + 8 * N_COLS); round(fwd_rnd, b1, b0, kp + 9 * N_COLS); round(fwd_lrnd, b0, b1, kp +10 * N_COLS); } #else #if (ENC_UNROLL == PARTIAL) { uint32_t rnd; for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) { kp += N_COLS; round(fwd_rnd, b1, b0, kp); kp += N_COLS; round(fwd_rnd, b0, b1, kp); } kp += N_COLS; round(fwd_rnd, b1, b0, kp); #else { uint32_t rnd; for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) { kp += N_COLS; round(fwd_rnd, b1, b0, kp); l_copy(b0, b1); } #endif kp += N_COLS; round(fwd_lrnd, b0, b1, kp); } #endif state_out(out, b0); return EXIT_SUCCESS; } #endif #if ( FUNCS_IN_C & DECRYPTION_IN_C) /* Visual C++ .Net v7.1 provides the fastest encryption code when using Pentium optimiation with small code but this is poor for decryption so we need to control this with the following VC++ pragmas */ #if defined( _MSC_VER ) && !defined( _WIN64 ) #pragma optimize( "t", on ) #endif /* Given the column (c) of the output state variable, the following macros give the input state variables which are needed in its computation for each row (r) of the state. All the alternative macros give the same end values but expand into different ways of calculating these values. In particular the complex macro used for dynamically variable block sizes is designed to expand to a compile time constant whenever possible but will expand to conditional clauses on some branches (I am grateful to Frank Yellin for this construction) */ #define inv_var(x,r,c)\ ( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\ : r == 1 ? ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2))\ : r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\ : ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))) #if defined(IT4_SET) #undef dec_imvars #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,n),inv_var,rf1,c)) #elif defined(IT1_SET) #undef dec_imvars #define inv_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,upr,t_use(i,n),inv_var,rf1,c)) #else #define inv_rnd(y,x,k,c) (s(y,c) = inv_mcol((k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c))) #endif #if defined(IL4_SET) #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(i,l),inv_var,rf1,c)) #elif defined(IL1_SET) #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ one_table(x,ups,t_use(i,l),inv_var,rf1,c)) #else #define inv_lrnd(y,x,k,c) (s(y,c) = (k)[c] ^ no_table(x,t_use(i,box),inv_var,rf1,c)) #endif /* This code can work with the decryption key schedule in the */ /* order that is used for encrytpion (where the 1st decryption */ /* round key is at the high end ot the schedule) or with a key */ /* schedule that has been reversed to put the 1st decryption */ /* round key at the low end of the schedule in memory (when */ /* AES_REV_DKS is defined) */ #ifdef AES_REV_DKS #define key_ofs 0 #define rnd_key(n) (kp + n * N_COLS) #else #define key_ofs 1 #define rnd_key(n) (kp - n * N_COLS) #endif AES_RETURN aes_xi(decrypt)(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]) { uint32_t locals(b0, b1); #if defined( dec_imvars ) dec_imvars; /* declare variables for inv_mcol() if needed */ #endif const uint32_t *kp; if(cx->inf.b[0] != 10 * 16 && cx->inf.b[0] != 12 * 16 && cx->inf.b[0] != 14 * 16) return EXIT_FAILURE; kp = cx->ks + (key_ofs ? (cx->inf.b[0] >> 2) : 0); state_in(b0, in, kp); #if (DEC_UNROLL == FULL) kp = cx->ks + (key_ofs ? 0 : (cx->inf.b[0] >> 2)); switch(cx->inf.b[0]) { case 14 * 16: round(inv_rnd, b1, b0, rnd_key(-13)); round(inv_rnd, b0, b1, rnd_key(-12)); case 12 * 16: round(inv_rnd, b1, b0, rnd_key(-11)); round(inv_rnd, b0, b1, rnd_key(-10)); case 10 * 16: round(inv_rnd, b1, b0, rnd_key(-9)); round(inv_rnd, b0, b1, rnd_key(-8)); round(inv_rnd, b1, b0, rnd_key(-7)); round(inv_rnd, b0, b1, rnd_key(-6)); round(inv_rnd, b1, b0, rnd_key(-5)); round(inv_rnd, b0, b1, rnd_key(-4)); round(inv_rnd, b1, b0, rnd_key(-3)); round(inv_rnd, b0, b1, rnd_key(-2)); round(inv_rnd, b1, b0, rnd_key(-1)); round(inv_lrnd, b0, b1, rnd_key( 0)); } #else #if (DEC_UNROLL == PARTIAL) { uint32_t rnd; for(rnd = 0; rnd < (cx->inf.b[0] >> 5) - 1; ++rnd) { kp = rnd_key(1); round(inv_rnd, b1, b0, kp); kp = rnd_key(1); round(inv_rnd, b0, b1, kp); } kp = rnd_key(1); round(inv_rnd, b1, b0, kp); #else { uint32_t rnd; for(rnd = 0; rnd < (cx->inf.b[0] >> 4) - 1; ++rnd) { kp = rnd_key(1); round(inv_rnd, b1, b0, kp); l_copy(b0, b1); } #endif kp = rnd_key(1); round(inv_lrnd, b0, b1, kp); } #endif state_out(out, b0); return EXIT_SUCCESS; } #endif #if defined(__cplusplus) } #endif open-zwave-1.5/cpp/src/aes/aeskey.c000066400000000000000000000402001264474202400172210ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 */ #include "aesopt.h" #include "aestab.h" #if defined( USE_INTEL_AES_IF_PRESENT ) # include "aes_ni.h" #else /* map names here to provide the external API ('name' -> 'aes_name') */ # define aes_xi(x) aes_ ## x #endif #ifdef USE_VIA_ACE_IF_PRESENT # include "aes_via_ace.h" #endif #if defined(__cplusplus) extern "C" { #endif /* Initialise the key schedule from the user supplied key. The key length can be specified in bytes, with legal values of 16, 24 and 32, or in bits, with legal values of 128, 192 and 256. These values correspond with Nk values of 4, 6 and 8 respectively. The following macros implement a single cycle in the key schedule generation process. The number of cycles needed for each cx->n_col and nk value is: nk = 4 5 6 7 8 ------------------------------ cx->n_col = 4 10 9 8 7 7 cx->n_col = 5 14 11 10 9 9 cx->n_col = 6 19 15 12 11 11 cx->n_col = 7 21 19 16 13 14 cx->n_col = 8 29 23 19 17 14 */ #if defined( REDUCE_CODE_SIZE ) # define ls_box ls_sub uint32_t ls_sub(const uint32_t t, const uint32_t n); # define inv_mcol im_sub uint32_t im_sub(const uint32_t x); # ifdef ENC_KS_UNROLL # undef ENC_KS_UNROLL # endif # ifdef DEC_KS_UNROLL # undef DEC_KS_UNROLL # endif #endif #if (FUNCS_IN_C & ENC_KEYING_IN_C) #if defined(AES_128) || defined( AES_VAR ) #define ke4(k,i) \ { k[4*(i)+4] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ k[4*(i)+5] = ss[1] ^= ss[0]; \ k[4*(i)+6] = ss[2] ^= ss[1]; \ k[4*(i)+7] = ss[3] ^= ss[2]; \ } AES_RETURN aes_xi(encrypt_key128)(const unsigned char *key, aes_encrypt_ctx cx[1]) { uint32_t ss[4]; cx->ks[0] = ss[0] = word_in(key, 0); cx->ks[1] = ss[1] = word_in(key, 1); cx->ks[2] = ss[2] = word_in(key, 2); cx->ks[3] = ss[3] = word_in(key, 3); #ifdef ENC_KS_UNROLL ke4(cx->ks, 0); ke4(cx->ks, 1); ke4(cx->ks, 2); ke4(cx->ks, 3); ke4(cx->ks, 4); ke4(cx->ks, 5); ke4(cx->ks, 6); ke4(cx->ks, 7); ke4(cx->ks, 8); #else { uint32_t i; for(i = 0; i < 9; ++i) ke4(cx->ks, i); } #endif ke4(cx->ks, 9); cx->inf.l = 0; cx->inf.b[0] = 10 * 16; #ifdef USE_VIA_ACE_IF_PRESENT if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff; #endif return EXIT_SUCCESS; } #endif #if defined(AES_192) || defined( AES_VAR ) #define kef6(k,i) \ { k[6*(i)+ 6] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ k[6*(i)+ 7] = ss[1] ^= ss[0]; \ k[6*(i)+ 8] = ss[2] ^= ss[1]; \ k[6*(i)+ 9] = ss[3] ^= ss[2]; \ } #define ke6(k,i) \ { kef6(k,i); \ k[6*(i)+10] = ss[4] ^= ss[3]; \ k[6*(i)+11] = ss[5] ^= ss[4]; \ } AES_RETURN aes_xi(encrypt_key192)(const unsigned char *key, aes_encrypt_ctx cx[1]) { uint32_t ss[6]; cx->ks[0] = ss[0] = word_in(key, 0); cx->ks[1] = ss[1] = word_in(key, 1); cx->ks[2] = ss[2] = word_in(key, 2); cx->ks[3] = ss[3] = word_in(key, 3); cx->ks[4] = ss[4] = word_in(key, 4); cx->ks[5] = ss[5] = word_in(key, 5); #ifdef ENC_KS_UNROLL ke6(cx->ks, 0); ke6(cx->ks, 1); ke6(cx->ks, 2); ke6(cx->ks, 3); ke6(cx->ks, 4); ke6(cx->ks, 5); ke6(cx->ks, 6); #else { uint32_t i; for(i = 0; i < 7; ++i) ke6(cx->ks, i); } #endif kef6(cx->ks, 7); cx->inf.l = 0; cx->inf.b[0] = 12 * 16; #ifdef USE_VIA_ACE_IF_PRESENT if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff; #endif return EXIT_SUCCESS; } #endif #if defined(AES_256) || defined( AES_VAR ) #define kef8(k,i) \ { k[8*(i)+ 8] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ k[8*(i)+ 9] = ss[1] ^= ss[0]; \ k[8*(i)+10] = ss[2] ^= ss[1]; \ k[8*(i)+11] = ss[3] ^= ss[2]; \ } #define ke8(k,i) \ { kef8(k,i); \ k[8*(i)+12] = ss[4] ^= ls_box(ss[3],0); \ k[8*(i)+13] = ss[5] ^= ss[4]; \ k[8*(i)+14] = ss[6] ^= ss[5]; \ k[8*(i)+15] = ss[7] ^= ss[6]; \ } AES_RETURN aes_xi(encrypt_key256)(const unsigned char *key, aes_encrypt_ctx cx[1]) { uint32_t ss[8]; cx->ks[0] = ss[0] = word_in(key, 0); cx->ks[1] = ss[1] = word_in(key, 1); cx->ks[2] = ss[2] = word_in(key, 2); cx->ks[3] = ss[3] = word_in(key, 3); cx->ks[4] = ss[4] = word_in(key, 4); cx->ks[5] = ss[5] = word_in(key, 5); cx->ks[6] = ss[6] = word_in(key, 6); cx->ks[7] = ss[7] = word_in(key, 7); #ifdef ENC_KS_UNROLL ke8(cx->ks, 0); ke8(cx->ks, 1); ke8(cx->ks, 2); ke8(cx->ks, 3); ke8(cx->ks, 4); ke8(cx->ks, 5); #else { uint32_t i; for(i = 0; i < 6; ++i) ke8(cx->ks, i); } #endif kef8(cx->ks, 6); cx->inf.l = 0; cx->inf.b[0] = 14 * 16; #ifdef USE_VIA_ACE_IF_PRESENT if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff; #endif return EXIT_SUCCESS; } #endif #endif #if (FUNCS_IN_C & DEC_KEYING_IN_C) /* this is used to store the decryption round keys */ /* in forward or reverse order */ #ifdef AES_REV_DKS #define v(n,i) ((n) - (i) + 2 * ((i) & 3)) #else #define v(n,i) (i) #endif #if DEC_ROUND == NO_TABLES #define ff(x) (x) #else #define ff(x) inv_mcol(x) #if defined( dec_imvars ) #define d_vars dec_imvars #endif #endif #if defined(AES_128) || defined( AES_VAR ) #define k4e(k,i) \ { k[v(40,(4*(i))+4)] = ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; \ k[v(40,(4*(i))+5)] = ss[1] ^= ss[0]; \ k[v(40,(4*(i))+6)] = ss[2] ^= ss[1]; \ k[v(40,(4*(i))+7)] = ss[3] ^= ss[2]; \ } #if 1 #define kdf4(k,i) \ { ss[0] = ss[0] ^ ss[2] ^ ss[1] ^ ss[3]; \ ss[1] = ss[1] ^ ss[3]; \ ss[2] = ss[2] ^ ss[3]; \ ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ ss[i % 4] ^= ss[4]; \ ss[4] ^= k[v(40,(4*(i)))]; k[v(40,(4*(i))+4)] = ff(ss[4]); \ ss[4] ^= k[v(40,(4*(i))+1)]; k[v(40,(4*(i))+5)] = ff(ss[4]); \ ss[4] ^= k[v(40,(4*(i))+2)]; k[v(40,(4*(i))+6)] = ff(ss[4]); \ ss[4] ^= k[v(40,(4*(i))+3)]; k[v(40,(4*(i))+7)] = ff(ss[4]); \ } #define kd4(k,i) \ { ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; \ ss[i % 4] ^= ss[4]; ss[4] = ff(ss[4]); \ k[v(40,(4*(i))+4)] = ss[4] ^= k[v(40,(4*(i)))]; \ k[v(40,(4*(i))+5)] = ss[4] ^= k[v(40,(4*(i))+1)]; \ k[v(40,(4*(i))+6)] = ss[4] ^= k[v(40,(4*(i))+2)]; \ k[v(40,(4*(i))+7)] = ss[4] ^= k[v(40,(4*(i))+3)]; \ } #define kdl4(k,i) \ { ss[4] = ls_box(ss[(i+3) % 4], 3) ^ t_use(r,c)[i]; ss[i % 4] ^= ss[4]; \ k[v(40,(4*(i))+4)] = (ss[0] ^= ss[1]) ^ ss[2] ^ ss[3]; \ k[v(40,(4*(i))+5)] = ss[1] ^ ss[3]; \ k[v(40,(4*(i))+6)] = ss[0]; \ k[v(40,(4*(i))+7)] = ss[1]; \ } #else #define kdf4(k,i) \ { ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ff(ss[0]); \ ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ff(ss[1]); \ ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ff(ss[2]); \ ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ff(ss[3]); \ } #define kd4(k,i) \ { ss[4] = ls_box(ss[3],3) ^ t_use(r,c)[i]; \ ss[0] ^= ss[4]; ss[4] = ff(ss[4]); k[v(40,(4*(i))+ 4)] = ss[4] ^= k[v(40,(4*(i)))]; \ ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[4] ^= k[v(40,(4*(i))+ 1)]; \ ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[4] ^= k[v(40,(4*(i))+ 2)]; \ ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[4] ^= k[v(40,(4*(i))+ 3)]; \ } #define kdl4(k,i) \ { ss[0] ^= ls_box(ss[3],3) ^ t_use(r,c)[i]; k[v(40,(4*(i))+ 4)] = ss[0]; \ ss[1] ^= ss[0]; k[v(40,(4*(i))+ 5)] = ss[1]; \ ss[2] ^= ss[1]; k[v(40,(4*(i))+ 6)] = ss[2]; \ ss[3] ^= ss[2]; k[v(40,(4*(i))+ 7)] = ss[3]; \ } #endif AES_RETURN aes_xi(decrypt_key128)(const unsigned char *key, aes_decrypt_ctx cx[1]) { uint32_t ss[5]; #if defined( d_vars ) d_vars; #endif cx->ks[v(40,(0))] = ss[0] = word_in(key, 0); cx->ks[v(40,(1))] = ss[1] = word_in(key, 1); cx->ks[v(40,(2))] = ss[2] = word_in(key, 2); cx->ks[v(40,(3))] = ss[3] = word_in(key, 3); #ifdef DEC_KS_UNROLL kdf4(cx->ks, 0); kd4(cx->ks, 1); kd4(cx->ks, 2); kd4(cx->ks, 3); kd4(cx->ks, 4); kd4(cx->ks, 5); kd4(cx->ks, 6); kd4(cx->ks, 7); kd4(cx->ks, 8); kdl4(cx->ks, 9); #else { uint32_t i; for(i = 0; i < 10; ++i) k4e(cx->ks, i); #if !(DEC_ROUND == NO_TABLES) for(i = N_COLS; i < 10 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]); #endif } #endif cx->inf.l = 0; cx->inf.b[0] = 10 * 16; #ifdef USE_VIA_ACE_IF_PRESENT if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff; #endif return EXIT_SUCCESS; } #endif #if defined(AES_192) || defined( AES_VAR ) #define k6ef(k,i) \ { k[v(48,(6*(i))+ 6)] = ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; \ k[v(48,(6*(i))+ 7)] = ss[1] ^= ss[0]; \ k[v(48,(6*(i))+ 8)] = ss[2] ^= ss[1]; \ k[v(48,(6*(i))+ 9)] = ss[3] ^= ss[2]; \ } #define k6e(k,i) \ { k6ef(k,i); \ k[v(48,(6*(i))+10)] = ss[4] ^= ss[3]; \ k[v(48,(6*(i))+11)] = ss[5] ^= ss[4]; \ } #define kdf6(k,i) \ { ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ff(ss[0]); \ ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ff(ss[1]); \ ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ff(ss[2]); \ ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ff(ss[3]); \ ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ff(ss[4]); \ ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ff(ss[5]); \ } #define kd6(k,i) \ { ss[6] = ls_box(ss[5],3) ^ t_use(r,c)[i]; \ ss[0] ^= ss[6]; ss[6] = ff(ss[6]); k[v(48,(6*(i))+ 6)] = ss[6] ^= k[v(48,(6*(i)))]; \ ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[6] ^= k[v(48,(6*(i))+ 1)]; \ ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[6] ^= k[v(48,(6*(i))+ 2)]; \ ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[6] ^= k[v(48,(6*(i))+ 3)]; \ ss[4] ^= ss[3]; k[v(48,(6*(i))+10)] = ss[6] ^= k[v(48,(6*(i))+ 4)]; \ ss[5] ^= ss[4]; k[v(48,(6*(i))+11)] = ss[6] ^= k[v(48,(6*(i))+ 5)]; \ } #define kdl6(k,i) \ { ss[0] ^= ls_box(ss[5],3) ^ t_use(r,c)[i]; k[v(48,(6*(i))+ 6)] = ss[0]; \ ss[1] ^= ss[0]; k[v(48,(6*(i))+ 7)] = ss[1]; \ ss[2] ^= ss[1]; k[v(48,(6*(i))+ 8)] = ss[2]; \ ss[3] ^= ss[2]; k[v(48,(6*(i))+ 9)] = ss[3]; \ } AES_RETURN aes_xi(decrypt_key192)(const unsigned char *key, aes_decrypt_ctx cx[1]) { uint32_t ss[7]; #if defined( d_vars ) d_vars; #endif cx->ks[v(48,(0))] = ss[0] = word_in(key, 0); cx->ks[v(48,(1))] = ss[1] = word_in(key, 1); cx->ks[v(48,(2))] = ss[2] = word_in(key, 2); cx->ks[v(48,(3))] = ss[3] = word_in(key, 3); #ifdef DEC_KS_UNROLL cx->ks[v(48,(4))] = ff(ss[4] = word_in(key, 4)); cx->ks[v(48,(5))] = ff(ss[5] = word_in(key, 5)); kdf6(cx->ks, 0); kd6(cx->ks, 1); kd6(cx->ks, 2); kd6(cx->ks, 3); kd6(cx->ks, 4); kd6(cx->ks, 5); kd6(cx->ks, 6); kdl6(cx->ks, 7); #else cx->ks[v(48,(4))] = ss[4] = word_in(key, 4); cx->ks[v(48,(5))] = ss[5] = word_in(key, 5); { uint32_t i; for(i = 0; i < 7; ++i) k6e(cx->ks, i); k6ef(cx->ks, 7); #if !(DEC_ROUND == NO_TABLES) for(i = N_COLS; i < 12 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]); #endif } #endif cx->inf.l = 0; cx->inf.b[0] = 12 * 16; #ifdef USE_VIA_ACE_IF_PRESENT if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff; #endif return EXIT_SUCCESS; } #endif #if defined(AES_256) || defined( AES_VAR ) #define k8ef(k,i) \ { k[v(56,(8*(i))+ 8)] = ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; \ k[v(56,(8*(i))+ 9)] = ss[1] ^= ss[0]; \ k[v(56,(8*(i))+10)] = ss[2] ^= ss[1]; \ k[v(56,(8*(i))+11)] = ss[3] ^= ss[2]; \ } #define k8e(k,i) \ { k8ef(k,i); \ k[v(56,(8*(i))+12)] = ss[4] ^= ls_box(ss[3],0); \ k[v(56,(8*(i))+13)] = ss[5] ^= ss[4]; \ k[v(56,(8*(i))+14)] = ss[6] ^= ss[5]; \ k[v(56,(8*(i))+15)] = ss[7] ^= ss[6]; \ } #define kdf8(k,i) \ { ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ff(ss[0]); \ ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ff(ss[1]); \ ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ff(ss[2]); \ ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ff(ss[3]); \ ss[4] ^= ls_box(ss[3],0); k[v(56,(8*(i))+12)] = ff(ss[4]); \ ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ff(ss[5]); \ ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ff(ss[6]); \ ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ff(ss[7]); \ } #define kd8(k,i) \ { ss[8] = ls_box(ss[7],3) ^ t_use(r,c)[i]; \ ss[0] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+ 8)] = ss[8] ^= k[v(56,(8*(i)))]; \ ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[8] ^= k[v(56,(8*(i))+ 1)]; \ ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[8] ^= k[v(56,(8*(i))+ 2)]; \ ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[8] ^= k[v(56,(8*(i))+ 3)]; \ ss[8] = ls_box(ss[3],0); \ ss[4] ^= ss[8]; ss[8] = ff(ss[8]); k[v(56,(8*(i))+12)] = ss[8] ^= k[v(56,(8*(i))+ 4)]; \ ss[5] ^= ss[4]; k[v(56,(8*(i))+13)] = ss[8] ^= k[v(56,(8*(i))+ 5)]; \ ss[6] ^= ss[5]; k[v(56,(8*(i))+14)] = ss[8] ^= k[v(56,(8*(i))+ 6)]; \ ss[7] ^= ss[6]; k[v(56,(8*(i))+15)] = ss[8] ^= k[v(56,(8*(i))+ 7)]; \ } #define kdl8(k,i) \ { ss[0] ^= ls_box(ss[7],3) ^ t_use(r,c)[i]; k[v(56,(8*(i))+ 8)] = ss[0]; \ ss[1] ^= ss[0]; k[v(56,(8*(i))+ 9)] = ss[1]; \ ss[2] ^= ss[1]; k[v(56,(8*(i))+10)] = ss[2]; \ ss[3] ^= ss[2]; k[v(56,(8*(i))+11)] = ss[3]; \ } AES_RETURN aes_xi(decrypt_key256)(const unsigned char *key, aes_decrypt_ctx cx[1]) { uint32_t ss[9]; #if defined( d_vars ) d_vars; #endif cx->ks[v(56,(0))] = ss[0] = word_in(key, 0); cx->ks[v(56,(1))] = ss[1] = word_in(key, 1); cx->ks[v(56,(2))] = ss[2] = word_in(key, 2); cx->ks[v(56,(3))] = ss[3] = word_in(key, 3); #ifdef DEC_KS_UNROLL cx->ks[v(56,(4))] = ff(ss[4] = word_in(key, 4)); cx->ks[v(56,(5))] = ff(ss[5] = word_in(key, 5)); cx->ks[v(56,(6))] = ff(ss[6] = word_in(key, 6)); cx->ks[v(56,(7))] = ff(ss[7] = word_in(key, 7)); kdf8(cx->ks, 0); kd8(cx->ks, 1); kd8(cx->ks, 2); kd8(cx->ks, 3); kd8(cx->ks, 4); kd8(cx->ks, 5); kdl8(cx->ks, 6); #else cx->ks[v(56,(4))] = ss[4] = word_in(key, 4); cx->ks[v(56,(5))] = ss[5] = word_in(key, 5); cx->ks[v(56,(6))] = ss[6] = word_in(key, 6); cx->ks[v(56,(7))] = ss[7] = word_in(key, 7); { uint32_t i; for(i = 0; i < 6; ++i) k8e(cx->ks, i); k8ef(cx->ks, 6); #if !(DEC_ROUND == NO_TABLES) for(i = N_COLS; i < 14 * N_COLS; ++i) cx->ks[i] = inv_mcol(cx->ks[i]); #endif } #endif cx->inf.l = 0; cx->inf.b[0] = 14 * 16; #ifdef USE_VIA_ACE_IF_PRESENT if(VIA_ACE_AVAILABLE) cx->inf.b[1] = 0xff; #endif return EXIT_SUCCESS; } #endif #endif #if defined( AES_VAR ) AES_RETURN aes_encrypt_key(const unsigned char *key, int key_len, aes_encrypt_ctx cx[1]) { switch(key_len) { case 16: case 128: return aes_encrypt_key128(key, cx); case 24: case 192: return aes_encrypt_key192(key, cx); case 32: case 256: return aes_encrypt_key256(key, cx); default: return EXIT_FAILURE; } } AES_RETURN aes_decrypt_key(const unsigned char *key, int key_len, aes_decrypt_ctx cx[1]) { switch(key_len) { case 16: case 128: return aes_decrypt_key128(key, cx); case 24: case 192: return aes_decrypt_key192(key, cx); case 32: case 256: return aes_decrypt_key256(key, cx); default: return EXIT_FAILURE; } } #endif #if defined(__cplusplus) } #endif open-zwave-1.5/cpp/src/aes/aesopt.h000066400000000000000000000666751264474202400172700ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 This file contains the compilation options for AES (Rijndael) and code that is common across encryption, key scheduling and table generation. OPERATION These source code files implement the AES algorithm Rijndael designed by Joan Daemen and Vincent Rijmen. This version is designed for the standard block size of 16 bytes and for key sizes of 128, 192 and 256 bits (16, 24 and 32 bytes). This version is designed for flexibility and speed using operations on 32-bit words rather than operations on bytes. It can be compiled with either big or little endian internal byte order but is faster when the native byte order for the processor is used. THE CIPHER INTERFACE The cipher interface is implemented as an array of bytes in which lower AES bit sequence indexes map to higher numeric significance within bytes. uint8_t (an unsigned 8-bit type) uint32_t (an unsigned 32-bit type) struct aes_encrypt_ctx (structure for the cipher encryption context) struct aes_decrypt_ctx (structure for the cipher decryption context) AES_RETURN the function return type C subroutine calls: AES_RETURN aes_encrypt_key128(const unsigned char *key, aes_encrypt_ctx cx[1]); AES_RETURN aes_encrypt_key192(const unsigned char *key, aes_encrypt_ctx cx[1]); AES_RETURN aes_encrypt_key256(const unsigned char *key, aes_encrypt_ctx cx[1]); AES_RETURN aes_encrypt(const unsigned char *in, unsigned char *out, const aes_encrypt_ctx cx[1]); AES_RETURN aes_decrypt_key128(const unsigned char *key, aes_decrypt_ctx cx[1]); AES_RETURN aes_decrypt_key192(const unsigned char *key, aes_decrypt_ctx cx[1]); AES_RETURN aes_decrypt_key256(const unsigned char *key, aes_decrypt_ctx cx[1]); AES_RETURN aes_decrypt(const unsigned char *in, unsigned char *out, const aes_decrypt_ctx cx[1]); IMPORTANT NOTE: If you are using this C interface with dynamic tables make sure that you call aes_init() before AES is used so that the tables are initialised. C++ aes class subroutines: Class AESencrypt for encryption Construtors: AESencrypt(void) AESencrypt(const unsigned char *key) - 128 bit key Members: AES_RETURN key128(const unsigned char *key) AES_RETURN key192(const unsigned char *key) AES_RETURN key256(const unsigned char *key) AES_RETURN encrypt(const unsigned char *in, unsigned char *out) const Class AESdecrypt for encryption Construtors: AESdecrypt(void) AESdecrypt(const unsigned char *key) - 128 bit key Members: AES_RETURN key128(const unsigned char *key) AES_RETURN key192(const unsigned char *key) AES_RETURN key256(const unsigned char *key) AES_RETURN decrypt(const unsigned char *in, unsigned char *out) const */ #if !defined( _AESOPT_H ) #define _AESOPT_H #if defined( __cplusplus ) #include "aescpp.h" #else #include "aes.h" #endif /* PLATFORM SPECIFIC INCLUDES */ #include "brg_endian.h" /* CONFIGURATION - THE USE OF DEFINES Later in this section there are a number of defines that control the operation of the code. In each section, the purpose of each define is explained so that the relevant form can be included or excluded by setting either 1's or 0's respectively on the branches of the related #if clauses. The following local defines should not be changed. */ #define ENCRYPTION_IN_C 1 #define DECRYPTION_IN_C 2 #define ENC_KEYING_IN_C 4 #define DEC_KEYING_IN_C 8 #define NO_TABLES 0 #define ONE_TABLE 1 #define FOUR_TABLES 4 #define NONE 0 #define PARTIAL 1 #define FULL 2 /* --- START OF USER CONFIGURED OPTIONS --- */ /* 1. BYTE ORDER WITHIN 32 BIT WORDS The fundamental data processing units in Rijndael are 8-bit bytes. The input, output and key input are all enumerated arrays of bytes in which bytes are numbered starting at zero and increasing to one less than the number of bytes in the array in question. This enumeration is only used for naming bytes and does not imply any adjacency or order relationship from one byte to another. When these inputs and outputs are considered as bit sequences, bits 8*n to 8*n+7 of the bit sequence are mapped to byte[n] with bit 8n+i in the sequence mapped to bit 7-i within the byte. In this implementation bits are numbered from 0 to 7 starting at the numerically least significant end of each byte (bit n represents 2^n). However, Rijndael can be implemented more efficiently using 32-bit words by packing bytes into words so that bytes 4*n to 4*n+3 are placed into word[n]. While in principle these bytes can be assembled into words in any positions, this implementation only supports the two formats in which bytes in adjacent positions within words also have adjacent byte numbers. This order is called big-endian if the lowest numbered bytes in words have the highest numeric significance and little-endian if the opposite applies. This code can work in either order irrespective of the order used by the machine on which it runs. Normally the internal byte order will be set to the order of the processor on which the code is to be run but this define can be used to reverse this in special situations WARNING: Assembler code versions rely on PLATFORM_BYTE_ORDER being set. This define will hence be redefined later (in section 4) if necessary */ #if 1 # define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER #elif 0 # define ALGORITHM_BYTE_ORDER IS_LITTLE_ENDIAN #elif 0 # define ALGORITHM_BYTE_ORDER IS_BIG_ENDIAN #else # error The algorithm byte order is not defined #endif /* 2. Intel AES AND VIA ACE SUPPORT */ #if defined( __GNUC__ ) && defined( __i386__ ) \ || defined(_WIN32) && defined(_M_IX86) \ && !(defined(_WIN64) || defined(_WIN32_WCE) || defined(_MSC_VER) && (_MSC_VER <= 800)) # define VIA_ACE_POSSIBLE #endif /* Define this option if support for the Intel AESNI is required (not currently available with GCC). If AESNI is known to be present, then defining ASSUME_INTEL_AES_VIA_PRESENT will replace the ordinary encryption/decryption. If USE_INTEL_AES_IF_PRESENT is defined then AESNI will be used if it is detected (both present and enabled). AESNI uses a decryption key schedule with the first decryption round key at the high end of the key scedule with the following round keys at lower positions in memory. So AES_REV_DKS must NOT be defined when AESNI will be used. ALthough it is unlikely that assembler code will be used with an AESNI build, if it is then AES_REV_DKS must NOT be defined when such assembler files are built */ #if 0 && defined( _WIN64 ) && defined( _MSC_VER ) # define INTEL_AES_POSSIBLE #endif #if defined( INTEL_AES_POSSIBLE ) && !defined( USE_INTEL_AES_IF_PRESENT ) # define USE_INTEL_AES_IF_PRESENT #endif /* Define this option if support for the VIA ACE is required. This uses inline assembler instructions and is only implemented for the Microsoft, Intel and GCC compilers. If VIA ACE is known to be present, then defining ASSUME_VIA_ACE_PRESENT will remove the ordinary encryption/decryption code. If USE_VIA_ACE_IF_PRESENT is defined then VIA ACE will be used if it is detected (both present and enabled) but the normal AES code will also be present. When VIA ACE is to be used, all AES encryption contexts MUST be 16 byte aligned; other input/output buffers do not need to be 16 byte aligned but there are very large performance gains if this can be arranged. VIA ACE also requires the decryption key schedule to be in reverse order (which later checks below ensure). AES_REV_DKS must be set for assembler code used with a VIA ACE build */ #if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( USE_VIA_ACE_IF_PRESENT ) # define USE_VIA_ACE_IF_PRESENT #endif #if 0 && defined( VIA_ACE_POSSIBLE ) && !defined( ASSUME_VIA_ACE_PRESENT ) # define ASSUME_VIA_ACE_PRESENT # endif /* 3. ASSEMBLER SUPPORT This define (which can be on the command line) enables the use of the assembler code routines for encryption, decryption and key scheduling as follows: ASM_X86_V1C uses the assembler (aes_x86_v1.asm) with large tables for encryption and decryption and but with key scheduling in C ASM_X86_V2 uses assembler (aes_x86_v2.asm) with compressed tables for encryption, decryption and key scheduling ASM_X86_V2C uses assembler (aes_x86_v2.asm) with compressed tables for encryption and decryption and but with key scheduling in C ASM_AMD64_C uses assembler (aes_amd64.asm) with compressed tables for encryption and decryption and but with key scheduling in C Change one 'if 0' below to 'if 1' to select the version or define as a compilation option. */ #if 0 && !defined( ASM_X86_V1C ) # define ASM_X86_V1C #elif 0 && !defined( ASM_X86_V2 ) # define ASM_X86_V2 #elif 0 && !defined( ASM_X86_V2C ) # define ASM_X86_V2C #elif 0 && !defined( ASM_AMD64_C ) # define ASM_AMD64_C #endif #if (defined ( ASM_X86_V1C ) || defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) \ && !defined( _M_IX86 ) || defined( ASM_AMD64_C ) && !defined( _M_X64 ) # error Assembler code is only available for x86 and AMD64 systems #endif /* 4. FAST INPUT/OUTPUT OPERATIONS. On some machines it is possible to improve speed by transferring the bytes in the input and output arrays to and from the internal 32-bit variables by addressing these arrays as if they are arrays of 32-bit words. On some machines this will always be possible but there may be a large performance penalty if the byte arrays are not aligned on the normal word boundaries. On other machines this technique will lead to memory access errors when such 32-bit word accesses are not properly aligned. The option SAFE_IO avoids such problems but will often be slower on those machines that support misaligned access (especially so if care is taken to align the input and output byte arrays on 32-bit word boundaries). If SAFE_IO is not defined it is assumed that access to byte arrays as if they are arrays of 32-bit words will not cause problems when such accesses are misaligned. */ #if 1 && !defined( _MSC_VER ) # define SAFE_IO #endif /* 5. LOOP UNROLLING The code for encryption and decrytpion cycles through a number of rounds that can be implemented either in a loop or by expanding the code into a long sequence of instructions, the latter producing a larger program but one that will often be much faster. The latter is called loop unrolling. There are also potential speed advantages in expanding two iterations in a loop with half the number of iterations, which is called partial loop unrolling. The following options allow partial or full loop unrolling to be set independently for encryption and decryption */ #if 1 # define ENC_UNROLL FULL #elif 0 # define ENC_UNROLL PARTIAL #else # define ENC_UNROLL NONE #endif #if 1 # define DEC_UNROLL FULL #elif 0 # define DEC_UNROLL PARTIAL #else # define DEC_UNROLL NONE #endif #if 1 # define ENC_KS_UNROLL #endif #if 1 # define DEC_KS_UNROLL #endif /* 6. FAST FINITE FIELD OPERATIONS If this section is included, tables are used to provide faster finite field arithmetic (this has no effect if FIXED_TABLES is defined). */ #if 1 # define FF_TABLES #endif /* 7. INTERNAL STATE VARIABLE FORMAT The internal state of Rijndael is stored in a number of local 32-bit word varaibles which can be defined either as an array or as individual names variables. Include this section if you want to store these local varaibles in arrays. Otherwise individual local variables will be used. */ #if 1 # define ARRAYS #endif /* 8. FIXED OR DYNAMIC TABLES When this section is included the tables used by the code are compiled statically into the binary file. Otherwise the subroutine aes_init() must be called to compute them before the code is first used. */ #if 1 && !(defined( _MSC_VER ) && ( _MSC_VER <= 800 )) # define FIXED_TABLES #endif /* 9. MASKING OR CASTING FROM LONGER VALUES TO BYTES In some systems it is better to mask longer values to extract bytes rather than using a cast. This option allows this choice. */ #if 0 # define to_byte(x) ((uint8_t)(x)) #else # define to_byte(x) ((x) & 0xff) #endif /* 10. TABLE ALIGNMENT On some sytsems speed will be improved by aligning the AES large lookup tables on particular boundaries. This define should be set to a power of two giving the desired alignment. It can be left undefined if alignment is not needed. This option is specific to the Microsft VC++ compiler - it seems to sometimes cause trouble for the VC++ version 6 compiler. */ #if 1 && defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) # define TABLE_ALIGN 32 #endif /* 11. REDUCE CODE AND TABLE SIZE This replaces some expanded macros with function calls if AES_ASM_V2 or AES_ASM_V2C are defined */ #if 0 && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C )) # define REDUCE_CODE_SIZE #endif /* 12. TABLE OPTIONS This cipher proceeds by repeating in a number of cycles known as 'rounds' which are implemented by a round function which can optionally be speeded up using tables. The basic tables are each 256 32-bit words, with either one or four tables being required for each round function depending on how much speed is required. The encryption and decryption round functions are different and the last encryption and decrytpion round functions are different again making four different round functions in all. This means that: 1. Normal encryption and decryption rounds can each use either 0, 1 or 4 tables and table spaces of 0, 1024 or 4096 bytes each. 2. The last encryption and decryption rounds can also use either 0, 1 or 4 tables and table spaces of 0, 1024 or 4096 bytes each. Include or exclude the appropriate definitions below to set the number of tables used by this implementation. */ #if 1 /* set tables for the normal encryption round */ # define ENC_ROUND FOUR_TABLES #elif 0 # define ENC_ROUND ONE_TABLE #else # define ENC_ROUND NO_TABLES #endif #if 1 /* set tables for the last encryption round */ # define LAST_ENC_ROUND FOUR_TABLES #elif 0 # define LAST_ENC_ROUND ONE_TABLE #else # define LAST_ENC_ROUND NO_TABLES #endif #if 1 /* set tables for the normal decryption round */ # define DEC_ROUND FOUR_TABLES #elif 0 # define DEC_ROUND ONE_TABLE #else # define DEC_ROUND NO_TABLES #endif #if 1 /* set tables for the last decryption round */ # define LAST_DEC_ROUND FOUR_TABLES #elif 0 # define LAST_DEC_ROUND ONE_TABLE #else # define LAST_DEC_ROUND NO_TABLES #endif /* The decryption key schedule can be speeded up with tables in the same way that the round functions can. Include or exclude the following defines to set this requirement. */ #if 1 # define KEY_SCHED FOUR_TABLES #elif 0 # define KEY_SCHED ONE_TABLE #else # define KEY_SCHED NO_TABLES #endif /* ---- END OF USER CONFIGURED OPTIONS ---- */ /* VIA ACE support is only available for VC++ and GCC */ #if !defined( _MSC_VER ) && !defined( __GNUC__ ) # if defined( ASSUME_VIA_ACE_PRESENT ) # undef ASSUME_VIA_ACE_PRESENT # endif # if defined( USE_VIA_ACE_IF_PRESENT ) # undef USE_VIA_ACE_IF_PRESENT # endif #endif #if defined( ASSUME_VIA_ACE_PRESENT ) && !defined( USE_VIA_ACE_IF_PRESENT ) # define USE_VIA_ACE_IF_PRESENT #endif /* define to reverse decryption key schedule */ #if 1 || defined( USE_VIA_ACE_IF_PRESENT ) && !defined ( AES_REV_DKS ) # define AES_REV_DKS #endif /* Intel AESNI uses a decryption key schedule in the encryption order */ #if defined( USE_INTEL_AES_IF_PRESENT ) && defined ( AES_REV_DKS ) # undef AES_REV_DKS #endif /* Assembler support requires the use of platform byte order */ #if ( defined( ASM_X86_V1C ) || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) ) \ && (ALGORITHM_BYTE_ORDER != PLATFORM_BYTE_ORDER) # undef ALGORITHM_BYTE_ORDER # define ALGORITHM_BYTE_ORDER PLATFORM_BYTE_ORDER #endif /* In this implementation the columns of the state array are each held in 32-bit words. The state array can be held in various ways: in an array of words, in a number of individual word variables or in a number of processor registers. The following define maps a variable name x and a column number c to the way the state array variable is to be held. The first define below maps the state into an array x[c] whereas the second form maps the state into a number of individual variables x0, x1, etc. Another form could map individual state colums to machine register names. */ #if defined( ARRAYS ) # define s(x,c) x[c] #else # define s(x,c) x##c #endif /* This implementation provides subroutines for encryption, decryption and for setting the three key lengths (separately) for encryption and decryption. Since not all functions are needed, masks are set up here to determine which will be implemented in C */ #if !defined( AES_ENCRYPT ) # define EFUNCS_IN_C 0 #elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) # define EFUNCS_IN_C ENC_KEYING_IN_C #elif !defined( ASM_X86_V2 ) # define EFUNCS_IN_C ( ENCRYPTION_IN_C | ENC_KEYING_IN_C ) #else # define EFUNCS_IN_C 0 #endif #if !defined( AES_DECRYPT ) # define DFUNCS_IN_C 0 #elif defined( ASSUME_VIA_ACE_PRESENT ) || defined( ASM_X86_V1C ) \ || defined( ASM_X86_V2C ) || defined( ASM_AMD64_C ) # define DFUNCS_IN_C DEC_KEYING_IN_C #elif !defined( ASM_X86_V2 ) # define DFUNCS_IN_C ( DECRYPTION_IN_C | DEC_KEYING_IN_C ) #else # define DFUNCS_IN_C 0 #endif #define FUNCS_IN_C ( EFUNCS_IN_C | DFUNCS_IN_C ) /* END OF CONFIGURATION OPTIONS */ #define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2)) /* Disable or report errors on some combinations of options */ #if ENC_ROUND == NO_TABLES && LAST_ENC_ROUND != NO_TABLES # undef LAST_ENC_ROUND # define LAST_ENC_ROUND NO_TABLES #elif ENC_ROUND == ONE_TABLE && LAST_ENC_ROUND == FOUR_TABLES # undef LAST_ENC_ROUND # define LAST_ENC_ROUND ONE_TABLE #endif #if ENC_ROUND == NO_TABLES && ENC_UNROLL != NONE # undef ENC_UNROLL # define ENC_UNROLL NONE #endif #if DEC_ROUND == NO_TABLES && LAST_DEC_ROUND != NO_TABLES # undef LAST_DEC_ROUND # define LAST_DEC_ROUND NO_TABLES #elif DEC_ROUND == ONE_TABLE && LAST_DEC_ROUND == FOUR_TABLES # undef LAST_DEC_ROUND # define LAST_DEC_ROUND ONE_TABLE #endif #if DEC_ROUND == NO_TABLES && DEC_UNROLL != NONE # undef DEC_UNROLL # define DEC_UNROLL NONE #endif #if defined( bswap32 ) # define aes_sw32 bswap32 #elif defined( bswap_32 ) # define aes_sw32 bswap_32 #else # define brot(x,n) (((uint32_t)(x) << n) | ((uint32_t)(x) >> (32 - n))) # define aes_sw32(x) ((brot((x),8) & 0x00ff00ff) | (brot((x),24) & 0xff00ff00)) #endif /* upr(x,n): rotates bytes within words by n positions, moving bytes to higher index positions with wrap around into low positions ups(x,n): moves bytes by n positions to higher index positions in words but without wrap around bval(x,n): extracts a byte from a word WARNING: The definitions given here are intended only for use with unsigned variables and with shift counts that are compile time constants */ #if ( ALGORITHM_BYTE_ORDER == IS_LITTLE_ENDIAN ) # define upr(x,n) (((uint32_t)(x) << (8 * (n))) | ((uint32_t)(x) >> (32 - 8 * (n)))) # define ups(x,n) ((uint32_t) (x) << (8 * (n))) # define bval(x,n) to_byte((x) >> (8 * (n))) # define bytes2word(b0, b1, b2, b3) \ (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0)) #endif #if ( ALGORITHM_BYTE_ORDER == IS_BIG_ENDIAN ) # define upr(x,n) (((uint32_t)(x) >> (8 * (n))) | ((uint32_t)(x) << (32 - 8 * (n)))) # define ups(x,n) ((uint32_t) (x) >> (8 * (n))) # define bval(x,n) to_byte((x) >> (24 - 8 * (n))) # define bytes2word(b0, b1, b2, b3) \ (((uint32_t)(b0) << 24) | ((uint32_t)(b1) << 16) | ((uint32_t)(b2) << 8) | (b3)) #endif #if defined( SAFE_IO ) # define word_in(x,c) bytes2word(((const uint8_t*)(x)+4*c)[0], ((const uint8_t*)(x)+4*c)[1], \ ((const uint8_t*)(x)+4*c)[2], ((const uint8_t*)(x)+4*c)[3]) # define word_out(x,c,v) { ((uint8_t*)(x)+4*c)[0] = bval(v,0); ((uint8_t*)(x)+4*c)[1] = bval(v,1); \ ((uint8_t*)(x)+4*c)[2] = bval(v,2); ((uint8_t*)(x)+4*c)[3] = bval(v,3); } #elif ( ALGORITHM_BYTE_ORDER == PLATFORM_BYTE_ORDER ) # define word_in(x,c) (*((uint32_t*)(x)+(c))) # define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = (v)) #else # define word_in(x,c) aes_sw32(*((uint32_t*)(x)+(c))) # define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = aes_sw32(v)) #endif /* the finite field modular polynomial and elements */ #define WPOLY 0x011b #define BPOLY 0x1b /* multiply four bytes in GF(2^8) by 'x' {02} in parallel */ #define gf_c1 0x80808080 #define gf_c2 0x7f7f7f7f #define gf_mulx(x) ((((x) & gf_c2) << 1) ^ ((((x) & gf_c1) >> 7) * BPOLY)) /* The following defines provide alternative definitions of gf_mulx that might give improved performance if a fast 32-bit multiply is not available. Note that a temporary variable u needs to be defined where gf_mulx is used. #define gf_mulx(x) (u = (x) & gf_c1, u |= (u >> 1), ((x) & gf_c2) << 1) ^ ((u >> 3) | (u >> 6)) #define gf_c4 (0x01010101 * BPOLY) #define gf_mulx(x) (u = (x) & gf_c1, ((x) & gf_c2) << 1) ^ ((u - (u >> 7)) & gf_c4) */ /* Work out which tables are needed for the different options */ #if defined( ASM_X86_V1C ) # if defined( ENC_ROUND ) # undef ENC_ROUND # endif # define ENC_ROUND FOUR_TABLES # if defined( LAST_ENC_ROUND ) # undef LAST_ENC_ROUND # endif # define LAST_ENC_ROUND FOUR_TABLES # if defined( DEC_ROUND ) # undef DEC_ROUND # endif # define DEC_ROUND FOUR_TABLES # if defined( LAST_DEC_ROUND ) # undef LAST_DEC_ROUND # endif # define LAST_DEC_ROUND FOUR_TABLES # if defined( KEY_SCHED ) # undef KEY_SCHED # define KEY_SCHED FOUR_TABLES # endif #endif #if ( FUNCS_IN_C & ENCRYPTION_IN_C ) || defined( ASM_X86_V1C ) # if ENC_ROUND == ONE_TABLE # define FT1_SET # elif ENC_ROUND == FOUR_TABLES # define FT4_SET # else # define SBX_SET # endif # if LAST_ENC_ROUND == ONE_TABLE # define FL1_SET # elif LAST_ENC_ROUND == FOUR_TABLES # define FL4_SET # elif !defined( SBX_SET ) # define SBX_SET # endif #endif #if ( FUNCS_IN_C & DECRYPTION_IN_C ) || defined( ASM_X86_V1C ) # if DEC_ROUND == ONE_TABLE # define IT1_SET # elif DEC_ROUND == FOUR_TABLES # define IT4_SET # else # define ISB_SET # endif # if LAST_DEC_ROUND == ONE_TABLE # define IL1_SET # elif LAST_DEC_ROUND == FOUR_TABLES # define IL4_SET # elif !defined(ISB_SET) # define ISB_SET # endif #endif #if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) # if ((FUNCS_IN_C & ENC_KEYING_IN_C) || (FUNCS_IN_C & DEC_KEYING_IN_C)) # if KEY_SCHED == ONE_TABLE # if !defined( FL1_SET ) && !defined( FL4_SET ) # define LS1_SET # endif # elif KEY_SCHED == FOUR_TABLES # if !defined( FL4_SET ) # define LS4_SET # endif # elif !defined( SBX_SET ) # define SBX_SET # endif # endif # if (FUNCS_IN_C & DEC_KEYING_IN_C) # if KEY_SCHED == ONE_TABLE # define IM1_SET # elif KEY_SCHED == FOUR_TABLES # define IM4_SET # elif !defined( SBX_SET ) # define SBX_SET # endif # endif #endif /* generic definitions of Rijndael macros that use tables */ #define no_table(x,box,vf,rf,c) bytes2word( \ box[bval(vf(x,0,c),rf(0,c))], \ box[bval(vf(x,1,c),rf(1,c))], \ box[bval(vf(x,2,c),rf(2,c))], \ box[bval(vf(x,3,c),rf(3,c))]) #define one_table(x,op,tab,vf,rf,c) \ ( tab[bval(vf(x,0,c),rf(0,c))] \ ^ op(tab[bval(vf(x,1,c),rf(1,c))],1) \ ^ op(tab[bval(vf(x,2,c),rf(2,c))],2) \ ^ op(tab[bval(vf(x,3,c),rf(3,c))],3)) #define four_tables(x,tab,vf,rf,c) \ ( tab[0][bval(vf(x,0,c),rf(0,c))] \ ^ tab[1][bval(vf(x,1,c),rf(1,c))] \ ^ tab[2][bval(vf(x,2,c),rf(2,c))] \ ^ tab[3][bval(vf(x,3,c),rf(3,c))]) #define vf1(x,r,c) (x) #define rf1(r,c) (r) #define rf2(r,c) ((8+r-c)&3) /* perform forward and inverse column mix operation on four bytes in long word x in */ /* parallel. NOTE: x must be a simple variable, NOT an expression in these macros. */ #if !(defined( REDUCE_CODE_SIZE ) && (defined( ASM_X86_V2 ) || defined( ASM_X86_V2C ))) #if defined( FM4_SET ) /* not currently used */ # define fwd_mcol(x) four_tables(x,t_use(f,m),vf1,rf1,0) #elif defined( FM1_SET ) /* not currently used */ # define fwd_mcol(x) one_table(x,upr,t_use(f,m),vf1,rf1,0) #else # define dec_fmvars uint32_t g2 # define fwd_mcol(x) (g2 = gf_mulx(x), g2 ^ upr((x) ^ g2, 3) ^ upr((x), 2) ^ upr((x), 1)) #endif #if defined( IM4_SET ) # define inv_mcol(x) four_tables(x,t_use(i,m),vf1,rf1,0) #elif defined( IM1_SET ) # define inv_mcol(x) one_table(x,upr,t_use(i,m),vf1,rf1,0) #else # define dec_imvars uint32_t g2, g4, g9 # define inv_mcol(x) (g2 = gf_mulx(x), g4 = gf_mulx(g2), g9 = (x) ^ gf_mulx(g4), g4 ^= g9, \ (x) ^ g2 ^ g4 ^ upr(g2 ^ g9, 3) ^ upr(g4, 2) ^ upr(g9, 1)) #endif #if defined( FL4_SET ) # define ls_box(x,c) four_tables(x,t_use(f,l),vf1,rf2,c) #elif defined( LS4_SET ) # define ls_box(x,c) four_tables(x,t_use(l,s),vf1,rf2,c) #elif defined( FL1_SET ) # define ls_box(x,c) one_table(x,upr,t_use(f,l),vf1,rf2,c) #elif defined( LS1_SET ) # define ls_box(x,c) one_table(x,upr,t_use(l,s),vf1,rf2,c) #else # define ls_box(x,c) no_table(x,t_use(s,box),vf1,rf2,c) #endif #endif #if defined( ASM_X86_V1C ) && defined( AES_DECRYPT ) && !defined( ISB_SET ) # define ISB_SET #endif #endif open-zwave-1.5/cpp/src/aes/aestab.c000066400000000000000000000364211264474202400172110ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 */ #define DO_TABLES #include "aes.h" #include "aesopt.h" #if defined(FIXED_TABLES) #define sb_data(w) {\ w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } #define isb_data(w) {\ w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } #define mm_data(w) {\ w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } #define rc_data(w) {\ w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\ w(0x1b), w(0x36) } #define h0(x) (x) #define w0(p) bytes2word(p, 0, 0, 0) #define w1(p) bytes2word(0, p, 0, 0) #define w2(p) bytes2word(0, 0, p, 0) #define w3(p) bytes2word(0, 0, 0, p) #define u0(p) bytes2word(f2(p), p, p, f3(p)) #define u1(p) bytes2word(f3(p), f2(p), p, p) #define u2(p) bytes2word(p, f3(p), f2(p), p) #define u3(p) bytes2word(p, p, f3(p), f2(p)) #define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p)) #define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p)) #define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p)) #define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p)) #endif #if defined(FIXED_TABLES) || !defined(FF_TABLES) #define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY)) #define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY)) #define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) \ ^ (((x>>5) & 4) * WPOLY)) #define f3(x) (f2(x) ^ x) #define f9(x) (f8(x) ^ x) #define fb(x) (f8(x) ^ f2(x) ^ x) #define fd(x) (f8(x) ^ f4(x) ^ x) #define fe(x) (f8(x) ^ f4(x) ^ f2(x)) #else #define f2(x) ((x) ? pow[log[x] + 0x19] : 0) #define f3(x) ((x) ? pow[log[x] + 0x01] : 0) #define f9(x) ((x) ? pow[log[x] + 0xc7] : 0) #define fb(x) ((x) ? pow[log[x] + 0x68] : 0) #define fd(x) ((x) ? pow[log[x] + 0xee] : 0) #define fe(x) ((x) ? pow[log[x] + 0xdf] : 0) #endif #include "aestab.h" #if defined(__cplusplus) extern "C" { #endif #if defined(FIXED_TABLES) /* implemented in case of wrong call for fixed tables */ AES_RETURN aes_init(void) { return EXIT_SUCCESS; } #else /* Generate the tables for the dynamic table option */ #if defined(FF_TABLES) #define gf_inv(x) ((x) ? pow[ 255 - log[x]] : 0) #else /* It will generally be sensible to use tables to compute finite field multiplies and inverses but where memory is scarse this code might sometimes be better. But it only has effect during initialisation so its pretty unimportant in overall terms. */ /* return 2 ^ (n - 1) where n is the bit number of the highest bit set in x with x in the range 1 < x < 0x00000200. This form is used so that locals within fi can be bytes rather than words */ static uint8_t hibit(const uint32_t x) { uint8_t r = (uint8_t)((x >> 1) | (x >> 2)); r |= (r >> 2); r |= (r >> 4); return (r + 1) >> 1; } /* return the inverse of the finite field element x */ static uint8_t gf_inv(const uint8_t x) { uint8_t p1 = x, p2 = BPOLY, n1 = hibit(x), n2 = 0x80, v1 = 1, v2 = 0; if(x < 2) return x; for( ; ; ) { if(n1) while(n2 >= n1) /* divide polynomial p2 by p1 */ { n2 /= n1; /* shift smaller polynomial left */ p2 ^= (p1 * n2) & 0xff; /* and remove from larger one */ v2 ^= v1 * n2; /* shift accumulated value and */ n2 = hibit(p2); /* add into result */ } else return v1; if(n2) /* repeat with values swapped */ while(n1 >= n2) { n1 /= n2; p1 ^= p2 * n1; v1 ^= v2 * n1; n1 = hibit(p1); } else return v2; } } #endif /* The forward and inverse affine transformations used in the S-box */ uint8_t fwd_affine(const uint8_t x) { uint32_t w = x; w ^= (w << 1) ^ (w << 2) ^ (w << 3) ^ (w << 4); return 0x63 ^ ((w ^ (w >> 8)) & 0xff); } uint8_t inv_affine(const uint8_t x) { uint32_t w = x; w = (w << 1) ^ (w << 3) ^ (w << 6); return 0x05 ^ ((w ^ (w >> 8)) & 0xff); } static int init = 0; AES_RETURN aes_init(void) { uint32_t i, w; #if defined(FF_TABLES) uint8_t pow[512], log[256]; if(init) return EXIT_SUCCESS; /* log and power tables for GF(2^8) finite field with WPOLY as modular polynomial - the simplest primitive root is 0x03, used here to generate the tables */ i = 0; w = 1; do { pow[i] = (uint8_t)w; pow[i + 255] = (uint8_t)w; log[w] = (uint8_t)i++; w ^= (w << 1) ^ (w & 0x80 ? WPOLY : 0); } while (w != 1); #else if(init) return EXIT_SUCCESS; #endif for(i = 0, w = 1; i < RC_LENGTH; ++i) { t_set(r,c)[i] = bytes2word(w, 0, 0, 0); w = f2(w); } for(i = 0; i < 256; ++i) { uint8_t b; b = fwd_affine(gf_inv((uint8_t)i)); w = bytes2word(f2(b), b, b, f3(b)); #if defined( SBX_SET ) t_set(s,box)[i] = b; #endif #if defined( FT1_SET ) /* tables for a normal encryption round */ t_set(f,n)[i] = w; #endif #if defined( FT4_SET ) t_set(f,n)[0][i] = w; t_set(f,n)[1][i] = upr(w,1); t_set(f,n)[2][i] = upr(w,2); t_set(f,n)[3][i] = upr(w,3); #endif w = bytes2word(b, 0, 0, 0); #if defined( FL1_SET ) /* tables for last encryption round (may also */ t_set(f,l)[i] = w; /* be used in the key schedule) */ #endif #if defined( FL4_SET ) t_set(f,l)[0][i] = w; t_set(f,l)[1][i] = upr(w,1); t_set(f,l)[2][i] = upr(w,2); t_set(f,l)[3][i] = upr(w,3); #endif #if defined( LS1_SET ) /* table for key schedule if t_set(f,l) above is*/ t_set(l,s)[i] = w; /* not of the required form */ #endif #if defined( LS4_SET ) t_set(l,s)[0][i] = w; t_set(l,s)[1][i] = upr(w,1); t_set(l,s)[2][i] = upr(w,2); t_set(l,s)[3][i] = upr(w,3); #endif b = gf_inv(inv_affine((uint8_t)i)); w = bytes2word(fe(b), f9(b), fd(b), fb(b)); #if defined( IM1_SET ) /* tables for the inverse mix column operation */ t_set(i,m)[b] = w; #endif #if defined( IM4_SET ) t_set(i,m)[0][b] = w; t_set(i,m)[1][b] = upr(w,1); t_set(i,m)[2][b] = upr(w,2); t_set(i,m)[3][b] = upr(w,3); #endif #if defined( ISB_SET ) t_set(i,box)[i] = b; #endif #if defined( IT1_SET ) /* tables for a normal decryption round */ t_set(i,n)[i] = w; #endif #if defined( IT4_SET ) t_set(i,n)[0][i] = w; t_set(i,n)[1][i] = upr(w,1); t_set(i,n)[2][i] = upr(w,2); t_set(i,n)[3][i] = upr(w,3); #endif w = bytes2word(b, 0, 0, 0); #if defined( IL1_SET ) /* tables for last decryption round */ t_set(i,l)[i] = w; #endif #if defined( IL4_SET ) t_set(i,l)[0][i] = w; t_set(i,l)[1][i] = upr(w,1); t_set(i,l)[2][i] = upr(w,2); t_set(i,l)[3][i] = upr(w,3); #endif } init = 1; return EXIT_SUCCESS; } #endif #if defined(__cplusplus) } #endif open-zwave-1.5/cpp/src/aes/aestab.h000066400000000000000000000123241264474202400172120ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 This file contains the code for declaring the tables needed to implement AES. The file aesopt.h is assumed to be included before this header file. If there are no global variables, the definitions here can be used to put the AES tables in a structure so that a pointer can then be added to the AES context to pass them to the AES routines that need them. If this facility is used, the calling program has to ensure that this pointer is managed appropriately. In particular, the value of the t_dec(in,it) item in the table structure must be set to zero in order to ensure that the tables are initialised. In practice the three code sequences in aeskey.c that control the calls to aes_init() and the aes_init() routine itself will have to be changed for a specific implementation. If global variables are available it will generally be preferable to use them with the precomputed FIXED_TABLES option that uses static global tables. The following defines can be used to control the way the tables are defined, initialised and used in embedded environments that require special features for these purposes the 't_dec' construction is used to declare fixed table arrays the 't_set' construction is used to set fixed table values the 't_use' construction is used to access fixed table values 256 byte tables: t_xxx(s,box) => forward S box t_xxx(i,box) => inverse S box 256 32-bit word OR 4 x 256 32-bit word tables: t_xxx(f,n) => forward normal round t_xxx(f,l) => forward last round t_xxx(i,n) => inverse normal round t_xxx(i,l) => inverse last round t_xxx(l,s) => key schedule table t_xxx(i,m) => key schedule table Other variables and tables: t_xxx(r,c) => the rcon table */ #if !defined( _AESTAB_H ) #define _AESTAB_H #if defined(__cplusplus) extern "C" { #endif #define t_dec(m,n) t_##m##n #define t_set(m,n) t_##m##n #define t_use(m,n) t_##m##n #if defined(FIXED_TABLES) # if !defined( __GNUC__ ) && (defined( __MSDOS__ ) || defined( __WIN16__ )) /* make tables far data to avoid using too much DGROUP space (PG) */ # define CONST const far # else # define CONST const # endif #else # define CONST #endif #if defined(DO_TABLES) # define EXTERN #else # define EXTERN extern #endif #if defined(_MSC_VER) && defined(TABLE_ALIGN) #define ALIGN __declspec(align(TABLE_ALIGN)) #else #define ALIGN #endif #if defined( __WATCOMC__ ) && ( __WATCOMC__ >= 1100 ) # define XP_DIR __cdecl #else # define XP_DIR #endif #if defined(DO_TABLES) && defined(FIXED_TABLES) #define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] = b(e) #define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] = { b(e), b(f), b(g), b(h) } EXTERN ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH] = rc_data(w0); #else #define d_1(t,n,b,e) EXTERN ALIGN CONST XP_DIR t n[256] #define d_4(t,n,b,e,f,g,h) EXTERN ALIGN CONST XP_DIR t n[4][256] EXTERN ALIGN CONST uint32_t t_dec(r,c)[RC_LENGTH]; #endif #if defined( SBX_SET ) d_1(uint8_t, t_dec(s,box), sb_data, h0); #endif #if defined( ISB_SET ) d_1(uint8_t, t_dec(i,box), isb_data, h0); #endif #if defined( FT1_SET ) d_1(uint32_t, t_dec(f,n), sb_data, u0); #endif #if defined( FT4_SET ) d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3); #endif #if defined( FL1_SET ) d_1(uint32_t, t_dec(f,l), sb_data, w0); #endif #if defined( FL4_SET ) d_4(uint32_t, t_dec(f,l), sb_data, w0, w1, w2, w3); #endif #if defined( IT1_SET ) d_1(uint32_t, t_dec(i,n), isb_data, v0); #endif #if defined( IT4_SET ) d_4(uint32_t, t_dec(i,n), isb_data, v0, v1, v2, v3); #endif #if defined( IL1_SET ) d_1(uint32_t, t_dec(i,l), isb_data, w0); #endif #if defined( IL4_SET ) d_4(uint32_t, t_dec(i,l), isb_data, w0, w1, w2, w3); #endif #if defined( LS1_SET ) #if defined( FL1_SET ) #undef LS1_SET #else d_1(uint32_t, t_dec(l,s), sb_data, w0); #endif #endif #if defined( LS4_SET ) #if defined( FL4_SET ) #undef LS4_SET #else d_4(uint32_t, t_dec(l,s), sb_data, w0, w1, w2, w3); #endif #endif #if defined( IM1_SET ) d_1(uint32_t, t_dec(i,m), mm_data, v0); #endif #if defined( IM4_SET ) d_4(uint32_t, t_dec(i,m), mm_data, v0, v1, v2, v3); #endif #if defined(__cplusplus) } #endif #endif open-zwave-1.5/cpp/src/aes/brg_endian.h000066400000000000000000000122521264474202400200430ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 */ #ifndef _BRG_ENDIAN_H #define _BRG_ENDIAN_H #define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */ #define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */ /* Include files where endian defines and byteswap functions may reside */ #if defined( __sun ) # include #elif defined( __FreeBSD__ ) || defined( __OpenBSD__ ) || defined( __NetBSD__ ) # include #elif defined( BSD ) && ( BSD >= 199103 ) || defined( __APPLE__ ) || \ defined( __CYGWIN32__ ) || defined( __DJGPP__ ) || defined( __osf__ ) # include #elif defined( __linux__ ) || defined( __GNUC__ ) || defined( __GNU_LIBRARY__ ) # if !defined( __MINGW32__ ) && !defined( _AIX ) # include # if !defined( __BEOS__ ) # include # endif # endif #endif /* Now attempt to set the define for platform byte order using any */ /* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */ /* seem to encompass most endian symbol definitions */ #if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN ) # if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif defined( BIG_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined( LITTLE_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #endif #if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN ) # if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif defined( _BIG_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined( _LITTLE_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #endif #if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN ) # if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif defined( __BIG_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined( __LITTLE_ENDIAN ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #endif #if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ ) # if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN # elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN # endif #elif defined( __BIG_ENDIAN__ ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif defined( __LITTLE_ENDIAN__ ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #endif /* if the platform byte order could not be determined, then try to */ /* set this define using common machine defines */ #if !defined(PLATFORM_BYTE_ORDER) #if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \ defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \ defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \ defined( vax ) || defined( vms ) || defined( VMS ) || \ defined( __VMS ) || defined( _M_X64 ) # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \ defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \ defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \ defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \ defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \ defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \ defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #elif 0 /* **** EDIT HERE IF NECESSARY **** */ # define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN #elif 0 /* **** EDIT HERE IF NECESSARY **** */ # define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN #else # error Please edit lines 126 or 128 in brg_endian.h to set the platform byte order #endif #endif #endif open-zwave-1.5/cpp/src/aes/brg_types.h000066400000000000000000000162671264474202400177630ustar00rootroot00000000000000/* --------------------------------------------------------------------------- Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved. The redistribution and use of this software (with or without changes) is allowed without the payment of fees or royalties provided that: source code distributions include the above copyright notice, this list of conditions and the following disclaimer; binary distributions include the above copyright notice, this list of conditions and the following disclaimer in their documentation. This software is provided 'as is' with no explicit or implied warranties in respect of its operation, including, but not limited to, correctness and fitness for purpose. --------------------------------------------------------------------------- Issue Date: 20/12/2007 The unsigned integer types defined here are of the form uint_t where is the length of the type; for example, the unsigned 32-bit type is 'uint32_t'. These are NOT the same as the 'C99 integer types' that are defined in the inttypes.h and stdint.h headers since attempts to use these types have shown that support for them is still highly variable. However, since the latter are of the form uint_t, a regular expression search and replace (in VC++ search on 'uint_{:z}t' and replace with 'uint\1_t') can be used to convert the types used here to the C99 standard types. */ #ifndef _BRG_TYPES_H #define _BRG_TYPES_H #if defined(__cplusplus) extern "C" { #endif #include #include #if defined( _MSC_VER ) && ( _MSC_VER >= 1300 ) # include # define ptrint_t intptr_t #elif defined( __ECOS__ ) # define intptr_t unsigned int # define ptrint_t intptr_t #elif defined( __GNUC__ ) && ( __GNUC__ >= 3 ) # define ptrint_t intptr_t #else # define ptrint_t int #endif #ifndef BRG_UI32 # define BRG_UI32 # if UINT_MAX == 4294967295u # define li_32(h) 0x##h##u # elif ULONG_MAX == 4294967295u # define li_32(h) 0x##h##ul # elif defined( _CRAY ) # error This code needs 32-bit data types, which Cray machines do not provide # else # error Please define uint32_t as a 32-bit unsigned integer type in brg_types.h # endif #endif #ifndef BRG_UI64 # if defined( __BORLANDC__ ) && !defined( __MSDOS__ ) # define BRG_UI64 # define li_64(h) 0x##h##ui64 # elif defined( _MSC_VER ) && ( _MSC_VER < 1300 ) /* 1300 == VC++ 7.0 */ # define BRG_UI64 # define li_64(h) 0x##h##ui64 # elif defined( __sun ) && defined( ULONG_MAX ) && ULONG_MAX == 0xfffffffful # define BRG_UI64 # define li_64(h) 0x##h##ull # elif defined( __MVS__ ) # define BRG_UI64 # define li_64(h) 0x##h##ull # elif defined( UINT_MAX ) && UINT_MAX > 4294967295u # if UINT_MAX == 18446744073709551615u # define BRG_UI64 # define li_64(h) 0x##h##u # endif # elif defined( ULONG_MAX ) && ULONG_MAX > 4294967295u # if ULONG_MAX == 18446744073709551615ul # define BRG_UI64 # define li_64(h) 0x##h##ul # endif # elif defined( ULLONG_MAX ) && ULLONG_MAX > 4294967295u # if ULLONG_MAX == 18446744073709551615ull # define BRG_UI64 # define li_64(h) 0x##h##ull # endif # elif defined( ULONG_LONG_MAX ) && ULONG_LONG_MAX > 4294967295u # if ULONG_LONG_MAX == 18446744073709551615ull # define BRG_UI64 # define li_64(h) 0x##h##ull # endif # endif #endif #if !defined( BRG_UI64 ) # if defined( NEED_UINT_64T ) # error Please define uint64_t as an unsigned 64 bit type in brg_types.h # endif #endif #ifndef RETURN_VALUES # define RETURN_VALUES # if defined( DLL_EXPORT ) # if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) # define VOID_RETURN __declspec( dllexport ) void __stdcall # define INT_RETURN __declspec( dllexport ) int __stdcall # elif defined( __GNUC__ ) # define VOID_RETURN __declspec( __dllexport__ ) void # define INT_RETURN __declspec( __dllexport__ ) int # else # error Use of the DLL is only available on the Microsoft, Intel and GCC compilers # endif # elif defined( DLL_IMPORT ) # if defined( _MSC_VER ) || defined ( __INTEL_COMPILER ) # define VOID_RETURN __declspec( dllimport ) void __stdcall # define INT_RETURN __declspec( dllimport ) int __stdcall # elif defined( __GNUC__ ) # define VOID_RETURN __declspec( __dllimport__ ) void # define INT_RETURN __declspec( __dllimport__ ) int # else # error Use of the DLL is only available on the Microsoft, Intel and GCC compilers # endif # elif defined( __WATCOMC__ ) # define VOID_RETURN void __cdecl # define INT_RETURN int __cdecl # else # define VOID_RETURN void # define INT_RETURN int # endif #endif /* These defines are used to detect and set the memory alignment of pointers. Note that offsets are in bytes. ALIGN_OFFSET(x,n) return the positive or zero offset of the memory addressed by the pointer 'x' from an address that is aligned on an 'n' byte boundary ('n' is a power of 2) ALIGN_FLOOR(x,n) return a pointer that points to memory that is aligned on an 'n' byte boundary and is not higher than the memory address pointed to by 'x' ('n' is a power of 2) ALIGN_CEIL(x,n) return a pointer that points to memory that is aligned on an 'n' byte boundary and is not lower than the memory address pointed to by 'x' ('n' is a power of 2) */ #define ALIGN_OFFSET(x,n) (((ptrint_t)(x)) & ((n) - 1)) #define ALIGN_FLOOR(x,n) ((uint8_t*)(x) - ( ((ptrint_t)(x)) & ((n) - 1))) #define ALIGN_CEIL(x,n) ((uint8_t*)(x) + (-((ptrint_t)(x)) & ((n) - 1))) /* These defines are used to declare buffers in a way that allows faster operations on longer variables to be used. In all these defines 'size' must be a power of 2 and >= 8. NOTE that the buffer size is in bytes but the type length is in bits UNIT_TYPEDEF(x,size) declares a variable 'x' of length 'size' bits BUFR_TYPEDEF(x,size,bsize) declares a buffer 'x' of length 'bsize' bytes defined as an array of variables each of 'size' bits (bsize must be a multiple of size / 8) UNIT_CAST(x,size) casts a variable to a type of length 'size' bits UPTR_CAST(x,size) casts a pointer to a pointer to a varaiable of length 'size' bits */ #define UI_TYPE(size) uint##size##_t #define UNIT_TYPEDEF(x,size) typedef UI_TYPE(size) x #define BUFR_TYPEDEF(x,size,bsize) typedef UI_TYPE(size) x[bsize / (size >> 3)] #define UNIT_CAST(x,size) ((UI_TYPE(size) )(x)) #define UPTR_CAST(x,size) ((UI_TYPE(size)*)(x)) #if defined(__cplusplus) } #endif #endif open-zwave-1.5/cpp/src/command_classes/000077500000000000000000000000001264474202400201635ustar00rootroot00000000000000open-zwave-1.5/cpp/src/command_classes/Alarm.cpp000066400000000000000000000211561264474202400217300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Alarm.cpp // // Implementation of the Z-Wave COMMAND_CLASS_ALARM // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Alarm.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" using namespace OpenZWave; enum AlarmCmd { AlarmCmd_Get = 0x04, AlarmCmd_Report = 0x05, // Version 2 AlarmCmd_SupportedGet = 0x07, AlarmCmd_SupportedReport = 0x08 }; enum { AlarmIndex_Type = 0, AlarmIndex_Level, AlarmIndex_SourceNodeId }; enum { Alarm_General = 0, Alarm_Smoke, Alarm_CarbonMonoxide, Alarm_CarbonDioxide, Alarm_Heat, Alarm_Flood, Alarm_Access_Control, Alarm_Burglar, Alarm_Power_Management, Alarm_System, Alarm_Emergency, Alarm_Clock, Alarm_Appliance, Alarm_HomeHealth, Alarm_Count }; static char const* c_alarmTypeName[] = { "General", "Smoke", "Carbon Monoxide", "Carbon Dioxide", "Heat", "Flood", "Access Control", "Burglar", "Power Management", "System", "Emergency", "Clock", "Appliance", "HomeHealth" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Alarm::Alarm ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ) { 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 ); return true; } } if( _requestFlags & RequestFlag_Dynamic ) { return RequestValue( _requestFlags, 0, _instance, _queue ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Alarm::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if( IsGetSupported() ) { 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 { bool res = false; for( uint8 i = 0; i < Alarm_Count; i++ ) { if( Value* value = GetValue( _instance, i + 3 ) ) { value->Release(); 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); // ? proprietary alarm ? msg->Append( i ); if( GetVersion() > 2 ) msg->Append(0x01); //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] ); } else { string alarm_type = ( _data[5] < Alarm_Count ) ? c_alarmTypeName[_data[5]] : "Unknown type"; Log::Write( LogLevel_Info, GetNodeId(), "Received Alarm report: type=%d, level=%d, sensorSrcID=%d, type:%s event:%d, status=%d", _data[1], _data[2], _data[3], alarm_type.c_str(), _data[6], _data[4] ); } ValueByte* value; if( (value = static_cast( GetValue( _instance, AlarmIndex_Type ) )) ) { value->OnValueRefreshed( _data[1] ); value->Release(); } if( (value = static_cast( GetValue( _instance, AlarmIndex_Level ) )) ) { value->OnValueRefreshed( _data[2] ); value->Release(); } // With Version=2, the data has more detailed information about the alarm if(( GetVersion() > 1 ) && ( _length >= 7 )) { if( (value = static_cast( GetValue( _instance, AlarmIndex_SourceNodeId ) )) ) { value->OnValueRefreshed( _data[3] ); value->Release(); } if( (value = static_cast( GetValue( _instance, _data[5]+3 ) )) ) { value->OnValueRefreshed( _data[6] ); value->Release(); } } 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" ); node->CreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, AlarmIndex_SourceNodeId, "SourceNodeId", "", true, false, 0, 0 ); Log::Write( LogLevel_Info, GetNodeId(), " Added alarm SourceNodeId" ); // Parse the data for the supported alarm types uint8 numBytes = _data[1]; for( uint32 i=0; iCreateValueByte( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index+3, c_alarmTypeName[index], "", true, false, 0, 0 ); Log::Write( LogLevel_Info, GetNodeId(), " Added alarm type: %s", c_alarmTypeName[index] ); } else { Log::Write( LogLevel_Info, GetNodeId(), " Unknown alarm type: %d", index ); } } } } } ClearStaticRequest( StaticRequest_Values ); return true; } return false; } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- void Alarm::CreateVars ( uint8 const _instance ) { if( Node* node = GetNodeUnsafe() ) { 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 ); } } open-zwave-1.5/cpp/src/command_classes/Alarm.h000066400000000000000000000053471264474202400214010ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Alarm.h // // Implementation of the Z-Wave COMMAND_CLASS_ALARM // // 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 . // //----------------------------------------------------------------------------- #ifndef _Alarm_H #define _Alarm_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_ALARM (0x71), a Z-Wave device command class. */ class Alarm: public CommandClass { 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_ALARM"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 3; } protected: virtual void CreateVars( uint8 const _instance ); private: Alarm( uint32 const _homeId, uint8 const _nodeId ); }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ApplicationStatus.cpp000066400000000000000000000050031264474202400243340ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ApplicationStatus.cpp // // Implementation of the Z-Wave COMMAND_CLASS_APPLICATION_STATUS // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/ApplicationStatus.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "platform/Log.h" using namespace OpenZWave; 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 ) { if( ApplicationStatusCmd_Busy == (ApplicationStatusCmd)_data[0] ) { char msg[64]; switch( _data[1] ) { case 0: { snprintf( msg, sizeof(msg), "Try again later" ); break; } case 1: { snprintf( msg, sizeof(msg), "Try again in %d seconds", _data[2] ); break; } case 2: { snprintf( msg, sizeof(msg), "Request queued, will be executed later" ); break; } default: { // Invalid status snprintf( msg, sizeof(msg), "Unknown status %d", _data[1] ); } } Log::Write( LogLevel_Info, GetNodeId(), "Received Application Status Busy: %s", msg ); return true; } if( ApplicationStatusCmd_RejectedRequest == (ApplicationStatusCmd)_data[0] ) { Log::Write( LogLevel_Info, "Received Application Rejected Request: Status=%d", _data[1] ); return true; } return false; } open-zwave-1.5/cpp/src/command_classes/ApplicationStatus.h000066400000000000000000000040711264474202400240050ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ApplicationStatus.h // // Implementation of the Z-Wave COMMAND_CLASS_APPLICATION_STATUS // // 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 . // //----------------------------------------------------------------------------- #ifndef _ApplicationStatus_H #define _ApplicationStatus_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_APPLICATION_STATUS (0x22), a Z-Wave device command class. */ 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"; } // 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 ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Association.cpp000066400000000000000000000277711264474202400231610ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Association.cpp // // Implementation of the Z-Wave COMMAND_CLASS_ASSOCIATION // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "command_classes/CommandClasses.h" #include "command_classes/Association.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "Group.h" #include "platform/Log.h" using namespace OpenZWave; 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 ); } //----------------------------------------------------------------------------- // // 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 ) ) { m_numGroups = (uint8)intVal; } 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; } associationsElement = associationsElement->NextSiblingElement(); } } //----------------------------------------------------------------------------- // // Save the association data //----------------------------------------------------------------------------- void Association::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); if( Node* node = GetNodeUnsafe() ) { TiXmlElement* associationsElement = new TiXmlElement( "Associations" ); char str[8]; snprintf( str, 8, "%d", m_numGroups ); associationsElement->SetAttribute( "num_groups", str ); _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 ); } return false; } //----------------------------------------------------------------------------- // // Nothing to do for Association //----------------------------------------------------------------------------- bool Association::RequestValue ( uint32 const _requestFlags, uint8 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; // 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 ) { if( _length >= 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; iGetGroup( 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( 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; } } handled = true; } } return handled; } //----------------------------------------------------------------------------- // // Request details of an association group //----------------------------------------------------------------------------- void Association::QueryGroup ( uint8 _groupIdx, uint32 const _requestFlags ) { if ( IsGetSupported() ) { 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 ); } //----------------------------------------------------------------------------- // // 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 ); } open-zwave-1.5/cpp/src/command_classes/Association.h000066400000000000000000000056651264474202400226240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Association.h // // Implementation of the Z-Wave COMMAND_CLASS_ASSOCIATION // // 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 . // //----------------------------------------------------------------------------- #ifndef _Association_H #define _Association_H #include #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_ASSOCIATION (0x85), a Z-Wave device command class. */ class Association: public CommandClass { friend class Group; 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"; } // 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, uint8 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 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 }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/AssociationCommandConfiguration.cpp000066400000000000000000000244341264474202400272010ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // AssociationCommandConfiguration.cpp // // Implementation of the COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/AssociationCommandConfiguration.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Group.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" #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 { AssociationCommandConfigurationIndex_MaxCommandLength = 0, AssociationCommandConfigurationIndex_CommandsAreValues, AssociationCommandConfigurationIndex_CommandsAreConfigurable, AssociationCommandConfigurationIndex_NumFreeCommands, AssociationCommandConfigurationIndex_MaxCommands }; //----------------------------------------------------------------------------- // // 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool AssociationCommandConfiguration::RequestValue ( uint32 const _requestFlags, uint8 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; } //----------------------------------------------------------------------------- // // Request the command data //----------------------------------------------------------------------------- void AssociationCommandConfiguration::RequestCommands ( uint8 const _groupIdx, uint8 const _nodeId ) { if ( IsGetSupported() ) { 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 ) { 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; iAddCommand( nodeIdx, length, start+1 ); start += length; } } } 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 ); } } //----------------------------------------------------------------------------- // // 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 ); } open-zwave-1.5/cpp/src/command_classes/AssociationCommandConfiguration.h000066400000000000000000000054331264474202400266440ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // AssociationCommandConfiguration.h // // Implementation of the COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION // // 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 . // //----------------------------------------------------------------------------- #ifndef _AssociationCommandConfiguration_H #define _AssociationCommandConfiguration_H #include "command_classes/CommandClass.h" #include "value_classes/ValueBool.h" #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. */ 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 ); // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: AssociationCommandConfiguration( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Basic.cpp000066400000000000000000000233551264474202400217200ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Basic.cpp // // Implementation of the Z-Wave COMMAND_CLASS_BASIC // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Basic.h" #include "command_classes/Association.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "Notification.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" #include "command_classes/NoOperation.h" #include "tinyxml.h" using namespace OpenZWave; enum BasicCmd { BasicCmd_Set = 0x01, BasicCmd_Get = 0x02, BasicCmd_Report = 0x03 }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Basic::Basic ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_mapping( 0 ), m_ignoreMapping( false ), m_setAsReport( false ) { } //----------------------------------------------------------------------------- // // Read configuration. //----------------------------------------------------------------------------- void Basic::ReadXML ( TiXmlElement const* _ccElement ) { CommandClass::ReadXML( _ccElement ); char const* str = _ccElement->Attribute("ignoremapping"); if( str ) { m_ignoreMapping = !strcmp( str, "true"); } int32 intVal; if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "mapping", &intVal ) ) { if( intVal < 256 && intVal != 0 ) { SetMapping( (uint8)intVal, false ); } } str = _ccElement->Attribute("setasreport"); if( str ) { m_setAsReport = !strcmp( str, "true"); } } //----------------------------------------------------------------------------- // // Save changed configuration //----------------------------------------------------------------------------- void Basic::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); if( m_ignoreMapping ) { _ccElement->SetAttribute( "ignoremapping", "true" ); } char str[32]; if( m_mapping != 0 ) { snprintf( str, sizeof(str), "%d", m_mapping ); _ccElement->SetAttribute( "mapping", str ); } if( m_setAsReport ) { _ccElement->SetAttribute( "setasreport", "true" ); } } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- bool Basic::RequestState ( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ) { if( _requestFlags & RequestFlag_Dynamic ) { if ( (m_ignoreMapping || (!m_ignoreMapping && m_mapping == 0))) return RequestValue( _requestFlags, 0, _instance, _queue ); } return false; } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- bool Basic::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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; } //----------------------------------------------------------------------------- // // 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_ignoreMapping && m_mapping != 0 ) { UpdateMappedClass( _instance, m_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_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_ignoreMapping && m_mapping != 0 ) { UpdateMappedClass( _instance, m_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] ); 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); 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; } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- 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(); } } //----------------------------------------------------------------------------- // // 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() ) { if( CommandClass* cc = node->GetCommandClass( _commandClassId ) ) { ccstr = cc->GetCommandClassName(); } } if( m_ignoreMapping ) { 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_mapping = _commandClassId; RemoveValue( 1, 0 ); res = true; } if( m_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 ); } } } return res; } open-zwave-1.5/cpp/src/command_classes/Basic.h000066400000000000000000000053121264474202400213560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Basic.h // // Implementation of the Z-Wave COMMAND_CLASS_BASIC // // 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 . // //----------------------------------------------------------------------------- #ifndef _Basic_H #define _Basic_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_BASIC (0x20), a Z-Wave device command class. */ class Basic: public CommandClass { 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"; } bool SetMapping( uint8 const _commandClassId, bool const _doLog = true ); // Map COMMAND_CLASS_BASIC messages to another command class uint8 GetMapping(){ return m_mapping; } // 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, uint8 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 Set( uint8 const _level ); protected: virtual void CreateVars( uint8 const _instance ); private: Basic( uint32 const _homeId, uint8 const _nodeId ); uint8 m_mapping; bool m_ignoreMapping; bool m_setAsReport; std::vector m_instances; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/BasicWindowCovering.cpp000066400000000000000000000075361264474202400246100ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // BasicWindowCovering.cpp // // Implementation of the Z-Wave COMMAND_CLASS_BASIC_WINDOW_COVERING // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/BasicWindowCovering.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "value_classes/ValueButton.h" using namespace OpenZWave; enum BasicWindowCoveringCmd { BasicWindowCoveringCmd_StartLevelChange = 0x01, BasicWindowCoveringCmd_StopLevelChange = 0x02 }; enum { BasicWindowCoveringIndex_Open = 0, BasicWindowCoveringIndex_Close }; //----------------------------------------------------------------------------- // // 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); uint8 action = 0x40; if( button->GetID().GetIndex() ) // 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; } } 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 ); } } open-zwave-1.5/cpp/src/command_classes/BasicWindowCovering.h000066400000000000000000000043421264474202400242450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // BasicWindowCovering.h // // Implementation of the Z-Wave COMMAND_CLASS_BASIC_WINDOW_COVERING // // 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 . // //----------------------------------------------------------------------------- #ifndef _BasicWindowCovering_H #define _BasicWindowCovering_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueButton; /** \brief Implements COMMAND_CLASS_BASIC_WINDOW_COVERING (0x50), a Z-Wave device command class. */ class BasicWindowCovering: public CommandClass { 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"; } // 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: BasicWindowCovering( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Battery.cpp000066400000000000000000000102171264474202400223020ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Battery.cpp // // Implementation of the Z-Wave COMMAND_CLASS_BATTERY // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Battery.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" using namespace OpenZWave; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Battery::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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; } 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/Battery.h000066400000000000000000000044301264474202400217470ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Battery.h // // Implementation of the Z-Wave COMMAND_CLASS_BATTERY // // 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 . // //----------------------------------------------------------------------------- #ifndef _Battery_H #define _Battery_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_BATTERY (0x80), a Z-Wave device command class. */ class Battery: public CommandClass { 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"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: Battery( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/CRC16Encap.cpp000066400000000000000000000053101264474202400224130ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // CRC16Encap.cpp // // Implementation of the Z-Wave COMMAND_CLASS_CRC_16_ENCAP // // Copyright (c) 2012 Greg Satz // // 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/CRC16Encap.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" using namespace OpenZWave; // // 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; } 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()); 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( Node const* node = GetNodeUnsafe() ) { uint8 commandClassId = _data[1]; if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) ) { pCommandClass->HandleMsg( &_data[2], _length - 4 ); } } return true; } return false; } open-zwave-1.5/cpp/src/command_classes/CRC16Encap.h000066400000000000000000000037541264474202400220720ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // CRC16Encap.h // // Implementation of the Z-Wave COMMAND_CLASS_CRC_16_ENCAP // // Copyright (c) 2012 Greg Satz // // 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 _CRC16_ENCAP_H #define _CRC16_ENCAP_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_CRC_16_ENCAP (0x56), a Z-Wave device command class. */ 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"; } // 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 ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/CentralScene.cpp000066400000000000000000000155431264474202400232450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // CentralScene.cpp // // Implementation of the Z-Wave COMMAND_CLASS_CENTRAL_SCENE // // Copyright (c) 2012 Greg Satz // // 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/CentralScene.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueInt.h" #include "tinyxml.h" using namespace OpenZWave; enum CentralSceneCmd { CentralSceneCmd_Capability_Get = 0x01, CentralSceneCmd_Capability_Report = 0x02, CentralSceneCmd_Set = 0x03 }; enum CentralScene_ValueID_Index { CentralScene_Count = 0x00 }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- CentralScene::CentralScene ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_scenecount(0) { Log::Write(LogLevel_Info, GetNodeId(), "CentralScene - Created %d", HasStaticRequest( StaticRequest_Values )); } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- bool CentralScene::RequestState ( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ) { Log::Write(LogLevel_Info, GetNodeId(), "CentralScene RequestState: %d", _requestFlags); bool requests = false; if( ( _requestFlags & RequestFlag_AfterMark )) { requests = RequestValue( _requestFlags, CentralSceneCmd_Capability_Get, _instance, _queue ); } else { Log::Write(LogLevel_Info, GetNodeId(), "CentralScene: Not a StaticRequest"); } return requests; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool CentralScene::RequestValue ( uint32 const _requestFlags, uint8 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( _what ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, _queue ); } return true; } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void CentralScene::ReadXML ( TiXmlElement const* _ccElement ) { int32 intVal; CommandClass::ReadXML( _ccElement ); if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "scenecount", &intVal ) ) { m_scenecount = intVal; } } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void CentralScene::WriteXML ( TiXmlElement* _ccElement ) { char str[32]; CommandClass::WriteXML( _ccElement ); snprintf( str, sizeof(str), "%d", m_scenecount ); _ccElement->SetAttribute( "scenecount", str); } //----------------------------------------------------------------------------- // // 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 int32 when; if( _data[2] == 0 ) when = 0; else if( _data[2] <= 0x7F ) when = _data[2]; else if( _data[2] <= 0xFE ) when = 60 * _data[2]; else when = 0; Log::Write( LogLevel_Info, GetNodeId(), "Received Central Scene set from node %d: scene id=%d in %d seconds. Sending event notification.", GetNodeId(), _data[3], when); if( ValueInt* value = static_cast( GetValue( _instance, _data[3] ) ) ) { value->OnValueRefreshed( when ); value->Release(); } else { Log::Write( LogLevel_Warning, GetNodeId(), "No ValueID created for Scene %d", _data[3]); return false; } return true; } else if (CentralSceneCmd_Capability_Report == (CentralSceneCmd)_data[0]) { /* Create a Number of ValueID's based on the m_scenecount variable * We prefer what the Config File specifies rather than what is returned by * the Device... */ int scenecount = _data[1]; if (m_scenecount != 0) m_scenecount = scenecount; if ( ValueInt* value = static_cast( GetValue( _instance, CentralScene_Count))) { value->OnValueRefreshed(m_scenecount); value->Release(); } else { Log::Write( LogLevel_Warning, GetNodeId(), "Can't find ValueID for SceneCount"); } if( Node* node = GetNodeUnsafe() ) { char lbl[64]; for (int i = 1; i <= m_scenecount; i++) { snprintf(lbl, 64, "Scene %d", i); node->CreateValueInt(ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, lbl, "", true, false, 0, 0 ); } } else { Log::Write(LogLevel_Info, GetNodeId(), "CentralScene: Can't find Node!"); } } return false; } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- void CentralScene::CreateVars ( uint8 const _instance ) { if( Node* node = GetNodeUnsafe() ) { node->CreateValueInt( ValueID::ValueGenre_System, GetCommandClassId(), _instance, CentralScene_Count, "Scene Count", "", true, false, 0, 0 ); } } open-zwave-1.5/cpp/src/command_classes/CentralScene.h000066400000000000000000000055721264474202400227130ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // CentralScene.h // // Implementation of the Z-Wave COMMAND_CLASS_CENTRAL_SCENE // // Copyright (c) 2012 Greg Satz // // 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 _CentralScene_H #define _CentralScene_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_CENTRAL_SCENE (0x5B), a Z-Wave device command class. */ class CentralScene: public CommandClass { 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"; } // 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 HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); /** \brief Create Default Vars for this CC */ void CreateVars( uint8 const _instance ); void ReadXML( TiXmlElement const* _ccElement ); void WriteXML( TiXmlElement* _ccElement ); bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); bool RequestValue( uint32 const _requestFlags, uint8 const _what, uint8 const _instance, Driver::MsgQueue const _queue ); private: CentralScene( uint32 const _homeId, uint8 const _nodeId ); int32 m_scenecount; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ClimateControlSchedule.cpp000066400000000000000000000314731264474202400252730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ClimateControlSchedule.cpp // // Implementation of the Z-Wave COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/ClimateControlSchedule.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueList.h" #include "value_classes/ValueSchedule.h" #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 { ClimateControlScheduleIndex_OverrideState = 8, ClimateControlScheduleIndex_OverrideSetback = 9 }; static char const* c_dayNames[] = { "Invalid", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" }; static char const* c_overrideStateNames[] = { "None", "Temporary", "Permanent", "Invalid" }; //----------------------------------------------------------------------------- // // Read the saved change-counter value //----------------------------------------------------------------------------- void ClimateControlSchedule::ReadXML ( TiXmlElement const* _ccElement ) { CommandClass::ReadXML( _ccElement ); int intVal; if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "change_counter", &intVal ) ) { m_changeCounter = (uint8)intVal; } } //----------------------------------------------------------------------------- // // Write the change-counter value //----------------------------------------------------------------------------- void ClimateControlSchedule::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); char str[8]; snprintf( str, 8, "%d", m_changeCounter ); _ccElement->SetAttribute( "change_counter", str ); } //----------------------------------------------------------------------------- // // 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool ClimateControlSchedule::RequestValue ( uint32 const _requestFlags, uint8 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 ) { 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; } if( ClimateControlScheduleCmd_ChangedReport == (ClimateControlScheduleCmd)_data[0] ) { Log::Write( LogLevel_Info, GetNodeId(), "Received climate control schedule changed report:" ); if( _data[1] ) { if( _data[1] != m_changeCounter ) { m_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; } 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" ); } 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 res = false; uint8 instance = _value.GetID().GetInstance(); uint8 idx = _value.GetID().GetIndex(); if( idx < 8 ) { // Set a schedule 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 i=0; i<9; ++i ) { uint8 hours; uint8 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 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 ); } } open-zwave-1.5/cpp/src/command_classes/ClimateControlSchedule.h000066400000000000000000000052531264474202400247350ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ClimateControlSchedule.h // // Implementation of the Z-Wave COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE // // 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 . // //----------------------------------------------------------------------------- #ifndef _ClimateControlSchedule_H #define _ClimateControlSchedule_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueSchedule; class ValueList; class ValueByte; /** \brief Implements COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE (0x46), a Z-Wave device command class. */ class ClimateControlSchedule: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ClimateControlSchedule( _homeId, _nodeId ); } virtual ~ClimateControlSchedule(){} static uint8 const StaticGetCommandClassId(){ return 0x46; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE"; } // 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, uint8 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 ); private: ClimateControlSchedule( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_changeCounter( 0 ){} uint8 m_changeCounter; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Clock.cpp000066400000000000000000000150751264474202400217320ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Clock.cpp // // Implementation of the Z-Wave COMMAND_CLASS_CLOCK // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Clock.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueList.h" using namespace OpenZWave; enum ClockCmd { ClockCmd_Set = 0x04, ClockCmd_Get = 0x05, ClockCmd_Report = 0x06 }; enum { ClockIndex_Day = 0, ClockIndex_Hour, ClockIndex_Minute }; 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; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Clock::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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; } //----------------------------------------------------------------------------- // // 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; uint8 hour = hourValue->GetValue(); uint8 minute = minuteValue->GetValue(); 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 ); } } open-zwave-1.5/cpp/src/command_classes/Clock.h000066400000000000000000000045061264474202400213740ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Clock.h // // Implementation of the Z-Wave COMMAND_CLASS_CLOCK // // 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 . // //----------------------------------------------------------------------------- #ifndef _Clock_H #define _Clock_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; class ValueList; /** \brief Implements COMMAND_CLASS_CLOCK (0x81), a Z-Wave device command class. */ class Clock: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Clock( _homeId, _nodeId ); } virtual ~Clock(){} static uint8 const StaticGetCommandClassId(){ return 0x81; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CLOCK"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: Clock( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Color.cpp000066400000000000000000001042001264474202400217420ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Color.cpp // // Implementation of the Z-Wave COMMAND_CLASS_COLOR // // Copyright (c) 2014 GizMoCuz // // 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 #include #include "command_classes/CommandClasses.h" #include "command_classes/Color.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueInt.h" #include "value_classes/ValueString.h" #include "value_classes/ValueByte.h" #include "tinyxml.h" using namespace OpenZWave; 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%) //1=Cold White (0x00 - 0xFF: 0 100%) //2=Red (0x00 - 0xFF: 0 100%) //3=Green (0x00 - 0xFF: 0 100%) //4=Blue (0x00 - 0xFF: 0 100%) //5=Amber (for 6ch Color mixing) (0x00 - 0xFF: 0 100%) //6=Cyan (for 6ch Color mixing) (0x00 - 0xFF: 0 100%) //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 }; 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 }; Color::Color ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_capabilities ( 0 ), m_coloridxbug ( false ), m_refreshinprogress ( false ), m_coloridxcount ( 0 ) { for (uint8 i = 0; i < 9; i++) m_colorvalues[i] = 0; SetStaticRequest( StaticRequest_Values ); } //----------------------------------------------------------------------------- // // Read configuration. //----------------------------------------------------------------------------- void Color::ReadXML ( TiXmlElement const* _ccElement ) { CommandClass::ReadXML( _ccElement ); int32 intVal; if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "colorchannels", &intVal ) ) { if (intVal <= 0x100) { m_capabilities = (uint16)intVal; } } char const* str = _ccElement->Attribute("coloridxbug"); if( str ) { m_coloridxbug = !strcmp( str, "true"); } } //----------------------------------------------------------------------------- // // Save changed configuration //----------------------------------------------------------------------------- void Color::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); char str[32]; if( m_capabilities != 0 ) { snprintf( str, sizeof(str), "%d", m_capabilities ); _ccElement->SetAttribute( "colorchannels", str ); } if( m_coloridxbug ) { _ccElement->SetAttribute( "coloridxbug", "true" ); } } //----------------------------------------------------------------------------- // // 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_capabilities == 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_coloridxbug && tmprequests) { m_refreshinprogress = true; break; } } } return requests; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Color::RequestValue ( uint32 const _requestFlags, uint8 const _what, uint8 const _instance, Driver::MsgQueue const _queue ) { if( IsGetSupported() && (_what == Value_Color || _what == Value_Color_Index)) { if (m_coloridxbug && 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_coloridxbug) { m_refreshinprogress = true; m_coloridxcount = 0; 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_capabilities) & (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; } //----------------------------------------------------------------------------- // // Get a Specific Color Value from a position in a RGB String // its assumed the string is formated such as #RRGGBB[WWCWAMCYPR] // where the color values in [] are optional. // throws a exception when position is out of bounds //----------------------------------------------------------------------------- uint16 GetColor(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; } //----------------------------------------------------------------------------- // // 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_capabilities = (_data[1] + (_data[2] << 8)); string helpstr = "#RRGGBB"; Log::Write(LogLevel_Info, GetNodeId(), "Received an Color Capability Report: Capability=%xd", m_capabilities); if (m_capabilities & 0x04) Log::Write(LogLevel_Info, GetNodeId(), "Red (0x02)"); if (m_capabilities & 0x08) Log::Write(LogLevel_Info, GetNodeId(), "Green (0x03)"); if (m_capabilities & 0x10) Log::Write(LogLevel_Info, GetNodeId(), "Blue (0x04)"); if (m_capabilities & 0x01) { Log::Write(LogLevel_Info, GetNodeId(), "Warm White (0x00)"); helpstr += "WW"; } if (m_capabilities & 0x02) { Log::Write(LogLevel_Info, GetNodeId(), "Cold White (0x01)"); helpstr += "CW"; } if (m_capabilities & 0x20) { Log::Write(LogLevel_Info, GetNodeId(), "Amber (0x05)"); helpstr += "AM"; } if (m_capabilities & 0x40) { Log::Write(LogLevel_Info, GetNodeId(), "Cyan (0x06)"); helpstr += "CY"; } if (m_capabilities & 0x80) { Log::Write(LogLevel_Info, GetNodeId(), "Purple (0x07)"); helpstr += "PR"; } if (m_capabilities & 0x100) Log::Write(LogLevel_Info, GetNodeId(), "Indexed Color (0x08)"); if( ValueInt* colorchannels = static_cast( GetValue( _instance, Value_Color_Channels_Capabilities ) ) ) { colorchannels->OnValueRefreshed( m_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 */ { vector items; unsigned int size = (sizeof(c_ColorIndex)/sizeof(c_ColorIndex[0])); for( unsigned int i=0; i < size; i++) { 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 ); } 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_coloridxbug) { 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]; /* test if there are any more valid coloridx */ for ( uint8 idx = coloridx+1; idx < 9; idx++ ) { if ((m_capabilities) & (1<<(idx))) { return true; } } if (m_coloridxbug) 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; ss << "#"; /* do R */ if ((m_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 ((m_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 ((m_capabilities) & (1<<(COLORIDX_BLUE))) ss << std::setw(2) << std::uppercase << std::hex << std::setfill('0') << (int)m_colorvalues[COLORIDX_BLUE]; else ss << "00"; /* if both whites are present.... */ if (((m_capabilities) & (1<<(COLORIDX_WARMWHITE))) && ((m_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 ((m_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 ((m_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 ((m_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 ((m_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 ((m_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 (!(m_capabilities & (1<<(COLORIDX_INDEXCOLOR)))) { if( ValueList* coloridx = static_cast( GetValue( _instance, Value_Color_Index ) ) ) { /* it supports the AMBER/CYAN/PURPLE Channels */ if (m_capabilities > 31) { /* Custom */ coloridx->OnValueRefreshed( 17 ); coloridx->Release(); return true; } if ((m_capabilities) & (1<<(COLORIDX_WARMWHITE))) { if (ss.str().substr(0, 9) == "#000000FF") { /* Warm White */ coloridx->OnValueRefreshed(2); coloridx->Release(); return true; } } if ((m_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_capabilities) & (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; } //----------------------------------------------------------------------------- // // 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 nocols = (s.length() -1) / 2; uint16 colvals[8] = { 0, 0, 0, 0, 0, 0, 0, 0}; bool colvalset[8] = { false, false, false, false, false, false, false, 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); /* 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 ); return true; } else if (Value_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_capabilities) & (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)"); /* figure out the size */ uint8 nocols = 3; if ((m_capabilities) & (1<<(COLORIDX_WARMWHITE))) { nocols++; } if ((m_capabilities) & (1<<(COLORIDX_COLDWHITE))) { nocols++; } if ((m_capabilities) & (1<<(COLORIDX_AMBER))) { nocols++; } if ((m_capabilities) & (1<<(COLORIDX_CYAN))) { nocols++; } if ((m_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, 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 ((m_capabilities) & (1<<(COLORIDX_COLDWHITE))) { if ((m_capabilities) & (1<<(COLORIDX_WARMWHITE))) { msg->Append(COLORIDX_WARMWHITE); msg->Append(0x00); wwset = true; } if ((m_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 ((m_capabilities) & (1 <<(COLORIDX_WARMWHITE))) { if ((m_capabilities) & (1<<(COLORIDX_WARMWHITE))) { msg->Append(COLORIDX_WARMWHITE); msg->Append(0xFF); wwset = true; } if ((m_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 (((m_capabilities) & (1<<(COLORIDX_WARMWHITE))) && !wwset) { msg->Append(COLORIDX_WARMWHITE); msg->Append(0x00); } if (((m_capabilities) & (1<<(COLORIDX_COLDWHITE))) && !cwset) { msg->Append(COLORIDX_COLDWHITE); msg->Append(0x00); } if ((m_capabilities) & (1<<(COLORIDX_AMBER))) { msg->Append(COLORIDX_AMBER); msg->Append(0x00); } if ((m_capabilities) & (1<<(COLORIDX_CYAN))) { msg->Append(COLORIDX_CYAN); msg->Append(0x00); } if ((m_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); } 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_capabilities = value->GetValue(); /* if the Capabilities is set to 0 by the user, then refresh the defaults from the device */ if (m_capabilities == 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_capabilities); 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_capabilities, 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 ); } open-zwave-1.5/cpp/src/command_classes/Color.h000066400000000000000000000055221264474202400214160ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Color.h // // Implementation of the Z-Wave COMMAND_CLASS_COLOR // // 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 . // //----------------------------------------------------------------------------- #ifndef _Color_H #define _Color_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_COLOR (0x33), a Z-Wave device command class. */ class Color: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Color( _homeId, _nodeId ); } virtual ~Color(){} static uint8 const StaticGetCommandClassId(){ return 0x33; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_COLOR"; } // 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, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: Color( uint32 const _homeId, uint8 const _nodeId ); uint16 m_capabilities; bool m_coloridxbug; // Fibaro RGBW before version 25.25 always reported the coloridx as 3 in the Report Message. Work around it bool m_refreshinprogress; uint8 m_coloridxcount; uint8 m_colorvalues[9]; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/CommandClass.cpp000066400000000000000000000545521264474202400232460ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // CommandClass.cpp // // Base class for all Z-Wave Command Classes // // 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 . // //----------------------------------------------------------------------------- #include #include #include "tinyxml.h" #include "command_classes/CommandClass.h" #include "command_classes/Basic.h" #include "command_classes/MultiInstance.h" #include "command_classes/CommandClasses.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "Manager.h" #include "platform/Log.h" #include "value_classes/ValueStore.h" using namespace OpenZWave; 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_homeId( _homeId ), m_nodeId( _nodeId ), m_version( 1 ), m_afterMark( false ), m_createVars( true ), m_overridePrecision( -1 ), m_getSupported( true ), m_isSecured( false ), m_SecureSupport( true ), m_inNIF(false), m_staticRequests( 0 ), m_sentCnt( 0 ), m_receivedCnt( 0 ) { } //----------------------------------------------------------------------------- // // 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(); } } //----------------------------------------------------------------------------- // // Get a pointer to our driver //----------------------------------------------------------------------------- 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 ) ); } //----------------------------------------------------------------------------- // // Get a pointer to a value by its instance and index //----------------------------------------------------------------------------- Value* CommandClass::GetValue ( uint8 const _instance, uint8 const _index ) { 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, uint8 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_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( IsCreateVars() ) { CreateVars( _endPoint ); } } } //----------------------------------------------------------------------------- // // Read the saved command class data //----------------------------------------------------------------------------- void CommandClass::ReadXML ( TiXmlElement const* _ccElement ) { int32 intVal; char const* str; if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "version", &intVal ) ) { m_version = (uint8)intVal; } uint8 instances = 1; if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "instances", &intVal ) ) { instances = (uint8)intVal; } if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "request_flags", &intVal ) ) { m_staticRequests = (uint8)intVal; } if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "override_precision", &intVal ) ) { m_overridePrecision = (int8)intVal; } str = _ccElement->Attribute( "after_mark" ); if( str ) { m_afterMark = !strcmp( str, "true" ); } str = _ccElement->Attribute( "create_vars" ); if( str ) { m_createVars = !strcmp( str, "true" ); } // Make sure previously created values are removed if create_vars=false if( !m_createVars ) { if( Node* node = GetNodeUnsafe() ) { node->GetValueStore()->RemoveCommandClassValues( GetCommandClassId() ); } } str = _ccElement->Attribute( "getsupported" ); if( str ) { m_getSupported = !strcmp( str, "true" ); } str = _ccElement->Attribute( "issecured" ); if( str ) { m_isSecured = !strcmp( str, "true" ); } str = _ccElement->Attribute( "innif" ); if( str ) { m_inNIF = !strcmp( str, "true" ); } // Setting the instance count will create all the values. SetInstances( instances ); // 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 ); } } 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(); } } //----------------------------------------------------------------------------- // // Read the config that contains a list of Values that should be refreshed when // 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); _ccElement->QueryIntAttribute( "Instance", (int*)&rcc->instance); _ccElement->QueryIntAttribute( "Index", (int*)&rcc->index); 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", (int*)&arcc->cc) != TIXML_SUCCESS) { Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - CommandClass Attribute is wrong type or missing"); continue; } if (child->QueryIntAttribute( "RequestFlags", (int*)&arcc->genre) != TIXML_SUCCESS) { Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - RequestFlags Attribute is wrong type or missing"); continue; } if (child->QueryIntAttribute( "Instance", (int*)&arcc->instance) != TIXML_SUCCESS) { Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - Instance Attribute is wrong type or missing"); continue; } if (child->QueryIntAttribute( "Index", (int*)&arcc->index) != TIXML_SUCCESS) { Log::Write(LogLevel_Warning, GetNodeId(), " Invalid XML - Index Attribute is wrong type or missing"); continue; } 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; } } //----------------------------------------------------------------------------- // // Scan our m_RefreshClassValues vector to see if we should call any other // 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()) ) { /* 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; } //----------------------------------------------------------------------------- // // Save the static node configuration data //----------------------------------------------------------------------------- void CommandClass::WriteXML ( TiXmlElement* _ccElement ) { char str[32]; snprintf( str, sizeof(str), "%d", GetCommandClassId() ); _ccElement->SetAttribute( "id", str ); _ccElement->SetAttribute( "name", GetCommandClassName().c_str() ); snprintf( str, sizeof(str), "%d", GetVersion() ); _ccElement->SetAttribute( "version", str ); if( m_staticRequests ) { snprintf( str, sizeof(str), "%d", m_staticRequests ); _ccElement->SetAttribute( "request_flags", str ); } if( m_overridePrecision >= 0 ) { snprintf( str, sizeof(str), "%d", m_overridePrecision ); _ccElement->SetAttribute( "override_precision", str ); } if( m_afterMark ) { _ccElement->SetAttribute( "after_mark", "true" ); } if( !m_createVars ) { _ccElement->SetAttribute( "create_vars", "false" ); } if( !m_getSupported ) { _ccElement->SetAttribute( "getsupported", "false" ); } if ( m_isSecured ) { _ccElement->SetAttribute( "issecured", "true" ); } if ( m_inNIF ) { _ccElement->SetAttribute( "innif", "true" ); } // 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 ); } } // 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); } } } //----------------------------------------------------------------------------- // // 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; if( _scale ) { *_scale = (_data[0] & c_scaleMask) >> c_scaleShift; } if( _precision ) { *_precision = precision; } uint32 value = 0; uint8 i; for( i=0; idecimal_point); // Copy the buffer into res res += &numBuf[start]; } 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 ); _msg->Append( (precision<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; } //----------------------------------------------------------------------------- // // 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; // Find the decimal point size_t pos = _value.find_first_of( "." ); if( pos == string::npos ) pos = _value.find_first_of( "," ); if( pos == 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); string str = _value.substr( 0, pos ) + _value.substr( pos+1 ); val = atol( str.c_str() ); } if ( m_overridePrecision > 0 ) { while ( precision < m_overridePrecision ) { precision++; val *= 10; } } 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; } } } 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( node->GetCurrentQueryStage() == Node::QueryStage_Complete && cc != NULL ) { cc->SetValueBasic( _instance, _level ); } } } } //----------------------------------------------------------------------------- // // The static data for this command class has been read from the device //----------------------------------------------------------------------------- void CommandClass::ClearStaticRequest ( uint8 _request ) { m_staticRequests &= ~_request; } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- bool CommandClass::RequestStateForAllInstances ( uint32 const _requestFlags, Driver::MsgQueue const _queue ) { bool res = false; if( m_createVars ) { 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 ); } } } return res; } open-zwave-1.5/cpp/src/command_classes/CommandClass.h000066400000000000000000000177451264474202400227160ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // CommandClass.h // // Base class for all Z-Wave Command Classes // // 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 . // //----------------------------------------------------------------------------- #ifndef _CommandClass_H #define _CommandClass_H #include #include #include #include "Defs.h" #include "Bitfield.h" #include "Driver.h" namespace OpenZWave { class Msg; class Node; class Value; /** \brief Base class for all Z-Wave command classes. */ 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, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue ) { return false; } virtual uint8 const GetCommandClassId()const = 0; virtual string const GetCommandClassName()const = 0; virtual bool HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ) = 0; 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 ){ m_version = _version; } 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_version; } 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, uint8 const _index ); bool RemoveValue( uint8 const _instance, uint8 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 ); void SetAfterMark(){ m_afterMark = true; } void SetEndPoint( uint8 const _instance, uint8 const _endpoint){ m_endPointMap[_instance] = _endpoint; } bool IsAfterMark()const{ return m_afterMark; } bool IsCreateVars()const{ return m_createVars; } bool IsGetSupported()const{ return m_getSupported; } bool IsSecured()const{ return m_isSecured; } void SetSecured(){ m_isSecured = true; } bool IsSecureSupported()const { return m_SecureSupport; } void ClearSecureSupport() { m_SecureSupport = false; } void SetSecureSupport() { m_SecureSupport = true; } void SetInNIF() { m_inNIF = true; } bool IsInNIF() { return m_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; uint8 index; std::vector RefreshClasses; } RefreshValue; protected: virtual void CreateVars( uint8 const _instance ){} void ReadValueRefreshXML ( TiXmlElement const* _ccElement ); public: virtual void CreateVars( uint8 const _instance, uint8 const _index ){} private: uint32 m_homeId; uint8 m_nodeId; uint8 m_version; Bitfield m_instances; OPENZWAVE_EXPORT_WARNINGS_OFF map m_endPointMap; OPENZWAVE_EXPORT_WARNINGS_ON bool m_afterMark; // Set to true if the command class is listed after COMMAND_CLASS_MARK, and should not create any values. bool m_createVars; // Do we want to create variables int8 m_overridePrecision; // Override precision when writing values if >=0 bool m_getSupported; // Get operation supported bool m_isSecured; // is this command class secured with the Security Command Class 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 ? bool m_inNIF; // Was this command class present in the NIF Frame we recieved (or was it created from our device_classes.xml file, or because it was in the Security SupportedReport message //----------------------------------------------------------------------------- // 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 _request )const{ return( (m_staticRequests & _request) != 0 ); } void SetStaticRequest( uint8 _request ){ m_staticRequests |= _request; } void ClearStaticRequest( uint8 _request ); private: uint8 m_staticRequests; //----------------------------------------------------------------------------- // 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 OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/CommandClasses.cpp000066400000000000000000000356741264474202400236020ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // CommandClasses.cpp // // Singleton holding methods to create each command class object // // 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 . // //----------------------------------------------------------------------------- #include #include "command_classes/CommandClasses.h" using namespace OpenZWave; #include "command_classes/Alarm.h" #include "command_classes/ApplicationStatus.h" #include "command_classes/Association.h" #include "command_classes/AssociationCommandConfiguration.h" #include "command_classes/Basic.h" #include "command_classes/BasicWindowCovering.h" #include "command_classes/Battery.h" #include "command_classes/CentralScene.h" #include "command_classes/ClimateControlSchedule.h" #include "command_classes/Clock.h" #include "command_classes/Color.h" #include "command_classes/Configuration.h" #include "command_classes/ControllerReplication.h" #include "command_classes/CRC16Encap.h" #include "command_classes/DeviceResetLocally.h" #include "command_classes/DoorLock.h" #include "command_classes/DoorLockLogging.h" #include "command_classes/EnergyProduction.h" #include "command_classes/Hail.h" #include "command_classes/Indicator.h" #include "command_classes/Language.h" #include "command_classes/Lock.h" #include "command_classes/ManufacturerSpecific.h" #include "command_classes/Meter.h" #include "command_classes/MeterPulse.h" #include "command_classes/MultiCmd.h" #include "command_classes/MultiInstance.h" #include "command_classes/MultiInstanceAssociation.h" #include "command_classes/NodeNaming.h" #include "command_classes/NoOperation.h" #include "command_classes/Powerlevel.h" #include "command_classes/Proprietary.h" #include "command_classes/Protection.h" #include "command_classes/SceneActivation.h" #include "command_classes/Security.h" #include "command_classes/SensorAlarm.h" #include "command_classes/SensorBinary.h" #include "command_classes/SensorMultilevel.h" #include "command_classes/SwitchAll.h" #include "command_classes/SwitchBinary.h" #include "command_classes/SwitchMultilevel.h" #include "command_classes/SwitchToggleBinary.h" #include "command_classes/SwitchToggleMultilevel.h" #include "command_classes/TimeParameters.h" #include "command_classes/ThermostatFanMode.h" #include "command_classes/ThermostatFanState.h" #include "command_classes/ThermostatMode.h" #include "command_classes/ThermostatOperatingState.h" #include "command_classes/ThermostatSetpoint.h" #include "command_classes/UserCode.h" #include "command_classes/Version.h" #include "command_classes/WakeUp.h" #include "command_classes/ZWavePlusInfo.h" #include "value_classes/ValueBool.h" #include "value_classes/ValueButton.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueDecimal.h" #include "value_classes/ValueInt.h" #include "value_classes/ValueList.h" #include "value_classes/ValueSchedule.h" #include "value_classes/ValueShort.h" #include "value_classes/ValueString.h" #include "Manager.h" #include "Options.h" #include "Utils.h" //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- 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"); } //----------------------------------------------------------------------------- // // Static method to register a command class creator method //----------------------------------------------------------------------------- void CommandClasses::Register ( uint8 const _commandClassId, string const& _commandClassName, pfnCreateCommandClass_t _creator ) { m_commandClassCreators[_commandClassId] = _creator; // Set the bit representing the command class Get().m_supportedCommandClasses[_commandClassId>>5] |= (1u<<(_commandClassId&0x1f)); m_namesToIDs[_commandClassName] = _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; } // Create an instance of the command class return creator( _homeId, _nodeId ); } //----------------------------------------------------------------------------- // // 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( 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( 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( MultiInstanceAssociation::StaticGetCommandClassId(), MultiInstanceAssociation::StaticGetCommandClassName(), MultiInstanceAssociation::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( 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 ); // 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 ); } } //----------------------------------------------------------------------------- // // 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; 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)); } } } } //----------------------------------------------------------------------------- // // 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; } return 0xff; } open-zwave-1.5/cpp/src/command_classes/CommandClasses.h000066400000000000000000000052171264474202400232350ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // CommandClasses.h // // Singleton holding methods to create each command class object // // 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 . // //----------------------------------------------------------------------------- #ifndef _CommandClasses_H #define _CommandClasses_H #include #include #include "Defs.h" namespace OpenZWave { class CommandClass; /** \brief Manages a map of command classes supported by a specific Z-Wave node. */ class CommandClasses { public: typedef CommandClass* (*pfnCreateCommandClass_t)( uint32 const _homeId, uint8 const _nodeId ); static void RegisterCommandClasses(); static CommandClass* CreateCommandClass( uint8 const _commandClassId, uint32 const _homeId, uint8 const _nodeId ); static bool IsSupported( uint8 const _commandClassId ); static string GetName(uint8 const _commandClassId); private: CommandClasses(); CommandClasses( CommandClasses const& ); // prevent copy CommandClasses& operator = ( CommandClasses const& ); // prevent assignment static CommandClasses& Get() { static CommandClasses instance; return instance; } void Register( uint8 const _commandClassId, string const& _commandClassName, pfnCreateCommandClass_t _create ); void ParseCommandClassOption( string const& _optionStr, bool const _include ); uint8 GetCommandClassId( string const& _name ); pfnCreateCommandClass_t m_commandClassCreators[256]; map m_namesToIDs; // 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 OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Configuration.cpp000066400000000000000000000201521264474202400234760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Configuration.cpp // // Implementation of the Z-Wave COMMAND_CLASS_CONFIGURATION // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Configuration.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" #include "value_classes/ValueButton.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueInt.h" #include "value_classes/ValueList.h" #include "value_classes/ValueShort.h" using namespace OpenZWave; 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() ) { 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: { 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; } //----------------------------------------------------------------------------- // // Set a value in the Z-Wave device //----------------------------------------------------------------------------- bool Configuration::SetValue ( Value const& _value ) { uint8 param = _value.GetID().GetIndex(); switch( _value.GetID().GetType() ) { 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; } //----------------------------------------------------------------------------- // // Request current parameter value from the device //----------------------------------------------------------------------------- bool Configuration::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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 ); 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 ( uint8 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 ); 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 ); } open-zwave-1.5/cpp/src/command_classes/Configuration.h000066400000000000000000000045031264474202400231450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Configuration.h // // Implementation of the Z-Wave COMMAND_CLASS_CONFIGURATION // // 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 . // //----------------------------------------------------------------------------- #ifndef _Configuration_H #define _Configuration_H #include #include "command_classes/CommandClass.h" namespace OpenZWave { class Value; /** \brief Implements COMMAND_CLASS_CONFIGURATION (0x70), a Z-Wave device command class. */ class Configuration: public CommandClass { friend class Node; public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Configuration( _homeId, _nodeId ); } virtual ~Configuration(){} static uint8 const StaticGetCommandClassId(){ return 0x70; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CONFIGURATION"; } virtual bool RequestValue( uint32 const _requestFlags, uint8 const _parameter, uint8 const _index, Driver::MsgQueue const _queue ); void Set( uint8 const _parameter, int32 const _value, uint8 const _size ); // 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 ); private: Configuration( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ControllerReplication.cpp000066400000000000000000000213621264474202400252100ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ControllerReplication.cpp // // Implementation of the Z-Wave COMMAND_CLASS_CONTROLLER_REPLICATION // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/ControllerReplication.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #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 { ControllerReplicationCmd_TransferGroup = 0x31, ControllerReplicationCmd_TransferGroupName = 0x32, ControllerReplicationCmd_TransferScene = 0x33, ControllerReplicationCmd_TransferSceneName = 0x34 }; enum { ControllerReplicationIndex_NodeId = 0, ControllerReplicationIndex_Function, ControllerReplicationIndex_Replicate }; 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 ) { } //----------------------------------------------------------------------------- // // 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 ); 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; } //----------------------------------------------------------------------------- // // 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, 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 ) ) ) { if( button->IsPressed() ) { res = StartReplication( instance ); } button->Release(); } 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; } if( ValueByte* value = static_cast( GetValue( _instance, ControllerReplicationIndex_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; } // 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; } //----------------------------------------------------------------------------- // // Send the next block of replication data //----------------------------------------------------------------------------- void ControllerReplication::SendNextData ( ) { uint16 i = 255; 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 ) { 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; } } //----------------------------------------------------------------------------- // // 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; 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 ); } } open-zwave-1.5/cpp/src/command_classes/ControllerReplication.h000066400000000000000000000045741264474202400246630ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ControllerReplication.h // // Implementation of the Z-Wave COMMAND_CLASS_CONTROLLER_REPLICATION // // 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 . // //----------------------------------------------------------------------------- #ifndef _ControllerReplication_H #define _ControllerReplication_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_CONTROLLER_REPLICATION (0x21), a Z-Wave device command class. */ class ControllerReplication: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ControllerReplication( _homeId, _nodeId ); } virtual ~ControllerReplication(){} static uint8 const StaticGetCommandClassId(){ return 0x21; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_CONTROLLER_REPLICATION"; } // 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 ); void SendNextData(); protected: virtual void CreateVars( uint8 const _instance ); 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; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/DeviceResetLocally.cpp000066400000000000000000000045671264474202400244250ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // DeviceResetLocally.cpp // // Implementation of the Z-Wave COMMAND_CLASS_DEVICE_RESET_LOCALLY // // Copyright (c) 2015 // // 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/DeviceResetLocally.h" #include "command_classes/NoOperation.h" #include "Defs.h" #include "Manager.h" #include "platform/Log.h" using namespace OpenZWave; 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() ) ) ) { noop->Set( true ); } } // the Controller now knows the node has failed Manager::Get()->HasNodeFailed( GetHomeId(), GetNodeId() ); m_deviceReset = true; return true; } return false; } open-zwave-1.5/cpp/src/command_classes/DeviceResetLocally.h000066400000000000000000000042051264474202400240570ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // DeviceResetLocally.h // // Implementation of the Z-Wave COMMAND_CLASS_DEVICE_RESET_LOCALLY // // Copyright (c) 2015 // // 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 _DeviceResetLocally_H #define _DeviceResetLocally_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_DEVICE_RESET_LOCALLY (0x5a), a Z-Wave device command class. */ 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{ 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 OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/DoorLock.cpp000066400000000000000000000460521264474202400224120ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // DoorLock.cpp // // Implementation of the Z-Wave COMMAND_CLASS_DOOR_LOCK // // Copyright (c) 2014 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 "command_classes/CommandClasses.h" #include "command_classes/DoorLock.h" #include "command_classes/WakeUp.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueInt.h" #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 { DoorLockControlState_Handle1 = 0x01, DoorLockControlState_Handle2 = 0x02, DoorLockControlState_Handle3 = 0x04, DoorLockControlState_Handle4 = 0x08 }; 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 }; 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_timeoutsupported(0), m_insidehandlemode(0), m_outsidehandlemode(0), m_timeoutmins(0xFE), m_timeoutsecs(0xFE) { SetStaticRequest( StaticRequest_Values ); } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void DoorLock::ReadXML ( TiXmlElement const* _ccElement ) { int32 intVal; CommandClass::ReadXML( _ccElement ); if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_timeoutsupported", &intVal ) ) { m_timeoutsupported = intVal; } if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_insidehandlemode", &intVal ) ) { m_insidehandlemode = intVal; } if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_outsidehandlemode", &intVal ) ) { m_outsidehandlemode = intVal; } if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_timeoutmins", &intVal ) ) { m_timeoutmins = intVal; } if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_timeoutsecs", &intVal ) ) { m_timeoutsecs = intVal; } } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void DoorLock::WriteXML ( TiXmlElement* _ccElement ) { char str[32]; CommandClass::WriteXML( _ccElement ); snprintf( str, sizeof(str), "%d", m_timeoutsupported ); _ccElement->SetAttribute( "m_timeoutsupported", str); snprintf( str, sizeof(str), "%d", m_insidehandlemode ); _ccElement->SetAttribute( "m_insidehandlemode", str); snprintf( str, sizeof(str), "%d", m_outsidehandlemode ); _ccElement->SetAttribute( "m_outsidehandlemode", str); snprintf( str, sizeof(str), "%d", m_timeoutmins ); _ccElement->SetAttribute( "m_timeoutmins", str); snprintf( str, sizeof(str), "%d", m_timeoutsecs ); _ccElement->SetAttribute( "m_timeoutsecs", str); } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool DoorLock::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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] ); 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_timeoutsupported = DoorLockConfig_NoTimeout; RemoveValue(_instance, Value_System_Config_Minutes); RemoveValue(_instance, Value_System_Config_Seconds); m_timeoutmins = 0xFE; m_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, 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 ); } m_timeoutsupported = DoorLockConfig_Timeout; m_timeoutmins = _data[3]; m_timeoutsecs = _data[4]; break; default: Log::Write(LogLevel_Warning, GetNodeId(), "Recieved 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_outsidehandlemode = ((_data[2] & 0xF0)>>4); } if( ValueByte* value = static_cast( GetValue( _instance, Value_System_Config_InsideHandles ) ) ) { value->OnValueRefreshed( (_data[2] & 0x0F) ); value->Release(); m_insidehandlemode = (_data[2] & 0x0F); } ClearStaticRequest( StaticRequest_Values ); } 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() ) { 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() ) ) ) { ValueList::Item const *item = (static_cast( &_value))->GetItem(); if (item != NULL) value->OnValueRefreshed( item->m_value ); value->Release(); } 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() ) ) ) { 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; } if( 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( ValueList* value = static_cast( GetValue( instance, Value_System_Config_Mode ) ) ) { ValueList::Item const *item = value->GetItem(); if (item != NULL) m_timeoutsupported = item->m_value; } else { ok = false; Log::Write(LogLevel_Warning, GetNodeId(), "Failed To Retrieve Value_System_Config_Mode For SetValue"); } uint8 control = 0; if( ValueByte* value = static_cast( GetValue( instance, Value_System_Config_OutsideHandles ) ) ) { control = (value->GetValue() << 4); m_insidehandlemode = 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_outsidehandlemode = (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_timeoutmins = value->GetValue(); } else { /* Minutes and Seconds Might Not Exist, this is fine. Set to 0xFE */ m_timeoutmins = 0xFE; } if( ValueInt* value = static_cast( GetValue( instance, Value_System_Config_Seconds ) ) ) { m_timeoutsecs = value->GetValue(); } else { /* Minutes and Seconds Might Not Exist, this is fine. Set to 0xFE */ m_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_timeoutsupported ); msg->Append( control ); msg->Append( m_timeoutmins ); msg->Append( m_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() ) { if( ValueBool* value = static_cast( GetValue( _instance, Value_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 ); } } open-zwave-1.5/cpp/src/command_classes/DoorLock.h000066400000000000000000000051351264474202400220540ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // DoorLock.h // // Implementation of the Z-Wave COMMAND_CLASS_DOOR_LOCK // // Copyright (c) 2014 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 _DoorLock_H #define _DoorLock_H #include "CommandClass.h" namespace OpenZWave { class ValueBool; /** \brief Implements COMMAND_CLASS_DOOR_LOCK (0x62), a Z-Wave device command class. */ class DoorLock: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new DoorLock( _homeId, _nodeId ); } virtual ~DoorLock(){} static uint8 const StaticGetCommandClassId(){ return 0x62; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_DOOR_LOCK"; } // 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, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: DoorLock( uint32 const _homeId, uint8 const _nodeId ); uint8 m_timeoutsupported; uint8 m_insidehandlemode; uint8 m_outsidehandlemode; uint8 m_timeoutmins; uint8 m_timeoutsecs; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/DoorLockLogging.cpp000066400000000000000000000301421264474202400237120ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // DoorLockLogging.cpp // // Implementation of the Z-Wave COMMAND_CLASS_DOOR_LOCK_LOGGING // // Copyright (c) 2014 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 "command_classes/CommandClasses.h" #include "command_classes/DoorLockLogging.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueInt.h" #include "value_classes/ValueString.h" #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[] = { "Locked via Access Code", "Unlocked via Access Code", "Locked via Lock Button", "Unlocked via UnLock Botton", "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 */ }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- DoorLockLogging::DoorLockLogging ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_MaxRecords(0), m_CurRecord(0) { SetStaticRequest( StaticRequest_Values ); } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void DoorLockLogging::ReadXML ( TiXmlElement const* _ccElement ) { int32 intVal; CommandClass::ReadXML( _ccElement ); if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "m_MaxRecords", &intVal ) ) { m_MaxRecords = intVal; } } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void DoorLockLogging::WriteXML ( TiXmlElement* _ccElement ) { char str[32]; CommandClass::WriteXML( _ccElement ); snprintf( str, sizeof(str), "%d", m_MaxRecords ); _ccElement->SetAttribute( "m_MaxRecords", str); } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool DoorLockLogging::RequestValue ( uint32 const _requestFlags, uint8 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_MaxRecords = _data[1]; if( ValueByte* value = static_cast( GetValue( _instance, Value_System_Config_MaxRecords ) ) ) { value->OnValueRefreshed( m_MaxRecords ); 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(), "Recieved 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) { valid = true; } uint8 userid = (_data[10]); uint8 usercodelength = (_data[11]); char usercode[254]; snprintf(usercode, sizeof(usercode), "UserCode:"); if (usercodelength > 0) for (int i = 0; i < usercodelength; i++ ) { snprintf(usercode, sizeof(usercode), "%s %d", usercode, (int)_data[12+i]); } 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/DoorLockLogging.h000066400000000000000000000050011264474202400233530ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // DoorLockLogging.h // // Implementation of the Z-Wave COMMAND_CLASS_DOOR_LOCK_LOGGING // // Copyright (c) 2014 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 _DoorLockLogging_H #define _DoorLockLogging_H #include "CommandClass.h" namespace OpenZWave { class ValueBool; /** \brief Implements COMMAND_CLASS_DOOR_LOCK_LOGGING (0x4C), a Z-Wave device command class. */ class DoorLockLogging: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new DoorLockLogging( _homeId, _nodeId ); } virtual ~DoorLockLogging(){} static uint8 const StaticGetCommandClassId(){ return 0x4c; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_DOOR_LOCK_LOGGING"; } // 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, uint8 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 ); private: DoorLockLogging( uint32 const _homeId, uint8 const _nodeId ); uint8 m_MaxRecords; uint8 m_CurRecord; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/EnergyProduction.cpp000066400000000000000000000142651264474202400241770ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // EnergyProduction.cpp // // Implementation of the Z-Wave COMMAND_CLASS_ENERGY_PRODUCTION // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/EnergyProduction.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueDecimal.h" using namespace OpenZWave; enum EnergyProductionCmd { EnergyProductionCmd_Get = 0x02, EnergyProductionCmd_Report = 0x03 }; enum { EnergyProductionIndex_Instant = 0, EnergyProductionIndex_Total, EnergyProductionIndex_Today, EnergyProductionIndex_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; } //----------------------------------------------------------------------------- // // Request current production from the device //----------------------------------------------------------------------------- bool EnergyProduction::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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 ); 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 ) { decimalValue->SetPrecision( precision ); } 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 ); } } open-zwave-1.5/cpp/src/command_classes/EnergyProduction.h000066400000000000000000000045721264474202400236440ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // EnergyProduction.h // // Implementation of the Z-Wave COMMAND_CLASS_ENERGY_PRODUCTION // // 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 . // //----------------------------------------------------------------------------- #ifndef _EnergyProduction_H #define _EnergyProduction_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueDecimal; /** \brief Implements COMMAND_CLASS_ENERGY_PRODUCTION (0x90), a Z-Wave device command class. */ class EnergyProduction: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new EnergyProduction( _homeId, _nodeId ); } virtual ~EnergyProduction(){} static uint8 const StaticGetCommandClassId(){ return 0x90; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ENERGY_PRODUCTION"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: EnergyProduction( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Hail.cpp000066400000000000000000000036311264474202400215470ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Hail.cpp // // Implementation of the Z-Wave COMMAND_CLASS_HAIL // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Hail.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" using namespace OpenZWave; 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; } open-zwave-1.5/cpp/src/command_classes/Hail.h000066400000000000000000000036601264474202400212160ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Hail.h // // Implementation of the Z-Wave COMMAND_CLASS_HAIL // // 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 . // //----------------------------------------------------------------------------- #ifndef _Hail_H #define _Hail_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_HAIL (0x82), a Z-Wave device command class. */ class Hail: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Hail( _homeId, _nodeId ); } virtual ~Hail(){} static uint8 const StaticGetCommandClassId(){ return 0x82; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_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 ); private: Hail( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Indicator.cpp000066400000000000000000000115361264474202400226110ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Indicator.cpp // // Implementation of the Z-Wave COMMAND_CLASS_INDICATOR // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Indicator.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" using namespace OpenZWave; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Indicator::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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] ); if( ValueByte* value = static_cast( GetValue( _instance, 0 ) ) ) { value->OnValueRefreshed( _data[1] != 0 ); value->Release(); } return true; } 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); 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/Indicator.h000066400000000000000000000045341264474202400222560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Indicator.h // // Implementation of the Z-Wave COMMAND_CLASS_INDICATOR // // 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 . // //----------------------------------------------------------------------------- #ifndef _Indicator_H #define _Indicator_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_INDICATOR (0x87), a Z-Wave device command class. */ class Indicator: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Indicator( _homeId, _nodeId ); } virtual ~Indicator(){} static uint8 const StaticGetCommandClassId(){ return 0x87; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_INDICATOR"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: Indicator( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Language.cpp000066400000000000000000000113441264474202400224150ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Language.cpp // // Implementation of the Z-Wave COMMAND_CLASS_LANGUAGE // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Language.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueString.h" using namespace OpenZWave; enum LanguageCmd { LanguageCmd_Set = 0x01, LanguageCmd_Get = 0x02, LanguageCmd_Report = 0x03 }; enum { LanguageIndex_Language = 0, LanguageIndex_Country }; //----------------------------------------------------------------------------- // // 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Language::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/Language.h000066400000000000000000000045171264474202400220660ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Language.h // // Implementation of the Z-Wave COMMAND_CLASS_LANGUAGE // // 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 . // //----------------------------------------------------------------------------- #ifndef _Language_H #define _Language_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueString; /** \brief Implements COMMAND_CLASS_LANGUAGE (0x89), a Z-Wave device command class. */ class Language: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Language( _homeId, _nodeId ); } virtual ~Language(){} static uint8 const StaticGetCommandClassId(){ return 0x89; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_LANGUAGE"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: Language( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); } }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Lock.cpp000066400000000000000000000114031264474202400215560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Lock.cpp // // Implementation of the Z-Wave COMMAND_CLASS_LOCK // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Lock.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" using namespace OpenZWave; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Lock::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/Lock.h000066400000000000000000000044521264474202400212310ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Lock.h // // Implementation of the Z-Wave COMMAND_CLASS_LOCK // // 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 . // //----------------------------------------------------------------------------- #ifndef _Lock_H #define _Lock_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueBool; /** \brief Implements COMMAND_CLASS_LOCK (0x76), a Z-Wave device command class. */ class Lock: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Lock( _homeId, _nodeId ); } virtual ~Lock(){} static uint8 const StaticGetCommandClassId(){ return 0x76; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_LOCK"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: Lock( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ManufacturerSpecific.cpp000066400000000000000000000324601264474202400247760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ManufacturerSpecific.cpp // // Implementation of the Z-Wave COMMAND_CLASS_MANUFACTURER_SPECIFIC // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/ManufacturerSpecific.h" #include "tinyxml.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Options.h" #include "Manager.h" #include "Driver.h" #include "Notification.h" #include "platform/Log.h" #include "value_classes/ValueStore.h" #include "value_classes/ValueString.h" using namespace OpenZWave; enum ManufacturerSpecificCmd { ManufacturerSpecificCmd_Get = 0x04, ManufacturerSpecificCmd_Report = 0x05 }; map ManufacturerSpecific::s_manufacturerMap; map ManufacturerSpecific::s_productMap; bool ManufacturerSpecific::s_bXmlLoaded = false; //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- bool ManufacturerSpecific::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; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool ManufacturerSpecific::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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 ManufacturerSpecific::SetProductDetails ( Node* node, uint16 manufacturerId, uint16 productType, uint16 productId ) { char str[64]; if (!s_bXmlLoaded) LoadProductXML(); snprintf( str, sizeof(str), "Unknown: id=%.4x", manufacturerId ); string manufacturerName = str; snprintf( str, sizeof(str), "Unknown: type=%.4x, id=%.4x", productType, productId ); string productName = str; string configPath = ""; // Try to get the real manufacturer and product names map::iterator mit = s_manufacturerMap.find( manufacturerId ); if( mit != s_manufacturerMap.end() ) { // Replace the id with the real name manufacturerName = mit->second; // Get the product map::iterator pit = s_productMap.find( Product::GetKey( manufacturerId, productType, productId ) ); if( pit != s_productMap.end() ) { productName = pit->second->GetProductName(); configPath = pit->second->GetConfigPath(); } } // Set the values into the node // Only set the manufacturer and product name if they are // empty - we don't want to overwrite any user defined names. if( node->GetManufacturerName() == "" ) { node->SetManufacturerName( manufacturerName ); } if( node->GetProductName() == "" ) { node->SetProductName( productName ); } // snprintf( str, sizeof(str), "%.4x", manufacturerId ); node->SetManufacturerId( manufacturerId ); // snprintf( str, sizeof(str), "%.4x", productType ); node->SetProductType( productType ); // snprintf( str, sizeof(str), "%.4x", productId ); node->SetProductId( productId ); return configPath; } //----------------------------------------------------------------------------- // // 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 string configPath = SetProductDetails( node, manufacturerId, productType, productId); if( configPath.size() > 0 ) { LoadConfigXML( node, configPath ); } 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 ); ClearStaticRequest( StaticRequest_Values ); node->m_manufacturerSpecificClassReceived = true; } // Notify the watchers of the name changes Notification* notification = new Notification( Notification::Type_NodeNaming ); notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() ); GetDriver()->QueueNotification( notification ); return true; } return false; } //----------------------------------------------------------------------------- // // Load the XML that maps manufacturer and product IDs to human-readable names //----------------------------------------------------------------------------- bool ManufacturerSpecific::LoadProductXML ( ) { s_bXmlLoaded = true; // Parse the Z-Wave manufacturer and product XML file. string configPath; Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); 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; } TiXmlElement const* root = pDoc->RootElement(); char const* str; char* pStopChar; 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 ) { Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing manufacturer id attribute", manufacturerElement->Row() ); delete pDoc; return false; } uint16 manufacturerId = (uint16)strtol( str, &pStopChar, 16 ); str = manufacturerElement->Attribute( "name" ); if( !str ) { Log::Write( LogLevel_Info, "Error in manufacturer_specific.xml at line %d - missing manufacturer name attribute", manufacturerElement->Row() ); delete pDoc; return false; } // Add this manufacturer to the map s_manufacturerMap[manufacturerId] = str; // Parse all the products for this manufacturer TiXmlElement const* productElement = manufacturerElement->FirstChildElement(); while( productElement ) { 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 configPath; str = productElement->Attribute( "config" ); if( str ) { configPath = str; } // Add the product to the map Product* product = new Product( manufacturerId, productType, productId, productName, configPath ); if ( s_productMap[product->GetKey()] != NULL ) { Product *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 { s_productMap[product->GetKey()] = product; } } // Move on to the next product. productElement = productElement->NextSiblingElement(); } } // Move on to the next manufacturer. manufacturerElement = manufacturerElement->NextSiblingElement(); } delete pDoc; return true; } //----------------------------------------------------------------------------- // // Free the XML that maps manufacturer and product IDs //----------------------------------------------------------------------------- void ManufacturerSpecific::UnloadProductXML ( ) { if (s_bXmlLoaded) { map::iterator pit = s_productMap.begin(); while( !s_productMap.empty() ) { delete pit->second; 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(); } s_bXmlLoaded = false; } } //----------------------------------------------------------------------------- // // Try to find and load an XML file describing the device's config params //----------------------------------------------------------------------------- bool ManufacturerSpecific::LoadConfigXML ( Node* _node, string const& _configXML ) { string configPath; Options::Get()->GetOptionAsString( "ConfigPath", &configPath ); string filename = configPath + _configXML; TiXmlDocument* doc = new TiXmlDocument(); Log::Write( LogLevel_Info, _node->GetNodeId(), " Opening config param file %s", filename.c_str() ); if( !doc->LoadFile( filename.c_str(), TIXML_ENCODING_UTF8 ) ) { delete doc; Log::Write( LogLevel_Info, _node->GetNodeId(), "Unable to find or load Config Param file %s", filename.c_str() ); return false; } Node::QueryStage qs = _node->GetCurrentQueryStage(); if( qs == Node::QueryStage_ManufacturerSpecific1 ) { _node->ReadDeviceProtocolXML( doc->RootElement() ); } else { if( !_node->m_manufacturerSpecificClassReceived ) { _node->ReadDeviceProtocolXML( doc->RootElement() ); } _node->ReadCommandClassesXML( doc->RootElement() ); } delete doc; return true; } //----------------------------------------------------------------------------- // // Reload previously discovered device configuration. //----------------------------------------------------------------------------- void ManufacturerSpecific::ReLoadConfigXML ( ) { if( Node* node = GetNodeUnsafe() ) { if (!s_bXmlLoaded) LoadProductXML(); uint16 manufacturerId = node->GetManufacturerId(); uint16 productType = node->GetProductType(); uint16 productId = node->GetProductId(); map::iterator mit = s_manufacturerMap.find( manufacturerId ); if( mit != s_manufacturerMap.end() ) { map::iterator pit = s_productMap.find( Product::GetKey( manufacturerId, productType, productId ) ); if( pit != s_productMap.end() ) { string configPath = pit->second->GetConfigPath(); if( configPath.size() > 0 ) { LoadConfigXML( node, configPath ); } } } } } open-zwave-1.5/cpp/src/command_classes/ManufacturerSpecific.h000066400000000000000000000076161264474202400244500ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ManufacturerSpecific.h // // Implementation of the Z-Wave COMMAND_CLASS_MANUFACTURER_SPECIFIC // // 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 . // //----------------------------------------------------------------------------- #ifndef _ManufacturerSpecific_H #define _ManufacturerSpecific_H #include #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_MANUFACTURER_SPECIFIC (0x72), a Z-Wave device command class. */ class ManufacturerSpecific: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ManufacturerSpecific( _homeId, _nodeId ); } virtual ~ManufacturerSpecific(){ UnloadProductXML(); } 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, uint8 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 string SetProductDetails( Node *_node, uint16 _manufacturerId, uint16 _productType, uint16 _productId ); static bool LoadConfigXML( Node* _node, string const& _configXML ); void ReLoadConfigXML(); private: ManufacturerSpecific( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); } static bool LoadProductXML(); static void UnloadProductXML(); class Product { public: Product ( uint16 _manufacturerId, uint16 _productType, uint16 _productId, string const& _productName, string const& _configPath ): m_manufacturerId( _manufacturerId ), m_productType( _productType ), m_productId( _productId ), m_productName( _productName ), m_configPath( _configPath ) { } int64 GetKey()const { return( GetKey( m_manufacturerId, m_productType, m_productId ) ); } static int64 GetKey( uint16 _manufacturerId, uint16 _productType, uint16 _productId ) { int64 key = (((int64)_manufacturerId)<<32) | (((int64)_productType)<<16) | (int64)_productId; return key; } uint16 GetManufacturerId()const{ return m_manufacturerId; } uint16 GetProductType()const{ return m_productType; } uint16 GetProductId()const{ return m_productId; } string GetProductName()const{ return m_productName; } string GetConfigPath()const{ return m_configPath; } private: uint16 m_manufacturerId; uint16 m_productType; uint16 m_productId; string m_productName; string m_configPath; }; static map s_manufacturerMap; static map s_productMap; static bool s_bXmlLoaded; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Meter.cpp000066400000000000000000000354261264474202400217550ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Meter.cpp // // Implementation of the Z-Wave COMMAND_CLASS_METER // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Meter.h" #include "command_classes/MultiInstance.h" #include "Defs.h" #include "Bitfield.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueDecimal.h" #include "value_classes/ValueList.h" #include "value_classes/ValueButton.h" #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 { 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" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Meter::Meter ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ) { 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; } } if( _requestFlags & RequestFlag_Dynamic ) { res |= RequestValue( _requestFlags, 0, _instance, _queue ); } return res; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Meter::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { bool res = false; if ( !IsGetSupported()) { 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; } //----------------------------------------------------------------------------- // // 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 ); } 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<( 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 ); } if( i != 0 ) msg += ", "; msg += c_gasUnits[i]; break; } case MeterType_Water: { if( ValueDecimal* value = static_cast( GetValue( _instance, baseIndex ) ) ) { value->SetLabel( c_meterTypes[MeterType_Water] ); value->SetUnits( c_waterUnits[i] ); value->Release(); } 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: { break; } } } } // 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: { 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; } 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(); // Read any previous value and time delta uint8 size = _data[2] & 0x07; uint16 delta = (uint16)( (_data[3+size]<<8) | _data[4+size]); 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 ) { // 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 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(); } } } } 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; } } 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 ); } } open-zwave-1.5/cpp/src/command_classes/Meter.h000066400000000000000000000050071264474202400214120ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Meter.h // // Implementation of the Z-Wave COMMAND_CLASS_METER // // 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 . // //----------------------------------------------------------------------------- #ifndef _Meter_H #define _Meter_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueDecimal; /** \brief Implements COMMAND_CLASS_METER (0x32), a Z-Wave device command class. */ class Meter: public CommandClass { 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, uint8 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; } protected: virtual void CreateVars( uint8 const _instance ); 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 ); }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/MeterPulse.cpp000066400000000000000000000077361264474202400227710ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MeterPulse.cpp // // Implementation of the Z-Wave COMMAND_CLASS_METER_PULSE // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/MeterPulse.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueInt.h" using namespace OpenZWave; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool MeterPulse::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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]; } 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(); } return true; } 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 ); } } open-zwave-1.5/cpp/src/command_classes/MeterPulse.h000066400000000000000000000044701264474202400224260ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MeterPulse.h // // Implementation of the Z-Wave COMMAND_CLASS_METER_PULSE // // 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 . // //----------------------------------------------------------------------------- #ifndef _MeterPulse_H #define _MeterPulse_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueInt; /** \brief Implements COMMAND_CLASS_METER_PULSE (0x35), a Z-Wave device command class. */ class MeterPulse: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MeterPulse( _homeId, _nodeId ); } virtual ~MeterPulse(){} static uint8 const StaticGetCommandClassId(){ return 0x35; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_METER_PULSE"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: MeterPulse( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/MultiCmd.cpp000066400000000000000000000043551264474202400224140ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MultiCmd.h // // Implementation of the Z-Wave COMMAND_CLASS_MULTI_CMD // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/MultiCmd.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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 ) { uint8 length = _data[base]; uint8 commandClassId = _data[base+1]; if( CommandClass* pCommandClass = node->GetCommandClass( commandClassId ) ) { pCommandClass->HandleMsg( &_data[base+2], length-1 ); } base += (length + 1); } } Log::Write( LogLevel_Info, GetNodeId(), "End of encapsulated multi-command from node %d", GetNodeId() ); return true; } return false; } open-zwave-1.5/cpp/src/command_classes/MultiCmd.h000066400000000000000000000040241264474202400220520ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MultiCmd.h // // Implementation of the Z-Wave COMMAND_CLASS_MULTI_CMD // // 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 . // //----------------------------------------------------------------------------- #ifndef _MultiCmd_H #define _MultiCmd_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_MULTI_CMD (0x8f), a Z-Wave device command class. */ class MultiCmd: public CommandClass { public: enum MultiCmdCmd { MultiCmdCmd_Encap = 0x01 }; static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MultiCmd( _homeId, _nodeId ); } virtual ~MultiCmd(){} static uint8 const StaticGetCommandClassId(){ return 0x8f; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MULTI_CMD"; } // 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: MultiCmd( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/MultiInstance.cpp000066400000000000000000000517361264474202400234620ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MultiInstance.cpp // // Implementation of the Z-Wave COMMAND_CLASS_MULTI_INSTANCE // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "command_classes/CommandClasses.h" #include "command_classes/Basic.h" #include "command_classes/MultiInstance.h" #include "command_classes/NoOperation.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" using namespace OpenZWave; // 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" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- MultiInstance::MultiInstance ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_numEndPoints( 0 ), m_numEndPointsHint( 0 ), m_endPointMap( MultiInstanceMapAll ), m_endPointFindSupported( false ), m_uniqueendpoints( false ) { } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void MultiInstance::ReadXML ( TiXmlElement const* _ccElement ) { int32 intVal; char const* str; CommandClass::ReadXML( _ccElement ); if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "endpoints", &intVal ) ) { m_numEndPointsHint = (uint8)intVal; } str = _ccElement->Attribute("mapping"); if( str ) { if( strcmp( str, "all") == 0 ) { m_endPointMap = MultiInstanceMapAll; } else if( strcmp( str, "endpoints") == 0 ) { m_endPointMap = MultiInstanceMapEndPoints; } else { Log::Write( LogLevel_Info, GetNodeId(), "Bad value for mapping: %s", str); } } str = _ccElement->Attribute("findsupport"); if( str ) { m_endPointFindSupported = !strcmp( str, "true"); } str = _ccElement->Attribute("ignoreUnsolicitedMultiChnCapReport"); if( str ) { m_ignoreUnsolicitedMultiChannelCapabilityReport = !strcmp( str, "true"); } str = _ccElement->Attribute("forceUniqueEndpoints"); if( str ) { m_uniqueendpoints = !strcmp( str, "true"); } } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void MultiInstance::WriteXML ( TiXmlElement* _ccElement ) { char str[32]; CommandClass::WriteXML( _ccElement ); if( m_numEndPointsHint != 0 ) { snprintf( str, sizeof(str), "%d", m_numEndPointsHint ); _ccElement->SetAttribute( "endpoints", str); } if( m_endPointMap == MultiInstanceMapEndPoints ) { _ccElement->SetAttribute( "mapping", "endpoints" ); } if( m_endPointFindSupported ) { _ccElement->SetAttribute( "findsupport", "true" ); } if( m_uniqueendpoints ) { _ccElement->SetAttribute( "forceUniqueEndpoints", "true" ); } } //----------------------------------------------------------------------------- // // 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 ) { 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; } } } } 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; } //----------------------------------------------------------------------------- // // 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: { HandleMultiChannelCapabilityReport( _data, _length ); break; } case MultiChannelCmd_EndPointFindReport: { HandleMultiChannelEndPointFindReport( _data, _length ); break; } case MultiChannelCmd_Encap: { HandleMultiChannelEncap( _data, _length ); break; } default: { handled = false; break; } } } 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]; 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]; 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 ); } } } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- void MultiInstance::HandleMultiChannelEndPointReport ( uint8 const* _data, uint32 const _length ) { int len; if( m_numEndPoints != 0 ) { return; } 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_uniqueendpoints ) m_endPointsAreSameClass = false; m_numEndPoints = _data[2] & 0x7f; if( m_numEndPointsHint != 0 ) { m_numEndPoints = m_numEndPointsHint; // 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 ); } // 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 ); } } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- 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_ignoreUnsolicitedMultiChannelCapabilityReport && (node->GetCurrentQueryStage() != Node::QueryStage_Instances)) && !dynamic && m_endPointCommandClasses.size() > 0) { Log::Write(LogLevel_Error, GetNodeId(), "Recieved 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; continue; } m_endPointCommandClasses.insert( commandClassId ); // Ensure the node supports this command class CommandClass* cc = node->GetCommandClass( commandClassId ); if( !cc ) { cc = node->AddCommandClass( commandClassId ); if( cc && afterMark ) { cc->SetAfterMark(); } } if( cc ) { Log::Write( LogLevel_Info, GetNodeId(), " %s", cc->GetCommandClassName().c_str() ); } } // 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; if( m_endPointMap == MultiInstanceMapAll ) // Include the non-endpoint instance { endPoint = 0; len = m_numEndPoints + 1; } else { endPoint = 1; len = m_numEndPoints; } // 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 ) { cc->SetInstance( i ); if( m_endPointMap != MultiInstanceMapAll || 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_endPointMap != MultiInstanceMapAll || i != 1 ) { basic->SetEndPoint( i, endPoint ); } } } } endPoint++; } } 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 ) { uint8 i; // Find the next free instance of this class for( i = 1; i <= 127; i++ ) { if( m_endPointMap == MultiInstanceMapAll ) // 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 ); } } } } } } //----------------------------------------------------------------------------- // // 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 ) { 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 ); } } } } 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 ) { // 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"); } } } } } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- 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 ) ) { uint8 instance = pCommandClass->GetInstance( endPoint ); if( instance == 0 ) { Log::Write( LogLevel_Error, GetNodeId(), "Cannot find endpoint map to instance for Command Class %s endpoint %d", pCommandClass->GetCommandClassName().c_str(), endPoint ); } else { 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 { Log::Write(LogLevel_Error, GetNodeId(), "Recieved a MultiChannelEncap for endpoint %d for Command Class %d, which we can't find", endPoint, commandClassId); } } } open-zwave-1.5/cpp/src/command_classes/MultiInstance.h000066400000000000000000000075701264474202400231240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MultiInstance.h // // Implementation of the Z-Wave COMMAND_CLASS_MULTI_INSTANCE // // 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 . // //----------------------------------------------------------------------------- #ifndef _MultiInstance_H #define _MultiInstance_H #include #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_MULTI_INSTANCE (0x60), a Z-Wave device command class. */ 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 }; enum MultiInstanceMapping { MultiInstanceMapAll, MultiInstanceMapEndPoints, MultiInstanceMapOther }; 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 void ReadXML( TiXmlElement const* _ccElement ); virtual void WriteXML( TiXmlElement* _ccElement ); 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; } MultiInstanceMapping GetEndPointMap(){ return m_endPointMap; } 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; // configuration uint8 m_numEndPointsHint; // for nodes that do not report correct number of end points MultiInstanceMapping m_endPointMap; // Determine how to map end points to value id instances bool m_endPointFindSupported; // for nodes that (someday may) support endpointfind bool m_ignoreUnsolicitedMultiChannelCapabilityReport; bool m_uniqueendpoints; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/MultiInstanceAssociation.cpp000066400000000000000000000345521264474202400256540ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MultiInstanceAssociation.cpp // // Implementation of the Z-Wave COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "command_classes/CommandClasses.h" #include "command_classes/MultiInstanceAssociation.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "Group.h" #include "platform/Log.h" using namespace OpenZWave; enum MultiInstanceAssociationCmd { MultiInstanceAssociationCmd_Set = 0x01, MultiInstanceAssociationCmd_Get = 0x02, MultiInstanceAssociationCmd_Report = 0x03, MultiInstanceAssociationCmd_Remove = 0x04, MultiInstanceAssociationCmd_GroupingsGet = 0x05, MultiInstanceAssociationCmd_GroupingsReport = 0x06 }; // // Constructor //----------------------------------------------------------------------------- MultiInstanceAssociation::MultiInstanceAssociation ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_queryAll(false), m_numGroups(0) { SetStaticRequest( StaticRequest_Values ); } //----------------------------------------------------------------------------- // // Read the saved association data //----------------------------------------------------------------------------- void MultiInstanceAssociation::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 ) ) { m_numGroups = (uint8)intVal; } 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; } associationsElement = associationsElement->NextSiblingElement(); } } //----------------------------------------------------------------------------- // // Save the association data //----------------------------------------------------------------------------- void MultiInstanceAssociation::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); if( Node* node = GetNodeUnsafe() ) { TiXmlElement* associationsElement = new TiXmlElement( "Associations" ); char str[8]; snprintf( str, 8, "%d", m_numGroups ); associationsElement->SetAttribute( "num_groups", str ); _ccElement->LinkEndChild( associationsElement ); node->WriteGroups( associationsElement ); } } //----------------------------------------------------------------------------- // // Nothing to do for Association //----------------------------------------------------------------------------- bool MultiInstanceAssociation::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; } //----------------------------------------------------------------------------- // // Nothing to do for Association //----------------------------------------------------------------------------- bool MultiInstanceAssociation::RequestValue ( uint32 const _requestFlags, uint8 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( "MultiInstanceAssociationCmd_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( MultiInstanceAssociationCmd_GroupingsGet ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, _queue ); return true; } //----------------------------------------------------------------------------- // // Request the contents of each group in turn //----------------------------------------------------------------------------- void MultiInstanceAssociation::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 ); } } //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- bool MultiInstanceAssociation::HandleMsg ( uint8 const* _data, uint32 const _length, uint32 const _instance // = 1 ) { bool handled = false; uint32 i; if( Node* node = GetNodeUnsafe() ) { if( MultiInstanceAssociationCmd_GroupingsReport == (MultiInstanceAssociationCmd)_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( MultiInstanceAssociationCmd_Report == (MultiInstanceAssociationCmd)_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 ) { if( _length >= 5 ) { // 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) { 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 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++; } } } } 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 { // 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 ) { // 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; } } handled = true; } } return handled; } //----------------------------------------------------------------------------- // // Request details of an association group //----------------------------------------------------------------------------- void MultiInstanceAssociation::QueryGroup ( uint8 _groupIdx, uint32 const _requestFlags ) { if ( IsGetSupported() ) { Log::Write( LogLevel_Info, GetNodeId(), "Get MultiInstanceAssociation for group %d of node %d", _groupIdx, GetNodeId() ); Msg* msg = new Msg( "MultiInstanceAssociationCmd_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( MultiInstanceAssociationCmd_Get ); msg->Append( _groupIdx ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); return; } else { Log::Write( LogLevel_Info, GetNodeId(), "MultiInstanceAssociationCmd_Get Not Supported on this node"); } return; } //----------------------------------------------------------------------------- // // Add an association between devices //----------------------------------------------------------------------------- void MultiInstanceAssociation::Set ( uint8 _groupIdx, uint8 _targetNodeId, uint8 _instance ) { Log::Write( LogLevel_Info, GetNodeId(), "MultiInstanceAssociation::Set - Adding instance %d on node %d to group %d of node %d", _instance, _targetNodeId, _groupIdx, GetNodeId() ); if ( _instance == 0x00 ) { Msg* msg = new Msg( "MultiInstanceAssociationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); msg->Append( GetNodeId() ); msg->Append( 4 ); msg->Append( GetCommandClassId() ); msg->Append( MultiInstanceAssociationCmd_Set ); msg->Append( _groupIdx ); msg->Append( _targetNodeId ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); } else { Msg* msg = new Msg( "MultiInstanceAssociationCmd_Set", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); msg->Append( GetNodeId() ); msg->Append( 6 ); msg->Append( GetCommandClassId() ); msg->Append( MultiInstanceAssociationCmd_Set ); msg->Append( _groupIdx ); msg->Append( 0x00 ); // marker msg->Append( _targetNodeId ); msg->Append( _instance ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); } } //----------------------------------------------------------------------------- // // Remove an association between devices //----------------------------------------------------------------------------- void MultiInstanceAssociation::Remove ( uint8 _groupIdx, uint8 _targetNodeId, uint8 _instance ) { Log::Write( LogLevel_Info, GetNodeId(), "MultiInstanceAssociation::Remove - Removing instance %d on node %d from group %d of node %d", _instance, _targetNodeId, _groupIdx, GetNodeId()); if ( _instance == 0x00 ) { Msg* msg = new Msg( "MultiInstanceAssociationCmd_Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); msg->Append( GetNodeId() ); msg->Append( 4 ); msg->Append( GetCommandClassId() ); msg->Append( MultiInstanceAssociationCmd_Remove ); msg->Append( _groupIdx ); msg->Append( _targetNodeId ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); } else { Msg* msg = new Msg( "MultiInstanceAssociationCmd_Remove", GetNodeId(), REQUEST, FUNC_ID_ZW_SEND_DATA, true ); msg->Append( GetNodeId() ); msg->Append( 6 ); msg->Append( GetCommandClassId() ); msg->Append( MultiInstanceAssociationCmd_Remove ); msg->Append( _groupIdx ); msg->Append( 0x00 ); // marker msg->Append( _targetNodeId ); msg->Append( _instance ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); } } open-zwave-1.5/cpp/src/command_classes/MultiInstanceAssociation.h000066400000000000000000000062251264474202400253150ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MultiInstanceAssociation.h // // Implementation of the Z-Wave COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION // // 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 . // //----------------------------------------------------------------------------- #ifndef _MultiInstanceAssociation_H #define _MultiInstanceAssociation_H #include #include "Group.h" #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION (0x8E), a Z-Wave device command class. */ class MultiInstanceAssociation: public CommandClass { friend class Group; public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new MultiInstanceAssociation( _homeId, _nodeId ); } virtual ~MultiInstanceAssociation(){} static uint8 const StaticGetCommandClassId(){ return 0x8e; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_MULTI_INSTANCE_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, uint8 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 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 ); private: MultiInstanceAssociation( 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 OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/NoOperation.cpp000066400000000000000000000050051264474202400231240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // NoOperation.cpp // // Implementation of the Z-Wave COMMAND_CLASS_NO_OPERATION // // Copyright (c) 2012 Greg Satz // // 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/NoOperation.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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" ); 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 ); } open-zwave-1.5/cpp/src/command_classes/NoOperation.h000066400000000000000000000041131264474202400225700ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // NoOperation.h // // Implementation of the Z-Wave COMMAND_CLASS_NO_OPERATION // // Copyright (c) 2012 Greg Satz // // 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 _NoOperation_H #define _NoOperation_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_NO_OPERATION (0x00), a Z-Wave device command class. */ 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"; } 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 ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/NodeNaming.cpp000066400000000000000000000412151264474202400227110ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // NodeNaming.cpp // // Implementation of the Z-Wave COMMAND_CLASS_NODE_NAMING // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/NodeNaming.h" #include "command_classes/Association.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #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 { 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 }; //----------------------------------------------------------------------------- // // 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 == "" ) { // 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 ); } } } return res; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool NodeNaming::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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 == "" ) { // 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 ); } 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] ); } 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] ); } msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); } //----------------------------------------------------------------------------- // // Extract a string from the report data //----------------------------------------------------------------------------- string NodeNaming::ExtractString ( uint8 const* _data, uint32 const _length ) { uint8 i; char str[32]; uint32 pos = 0; str[0] = 0; StringEncoding encoding = (StringEncoding)( _data[1] & 0x07 ); if( _length >= 3 ) { // Get the length of the string (maximum allowed is 16 bytes) uint8 numBytes = _length - 3; if( numBytes > 16 ) { numBytes = 16; } switch( encoding ) { case StringEncoding_ASCII: { // Copy data as-is for( i=0; i= 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 // Convert a UTF-16 string into UTF-8 encoding. //----------------------------------------------------------------------------- uint32 NodeNaming::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 ) { 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; } } return pos; } open-zwave-1.5/cpp/src/command_classes/NodeNaming.h000066400000000000000000000047161264474202400223630ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // NodeNaming.h // // Implementation of the Z-Wave COMMAND_CLASS_NODE_NAMING // // 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 . // //----------------------------------------------------------------------------- #ifndef _NodeNaming_H #define _NodeNaming_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_NODE_NAMING (0x77), a Z-Wave device command class. */ class NodeNaming: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new NodeNaming( _homeId, _nodeId ); } virtual ~NodeNaming(){} static uint8 const StaticGetCommandClassId(){ return 0x77; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_NODE_NAMING"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 SetName( string const& _name ); void SetLocation( string const& _location ); private: NodeNaming( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} string ExtractString( uint8 const* _data, uint32 const _length ); uint32 ConvertUFT16ToUTF8( uint16 _utf16, char* _buffer, uint32 pos ); }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Powerlevel.cpp000066400000000000000000000361221264474202400230170ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Powerlevel.cpp // // Implementation of the Z-Wave COMMAND_CLASS_POWERLEVEL // // 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 . // //----------------------------------------------------------------------------- #include #include "command_classes/CommandClasses.h" #include "command_classes/Powerlevel.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueShort.h" #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 { PowerlevelIndex_Powerlevel = 0, PowerlevelIndex_Timeout, PowerlevelIndex_Set, PowerlevelIndex_TestNode, PowerlevelIndex_TestPowerlevel, PowerlevelIndex_TestFrames, PowerlevelIndex_Test, PowerlevelIndex_Report, PowerlevelIndex_TestStatus, PowerlevelIndex_TestAckFrames }; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Powerlevel::RequestValue ( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue ) { if( _index == 0 ) { if ( IsGetSupported() ) { 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 ) ) ) { if( button->IsPressed() ) { res = Set( instance ); } 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() ) { res = Test( instance ); } button->Release(); } break; } case PowerlevelIndex_Report: { // Test if( ValueButton* button = static_cast( GetValue( instance, PowerlevelIndex_Report ) ) ) { if( button->IsPressed() ) { res = Report( instance ); } button->Release(); } 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; } 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; } 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; } 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( 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; } 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/Powerlevel.h000066400000000000000000000055561264474202400224730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Powerlevel.h // // Implementation of the Z-Wave COMMAND_CLASS_POWERLEVEL // // 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 . // //----------------------------------------------------------------------------- #ifndef _Powerlevel_H #define _Powerlevel_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueList; /** \brief Implements COMMAND_CLASS_POWERLEVEL (0x73), a Z-Wave device command class. */ 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 }; enum PowerLevelStatusEnum { PowerLevelStatus_Failed = 0, PowerLevelStatus_Success, PowerLevelStatus_InProgress }; static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Powerlevel( _homeId, _nodeId ); } virtual ~Powerlevel(){} static uint8 const StaticGetCommandClassId(){ return 0x73; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_POWERLEVEL"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); 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 OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Proprietary.cpp000066400000000000000000000033731264474202400232150ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Proprietary.cpp // // Implementation of the Z-Wave COMMAND_CLASS_PROPRIETARY // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Proprietary.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "platform/Log.h" using namespace OpenZWave; 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; } open-zwave-1.5/cpp/src/command_classes/Proprietary.h000066400000000000000000000037661264474202400226700ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Proprietary.h // // Implementation of the Z-Wave COMMAND_CLASS_PROPRIETARY // // 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 . // //----------------------------------------------------------------------------- #ifndef _Proprietary_H #define _Proprietary_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_PROPRIETARY (0x88), a Z-Wave device command class. */ class Proprietary: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Proprietary( _homeId, _nodeId ); } virtual ~Proprietary(){} static uint8 const StaticGetCommandClassId(){ return 0x88; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_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 ); private: Proprietary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Protection.cpp000066400000000000000000000130571264474202400230230ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Protection.cpp // // Implementation of the Z-Wave COMMAND_CLASS_PROTECTION // // 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 . // //----------------------------------------------------------------------------- #include #include "command_classes/CommandClasses.h" #include "command_classes/Protection.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueList.h" using namespace OpenZWave; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Protection::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/Protection.h000066400000000000000000000047171264474202400224730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Protection.h // // Implementation of the Z-Wave COMMAND_CLASS_PROTECTION // // 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 . // //----------------------------------------------------------------------------- #ifndef _Protection_H #define _Protection_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueList; /** \brief Implements COMMAND_CLASS_PROTECTION (0x75), a Z-Wave device command class. */ class Protection: public CommandClass { public: enum ProtectionEnum { Protection_Unprotected = 0, Protection_Sequence, Protection_NOP }; static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Protection( _homeId, _nodeId ); } virtual ~Protection(){} static uint8 const StaticGetCommandClassId(){ return 0x75; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_PROTECTION"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: Protection( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SceneActivation.cpp000066400000000000000000000050111264474202400237430ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SceneActivation.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SCENE_ACTIVATION // // Copyright (c) 2012 Greg Satz // // 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/SceneActivation.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "Notification.h" #include "platform/Log.h" using namespace OpenZWave; enum SceneActivationCmd { SceneActivationCmd_Set = 0x01 }; //----------------------------------------------------------------------------- // // Handle a message from the Z-Wave network //----------------------------------------------------------------------------- bool SceneActivation::HandleMsg ( 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]; if( _data[2] == 0 ) snprintf( msg, sizeof(msg), "now" ); else if( _data[2] <= 0x7F ) snprintf( msg, sizeof(msg), "%d seconds", _data[2] ); else if( _data[2] <= 0xFE ) snprintf( msg, sizeof(msg), "%d minutes", _data[2] ); else snprintf( msg, sizeof(msg), "via configuration" ); Log::Write( LogLevel_Info, GetNodeId(), "Received Scene Activation set from node %d: scene id=%d %s. Sending event notification.", GetNodeId(), _data[1], msg ); Notification* notification = new Notification( Notification::Type_SceneEvent ); notification->SetHomeAndNodeIds( GetHomeId(), GetNodeId() ); notification->SetSceneId( _data[1] ); GetDriver()->QueueNotification( notification ); return true; } return false; } open-zwave-1.5/cpp/src/command_classes/SceneActivation.h000066400000000000000000000050061264474202400234140ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SceneActivation.h // // Implementation of the Z-Wave COMMAND_CLASS_SCENE_ACTIVATION // // Copyright (c) 2012 Greg Satz // // 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 _SceneActivation_H #define _SceneActivation_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_SCENEACTIVATION (0x2B), a Z-Wave device command class. */ class SceneActivation: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SceneActivation( _homeId, _nodeId ); } virtual ~SceneActivation(){} /** \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"; } // 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 HandleMsg( uint8 const* _data, uint32 const _length, uint32 const _instance = 1 ); private: SceneActivation( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Security.cpp000066400000000000000000000241241264474202400225010ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Security.cpp // // Implementation of the Z-Wave COMMAND_CLASS_Security // // Copyright (c) 2011 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 . // //----------------------------------------------------------------------------- #include #include "command_classes/CommandClasses.h" #include "command_classes/Security.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "Utils.h" #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) { /* 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(); } Security::~Security ( ) { } //----------------------------------------------------------------------------- // // Read configuration. //----------------------------------------------------------------------------- void Security::ReadXML ( TiXmlElement const* _ccElement ) { CommandClass::ReadXML( _ccElement ); } //----------------------------------------------------------------------------- // // Save changed configuration //----------------------------------------------------------------------------- void Security::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); } bool Security::Init ( ) { 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_Security); 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_Security); return true; } return false; } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- bool Security::RequestState ( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ) { #if 0 if( _requestFlags & RequestFlag_Static ) { } return false; #endif return true; } //----------------------------------------------------------------------------- // // Request current state from the device //----------------------------------------------------------------------------- bool Security::RequestValue ( uint32 const _requestFlags, uint8 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 ) { #ifdef DEBUG PrintHex("Security Classes", _data, _length); #endif GetNodeUnsafe()->SetSecuredClasses(_data, _length); 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", GetNodeId() ); m_secured = true; if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) { value->OnValueRefreshed( m_secured ); value->Release(); } HandleSupportedReport(&_data[2], _length-2); 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_Security); 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_Security); 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(), "Recieved a Security Message that should have been handled in the Driver"); break; } default: { return false; } } 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 ); } } open-zwave-1.5/cpp/src/command_classes/Security.h000066400000000000000000000060211264474202400221420ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Security.h // // Implementation of the Z-Wave COMMAND_CLASS_Security // // 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 . // //----------------------------------------------------------------------------- #ifndef _Security_H #define _Security_H #include #include "aes/aescpp.h" #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_SECURITY (0x98), a Z-Wave device command class. */ 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, }; 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(); 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 ReadXML(TiXmlElement const* _ccElement); void WriteXML(TiXmlElement* _ccElement); 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, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue); bool HandleSupportedReport(uint8 const* _data, uint32 const _length); bool m_schemeagreed; bool m_secured; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SensorAlarm.cpp000066400000000000000000000142741264474202400231250ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SensorAlarm.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SENSOR_ALARM // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/SensorAlarm.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" using namespace OpenZWave; 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 ); } //----------------------------------------------------------------------------- // // 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 ); } } } return requests; } //----------------------------------------------------------------------------- // // Get the sensor alarm details from the device //----------------------------------------------------------------------------- bool SensorAlarm::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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 ); 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 ); } return true; } 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" ); // 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] ); } } } } } ClearStaticRequest( StaticRequest_Values ); return true; } return false; } open-zwave-1.5/cpp/src/command_classes/SensorAlarm.h000066400000000000000000000047111264474202400225650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SensorAlarm.h // // Implementation of the Z-Wave COMMAND_CLASS_SENSOR_ALARM // // 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 . // //----------------------------------------------------------------------------- #ifndef _SensorAlarm_H #define _SensorAlarm_H #include #include #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_SENSOR_ALARM (0x9c), a Z-Wave device command class. */ class SensorAlarm: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorAlarm( _homeId, _nodeId ); } virtual ~SensorAlarm(){} static uint8 const StaticGetCommandClassId(){ return 0x9c; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_ALARM"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); 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 OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SensorBinary.cpp000066400000000000000000000161171264474202400233130ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SensorBinary.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SENSOR_BINARY // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/SensorBinary.h" #include "command_classes/WakeUp.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" #include "tinyxml.h" using namespace OpenZWave; 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(); char const* str; int index; int type; while( child ) { 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(); } } //----------------------------------------------------------------------------- // // Write node configuration data //----------------------------------------------------------------------------- void SensorBinary::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); char str[8]; 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->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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool SensorBinary::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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; } } 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() ) { if( 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 ); } } open-zwave-1.5/cpp/src/command_classes/SensorBinary.h000066400000000000000000000050501264474202400227520ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SensorBinary.h // // Implementation of the Z-Wave COMMAND_CLASS_SENSOR_BINARY // // 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 . // //----------------------------------------------------------------------------- #ifndef _SensorBinary_H #define _SensorBinary_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueBool; /** \brief Implements COMMAND_CLASS_SENSOR_BINARY (0x30), a Z-Wave device command class. */ class SensorBinary: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorBinary( _homeId, _nodeId ); } virtual ~SensorBinary(){} static uint8 const StaticGetCommandClassId(){ return 0x30; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_BINARY"; } // 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, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: SensorBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} map m_sensorsMap; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SensorMultilevel.cpp000066400000000000000000000323241264474202400242070ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SensorMultilevel.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SENSOR_MULTILEVEL // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/SensorMultilevel.h" #include "command_classes/MultiInstance.h" #include "Defs.h" #include "Bitfield.h" #include "Msg.h" #include "Node.h" #include "Driver.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, 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_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" }; 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", "" }; static char const* c_seismicIntensityUnits[] = { "mercalli", "EU macroseismic", "liedu", "shindo", "" }; static char const* c_seismicMagnitudeUnits[] = { "local", "moment", "surface wave", "body wave", "" }; 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; } } if( _requestFlags & RequestFlag_Dynamic ) { res |= RequestValue( _requestFlags, 0, _instance, _queue ); } return res; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool SensorMultilevel::RequestValue ( uint32 const _requestFlags, uint8 const _dummy, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { bool res = false; if ( !IsGetSupported() ) { 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 ) { 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++ ) { if( _data[i] & ( 1 << j ) ) { if( msg != "" ) msg += ", "; uint8 index = ( ( i - 1 ) * 8 ) + j + 1; if (index >= SensorType_MaxType) /* max size for c_sensorTypeNames */ { Log::Write (LogLevel_Warning, GetNodeId(), "SensorType Value was greater than range. Dropping"); continue; } 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 ); } } } } } 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 ) { 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 { units = c_seismicIntensityUnits[scale]; } } break; case SensorType_SeismicMagnitude: { if (scale > 3) /* size of c_seismicMagnitudeUnits minus invalid */ { Log::Write (LogLevel_Warning, GetNodeId(), "Scale Value for c_seismicMagnitudeUnits was greater than range. Setting to empty"); units = c_seismicMagnitudeUnits[4]; /* empty entry */ } else { units = c_seismicMagnitudeUnits[scale]; } } 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 { units = c_moistureUnits[scale]; } } 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 ); } 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. } open-zwave-1.5/cpp/src/command_classes/SensorMultilevel.h000066400000000000000000000046511264474202400236560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SensorMultilevel.h // // Implementation of the Z-Wave COMMAND_CLASS_SENSOR_MULTILEVEL // // 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 . // //----------------------------------------------------------------------------- #ifndef _SensorMultilevel_H #define _SensorMultilevel_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueDecimal; /** \brief Implements COMMAND_CLASS_SENSOR_MULTILEVEL (0x31), a Z-Wave device command class. */ class SensorMultilevel: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SensorMultilevel( _homeId, _nodeId ); } virtual ~SensorMultilevel(){} static uint8 const StaticGetCommandClassId(){ return 0x31; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SENSOR_MULTILEVEL"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); virtual uint8 GetMaxVersion(){ return 5; } protected: virtual void CreateVars( uint8 const _instance ); private: SensorMultilevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SwitchAll.cpp000066400000000000000000000155061264474202400225700ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchAll.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_ALL // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/SwitchAll.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #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[] = { "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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool SwitchAll::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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 ); } //----------------------------------------------------------------------------- // // 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 ); } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/SwitchAll.h000066400000000000000000000047251264474202400222360ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchAll.h // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_ALL // // 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 . // //----------------------------------------------------------------------------- #ifndef _SwitchAll_H #define _SwitchAll_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueList; /** \brief Implements COMMAND_CLASS_SWITCH_ALL (0x27), a Z-Wave device command class. */ class SwitchAll: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchAll( _homeId, _nodeId ); } virtual ~SwitchAll(){} static uint8 const StaticGetCommandClassId(){ return 0x27; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_ALL"; } static void On( Driver* _driver, uint8 const _nodeId ); static void Off( Driver* _driver, uint8 const _nodeId ); // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: SwitchAll( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SwitchBinary.cpp000066400000000000000000000141111264474202400232730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchBinary.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_BINARY // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/SwitchBinary.h" #include "command_classes/WakeUp.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" using namespace OpenZWave; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool SwitchBinary::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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" ); if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) { value->OnValueRefreshed( _data[1] != 0 ); value->Release(); } return true; } return false; } //----------------------------------------------------------------------------- // // Set the state of the switch //----------------------------------------------------------------------------- bool SwitchBinary::SetValue ( Value const& _value ) { if( ValueID::ValueType_Bool == _value.GetID().GetType() ) { ValueBool const* value = static_cast(&_value); Log::Write( LogLevel_Info, GetNodeId(), "SwitchBinary::Set - Setting node %d to %s", GetNodeId(), value->GetValue() ? "On" : "Off" ); Msg* msg = new Msg( "SwitchBinaryCmd_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( SwitchBinaryCmd_Set ); msg->Append( value->GetValue() ? 0xff : 0x00 ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); return true; } return false; } //----------------------------------------------------------------------------- // // 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() ) { if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) { value->OnValueRefreshed( _value != 0 ); value->Release(); } } } } } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- void SwitchBinary::CreateVars ( uint8 const _instance ) { if( Node* node = GetNodeUnsafe() ) { node->CreateValueBool( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Switch", "", false, false, false, 0 ); } } open-zwave-1.5/cpp/src/command_classes/SwitchBinary.h000066400000000000000000000047101264474202400227440ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchBinary.h // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_BINARY // // 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 . // //----------------------------------------------------------------------------- #ifndef _SwitchBinary_H #define _SwitchBinary_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueBool; /** \brief Implements COMMAND_CLASS_SWITCH_BINARY (0x25), a Z-Wave device command class. */ 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"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: SwitchBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SwitchMultilevel.cpp000066400000000000000000000454131264474202400242020ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchMultilevel.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_MULTILEVEL // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/SwitchMultilevel.h" #include "command_classes/WakeUp.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" #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_Level = 0, SwitchMultilevelIndex_Bright, SwitchMultilevelIndex_Dim, SwitchMultilevelIndex_IgnoreStartLevel, SwitchMultilevelIndex_StartLevel, SwitchMultilevelIndex_Duration, SwitchMultilevelIndex_Step, SwitchMultilevelIndex_Inc, SwitchMultilevelIndex_Dec }; static uint8 c_directionParams[] = { 0x18, 0x58, 0xc0, 0xc8 }; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool SwitchMultilevel::RequestValue ( uint32 const _requestFlags, uint8 const _index, uint8 const _instance, Driver::MsgQueue const _queue ) { if( _index == SwitchMultilevelIndex_Level ) { if ( IsGetSupported() ) { 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; } //----------------------------------------------------------------------------- // // 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(); } 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( switchType2 ) { if( NULL != ( button = static_cast( GetValue( _instance, SwitchMultilevelIndex_Inc ) ) ) ) { button->SetLabel( c_switchLabelsPos[switchtype2label] ); button->Release(); } 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 ); 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 ) ) ) { 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 { res = StopLevelChange( instance ); } button->Release(); } break; } } 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() ) { if( ValueByte* value = static_cast( GetValue( _instance, SwitchMultilevelIndex_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() ); if( 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 ); } 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" ); 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() ) { ignoreStartLevel->Release(); // Set the ignore start level flag direction |= 0x20; } } 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 ); 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 ); msg->Append( direction ); msg->Append( startLevel ); if( length >= 5 ) { msg->Append( duration ); } if( length == 6 ) { msg->Append( step ); } msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, 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; } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- void SwitchMultilevel::CreateVars ( uint8 const _instance ) { if( Node* node = GetNodeUnsafe() ) { switch( GetVersion() ) { case 3: { 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; } } } } open-zwave-1.5/cpp/src/command_classes/SwitchMultilevel.h000066400000000000000000000057731264474202400236540ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchMultilevel.h // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_MULTILEVEL // // 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 . // //----------------------------------------------------------------------------- #ifndef _SwitchMultilevel_H #define _SwitchMultilevel_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueBool; class ValueButton; class ValueByte; /** \brief Implements COMMAND_CLASS_SWITCH_MULTILEVEL (0x26), a Z-Wave device command class. */ class SwitchMultilevel: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchMultilevel( _homeId, _nodeId ); } virtual ~SwitchMultilevel(){} static uint8 const StaticGetCommandClassId(){ return 0x26; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_MULTILEVEL"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); virtual void SetVersion( uint8 const _version ); virtual uint8 GetMaxVersion(){ return 3; } protected: virtual void CreateVars( uint8 const _instance ); private: enum SwitchMultilevelDirection { SwitchMultilevelDirection_Up = 0, SwitchMultilevelDirection_Down, SwitchMultilevelDirection_Inc, SwitchMultilevelDirection_Dec }; 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 OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SwitchToggleBinary.cpp000066400000000000000000000115601264474202400244420ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchToggleBinary.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_TOGGLE_BINARY // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/SwitchToggleBinary.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "value_classes/ValueBool.h" using namespace OpenZWave; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool SwitchToggleBinary::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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" ); if( ValueBool* value = static_cast( GetValue( _instance, 0 ) ) ) { value->OnValueRefreshed( _data[1] != 0 ); value->Release(); } return true; } 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/SwitchToggleBinary.h000066400000000000000000000046741264474202400241170ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchToggleBinary.h // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_TOGGLE_BINARY // // 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 . // //----------------------------------------------------------------------------- #ifndef _SwitchToggleBinary_H #define _SwitchToggleBinary_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueBool; /** \brief Implements COMMAND_CLASS_SWITCH_TOGGLE_BINARY (0x28), a Z-Wave device command class. */ class SwitchToggleBinary: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchToggleBinary( _homeId, _nodeId ); } virtual ~SwitchToggleBinary(){} static uint8 const StaticGetCommandClassId(){ return 0x28; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_TOGGLE_BINARY"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: SwitchToggleBinary( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/SwitchToggleMultilevel.cpp000066400000000000000000000155621264474202400253460ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchToggleMultilevel.cpp // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/SwitchToggleMultilevel.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" using namespace OpenZWave; 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool SwitchToggleMultilevel::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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] ); if( ValueByte* value = static_cast( GetValue( _instance, 0 ) ) ) { value->OnValueRefreshed( _data[1] ); value->Release(); } return true; } 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; } //----------------------------------------------------------------------------- // // 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 ); 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() ); } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/SwitchToggleMultilevel.h000066400000000000000000000054211264474202400250040ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SwitchToggleMultilevel.h // // Implementation of the Z-Wave COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL // // 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 . // //----------------------------------------------------------------------------- #ifndef _SwitchToggleMultilevel_H #define _SwitchToggleMultilevel_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; /** \brief Implements COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL (0x29), a Z-Wave device command class. */ class SwitchToggleMultilevel: public CommandClass { public: enum SwitchToggleMultilevelDirection { SwitchToggleMultilevelDirection_Up = 0x00, SwitchToggleMultilevelDirection_Down = 0x40 }; static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new SwitchToggleMultilevel( _homeId, _nodeId ); } virtual ~SwitchToggleMultilevel(){} static uint8 const StaticGetCommandClassId(){ return 0x29; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL"; } void StartLevelChange( SwitchToggleMultilevelDirection const _direction, bool const _bIgnoreStartLevel, bool const _bRollover ); void StopLevelChange(); // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: SwitchToggleMultilevel( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ThermostatFanMode.cpp000066400000000000000000000247011264474202400242570ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatFanMode.cpp // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_FAN_MODE // // 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 . // //----------------------------------------------------------------------------- #include #include "command_classes/CommandClasses.h" #include "command_classes/ThermostatFanMode.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueList.h" #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[] = { "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 ) { 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; } 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 ); } } } //----------------------------------------------------------------------------- // // Save the supported modes //----------------------------------------------------------------------------- void ThermostatFanMode::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); 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; 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() ); } } } //----------------------------------------------------------------------------- // // 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 ); } if( _requestFlags & RequestFlag_Dynamic ) { // Request the current fan mode requests |= RequestValue( _requestFlags, ThermostatFanModeCmd_Get, _instance, _queue ); } return requests; } //----------------------------------------------------------------------------- // // Get the thermostat fan mode details from the device //----------------------------------------------------------------------------- bool ThermostatFanMode::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { // 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 ) { if( ( _data[i] & (1<= (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; } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- 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 ); } } open-zwave-1.5/cpp/src/command_classes/ThermostatFanMode.h000066400000000000000000000053161264474202400237250ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatFanMode.h // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_FAN_MODE // // 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 . // //----------------------------------------------------------------------------- #ifndef _ThermostatFanMode_H #define _ThermostatFanMode_H #include #include #include "command_classes/CommandClass.h" #include "value_classes/ValueList.h" namespace OpenZWave { class ValueList; /** \brief Implements COMMAND_CLASS_THERMOSTAT_FAN_MODE (0x44), a Z-Wave device command class. */ 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"; } // 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, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: ThermostatFanMode( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); } vector m_supportedModes; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ThermostatFanState.cpp000066400000000000000000000113011264474202400244430ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatFanState.cpp // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_FAN_STATE // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/ThermostatFanState.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueString.h" using namespace OpenZWave; 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; } //----------------------------------------------------------------------------- // // Get the thermostat fan state details from the device //----------------------------------------------------------------------------- bool ThermostatFanState::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { // 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); 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/ThermostatFanState.h000066400000000000000000000047341264474202400241240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatFanState.h // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_FAN_STATE // // 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 . // //----------------------------------------------------------------------------- #ifndef _ThermostatFanState_H #define _ThermostatFanState_H #include #include #include "command_classes/CommandClass.h" #include "value_classes/ValueList.h" namespace OpenZWave { class ValueString; /** \brief Implements COMMAND_CLASS_THERMOSTAT_FAN_STATE (0x45), a Z-Wave device command class. */ class ThermostatFanState: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatFanState( _homeId, _nodeId ); } virtual ~ThermostatFanState(){} static uint8 const StaticGetCommandClassId(){ return 0x45; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_FAN_STATE"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: ThermostatFanState( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ThermostatMode.cpp000066400000000000000000000273451264474202400236410ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatMode.cpp // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_MODE // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/ThermostatMode.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueList.h" #include "tinyxml.h" using namespace OpenZWave; enum ThermostatModeCmd { ThermostatModeCmd_Set = 0x01, ThermostatModeCmd_Get = 0x02, ThermostatModeCmd_Report = 0x03, ThermostatModeCmd_SupportedGet = 0x04, ThermostatModeCmd_SupportedReport = 0x05 }; 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" }; //----------------------------------------------------------------------------- // // 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 ) { char const* str = modeElement->Value(); if( str && !strcmp( str, "Mode" ) ) { int index; if( TIXML_SUCCESS == modeElement->QueryIntAttribute( "index", &index ) ) { if (index > 13) /* size of c_modeName minus Invalid */ { Log::Write (LogLevel_Warning, GetNodeId(), "index Value in XML was greater than range. Setting to Invalid"); index = 14; } 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 ); } } } //----------------------------------------------------------------------------- // // Save the supported modes //----------------------------------------------------------------------------- void ThermostatMode::WriteXML ( TiXmlElement* _ccElement ) { if( m_supportedModes.empty() ) { return; } CommandClass::WriteXML( _ccElement ); 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; 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() ); } } } //----------------------------------------------------------------------------- // // 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 ); } if( _requestFlags & RequestFlag_Dynamic ) { // Request the current mode requests |= RequestValue( _requestFlags, 0, _instance, _queue ); } return requests; } //----------------------------------------------------------------------------- // // Get the static thermostat mode details from the device //----------------------------------------------------------------------------- bool ThermostatMode::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { // 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 ) { if( ( _data[i] & (1<= (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; } 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->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 ) ) ) { node->RemoveValueList( valueList ); valueList->Release(); } } node->CreateValueList( ValueID::ValueGenre_User, GetCommandClassId(), _instance, 0, "Mode", "", false, false, 1, m_supportedModes, defaultValue, 0 ); } } open-zwave-1.5/cpp/src/command_classes/ThermostatMode.h000066400000000000000000000052521264474202400232770ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatMode.h // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_MODE // // 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 . // //----------------------------------------------------------------------------- #ifndef _ThermostatMode_H #define _ThermostatMode_H #include #include #include "command_classes/CommandClass.h" #include "value_classes/ValueList.h" namespace OpenZWave { class ValueList; /** \brief Implements COMMAND_CLASS_THERMOSTAT_MODE (0x40), a Z-Wave device command class. */ class ThermostatMode: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatMode( _homeId, _nodeId ); } virtual ~ThermostatMode(){} static uint8 const StaticGetCommandClassId(){ return 0x40; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_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, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: ThermostatMode( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){ SetStaticRequest( StaticRequest_Values ); } vector m_supportedModes; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ThermostatOperatingState.cpp000066400000000000000000000113261264474202400256760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatOperatingState.cpp // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_OPERATING_STATE // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/ThermostatOperatingState.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueString.h" using namespace OpenZWave; 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; } //----------------------------------------------------------------------------- // // Get a thermostat mode value from the device //----------------------------------------------------------------------------- bool ThermostatOperatingState::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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; } 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 ); } } open-zwave-1.5/cpp/src/command_classes/ThermostatOperatingState.h000066400000000000000000000050301264474202400253360ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatOperatingState.h // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_OPERATING_STATE // // 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 . // //----------------------------------------------------------------------------- #ifndef _ThermostatOperatingState_H #define _ThermostatOperatingState_H #include #include #include "command_classes/CommandClass.h" #include "value_classes/ValueList.h" namespace OpenZWave { class ValueString; /** \brief Implements COMMAND_CLASS_THERMOSTAT_OPERATING_STATE (0x42), a Z-Wave device command class. */ class ThermostatOperatingState: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatOperatingState( _homeId, _nodeId ); } virtual ~ThermostatOperatingState(){} static uint8 const StaticGetCommandClassId(){ return 0x42; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_OPERATING_STATE"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: ThermostatOperatingState( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ){} }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ThermostatSetpoint.cpp000066400000000000000000000231201264474202400245450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatSetpoint.cpp // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_SETPOINT // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/ThermostatSetpoint.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueDecimal.h" #include "tinyxml.h" using namespace OpenZWave; enum ThermostatSetpointCmd { ThermostatSetpointCmd_Set = 0x01, ThermostatSetpointCmd_Get = 0x02, ThermostatSetpointCmd_Report = 0x03, ThermostatSetpointCmd_SupportedGet = 0x04, ThermostatSetpointCmd_SupportedReport = 0x05 }; 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_Count }; 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" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ThermostatSetpoint::ThermostatSetpoint ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_setPointBase( 1 ) { SetStaticRequest( StaticRequest_Values ); } //----------------------------------------------------------------------------- // // Read the saved change-counter value //----------------------------------------------------------------------------- void ThermostatSetpoint::ReadXML ( TiXmlElement const* _ccElement ) { CommandClass::ReadXML( _ccElement ); int intVal; if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "base", &intVal ) ) { m_setPointBase = (uint8)intVal; } } //----------------------------------------------------------------------------- // // Write the change-counter value //----------------------------------------------------------------------------- void ThermostatSetpoint::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); char str[8]; snprintf( str, 8, "%d", m_setPointBase ); _ccElement->SetAttribute( "base", str ); } //----------------------------------------------------------------------------- // // 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 ); } if( _requestFlags & RequestFlag_Session ) { for( uint8 i=0; i // Request current state from the device //----------------------------------------------------------------------------- bool ThermostatSetpoint::RequestValue ( uint32 const _requestFlags, uint8 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 ( !IsGetSupported() ) { 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 ); 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 ) { value->SetPrecision( precision ); } value->Release(); 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; } 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" ); // Parse the data for the supported setpoints for( uint32 i=1; i<_length-1; ++i ) { for( int32 bit=0; bit<8; ++bit ) { if( ( _data[i] & (1<CreateValueDecimal( ValueID::ValueGenre_User, GetCommandClassId(), _instance, index, c_setpointName[index], "C", false, false, "0.0", 0 ); Log::Write( LogLevel_Info, GetNodeId(), " Added setpoint: %s", c_setpointName[index] ); } } } } } ClearStaticRequest( StaticRequest_Values ); return true; } 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; 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( value->GetID().GetIndex() ); AppendValue( msg, value->GetValue(), scale ); msg->Append( GetDriver()->GetTransmitOptions() ); GetDriver()->SendMsg( msg, Driver::MsgQueue_Send ); return true; } 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 ); } } open-zwave-1.5/cpp/src/command_classes/ThermostatSetpoint.h000066400000000000000000000051371264474202400242220ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThermostatSetpoint.h // // Implementation of the Z-Wave COMMAND_CLASS_THERMOSTAT_SETPOINT // // 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 . // //----------------------------------------------------------------------------- #ifndef _ThermostatSetpoint_H #define _ThermostatSetpoint_H #include #include #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueDecimal; /** \brief Implements COMMAND_CLASS_THERMOSTAT_SETPOINT (0x43), a Z-Wave device command class. */ class ThermostatSetpoint: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ThermostatSetpoint( _homeId, _nodeId ); } virtual ~ThermostatSetpoint(){} static uint8 const StaticGetCommandClassId(){ return 0x43; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_THERMOSTAT_SETPOINT"; } // 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, uint8 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 ); public: virtual void CreateVars( uint8 const _instance, uint8 const _index ); private: ThermostatSetpoint( uint32 const _homeId, uint8 const _nodeId ); uint8 m_setPointBase; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/TimeParameters.cpp000066400000000000000000000173271264474202400236230ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeParameters.cpp // // Implementation of the Z-Wave COMMAND_CLASS_TIME_PARAMETERS // // Copyright (c) 2014 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 #include "command_classes/CommandClasses.h" #include "command_classes/TimeParameters.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #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 { TimeParametersIndex_Date = 0, TimeParametersIndex_Time, TimeParametersIndex_Set, TimeParametersIndex_Refresh }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool TimeParameters::RequestValue ( uint32 const _requestFlags, uint8 const _dummy1, // = 0 (not used) uint8 const _instance, Driver::MsgQueue const _queue ) { if ( IsGetSupported() ) { 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; } //----------------------------------------------------------------------------- // // 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); #ifdef WINAPI_FAMILY_APP #pragma warning(push) #pragma warning(disable:4996) #endif timeinfo = localtime(&rawtime); #ifdef WINAPI_FAMILY_APP #pragma warning(pop) #endif 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; } //----------------------------------------------------------------------------- // // 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); } } open-zwave-1.5/cpp/src/command_classes/TimeParameters.h000066400000000000000000000045751264474202400232710ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeParameters.h // // Implementation of the Z-Wave COMMAND_CLASS_TIME_PARAMETERS // // Copyright (c) 2014 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 _TimeParameters_H #define _TimeParameters_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueByte; class ValueList; /** \brief Implements COMMAND_CLASS_TIME_PARAMETERS (0x8B), a Z-Wave device command class. */ class TimeParameters: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new TimeParameters( _homeId, _nodeId ); } virtual ~TimeParameters(){} static uint8 const StaticGetCommandClassId(){ return 0x8B; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_TIME_PARAMETERS"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: TimeParameters( uint32 const _homeId, uint8 const _nodeId ); }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/UserCode.cpp000066400000000000000000000246251264474202400224110ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // UserCode.cpp // // Implementation of the Z-Wave COMMAND_CLASS_USER_CODE // // Copyright (c) 2012 Greg Satz // // 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 "tinyxml.h" #include "command_classes/CommandClasses.h" #include "command_classes/UserCode.h" #include "Node.h" #include "Options.h" #include "platform/Log.h" #include "value_classes/ValueByte.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 { UserCodeIndex_Refresh = 254, UserCodeIndex_Count = 255 }; const uint8 UserCodeLength = 10; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- UserCode::UserCode ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_queryAll( false ), m_currentCode( 0 ), m_userCodeCount( 0 ), m_refreshUserCodes(false) { SetStaticRequest( StaticRequest_Values ); memset( m_userCodesStatus, 0xff, sizeof(m_userCodesStatus) ); Options::Get()->GetOptionAsBool("RefreshAllUserCodes", &m_refreshUserCodes ); } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void UserCode::ReadXML ( TiXmlElement const* _ccElement ) { int32 intVal; CommandClass::ReadXML( _ccElement ); if( TIXML_SUCCESS == _ccElement->QueryIntAttribute( "codes", &intVal ) ) { m_userCodeCount = intVal; } } //----------------------------------------------------------------------------- // // Class specific configuration //----------------------------------------------------------------------------- void UserCode::WriteXML ( TiXmlElement* _ccElement ) { char str[32]; CommandClass::WriteXML( _ccElement ); snprintf( str, sizeof(str), "%d", m_userCodeCount ); _ccElement->SetAttribute( "codes", str); } //----------------------------------------------------------------------------- // // 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 ); } if( _requestFlags & RequestFlag_Session ) { if( m_userCodeCount > 0 ) { m_queryAll = true; m_currentCode = 1; requests |= RequestValue( _requestFlags, m_currentCode, _instance, _queue ); } } return requests; } //----------------------------------------------------------------------------- // // Nothing to do for UserCode //----------------------------------------------------------------------------- bool UserCode::RequestValue ( uint32 const _requestFlags, uint8 const _userCodeIdx, uint8 const _instance, Driver::MsgQueue const _queue ) { if( _instance != 1 ) { // This command class doesn't work with multiple instances return false; } if ( !IsGetSupported() ) { 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; } 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 ); 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_userCodeCount = _data[1]; if( m_userCodeCount > 254 ) { // Make space for code count. m_userCodeCount = 254; } ClearStaticRequest( StaticRequest_Values ); if( m_userCodeCount == 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(), m_userCodeCount, _data[1] ); } if( ValueByte* value = static_cast( GetValue( _instance, UserCodeIndex_Count ) ) ) { value->OnValueRefreshed( m_userCodeCount ); value->Release(); } if( Node* node = GetNodeUnsafe() ) { uint8 data[UserCodeLength]; memset( data, 0, UserCodeLength ); for( uint8 i = 0; i <= m_userCodeCount; i++ ) { char str[16]; if (i == 0) { snprintf( str, sizeof(str), "Enrollment Code"); node->CreateValueRaw( ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, str, "", true, false, data, UserCodeLength, 0 ); } else { snprintf( str, sizeof(str), "Code %d:", i); node->CreateValueRaw( ValueID::ValueGenre_User, GetCommandClassId(), _instance, i, str, "", false, false, data, UserCodeLength, 0 ); } } } return true; } else if( UserCodeCmd_Report == (UserCodeCmd)_data[0] ) { int i = _data[1]; if( ValueRaw* value = static_cast( GetValue( _instance, i ) ) ) { uint8 data[UserCodeLength]; uint8 size = _length - 4; if( size > UserCodeLength ) { Log::Write( LogLevel_Warning, GetNodeId(), "User Code length %d is larger then maximum %d", size, UserCodeLength ); size = UserCodeLength; } m_userCodesStatus[i] = _data[2]; memcpy( data, &_data[3], size ); value->OnValueRefreshed( data, size ); value->Release(); } Log::Write( LogLevel_Info, GetNodeId(), "Received User Code Report from node %d for User Code %d (%s)", GetNodeId(), i, CodeStatus( _data[2] ).c_str() ); if( m_queryAll && i == m_currentCode ) { if (m_refreshUserCodes || (_data[2] != UserCode_Available)) { if( ++i <= m_userCodeCount ) { 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; } return false; } //----------------------------------------------------------------------------- // // Set a User Code value //----------------------------------------------------------------------------- bool UserCode::SetValue ( Value const& _value ) { if( (ValueID::ValueType_Raw == _value.GetID().GetType()) && (_value.GetID().GetIndex() < UserCodeIndex_Refresh) ) { ValueRaw const* value = static_cast(&_value); uint8* s = value->GetValue(); uint8 len = value->GetLength(); if( len > UserCodeLength ) { return false; } m_userCodesStatus[value->GetID().GetIndex()] = UserCode_Occupied; 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( value->GetID().GetIndex() ); 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; } return false; } //----------------------------------------------------------------------------- // // Create the values managed by this command class //----------------------------------------------------------------------------- void UserCode::CreateVars ( uint8 const _instance ) { if( Node* node = GetNodeUnsafe() ) { node->CreateValueByte( 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); } } open-zwave-1.5/cpp/src/command_classes/UserCode.h000066400000000000000000000062771264474202400220610ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // UserCode.h // // Implementation of the Z-Wave COMMAND_CLASS_USER_CODE // // Copyright (c) 2012 Greg Satz // // 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 _UserCode_H #define _UserCode_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_USER_CODE (0x63), a Z-Wave device command class. */ class UserCode: public CommandClass { public: enum UserCodeStatus { UserCode_Available = 0x00, UserCode_Occupied = 0x01, UserCode_Reserved = 0x02, UserCode_NotAvailable = 0xfe, UserCode_Unset = 0xff }; 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"; } // 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, uint8 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 ); 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. uint8 m_currentCode; uint8 m_userCodeCount; uint8 m_userCodesStatus[256]; bool m_refreshUserCodes; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/Version.cpp000066400000000000000000000177071264474202400223300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Version.cpp // // Implementation of the Z-Wave COMMAND_CLASS_VERSION // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/Version.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "value_classes/ValueString.h" #include "tinyxml.h" using namespace OpenZWave; enum VersionCmd { VersionCmd_Get = 0x11, VersionCmd_Report = 0x12, VersionCmd_CommandClassGet = 0x13, VersionCmd_CommandClassReport = 0x14 }; enum { VersionIndex_Library = 0, VersionIndex_Protocol, VersionIndex_Application }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Version::Version ( uint32 const _homeId, uint8 const _nodeId ): CommandClass( _homeId, _nodeId ), m_classGetSupported( true ) { SetStaticRequest( StaticRequest_Values ); } //----------------------------------------------------------------------------- // // Read configuration. //----------------------------------------------------------------------------- void Version::ReadXML ( TiXmlElement const* _ccElement ) { CommandClass::ReadXML( _ccElement ); char const* str = _ccElement->Attribute("classgetsupported"); if( str ) { m_classGetSupported = !strcmp( str, "true"); } } //----------------------------------------------------------------------------- // // Save changed configuration //----------------------------------------------------------------------------- void Version::WriteXML ( TiXmlElement* _ccElement ) { CommandClass::WriteXML( _ccElement ); if( !m_classGetSupported ) { _ccElement->SetAttribute( "classgetsupported", "false" ); } } //----------------------------------------------------------------------------- // // 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 ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool Version::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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 ) ) ) { protocolValue->OnValueRefreshed( protocol ); protocolValue->Release(); } 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_classGetSupported ) { 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 ); } } open-zwave-1.5/cpp/src/command_classes/Version.h000066400000000000000000000047141264474202400217670ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Version.h // // Implementation of the Z-Wave COMMAND_CLASS_VERSION // // 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 . // //----------------------------------------------------------------------------- #ifndef _Version_H #define _Version_H #include "command_classes/CommandClass.h" namespace OpenZWave { class ValueString; /** \brief Implements COMMAND_CLASS_VERSION (0x86), a Z-Wave device command class. */ class Version: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new Version( _homeId, _nodeId ); } virtual ~Version(){} static uint8 const StaticGetCommandClassId(){ return 0x86; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_VERSION"; } bool RequestCommandClassVersion( CommandClass const* _commandClass ); // 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, uint8 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 ); protected: virtual void CreateVars( uint8 const _instance ); private: Version( uint32 const _homeId, uint8 const _nodeId ); bool m_classGetSupported; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/WakeUp.cpp000066400000000000000000000373141264474202400220730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // WakeUp.cpp // // Implementation of the Z-Wave COMMAND_CLASS_WAKE_UP // // 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 . // //----------------------------------------------------------------------------- #include "command_classes/CommandClasses.h" #include "command_classes/WakeUp.h" #include "command_classes/MultiCmd.h" #include "Defs.h" #include "Msg.h" #include "Driver.h" #include "Node.h" #include "Notification.h" #include "Options.h" #include "platform/Log.h" #include "platform/Mutex.h" #include "value_classes/ValueInt.h" using namespace OpenZWave; 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_pollRequired( false ), m_notification( false ) { m_awake = true; Options::Get()->GetOptionAsBool("AssumeAwake", &m_awake); 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(); } } //----------------------------------------------------------------------------- // // 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 ); } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // Nothing to do for wakeup //----------------------------------------------------------------------------- bool WakeUp::RequestValue ( uint32 const _requestFlags, uint8 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; } 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 ) { 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() ); m_notification = true; 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() ); 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; } //----------------------------------------------------------------------------- // // Set the command class version //----------------------------------------------------------------------------- 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 ) { 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(); } } //----------------------------------------------------------------------------- // // 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 ) { 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(); } //----------------------------------------------------------------------------- // // The device is awake, so send all the pending messages //----------------------------------------------------------------------------- void WakeUp::SendPending ( ) { m_awake = true; 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; } it = m_pendingQueue.erase( it ); } m_mutex->Unlock(); // Send the device back to sleep, unless we have outstanding queries. bool sendToSleep = m_notification; Node* node = GetNodeUnsafe(); if( node != NULL ) { if( !node->AllQueriesCompleted() ) { sendToSleep = false; } } if( sendToSleep ) { m_notification = false; 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: { 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; } } } } } open-zwave-1.5/cpp/src/command_classes/WakeUp.h000066400000000000000000000057231264474202400215370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // WakeUp.h // // Implementation of the Z-Wave COMMAND_CLASS_WAKE_UP // // 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 . // //----------------------------------------------------------------------------- #ifndef _WakeUp_H #define _WakeUp_H #include #include "command_classes/CommandClass.h" #include "Driver.h" namespace OpenZWave { class Msg; class ValueInt; class Mutex; /** \brief Implements COMMAND_CLASS_WAKE_UP (0x84), a Z-Wave device command class. */ class WakeUp: public CommandClass { 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 ); void SendPending(); 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, uint8 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; bool m_notification; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/command_classes/ZWavePlusInfo.cpp000066400000000000000000000131041264474202400234020ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ZWavePlusInfo.cpp // // Implementation of the Z-Wave COMMAND_CLASS_ZWAVE_PLUS_INFO // // Copyright (c) 2015 // // 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/ZWavePlusInfo.h" #include "Defs.h" #include "Msg.h" #include "Node.h" #include "Driver.h" #include "platform/Log.h" #include "value_classes/ValueByte.h" #include "value_classes/ValueShort.h" #include "value_classes/ValueList.h" using namespace OpenZWave; enum ZWavePlusInfoCmdEnum { ZWavePlusInfoCmd_Get = 0x01, ZWavePlusInfoCmd_Report }; enum { ZWavePlusInfoIndex_Version = 0x00, ZWavePlusInfoIndex_InstallerIcon, ZWavePlusInfoIndex_UserIcon, }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- 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) && HasStaticRequest( StaticRequest_Values ) ) { return RequestValue( _requestFlags, 0, _instance, _queue ); } return false; } //----------------------------------------------------------------------------- // // Request current value from the device //----------------------------------------------------------------------------- bool ZWavePlusInfo::RequestValue ( uint32 const _requestFlags, uint8 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 ( IsGetSupported() ) { 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]; 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; } //----------------------------------------------------------------------------- // // 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 ); } } open-zwave-1.5/cpp/src/command_classes/ZWavePlusInfo.h000066400000000000000000000043631264474202400230560ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ZWavePlusInfo.h // // Implementation of the Z-Wave COMMAND_CLASS_ZWAVE_PLUS_INFO // // Copyright (c) 2015 // // 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 _ZWavePlusInfo_H #define _ZWavePlusInfo_H #include "command_classes/CommandClass.h" namespace OpenZWave { /** \brief Implements COMMAND_CLASS_ZWAVE_PLUS_INFO (0x5E), a Z-Wave device command class. */ class ZWavePlusInfo: public CommandClass { public: static CommandClass* Create( uint32 const _homeId, uint8 const _nodeId ){ return new ZWavePlusInfo( _homeId, _nodeId ); } virtual ~ZWavePlusInfo(){} static uint8 const StaticGetCommandClassId(){ return 0x5E; } static string const StaticGetCommandClassName(){ return "COMMAND_CLASS_ZWAVE_PLUS_INFO"; } // From CommandClass virtual bool RequestState( uint32 const _requestFlags, uint8 const _instance, Driver::MsgQueue const _queue ); virtual bool RequestValue( uint32 const _requestFlags, uint8 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 ); private: ZWavePlusInfo( uint32 const _homeId, uint8 const _nodeId ); }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/platform/000077500000000000000000000000001264474202400166545ustar00rootroot00000000000000open-zwave-1.5/cpp/src/platform/Controller.cpp000066400000000000000000000052511264474202400215060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Controller.cpp // // Cross-platform, hardware-abstracted controller data interface // // Copyright (c) 2010 Jason Frazier // // 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 "Defs.h" #include "Driver.h" #include "platform/Controller.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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 } //----------------------------------------------------------------------------- // // 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; } open-zwave-1.5/cpp/src/platform/Controller.h000066400000000000000000000063321264474202400211540ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Controller.h // // Cross-platform, hardware-abstracted controller data interface // // Copyright (c) 2010 Jason Frazier // // 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 _Controller_H #define _Controller_H #include #include #include "Defs.h" #include "Driver.h" #include "platform/Stream.h" namespace OpenZWave { class Driver; class Controller: public Stream { // 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. 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 OpenZWave #endif //_Controller_H open-zwave-1.5/cpp/src/platform/Event.cpp000066400000000000000000000057251264474202400204520ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Event.cpp // // Cross-platform event // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 "Defs.h" #include "platform/Event.h" #ifdef WIN32 #include "platform/windows/EventImpl.h" // Platform-specific implementation of an event #elif defined WINRT #include "platform/winRT/EventImpl.h" // Platform-specific implementation of an event #else #include "platform/unix/EventImpl.h" // Platform-specific implementation of an event #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Event::Event ( ): m_pImpl( new EventImpl() ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 } //----------------------------------------------------------------------------- // // Set the event to not signalled //----------------------------------------------------------------------------- void Event::Reset ( ) { m_pImpl->Reset(); } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- 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 ); } open-zwave-1.5/cpp/src/platform/Event.h000066400000000000000000000042461264474202400201140ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Event.h // // Cross-platform manual-reset event // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _Event_H #define _Event_H #include "platform/Wait.h" namespace OpenZWave { class EventImpl; /** \brief Platform-independent definition of event objects. */ class Event: public Wait { friend class SerialControllerImpl; friend class Wait; public: /** * Constructor. * Creates a cross-platform event object equivalent to the Windows manual-reset event */ Event(); /** * Set the event to signalled. * \see Reset, Wait */ void Set(); /** * Set the event to not signalled. * \see Set, Wait */ void Reset(); protected: /** * Used by the Wait class to test whether the event is set. */ virtual bool IsSignalled(); /** * Used by the Wait::Multiple method. * returns true if the event signalled, false if it timed out */ bool Wait( int32 _timeout ); /** * Destructor. * Destroys the event object. */ ~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 OpenZWave #endif //_Event_H open-zwave-1.5/cpp/src/platform/FileOps.cpp000066400000000000000000000057631264474202400207340ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FileOps.cpp // // Cross-platform File Operations // // Copyright (c) 2012 Greg Satz // All rights reserved. // // 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 #include "platform/FileOps.h" #ifdef WIN32 #include "platform/windows/FileOpsImpl.h" // Platform-specific implementation of a File Operations #elif defined WINRT #include "platform/winRT/FileOpsImpl.h" // Platform-specific implementation of a File Operations #else #include "platform/unix/FileOpsImpl.h" // Platform-specific implementation of a File Operations #endif using namespace OpenZWave; 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; } //----------------------------------------------------------------------------- // // Static method to destroy the fileops singleton. //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- FileOps::FileOps ( ) { m_pImpl = new FileOpsImpl(); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- FileOps::~FileOps ( ) { delete m_pImpl; } open-zwave-1.5/cpp/src/platform/FileOps.h000066400000000000000000000036611264474202400203740ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FileOps.h // // Cross-platform File Operations // // Copyright (c) 2012 Greg Satz // All rights reserved. // // 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 _FileOps_H #define _FileOps_H #include #include #include "Defs.h" namespace OpenZWave { class FileOpsImpl; /** \brief Implements platform-independent File Operations. */ 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 existance of a folder. * \param string. Folder name. * \return Bool value indicating existance. */ static bool FolderExists( 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 OpenZWave #endif //_FileOps_H open-zwave-1.5/cpp/src/platform/HidController.cpp000066400000000000000000000365231264474202400221410ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // HidController.h // // Cross-platform HID port handler // // Copyright (c) 2010 Jason Frazier // // 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 "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" #define CHECK_HIDAPI_RESULT(RESULT, ERRORLABEL) if (RESULT < 0) goto ERRORLABEL #define PACKET_BUFFER_LENGTH 256 // are these specific to Wayne-Dalton? #define FEATURE_REPORT_LENGTH 0x40 #define INPUT_REPORT_LENGTH 0x5 #define OUTPUT_REPORT_LENGTH 0x0 using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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 ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; } 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; } 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; } m_serialNumber = _serialNumber; return true; } //----------------------------------------------------------------------------- // // Open and configure a HID port //----------------------------------------------------------------------------- bool HidController::Open ( string const& _hidControllerName ) { if( m_bOpen ) { return false; } 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; } m_thread = new Thread( "HidController" ); // 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; } hid_close( m_hHidController ); m_hHidController = NULL; 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 ); } } //----------------------------------------------------------------------------- // // 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 ) { // Exit signalled. break; } } else { // ...retry every 30 seconds after that if( Wait::Single( _exitEvent, 30000 ) >= 0 ) { // Exit signalled. break; } } 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 ); } 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 ) { 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); } 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; } 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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; } open-zwave-1.5/cpp/src/platform/HidController.h000066400000000000000000000111301264474202400215710ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // HidController.h // // Cross-platform HID port handler // // Copyright (c) 2010 Jason Frazier // // 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 _HidController_H #define _HidController_H #include #include "Defs.h" #include "platform/Controller.h" struct hid_device_; typedef struct hid_device_ hid_device; namespace OpenZWave { class Driver; class Msg; class Thread; class Event; 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: 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 OpenZWave #endif //_HidController_H open-zwave-1.5/cpp/src/platform/Log.cpp000066400000000000000000000245221264474202400201060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Log.cpp // // Cross-platform message and error logging // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 #include "Defs.h" #include "platform/Mutex.h" #include "platform/Log.h" #ifdef WIN32 #include "platform/windows/LogImpl.h" // Platform-specific implementation of a log #elif defined WINRT #include "platform/winRT/LogImpl.h" // Platform-specific implementation of a log #else #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.) */ }; Log* Log::s_instance = NULL; i_LogImpl* Log::m_pImpl = NULL; 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 ) { if( NULL == s_instance ) { 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 { Log::Destroy(); 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 } return s_instance; } //----------------------------------------------------------------------------- // // 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; } */ //----------------------------------------------------------------------------- // // Static method to destroy the logging singleton. //----------------------------------------------------------------------------- void Log::Destroy ( ) { delete s_instance; s_instance = NULL; } //----------------------------------------------------------------------------- // // Set log class //----------------------------------------------------------------------------- bool Log::SetLoggingClass ( i_LogImpl *LogClass ) { delete m_pImpl; m_pImpl = LogClass; return true; } //----------------------------------------------------------------------------- // // Set flag to actually write to log or skip it (legacy version) // If logging is enabled, the default log detail settings will be used // Write to file/screen LogLevel_Detail // Save in queue for errors LogLevel_Debug // Trigger for dumping queue LogLevel_Warning // Console output? Yes // Append to an existing log? No (overwrite) //----------------------------------------------------------------------------- void Log::SetLoggingState ( bool _dologging ) { bool prevLogging = s_dologging; s_dologging = _dologging; 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 ) { // 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." ); 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) ) { s_dologging = true; } else { s_dologging = false; } if( s_instance && s_dologging && s_instance->m_pImpl ) { s_instance->m_logMutex->Lock(); s_instance->m_pImpl->SetLoggingState( _saveLevel, _queueLevel, _dumpTrigger ); s_instance->m_logMutex->Unlock(); } if (!prevLogging && s_dologging) Log::Write(LogLevel_Always, "Logging started\n\n"); } //----------------------------------------------------------------------------- // // Return a flag to indicate whether logging is enabled //----------------------------------------------------------------------------- bool Log::GetLoggingState ( ) { return s_dologging; } //----------------------------------------------------------------------------- // // Write to the log //----------------------------------------------------------------------------- void Log::Write ( LogLevel _level, char const* _format, ... ) { if( s_instance && s_dologging && s_instance->m_pImpl ) { 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 ); s_instance->m_logMutex->Unlock(); } } //----------------------------------------------------------------------------- // // Write to the log //----------------------------------------------------------------------------- void Log::Write ( LogLevel _level, uint8 const _nodeId, char const* _format, ... ) { if( s_instance && s_dologging && s_instance->m_pImpl ) { 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 ) s_instance->m_logMutex->Unlock(); } } //----------------------------------------------------------------------------- // // Send queued messages to the log (and empty the queue) //----------------------------------------------------------------------------- void Log::QueueDump ( ) { if( s_instance && s_dologging && s_instance->m_pImpl ) { s_instance->m_logMutex->Lock(); s_instance->m_pImpl->QueueDump(); s_instance->m_logMutex->Unlock(); } } //----------------------------------------------------------------------------- // // Empty the queued message queue //----------------------------------------------------------------------------- void Log::QueueClear ( ) { if( s_instance && s_dologging && s_instance->m_pImpl ) { s_instance->m_logMutex->Lock(); s_instance->m_pImpl->QueueClear(); s_instance->m_logMutex->Unlock(); } } //----------------------------------------------------------------------------- // // Change the name of the log file (will start writing a new file) //----------------------------------------------------------------------------- void Log::SetLogFileName ( const string &_filename ) { if( s_instance && s_dologging && s_instance->m_pImpl ) { s_instance->m_logMutex->Lock(); s_instance->m_pImpl->SetLogFileName( _filename ); s_instance->m_logMutex->Unlock(); } } //----------------------------------------------------------------------------- // // 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() ) { if (NULL == m_pImpl) m_pImpl = new LogImpl( _filename, _bAppend, _bConsoleOutput, _saveLevel, _queueLevel, _dumpTrigger ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Log::~Log ( ) { m_logMutex->Release(); delete m_pImpl; m_pImpl = NULL; } open-zwave-1.5/cpp/src/platform/Log.h000066400000000000000000000162741264474202400175600ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Log.h // // Cross-platform message and error logging // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _Log_H #define _Log_H #include #include #include "Defs.h" namespace OpenZWave { class Mutex; extern char const *LogLevelString[]; 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's 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.) */ }; 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; }; /** \brief Implements a platform-independent log...written to the console and, optionally, a file. */ class Log { public: /** * 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 ); /** * 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 ); /** * 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 Implmentation Class to replace the standard File/Console Loggin * \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 ); /** * 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, ... ); /** * 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, ... ); /** * 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; Mutex* m_logMutex; }; } // namespace OpenZWave #endif //_Log_H open-zwave-1.5/cpp/src/platform/Mutex.cpp000066400000000000000000000053511264474202400204660ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Mutex.cpp // // Cross-platform mutex // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 "Defs.h" #include "platform/Mutex.h" #ifdef WIN32 #include "platform/windows/MutexImpl.h" // Platform-specific implementation of a mutex #elif defined WINRT #include "platform/winRT/MutexImpl.h" // Platform-specific implementation of a mutex #else #include "platform/unix/MutexImpl.h" // Platform-specific implementation of a mutex #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Mutex::Mutex ( ): m_pImpl( new MutexImpl() ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Mutex::~Mutex ( ) { delete m_pImpl; } //----------------------------------------------------------------------------- // // Lock the mutex //----------------------------------------------------------------------------- bool Mutex::Lock ( bool const _bWait // = true; ) { return m_pImpl->Lock( _bWait ); } //----------------------------------------------------------------------------- // // Release our lock on the mutex //----------------------------------------------------------------------------- void Mutex::Unlock ( ) { m_pImpl->Unlock(); 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(); } open-zwave-1.5/cpp/src/platform/Mutex.h000066400000000000000000000045431264474202400201350ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Mutex.h // // Cross-platform mutex // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _Mutex_H #define _Mutex_H #include "platform/Wait.h" namespace OpenZWave { class MutexImpl; /** \brief Implements a platform-independent mutex--for serializing access to a shared resource. */ class Mutex: public Wait { public: /** * Constructor. * Creates a mutex object that can be used to serialize access to a shared resource. */ Mutex(); /** * 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 ); /** * Releases the lock on the mutex. * There must be a matching call to Release for every call to Lock. * \see Lock */ void Unlock(); /** * Used by the Wait class to test whether the mutex is free. */ virtual bool IsSignalled(); protected: /** * Destructor. * Destroys the mutex object. */ ~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 OpenZWave #endif //_Mutex_H open-zwave-1.5/cpp/src/platform/Ref.h000066400000000000000000000044211264474202400175420ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Ref.h // // Reference counting for objects. // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _Ref_H #define _Ref_H #pragma once #include "Defs.h" 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. */ class Ref { 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() { if( 0 >= ( --m_refs ) ) { delete this; return 0; } return m_refs; } protected: virtual ~Ref(){} private: // Reference counting int32 m_refs; }; // class Ref } // namespace OpenZWave #endif // _Ref_H open-zwave-1.5/cpp/src/platform/SerialController.cpp000066400000000000000000000113641264474202400226500ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SerialController.h // // Cross-platform serial port handler // // Copyright (c) 2010 Jason Frazier // // 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 "Msg.h" #include "platform/Event.h" #include "platform/Thread.h" #include "platform/SerialController.h" #include "platform/Log.h" #ifdef WIN32 #include "platform/windows/SerialControllerImpl.h" // Platform-specific implementation of a serial port #elif defined WINRT #include "platform/winRT/SerialControllerImpl.h" // Platform-specific implementation of a serial port #else #include "platform/unix/SerialControllerImpl.h" // Platform-specific implementation of a serial port #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // 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; } 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; } 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; } m_stopBits = _stopBits; return true; } //----------------------------------------------------------------------------- // // Open and configure a serial port //----------------------------------------------------------------------------- bool SerialController::Open ( string const& _serialControllerName ) { if( m_bOpen ) { return false; } m_serialControllerName = _serialControllerName; m_bOpen = m_pImpl->Open(); return m_bOpen; } //----------------------------------------------------------------------------- // // Close a serial port //----------------------------------------------------------------------------- bool SerialController::Close ( ) { if( !m_bOpen ) { return false; } 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 ) ); } open-zwave-1.5/cpp/src/platform/SerialController.h000066400000000000000000000100431264474202400223060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SerialController.h // // Cross-platform serial port handler // // Copyright (c) 2010 Jason Frazier // // 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 _SerialController_H #define _SerialController_H #include #include "Defs.h" #include "platform/Controller.h" namespace OpenZWave { class Driver; class Msg; class SerialControllerImpl; 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 paramters. * @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; }; } // namespace OpenZWave #endif //_SerialController_H open-zwave-1.5/cpp/src/platform/Stream.cpp000066400000000000000000000132401264474202400206130ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Stream.h // // Cross-platform circular buffer with signalling // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 "platform/Stream.h" #include "platform/Mutex.h" #include "platform/Log.h" #include #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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]; } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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(); } } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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 ); m_head = block2; LogData( m_buffer + m_head - block1, 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; } //----------------------------------------------------------------------------- // // Test whether there is enough data to be signalled //----------------------------------------------------------------------------- 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() ); } open-zwave-1.5/cpp/src/platform/Stream.h000066400000000000000000000102661264474202400202650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Stream.h // // Cross-platform circular buffer with signalling // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _Stream_H #define _Stream_H #include "Defs.h" #include "platform/Wait.h" #include namespace OpenZWave { class Mutex; /** \brief Platform-independent definition of a circular buffer. */ 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 amoutn 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 OpenZWave #endif //_Event_H open-zwave-1.5/cpp/src/platform/Thread.cpp000066400000000000000000000065731264474202400206020ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Thread.cpp // // Cross-platform threads // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 "Defs.h" #include "platform/Event.h" #include "platform/Thread.h" #ifdef WIN32 #include "platform/windows/ThreadImpl.h" // Platform-specific implementation of a thread #elif defined WINRT #include "platform/winRT/ThreadImpl.h" // Platform-specific implementation of a thread #else #include "platform/unix/ThreadImpl.h" // Platform-specific implementation of a thread #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Thread::Thread ( string const& _name ) { m_exitEvent = new Event(); m_pImpl = new ThreadImpl( this, _name ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 ) ); } //----------------------------------------------------------------------------- // // Stop a function running on this thread //----------------------------------------------------------------------------- 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; } return true; } //----------------------------------------------------------------------------- // // Causes the thread to sleep for the specified number of milliseconds. //----------------------------------------------------------------------------- void Thread::Sleep ( uint32 _milliseconds ) { return( m_pImpl->Sleep( _milliseconds ) ); } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- bool Thread::IsSignalled ( ) { return m_pImpl->IsSignalled(); } open-zwave-1.5/cpp/src/platform/Thread.h000066400000000000000000000057461264474202400202500ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Thread.h // // Cross-platform threads // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _Thread_H #define _Thread_H #include #include "Defs.h" #include "platform/Wait.h" namespace OpenZWave { class ThreadImpl; class Event; /** \brief Implements a platform-independent thread management class. */ class Thread: public Wait { public: typedef void (*pfnThreadProc_t)( Event* _exitEvent, void* _context ); /** * Constructor. * Creates a thread object that can be used to serialize access to a shared resource. */ Thread( string const& _name ); /** * 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 ); /** * 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(); /** * Causes the thread to sleep for the specified number of milliseconds. * \param _millisecs Number of milliseconds to sleep. */ void Sleep( uint32 _millisecs ); protected: /** * Used by the Wait class to test whether the thread has been completed. */ virtual bool IsSignalled(); /** * 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 OpenZWave #endif //_Thread_H open-zwave-1.5/cpp/src/platform/TimeStamp.cpp000066400000000000000000000063631264474202400212730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeStamp.h // // Cross-platform TimeStamp // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 #include "Defs.h" #include "platform/TimeStamp.h" #ifdef WIN32 #include "platform/windows/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp #elif defined WINRT #include "platform/winRT/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp #else #include "platform/unix/TimeStampImpl.h" // Platform-specific implementation of a TimeStamp #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- TimeStamp::TimeStamp ( ): m_pImpl( new TimeStampImpl() ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 ); } //----------------------------------------------------------------------------- // // Gets the difference between now and the timestamp time in milliseconds //----------------------------------------------------------------------------- int32 TimeStamp::TimeRemaining ( ) { return m_pImpl->TimeRemaining(); } //----------------------------------------------------------------------------- // // Return object as a string //----------------------------------------------------------------------------- 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); } open-zwave-1.5/cpp/src/platform/TimeStamp.h000066400000000000000000000046671264474202400207450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeStamp.h // // Cross-platform TimeStamp // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _TimeStamp_H #define _TimeStamp_H #include "Defs.h" namespace OpenZWave { class TimeStampImpl; /** \brief Implements a platform-independent TimeStamp. */ class OPENZWAVE_EXPORT TimeStamp { public: /** * Constructor. * Creates a TimeStamp object. */ TimeStamp(); /** * Destructor. * Destroys the 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 ); /** * 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 a string for output. * \return string */ string GetAsString(); /** * Overload the subtract operator to get the difference between * two timestamps in milliseconds. */ int32 operator- ( TimeStamp const& _other ); 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 OpenZWave #endif //_TimeStamp_H open-zwave-1.5/cpp/src/platform/Wait.cpp000066400000000000000000000115301264474202400202640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Wait.cpp // // Base class for objects we want to be able to wait for. // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 #include "Defs.h" #include "platform/Wait.h" #include "platform/Event.h" #include "platform/Log.h" #ifdef WIN32 #include "platform/windows/WaitImpl.h" // Platform-specific implementation of a Wait object #elif defined WINRT #include "platform/winRT/WaitImpl.h" // Platform-specific implementation of a Wait object #else #include "platform/unix/WaitImpl.h" // Platform-specific implementation of a Wait object #endif using namespace OpenZWave; void WaitMultipleCallback( void* _context ); //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Wait::Wait ( ) { m_pImpl = new WaitImpl( this ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- Wait::~Wait ( ) { delete m_pImpl; } //----------------------------------------------------------------------------- // // Add a watcher to our object. //----------------------------------------------------------------------------- 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 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(); } } //----------------------------------------------------------------------------- // // Notify all the watchers that the object has become signalled //----------------------------------------------------------------------------- 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; // 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 ) { _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; } //----------------------------------------------------------------------------- // // Callback handler for the watchers added during WaitImpl::Multiple //----------------------------------------------------------------------------- void WaitMultipleCallback ( void* _context ) { Event* waitEvent = (Event*)_context; waitEvent->Set(); } open-zwave-1.5/cpp/src/platform/Wait.h000066400000000000000000000072221264474202400177340ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Wait.h // // Cross-platform abstract base class for objects we // want to be able to wait for. // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _Wait_H #define _Wait_H #include #include "platform/Ref.h" namespace OpenZWave { class WaitImpl; /** \brief Platform-independent definition of Wait objects. */ 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 OpenZWave #endif //_Wait_H open-zwave-1.5/cpp/src/platform/unix/000077500000000000000000000000001264474202400176375ustar00rootroot00000000000000open-zwave-1.5/cpp/src/platform/unix/EventImpl.cpp000066400000000000000000000143161264474202400222530ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // EventImpl.cpp // // POSIX implementation of a cross-platform event // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 "Defs.h" #include "EventImpl.h" #include #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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 ); pthread_condattr_setpshared( &ca, PTHREAD_PROCESS_PRIVATE ); pthread_cond_init( &m_condition, &ca ); pthread_condattr_destroy( &ca ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 ) { 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 ); } } //----------------------------------------------------------------------------- // // 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 ); } } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- bool EventImpl::IsSignalled ( ) { return m_isSignaled; } //----------------------------------------------------------------------------- // // Wait for the event to become signalled //----------------------------------------------------------------------------- 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; gettimeofday(&now, NULL); abstime.tv_sec = now.tv_sec + (_timeout / 1000); // Now add the remainder of our timeout to the microseconds part of 'now' now.tv_usec += (_timeout % 1000) * 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); 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 { while( !m_isSignaled ) { int oldstate; pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate); err = pthread_cond_wait( &m_condition, &m_lock ); 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; } err = pthread_mutex_unlock( &m_lock ); if( err != 0 ) { fprintf(stderr, "EventImpl::Wait unlock error %d (%d)\n", errno, err ); assert( 0 ); } return result; } open-zwave-1.5/cpp/src/platform/unix/EventImpl.h000066400000000000000000000031401264474202400217110ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // EventImpl.h // // POSIX implementation of a cross-platform event // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 _EventImpl_H #define _EventImpl_H #include #include namespace OpenZWave { 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 OpenZWave #endif //_EventImpl_H open-zwave-1.5/cpp/src/platform/unix/FileOpsImpl.cpp000066400000000000000000000037271264474202400225370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FileOpsImpl.cpp // // Unix implementation of file operations // // Copyright (c) 2012, Greg Satz // All rights reserved. // // 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 #include "FileOpsImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- FileOpsImpl::FileOpsImpl ( ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- FileOpsImpl::~FileOpsImpl ( ) { } //----------------------------------------------------------------------------- // // Determine if a folder exists //----------------------------------------------------------------------------- bool FileOpsImpl::FolderExists ( string _folderName ) { DIR *dirp = opendir( _folderName.c_str() ); if( dirp != NULL ) { closedir( dirp ); return true; } else return false; } open-zwave-1.5/cpp/src/platform/unix/FileOpsImpl.h000066400000000000000000000025521264474202400221770ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FileOpsImpl.h // // Unix implementation of file operations // // Copyright (c) 2012, Greg Satz // All rights reserved. // // 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 _FileOpsImpl_H #define _FileOpsImpl_H #include #include #include "Defs.h" #include "platform/FileOps.h" namespace OpenZWave { class FileOpsImpl { friend class FileOps; private: FileOpsImpl(); ~FileOpsImpl(); bool FolderExists( string _filename ); }; } // namespace OpenZWave #endif //_FileOpsImpl_H open-zwave-1.5/cpp/src/platform/unix/LogImpl.cpp000066400000000000000000000227701264474202400217160ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // LogImpl.cpp // // Unix implementation of message and error logging // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 #include #include #include #include "Defs.h" #include "LogImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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 } //----------------------------------------------------------------------------- // // 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) } 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] = {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 ); } // 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"); } // 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"); } } } 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(); } //----------------------------------------------------------------------------- // // Write to the log queue //----------------------------------------------------------------------------- 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(); } } //----------------------------------------------------------------------------- // // 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, "" ); } //----------------------------------------------------------------------------- // // Clear the LogQueue //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // Generate a string with formatted current time //----------------------------------------------------------------------------- string LogImpl::GetTimeStampString ( ) { // Get a timestamp struct timeval tv; gettimeofday(&tv, NULL); struct tm *tm; tm = localtime( &tv.tv_sec ); // 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; } } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- 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, "; } open-zwave-1.5/cpp/src/platform/unix/LogImpl.h000066400000000000000000000046641264474202400213650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // LogImpl.h // // Unix implementation of message and error logging // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 _LogImpl_H #define _LogImpl_H #include #include #include #include #include #include "platform/Log.h" namespace OpenZWave { class LogImpl : public i_LogImpl { private: friend class Log; LogImpl( string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger ); ~LogImpl(); 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; }; } // namespace OpenZWave #endif //_LogImpl_H open-zwave-1.5/cpp/src/platform/unix/MutexImpl.cpp000066400000000000000000000066431264474202400223000ustar00rootroot00000000000000//---------------------------------------------------------------------------- // // MutexImpl.cpp // // POSIX implementation of the cross-platform mutex // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 "Defs.h" #include "platform/Log.h" #include "MutexImpl.h" #include #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- 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 ) { fprintf(stderr, "MutexImpl::MutexImpl error %d (%d)\n", errno, err ); } pthread_mutexattr_destroy( &ma ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- MutexImpl::~MutexImpl ( ) { pthread_mutex_destroy( &m_criticalSection ); } //----------------------------------------------------------------------------- // // Lock the mutex //----------------------------------------------------------------------------- bool MutexImpl::Lock ( bool const _bWait ) { if( _bWait ) { // We will wait for the lock int err = pthread_mutex_lock( &m_criticalSection ); if( err == 0 ) { ++m_lockCount; return true; } fprintf(stderr, "MutexImpl::Lock error %d (%d)\n", 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; } //----------------------------------------------------------------------------- // // 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; int err = pthread_mutex_unlock( &m_criticalSection ); if( err != 0 ) { fprintf(stderr, "MutexImpl::Unlock error %d (%d)\n", errno, err); } } } //----------------------------------------------------------------------------- // // Test whether the mutex is free //----------------------------------------------------------------------------- bool MutexImpl::IsSignalled ( ) { return( 0 == m_lockCount ); } open-zwave-1.5/cpp/src/platform/unix/MutexImpl.h000066400000000000000000000027711264474202400217430ustar00rootroot00000000000000//---------------------------------------------------------------------------- // // MutexImpl.h // // POSIX implementation of the cross-platform mutex // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 _MutexImpl_H #define _MutexImpl_H #include #include namespace OpenZWave { class MutexImpl { private: friend class Mutex; MutexImpl(); ~MutexImpl(); bool Lock( bool const _bWait = true ); void Unlock(); bool IsSignalled(); uint32 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 OpenZWave #endif //_MutexIF_H open-zwave-1.5/cpp/src/platform/unix/SerialControllerImpl.cpp000066400000000000000000000223041264474202400244510ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SerialControllerImpl.cpp // // POSIX implementation of a cross-platform serial port // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 #include #include "Defs.h" #include "platform/Thread.h" #include "platform/Event.h" #include "SerialControllerImpl.h" #include "platform/Log.h" #ifdef __linux__ #include #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- SerialControllerImpl::SerialControllerImpl ( SerialController* _owner ): m_owner( _owner ), m_hSerialController( -1 ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; } // Start the read thread m_pThread = new Thread( "SerialController" ); m_pThread->Start( SerialReadThreadEntryPoint, this ); 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; } //----------------------------------------------------------------------------- // // 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 ); } } //----------------------------------------------------------------------------- // // Handle receiving data //----------------------------------------------------------------------------- void SerialControllerImpl::ReadThreadProc ( 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( -1 != 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; } 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 ); } } //----------------------------------------------------------------------------- // // 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 ); m_hSerialController = open( device.c_str(), O_RDWR | O_NOCTTY, 0 ); 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 ); } int bits; bits = 0; ioctl( m_hSerialController, TIOCMSET, &bits ); // 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; #ifdef DARWIN 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; } tcflush( m_hSerialController, TCIOFLUSH ); // 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; } //----------------------------------------------------------------------------- // // Read data from the serial port //----------------------------------------------------------------------------- void SerialControllerImpl::Read ( ) { uint8 buffer[256]; while( 1 ) { int32 bytesRead; int err; 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 ); } } //----------------------------------------------------------------------------- // // 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; } open-zwave-1.5/cpp/src/platform/unix/SerialControllerImpl.h000066400000000000000000000035151264474202400241210ustar00rootroot00000000000000// // SerialControllerImpl.h // // POSIX implementation of a cross-platform serial port // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 _SerialControllerImpl_H #define _SerialControllerImpl_H #include #include #include #include #include #include #include #include #include "Defs.h" #include "platform/SerialController.h" namespace OpenZWave { class SerialControllerImpl { public: void ReadThreadProc( Event* _exitEvent ); private: friend class SerialController; SerialControllerImpl( SerialController* _owner ); ~SerialControllerImpl(); bool Open(); void Close(); uint32 Write( uint8* _buffer, uint32 _length ); bool Init( uint32 const _attempts ); void Read(); SerialController* m_owner; int m_hSerialController; Thread* m_pThread; static void SerialReadThreadEntryPoint( Event* _exitEvent, void* _content ); }; } // namespace OpenZWave #endif //_SerialControllerImpl_H open-zwave-1.5/cpp/src/platform/unix/ThreadImpl.cpp000066400000000000000000000120771264474202400224030ustar00rootroot00000000000000//---------------------------------------------------------------------------- // // ThreadImpl.h // // POSIX implementation of a cross-platform thread // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 #include "Defs.h" #include "platform/Event.h" #include "platform/Thread.h" #include "ThreadImpl.h" #ifdef DARWIN #define pthread_yield pthread_yield_np #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- 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 ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 ); //fprintf(stderr, "thread %s starting %08x\n", m_name.c_str(), m_hThread); //fflush(stderr); pthread_attr_destroy ( &ta ); return true; } //----------------------------------------------------------------------------- // // End this thread //----------------------------------------------------------------------------- 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; } // 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 ); return true; } //----------------------------------------------------------------------------- // // Cause thread to sleep for the specified number of milliseconds //----------------------------------------------------------------------------- void ThreadImpl::Sleep ( uint32 _millisecs ) { usleep( _millisecs*1000 ); } //----------------------------------------------------------------------------- // // Test whether the thread has completed //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // 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(); } open-zwave-1.5/cpp/src/platform/unix/ThreadImpl.h000066400000000000000000000037341264474202400220500ustar00rootroot00000000000000//---------------------------------------------------------------------------- // // ThreadImpl.h // // POSIX implementation of a cross-platform thread // // Copyright (c) 2010, Greg Satz // All rights reserved. // // 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 _ThreadImpl_H #define _ThreadImpl_H #include #include #include #include namespace OpenZWave { class Thread; class Event; class ThreadImpl { private: friend class Thread; ThreadImpl( Thread* _owner, string const& _tname ); ~ThreadImpl(); 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 OpenZWave #endif //_ThreadImpl_H open-zwave-1.5/cpp/src/platform/unix/TimeStampImpl.cpp000066400000000000000000000100621264474202400230670ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeStampImpl.cpp // // OSX implementation of a TimeStamp // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 #include #include "Defs.h" #include "TimeStampImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- TimeStampImpl::TimeStampImpl ( ) { SetTime(0); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // Return a string representation //----------------------------------------------------------------------------- string TimeStampImpl::GetAsString ( ) { char str[100]; struct tm *tm; tm = localtime( &m_stamp.tv_sec ); 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; } open-zwave-1.5/cpp/src/platform/unix/TimeStampImpl.h000066400000000000000000000045421264474202400225420ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeStampImpl.h // // OSX implementation of a TimeStamp // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _TimeStampImpl_H #define _TimeStampImpl_H #include #include #include #include "Defs.h" namespace OpenZWave { /** \brief Windows implementation of a timestamp. */ class TimeStampImpl { public: /** * Constructor. * Creates a 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 ); /** * 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(); /** * 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; }; } // namespace OpenZWave #endif //_TimeStampImpl_H open-zwave-1.5/cpp/src/platform/unix/WaitImpl.cpp000066400000000000000000000106051264474202400220730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // WaitImpl.cpp // // POSIX implementation of an abstract base class for objects we // want to be able to wait for. // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 "Defs.h" #include "platform/Wait.h" #include "WaitImpl.h" #include #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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 ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; if( pthread_mutex_lock( &m_criticalSection ) != 0 ) { fprintf(stderr, "WaitImpl::AddWatcher lock error %d\n", errno ); assert( 0 ); } m_watchers.push_back( watcher ); if( pthread_mutex_unlock( &m_criticalSection ) != 0 ) { fprintf(stderr, "WaitImpl::AddWatcher unlock error %d\n", errno ); 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; 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; } } 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 ); } } open-zwave-1.5/cpp/src/platform/unix/WaitImpl.h000066400000000000000000000040061264474202400215360ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // WaitImpl.h // // POSIX implementation of a base class for objects we // want to be able to wait for. // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _WaitImpl_H #define _WaitImpl_H #include #include #include #include "Defs.h" #include "platform/Ref.h" #include "platform/Wait.h" namespace OpenZWave { /** \brief Windows specific implementation of Wait objects. */ class WaitImpl { private: friend class Wait; WaitImpl( Wait* _owner ); virtual ~WaitImpl(); void AddWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); bool RemoveWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); void Notify(); static int32 Multiple( Wait** _objects, uint32 _numObjects, int32 _timeout = -1 ); WaitImpl( Wait const& ); // prevent copy WaitImpl& operator = ( WaitImpl const& ); // prevent assignment struct Watcher { Wait::pfnWaitNotification_t m_callback; void* m_context; }; list m_watchers; Wait* m_owner; pthread_mutex_t m_criticalSection; }; } // namespace OpenZWave #endif //_WaitImpl_H open-zwave-1.5/cpp/src/platform/winRT/000077500000000000000000000000001264474202400177175ustar00rootroot00000000000000open-zwave-1.5/cpp/src/platform/winRT/EventImpl.cpp000066400000000000000000000056561264474202400223420ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // EventImpl.cpp // // WinRT implementation of a cross-platform event // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 #include "Defs.h" #include "EventImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- 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 ); } //----------------------------------------------------------------------------- // // Set the event to signalled //----------------------------------------------------------------------------- void EventImpl::Set ( ) { ::SetEvent( m_hEvent ); } //----------------------------------------------------------------------------- // // Set the event to not signalled //----------------------------------------------------------------------------- void EventImpl::Reset ( ) { ::ResetEvent( m_hEvent ); } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- 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 ) ); } open-zwave-1.5/cpp/src/platform/winRT/EventImpl.h000066400000000000000000000030421264474202400217720ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // EventImpl.h // // WinRT implementation of a cross-platform event // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _EventImpl_H #define _EventImpl_H #include #include "Defs.h" namespace OpenZWave { /** \brief Windows-specific implementation of the Event class. */ 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(); HANDLE m_hEvent; }; } // namespace OpenZWave #endif //_EventImpl_H open-zwave-1.5/cpp/src/platform/winRT/FileOpsImpl.cpp000066400000000000000000000042141264474202400226070ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FileOpsImpl.cpp // // WinRT implementation of file operations // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 #include "FileOpsImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- FileOpsImpl::FileOpsImpl ( ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; } open-zwave-1.5/cpp/src/platform/winRT/FileOpsImpl.h000066400000000000000000000025521264474202400222570ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FileOpsImpl.h // // WinRT implementation of file operations // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _FileOpsImpl_H #define _FileOpsImpl_H #include #include #include "Defs.h" #include "platform/FileOps.h" namespace OpenZWave { class FileOpsImpl { friend class FileOps; private: FileOpsImpl(); ~FileOpsImpl(); bool FolderExists( const string &_filename ); }; } // namespace OpenZWave #endif //_FileOpsImpl_H open-zwave-1.5/cpp/src/platform/winRT/HidControllerWinRT.cpp000066400000000000000000000175641264474202400241340ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // HidControllerWinRT.cpp // // WinRT implementation of a HidController // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 "Defs.h" #include "HidControllerWinRT.h" #include "platform/Log.h" #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; #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 //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- 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; } } //----------------------------------------------------------------------------- // // 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; } 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; } 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; } m_serialNumber = _serialNumber; return true; } //----------------------------------------------------------------------------- // // Open and configure a HID port //----------------------------------------------------------------------------- bool HidController::Open(string const& _hidControllerName) { if (m_bOpen) { return false; } 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) { 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); } }); } }).wait(); } catch (Platform::Exception^ ex) { } 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; } //----------------------------------------------------------------------------- // // 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); 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; }).then([this](String ^deviceId) -> IAsyncOperation ^ { return HidDevice::FromIdAsync(deviceId, Windows::Storage::FileAccessMode::Read); }).then([this](task deviceTask) -> bool { try { m_device = deviceTask.get(); 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); 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); } //----------------------------------------------------------------------------- // // 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(); auto array = ref new Array(_buffer, _length); dataWriter->WriteBytes(ArrayReference(_buffer, _length)); featureReport->Data = dataWriter->DetachBuffer(); uint32 bytesWritten = 0; try { bytesWritten = create_task(m_device->SendFeatureReportAsync(featureReport)).get(); } catch (Platform::Exception^) { } return bytesWritten; } open-zwave-1.5/cpp/src/platform/winRT/HidControllerWinRT.h000066400000000000000000000073461264474202400235760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // HidControllerImpl.h // // WinRT implementation of a HidController // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _HidControllerImpl_H #define _HidControllerImpl_H #include #include "Defs.h" #include "platform/Controller.h" #include namespace OpenZWave { 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 OpenZWave #endif //_HidControllerImpl_H open-zwave-1.5/cpp/src/platform/winRT/LogImpl.cpp000066400000000000000000000217501264474202400217730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // LogImpl.cpp // // WinRT implementation of message and error logging // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 #include #include "Defs.h" #include "LogImpl.h" #ifdef MINGW #define vsprintf_s vsnprintf #define strcpy_s(DEST, NUM, SOURCE) strncpy(DEST, SOURCE, NUM) errno_t fopen_s(FILE** pFile, const char *filename, const char *mode) { if (!pFile) { _set_errno(EINVAL); return EINVAL; } *pFile = fopen(filename, mode); if (!*pFile) { return errno; } return 0; } #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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; // create an adjusted file name and timestamp string string timeStr = GetTimeStampString(); 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 ); } } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 ) { 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 ); } } // 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 ); // 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"); } //----------------------------------------------------------------------------- // // Clear the LogQueue //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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; } } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- 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, "; } open-zwave-1.5/cpp/src/platform/winRT/LogImpl.h000066400000000000000000000046131264474202400214370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // LogImpl.h // // WinRT implementation of message and error logging // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _LogImpl_H #define _LogImpl_H #include "Defs.h" #include #include "platform/Log.h" #include "Windows.h" namespace OpenZWave { /** \brief Windows-specific implementation of the Log class. */ class LogImpl : public i_LogImpl { private: friend class Log; LogImpl( string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger ); ~LogImpl(); 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); 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 OpenZWave #endif //_LogImpl_H open-zwave-1.5/cpp/src/platform/winRT/MutexImpl.cpp000066400000000000000000000056211264474202400223530ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MutexImpl.cpp // // WinRT implementation of the cross-platform mutex // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 "Defs.h" #include "MutexImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- MutexImpl::MutexImpl ( ): m_lockCount( 0 ) { InitializeCriticalSectionEx( &m_criticalSection, 0, 0 ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; } // Returns immediately, even if the lock was not available. if( TryEnterCriticalSection( &m_criticalSection ) ) { ++m_lockCount; return true; } 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 ); } } //----------------------------------------------------------------------------- // // Test whether the mutex is free //----------------------------------------------------------------------------- bool MutexImpl::IsSignalled ( ) { return( 0 == m_lockCount ); } open-zwave-1.5/cpp/src/platform/winRT/MutexImpl.h000066400000000000000000000030431264474202400220140ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MutexImpl.h // // WinRT implementation of the cross-platform mutex // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _MutexImpl_H #define _MutexImpl_H #include namespace OpenZWave { /** \brief Windows-specific implementation of the Mutex class. */ class MutexImpl { private: friend class Mutex; MutexImpl(); ~MutexImpl(); bool Lock( bool const _bWait = true ); void Unlock(); 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 OpenZWave #endif //_MutexIF_H open-zwave-1.5/cpp/src/platform/winRT/SerialControllerImpl.cpp000066400000000000000000000157641264474202400245450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SerialControllerImpl.cpp // // WinRT Implementation of the cross-platform serial port // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 "Defs.h" #include "SerialControllerImpl.h" #include "platform/Log.h" #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; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- SerialControllerImpl::SerialControllerImpl( SerialController* _owner) : m_owner( _owner ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- SerialControllerImpl::~SerialControllerImpl() { Close(); } //----------------------------------------------------------------------------- // // Close the serial port //----------------------------------------------------------------------------- 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::GetDeviceSelectorFromUsbVidPid(0x10C4, 0xEA60); 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; }); }).then([this](SerialDevice ^ device) -> bool { if (device == nullptr) { return false; } m_serialDevice = device; 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; } } 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; } } Windows::Foundation::TimeSpan timespan; timespan.Duration = 1; m_serialDevice->ReadTimeout = timespan; 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 (;;) { try { create_task(m_serialDevice->InputStream->ReadAsync(buffer, readBufferLength, InputStreamOptions::None)) .then([&, this](IBuffer ^ outBuffer) { auto reader = DataReader::FromBuffer(outBuffer); auto bytesRead = reader->UnconsumedBufferLength; 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) { if (ex->HResult == HRESULT_FROM_WIN32(ERROR_OPERATION_ABORTED)) { m_owner->Close(); } } if (token.is_canceled()) { cancel_current_task(); } } }, token); } //----------------------------------------------------------------------------- // // Send data to the serial port //----------------------------------------------------------------------------- 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; } 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; } return retVal; } open-zwave-1.5/cpp/src/platform/winRT/SerialControllerImpl.h000066400000000000000000000033331264474202400241770ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SerialControllerImpl.h // // WinRT Implementation of the cross-platform serial port // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _SerialControllerImpl_H #define _SerialControllerImpl_H #include #include #include "Defs.h" #include "platform/SerialController.h" namespace OpenZWave { class SerialControllerImpl { private: friend class SerialController; SerialControllerImpl( SerialController* _owner ); ~SerialControllerImpl(); bool Open(); void Close(); uint32 Write( uint8* _buffer, uint32 _length ); void StartReadTask(); Windows::Devices::SerialCommunication::SerialDevice ^ m_serialDevice; Concurrency::cancellation_token_source m_readTaskCancelationTokenSource; SerialController* m_owner; }; } // namespace OpenZWave #endif //_SerialControllerImpl_H open-zwave-1.5/cpp/src/platform/winRT/ThreadImpl.cpp000066400000000000000000000076511264474202400224650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThreadImpl.cpp // // WinRT implementation of a cross-platform thread // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 "Defs.h" #include "platform/Event.h" #include "platform/Thread.h" #include "ThreadImpl.h" #include "Options.h" using namespace OpenZWave; using namespace Concurrency; using namespace Windows::Foundation; using namespace Windows::System::Threading; 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; } } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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(); 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; } //----------------------------------------------------------------------------- // // Cause thread to sleep for the specified number of milliseconds //----------------------------------------------------------------------------- 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; } if (Wait::Single(m_owner, s_threadTerminateTimeout) < 0) { return false; } return true; } //----------------------------------------------------------------------------- // // Test whether the thread has completed //----------------------------------------------------------------------------- bool ThreadImpl::IsSignalled() { return !m_bIsRunning; }open-zwave-1.5/cpp/src/platform/winRT/ThreadImpl.h000066400000000000000000000036011264474202400221210ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThreadImpl.h // // WinRT implementation of a cross-platform thread // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _ThreadImpl_H #define _ThreadImpl_H #include #include #include "platform/Thread.h" #include namespace OpenZWave { class Thread; class Event; /** \brief Windows-specific implementation of the Thread class. */ class ThreadImpl { private: friend class Thread; ThreadImpl( Thread* _owner, string const& _name ); ~ThreadImpl(); bool Start( Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context ); void Sleep( uint32 _milliseconds ); bool Terminate(); bool IsSignalled(); void Run(); static DWORD WINAPI ThreadProc( void* _pArg ); 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 OpenZWave #endif //_ThreadImpl_H open-zwave-1.5/cpp/src/platform/winRT/TimeStampImpl.cpp000066400000000000000000000067731264474202400231650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeStampImpl.cpp // // WinRT implementation of a TimeStamp // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 #include #include "Defs.h" #include "TimeStampImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- TimeStampImpl::TimeStampImpl ( ) { SetTime(0); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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. 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 ); 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 ); 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 ); } open-zwave-1.5/cpp/src/platform/winRT/TimeStampImpl.h000066400000000000000000000044211264474202400226160ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeStampImpl.h // // WinRT implementation of a TimeStamp // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _TimeStampImpl_H #define _TimeStampImpl_H #include "Defs.h" namespace OpenZWave { /** \brief Windows implementation of a timestamp. */ class TimeStampImpl { public: /** * Constructor. * Creates a 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 ); /** * 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(); /** * 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 int64 m_stamp; }; } // namespace OpenZWave #endif //_TimeStampImpl_H open-zwave-1.5/cpp/src/platform/winRT/WaitImpl.cpp000066400000000000000000000072131264474202400221540ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // WaitImpl.cpp // // WinRT implementation of a base class for objects we // want to be able to wait for. // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 "Defs.h" #include "platform/Wait.h" #include "WaitImpl.h" #include "platform/Log.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- WaitImpl::WaitImpl ( Wait* _owner ): m_owner( _owner ) { InitializeCriticalSectionEx( &m_criticalSection, 0, 0 ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 ); m_watchers.push_back( watcher ); 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 ); 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; } //----------------------------------------------------------------------------- // // Notify all the watchers that the object has become signalled //----------------------------------------------------------------------------- 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 ); } LeaveCriticalSection( &m_criticalSection ); } open-zwave-1.5/cpp/src/platform/winRT/WaitImpl.h000066400000000000000000000037521264474202400216250ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // WaitImpl.h // // WinRT implementation of a base class for objects we // want to be able to wait for. // // Copyright (c) 2015 Microsoft Corporation // All rights reserved. // // 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 _WaitImpl_H #define _WaitImpl_H #include #include #include "Defs.h" #include "platform/Ref.h" #include "platform/Wait.h" namespace OpenZWave { /** \brief Windows specific implementation of Wait objects. */ class WaitImpl { private: friend class Wait; WaitImpl( Wait* _owner ); virtual ~WaitImpl(); void AddWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); bool RemoveWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); void Notify(); static int32 Multiple( Wait** _objects, uint32 _numObjects, int32 _timeout = -1 ); WaitImpl( Wait const& ); // prevent copy WaitImpl& operator = ( WaitImpl const& ); // prevent assignment struct Watcher { Wait::pfnWaitNotification_t m_callback; void* m_context; }; list m_watchers; Wait* m_owner; CRITICAL_SECTION m_criticalSection; }; } // namespace OpenZWave #endif //_WaitImpl_H open-zwave-1.5/cpp/src/platform/windows/000077500000000000000000000000001264474202400203465ustar00rootroot00000000000000open-zwave-1.5/cpp/src/platform/windows/EventImpl.cpp000066400000000000000000000055651264474202400227700ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // EventImpl.cpp // // Windows implementation of a cross-platform event // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 #include "Defs.h" #include "EventImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- EventImpl::EventImpl ( ) { // Create a manual reset event m_hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- EventImpl::~EventImpl ( ) { ::CloseHandle( m_hEvent ); } //----------------------------------------------------------------------------- // // Set the event to signalled //----------------------------------------------------------------------------- void EventImpl::Set ( ) { ::SetEvent( m_hEvent ); } //----------------------------------------------------------------------------- // // Set the event to not signalled //----------------------------------------------------------------------------- void EventImpl::Reset ( ) { ::ResetEvent( m_hEvent ); } //----------------------------------------------------------------------------- // // Test whether the event is set //----------------------------------------------------------------------------- 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 ) ); } open-zwave-1.5/cpp/src/platform/windows/EventImpl.h000066400000000000000000000030541264474202400224240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // EventImpl.h // // Windows implementation of a cross-platform event // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _EventImpl_H #define _EventImpl_H #include #include "Defs.h" namespace OpenZWave { /** \brief Windows-specific implementation of the Event class. */ 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(); HANDLE m_hEvent; }; } // namespace OpenZWave #endif //_EventImpl_H open-zwave-1.5/cpp/src/platform/windows/FileOpsImpl.cpp000066400000000000000000000041061264474202400232360ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FileOpsImpl.cpp // // Unix implementation of file operations // // Copyright (c) 2012, Greg Satz // All rights reserved. // // 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 #include "FileOpsImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- FileOpsImpl::FileOpsImpl ( ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- FileOpsImpl::~FileOpsImpl ( ) { } //----------------------------------------------------------------------------- // // Determine if a folder exists //----------------------------------------------------------------------------- bool FileOpsImpl::FolderExists( const string &_folderName ) { int32 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; } open-zwave-1.5/cpp/src/platform/windows/FileOpsImpl.h000066400000000000000000000025611264474202400227060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // FileOpsImpl.h // // Unix implementation of file operations // // Copyright (c) 2012, Greg Satz // All rights reserved. // // 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 _FileOpsImpl_H #define _FileOpsImpl_H #include #include #include "Defs.h" #include "platform/FileOps.h" namespace OpenZWave { class FileOpsImpl { friend class FileOps; private: FileOpsImpl(); ~FileOpsImpl(); bool FolderExists( const string &_filename ); }; } // namespace OpenZWave #endif //_FileOpsImpl_H open-zwave-1.5/cpp/src/platform/windows/LogImpl.cpp000066400000000000000000000243761264474202400224310ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // LogImpl.cpp // // Windows implementation of message and error logging // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 #include #include "Defs.h" #include "LogImpl.h" #ifdef MINGW #define vsprintf_s vsnprintf #define strcpy_s(DEST, NUM, SOURCE) strncpy(DEST, SOURCE, NUM) errno_t fopen_s(FILE** pFile, const char *filename, const char *mode) { if (!pFile) { _set_errno(EINVAL); return EINVAL; } *pFile = fopen(filename, mode); if (!*pFile) { return errno; } return 0; } #endif using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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; // create an adjusted file name and timestamp string string timeStr = GetTimeStampString(); 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 ); } } //----------------------------------------------------------------------------- // // 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); } //----------------------------------------------------------------------------- // // 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 ) { 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 ); } } // 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 ); // 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"); } //----------------------------------------------------------------------------- // // Clear the LogQueue //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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; } } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // Provide a new log file name (applicable to future writes) //----------------------------------------------------------------------------- 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, "; } open-zwave-1.5/cpp/src/platform/windows/LogImpl.h000066400000000000000000000047031264474202400220660ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // LogImpl.h // // Windows implementation of message and error logging // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _LogImpl_H #define _LogImpl_H #include "Defs.h" #include #include "platform/Log.h" #include "Windows.h" namespace OpenZWave { /** \brief Windows-specific implementation of the Log class. */ class LogImpl : public i_LogImpl { private: friend class Log; LogImpl( string const& _filename, bool const _bAppendLog, bool const _bConsoleOutput, LogLevel const _saveLevel, LogLevel const _queueLevel, LogLevel const _dumpTrigger ); ~LogImpl(); 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; }; } // namespace OpenZWave #endif //_LogImpl_H open-zwave-1.5/cpp/src/platform/windows/MutexImpl.cpp000066400000000000000000000056231264474202400230040ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MutexImpl.cpp // // Windows Implementation of the cross-platform mutex // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 "Defs.h" #include "MutexImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- MutexImpl::MutexImpl ( ): m_lockCount( 0 ) { InitializeCriticalSection( &m_criticalSection ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; } // Returns immediately, even if the lock was not available. if( TryEnterCriticalSection( &m_criticalSection ) ) { ++m_lockCount; return true; } 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 ); } } //----------------------------------------------------------------------------- // // Test whether the mutex is free //----------------------------------------------------------------------------- bool MutexImpl::IsSignalled ( ) { return( 0 == m_lockCount ); } open-zwave-1.5/cpp/src/platform/windows/MutexImpl.h000066400000000000000000000030551264474202400224460ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MutexImpl.h // // Windows Implementation of the cross-platform mutex // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _MutexImpl_H #define _MutexImpl_H #include namespace OpenZWave { /** \brief Windows-specific implementation of the Mutex class. */ class MutexImpl { private: friend class Mutex; MutexImpl(); ~MutexImpl(); bool Lock( bool const _bWait = true ); void Unlock(); 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 OpenZWave #endif //_MutexIF_H open-zwave-1.5/cpp/src/platform/windows/SerialControllerImpl.cpp000066400000000000000000000263241264474202400251660ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SerialControllerImpl.cpp // // Windows Implementation of the cross-platform serial port // // Copyright (c) 2010 Jason Frazier // // 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 "Defs.h" #include "SerialControllerImpl.h" #include "platform/Log.h" using namespace OpenZWave; DWORD WINAPI SerialReadThreadEntryPoint( void* _context ); //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- SerialControllerImpl::SerialControllerImpl ( SerialController* _owner ): m_owner( _owner ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; } // 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 ); return true; } //----------------------------------------------------------------------------- // // Close the serial port //----------------------------------------------------------------------------- void SerialControllerImpl::Close ( ) { ::SetEvent( m_hExit ); ::WaitForSingleObject( m_hThread, INFINITE ); CloseHandle( m_hThread ); m_hThread = INVALID_HANDLE_VALUE; CloseHandle( m_hExit ); m_hExit = 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(); } 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(); // 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; } } 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; } // 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; 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 ) ) { // 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 ) ) { 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 ); } } // 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; } open-zwave-1.5/cpp/src/platform/windows/SerialControllerImpl.h000066400000000000000000000033011264474202400246210ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // SerialControllerImpl.h // // Windows Implementation of the cross-platform serial port // // Copyright (c) 2010 Jason Frazier // // 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 _SerialControllerImpl_H #define _SerialControllerImpl_H #include #include "Defs.h" #include "platform/SerialController.h" namespace OpenZWave { class SerialControllerImpl { public: void ReadThreadProc(); private: friend class SerialController; SerialControllerImpl( SerialController* _owner ); ~SerialControllerImpl(); bool Open(); void Close(); uint32 Write( uint8* _buffer, uint32 _length ); bool Init( uint32 const _attempts ); void Read(); SerialController* m_owner; HANDLE m_hThread; HANDLE m_hExit; HANDLE m_hSerialController; }; } // namespace OpenZWave #endif //_SerialControllerImpl_H open-zwave-1.5/cpp/src/platform/windows/ThreadImpl.cpp000066400000000000000000000103401264474202400231010ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThreadImpl.cpp // // Windows implementation of a cross-platform thread // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 "Defs.h" #include "platform/Event.h" #include "platform/Thread.h" #include "ThreadImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ThreadImpl::ThreadImpl ( Thread* _owner, string const& _name ): m_owner( _owner ), m_hThread( INVALID_HANDLE_VALUE ), m_bIsRunning( false ), m_name( _name ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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(); HANDLE hThread = ::CreateThread( NULL, 0, ThreadImpl::ThreadProc, this, CREATE_SUSPENDED, NULL ); m_hThread = hThread; ::ResumeThread( hThread ); return true; } //----------------------------------------------------------------------------- // // Cause thread to sleep for the specified number of milliseconds //----------------------------------------------------------------------------- void ThreadImpl::Sleep ( uint32 _millisecs ) { ::Sleep(_millisecs); } //----------------------------------------------------------------------------- // // Force the thread to stop //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // Test whether the thread has completed //----------------------------------------------------------------------------- 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; } //----------------------------------------------------------------------------- // // 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(); } open-zwave-1.5/cpp/src/platform/windows/ThreadImpl.h000066400000000000000000000035411264474202400225530ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ThreadImpl.h // // Windows implementation of a cross-platform thread // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _ThreadImpl_H #define _ThreadImpl_H #include #include #include "platform/Thread.h" namespace OpenZWave { class Thread; class Event; /** \brief Windows-specific implementation of the Thread class. */ class ThreadImpl { private: friend class Thread; ThreadImpl( Thread* _owner, string const& _name ); ~ThreadImpl(); bool Start( Thread::pfnThreadProc_t _pfnThreadProc, Event* _exitEvent, void* _context ); void Sleep( uint32 _milliseconds ); bool Terminate(); bool IsSignalled(); 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 OpenZWave #endif //_ThreadImpl_H open-zwave-1.5/cpp/src/platform/windows/TimeStampImpl.cpp000066400000000000000000000067711264474202400236120ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeStampImpl.h // // Cross-platform TimeStampImpl // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 #include #include "Defs.h" #include "TimeStampImpl.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- TimeStampImpl::TimeStampImpl ( ) { SetTime(0); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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. 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 ); 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 ); 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 ); } open-zwave-1.5/cpp/src/platform/windows/TimeStampImpl.h000066400000000000000000000044351264474202400232520ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // TimeStampImpl.h // // Windows implementation of a TimeStamp // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _TimeStampImpl_H #define _TimeStampImpl_H #include "Defs.h" namespace OpenZWave { /** \brief Windows implementation of a timestamp. */ class TimeStampImpl { public: /** * Constructor. * Creates a 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 ); /** * 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(); /** * 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 int64 m_stamp; }; } // namespace OpenZWave #endif //_TimeStampImpl_H open-zwave-1.5/cpp/src/platform/windows/WaitImpl.cpp000066400000000000000000000072361264474202400226100ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // WaitImpl.cpp // // Windows implementation of an abstract base class for objects we // want to be able to wait for. // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 "Defs.h" #include "platform/Wait.h" #include "WaitImpl.h" #include "platform/Log.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- WaitImpl::WaitImpl ( Wait* _owner ): m_owner( _owner ) { InitializeCriticalSection( &m_criticalSection ); } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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 ); m_watchers.push_back( watcher ); 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 ); 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; } //----------------------------------------------------------------------------- // // Notify all the watchers that the object has become signalled //----------------------------------------------------------------------------- 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 ); } LeaveCriticalSection( &m_criticalSection ); } open-zwave-1.5/cpp/src/platform/windows/WaitImpl.h000066400000000000000000000037651264474202400222600ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // WaitImpl.h // // Windows implementation of a base class for objects we // want to be able to wait for. // // Copyright (c) 2010 Mal Lansell // All rights reserved. // // 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 _WaitImpl_H #define _WaitImpl_H #include #include #include "Defs.h" #include "platform/Ref.h" #include "platform/Wait.h" namespace OpenZWave { /** \brief Windows specific implementation of Wait objects. */ class WaitImpl { private: friend class Wait; WaitImpl( Wait* _owner ); virtual ~WaitImpl(); void AddWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); bool RemoveWatcher( Wait::pfnWaitNotification_t _callback, void* _context ); void Notify(); static int32 Multiple( Wait** _objects, uint32 _numObjects, int32 _timeout = -1 ); WaitImpl( Wait const& ); // prevent copy WaitImpl& operator = ( WaitImpl const& ); // prevent assignment struct Watcher { Wait::pfnWaitNotification_t m_callback; void* m_context; }; list m_watchers; Wait* m_owner; CRITICAL_SECTION m_criticalSection; }; } // namespace OpenZWave #endif //_WaitImpl_H open-zwave-1.5/cpp/src/value_classes/000077500000000000000000000000001264474202400176615ustar00rootroot00000000000000open-zwave-1.5/cpp/src/value_classes/Value.cpp000066400000000000000000000523071264474202400214500ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Value.cpp // // Base class for all OpenZWave Value Classes // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "Manager.h" #include "Driver.h" #include "Node.h" #include "Notification.h" #include "Msg.h" #include "value_classes/Value.h" #include "platform/Log.h" #include "command_classes/CommandClass.h" #include #include "Options.h" using namespace OpenZWave; 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", "invalid type" }; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- Value::Value ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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_label( _label ), m_units( _units ), m_help( "" ), m_readOnly( _readOnly ), m_writeOnly( _writeOnly ), m_isSet( _isSet ), m_affectsLength( 0 ), m_affects(), m_affectsAll( false ), m_checkChange( false ), m_pollIntensity( _pollIntensity ) { } //----------------------------------------------------------------------------- // // 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 ) { } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- 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; 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 index = 0; if( TIXML_SUCCESS == _valueElement->QueryIntAttribute( "index", &intVal ) ) { index = (uint8)intVal; } m_id = ValueID( _homeId, _nodeId, genre, _commandClassId, instance, index, type ); char const* label = _valueElement->Attribute( "label" ); if( label ) { m_label = label; } 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* writeOnly = _valueElement->Attribute( "write_only" ); if( writeOnly ) { m_writeOnly = !strcmp( writeOnly, "true" ); } 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++ ) { 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++; } } } } 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( "max", &intVal ) ) { m_max = intVal; } TiXmlElement const* helpElement = _valueElement->FirstChildElement(); while( helpElement ) { char const* str = helpElement->Value(); if( str && !strcmp( str, "Help" ) ) { str = helpElement->GetText(); if( str ) { m_help = str; } break; } helpElement = helpElement->NextSiblingElement(); } } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- void Value::WriteXML ( TiXmlElement* _valueElement ) { char str[16]; _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.GetIndex() ); _valueElement->SetAttribute( "index", str ); _valueElement->SetAttribute( "label", m_label.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_min ); _valueElement->SetAttribute( "min", 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 + ","; } } _valueElement->SetAttribute( "affects", s.c_str() ); } if( m_help.length() > 0 ) { TiXmlElement* helpElement = new TiXmlElement( "Help" ); _valueElement->LinkEndChild( helpElement ); TiXmlText* textElement = new TiXmlText( m_help.c_str() ); helpElement->LinkEndChild( textElement ); } } //----------------------------------------------------------------------------- // // 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() ) ) { 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 ) { 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; } //----------------------------------------------------------------------------- // // 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; 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() ) ) { 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] ) ) { genre = (ValueID::ValueGenre)i; break; } } } return genre; } //----------------------------------------------------------------------------- // // Static helper to get a genre enum as a string //----------------------------------------------------------------------------- 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] ) ) { type = (ValueID::ValueType)i; break; } } } 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]; } return c_typeName[_type]; } //----------------------------------------------------------------------------- // // Check a refreshed value //----------------------------------------------------------------------------- int Value::VerifyRefreshedValue ( void* _originalValue, void* _checkValue, void* _newValue, ValueID::ValueType _type, int _length // = 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 { 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 { 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 = ( memcmp( _originalValue, _newValue, _length ) == 0 ); break; case ValueID::ValueType_Schedule: // Schedule /* Should not get here */ 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 = ( memcmp( _checkValue, _newValue, _length ) == 0 ); break; case ValueID::ValueType_Schedule: /* Should not get here */ 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; } } open-zwave-1.5/cpp/src/value_classes/Value.h000066400000000000000000000105351264474202400211120ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Value.h // // Base class for all OpenZWave Value Classes // // 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 . // //----------------------------------------------------------------------------- #ifndef _Value_H #define _Value_H #include #ifdef __FreeBSD__ #include #endif #include "Defs.h" #include "platform/Ref.h" #include "value_classes/ValueID.h" class TiXmlElement; namespace OpenZWave { class Node; /** \brief Base class for values associated with a node. */ class Value: public Ref { friend class Driver; friend class ValueStore; public: Value( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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{ return m_label; } void SetLabel( string const& _label ){ m_label = _label; } string const& GetUnits()const{ return m_units; } void SetUnits( string const& _units ){ m_units = _units; } string const& GetHelp()const{ return m_help; } void SetHelp( string const& _help ){ m_help = _help; } 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& _value ) { 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 _length = 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 private: ValueID m_id; string m_label; string m_units; string m_help; 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 OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueBool.cpp000066400000000000000000000111311264474202400222520ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueBool.cpp // // Represents a boolean value // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "value_classes/ValueBool.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" #include "Manager.h" #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueBool::ValueBool ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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 ), m_newValue( 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 ); 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" ); } //----------------------------------------------------------------------------- // // 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; // Set the value in the device. bool ret = ((Value*)tempValue)->Set(); // clean up the temporary value delete tempValue; 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; } } open-zwave-1.5/cpp/src/value_classes/ValueBool.h000066400000000000000000000045511264474202400217270ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueBool.h // // Represents a boolean value // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueBool_H #define _ValueBool_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; class CommandClass; /** \brief Boolean value sent to/received from a node. */ class ValueBool: public Value { public: ValueBool( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, bool const _value, uint8 const _pollIntensity ); ValueBool(){} virtual ~ValueBool(){} bool Set( bool const _value ); void OnValueRefreshed( bool const _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 ); 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) bool m_newValue; // a new value to be set on the appropriate device }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueButton.cpp000066400000000000000000000066151264474202400226450ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueButton.h // // Represents a write-only value that triggers activity in a device // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "value_classes/ValueButton.h" #include "Manager.h" #include "Driver.h" #include "Node.h" #include "platform/Log.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueButton::ValueButton ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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 ); } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- 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(); } //----------------------------------------------------------------------------- // // Stop an activity in a device //----------------------------------------------------------------------------- bool ValueButton::ReleaseButton ( ) { // Set the value in the device. m_pressed = false; bool res = Value::Set(); if( Driver* driver = Manager::Get()->GetDriver( GetID().GetHomeId() ) ) { if( Node* node = driver->GetNodeUnsafe( GetID().GetNodeId() ) ) { node->RequestDynamicValues(); } } return res; } open-zwave-1.5/cpp/src/value_classes/ValueButton.h000066400000000000000000000040351264474202400223040ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueButton.h // // Represents a write-only value that triggers activity in a device // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueButton_H #define _ValueButton_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; class CommandClass; /** \brief Button value ???. */ class ValueButton: public Value { public: ValueButton( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _index, string const& _label, uint8 const _pollIntensity ); ValueButton(): m_pressed( false ){} virtual ~ValueButton(){} bool PressButton(); bool ReleaseButton(); virtual string const GetAsString() const { return ( IsPressed() ? "true" : "false" ); } // From Value virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); virtual void WriteXML( TiXmlElement* _valueElement ); bool IsPressed()const{ return m_pressed; } private: bool m_pressed; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueByte.cpp000066400000000000000000000117401264474202400222700ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueByte.cpp // // Represents an 8-bit value // // 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 . // //----------------------------------------------------------------------------- #include #include "tinyxml.h" #include "value_classes/ValueByte.h" #include "Msg.h" #include "platform/Log.h" #include "Manager.h" #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueByte::ValueByte ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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_newValue( 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 << 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() ); } } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- void ValueByte::WriteXML ( TiXmlElement* _valueElement ) { Value::WriteXML( _valueElement ); 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; // Set the value in the device. bool ret = ((Value*)tempValue)->Set(); // clean up the temporary value delete tempValue; 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; } } open-zwave-1.5/cpp/src/value_classes/ValueByte.h000066400000000000000000000044231264474202400217350ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueByte.h // // Represents an 8-bit value // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueByte_H #define _ValueByte_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; /** \brief Byte value sent to/received from a node. */ class ValueByte: public Value { public: ValueByte( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _value, uint8 const _pollIntensity ); ValueByte(); virtual ~ValueByte(){} bool Set( uint8 const _value ); void OnValueRefreshed( uint8 const _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 ); 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) uint8 m_newValue; // a new value to be set on the appropriate device }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueDecimal.cpp000066400000000000000000000106521264474202400227240ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueDecimal.cpp // // Represents a value that may have a fractional component // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "value_classes/ValueDecimal.h" #include "Msg.h" #include "platform/Log.h" #include "Manager.h" #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueDecimal::ValueDecimal ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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 ); 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() ); } //----------------------------------------------------------------------------- // // 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; // Set the value in the device. bool ret = ((Value*)tempValue)->Set(); // clean up the temporary value delete tempValue; 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; } } open-zwave-1.5/cpp/src/value_classes/ValueDecimal.h000066400000000000000000000052461264474202400223740ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueDecimal.h // // Represents a value that may have a fractional component // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueDecimal_H #define _ValueDecimal_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; /** \brief Decimal value sent to/received from a node. */ class ValueDecimal: public Value { 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, uint8 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 OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueID.h000066400000000000000000000261501264474202400213270ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueID.h // // Unique identifier for a Value object // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueID_H #define _ValueID_H #include #include #include "Defs.h" class TiXmlElement; namespace OpenZWave { /** \brief Provides a unique ID for a value reported by a Z-Wave device. * * The ValueID is used to uniquely identify a value reported by a * Z-Wave device. *

* The ID is built by packing various identifying characteristics into a single * 32-bit number - the Z-Wave driver index, device node ID, the command class and * command class instance that handles the value, plus an index for the value * to distinguish it among all the other values managed by that command class * instance. The type (bool, byte, string etc) of the value is also stored. *

* 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_Max = ValueType_Raw /**< 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{ 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{ 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{ 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{ return( (uint8)( ( (m_id1 & 0xff000000) ) >> 24 ) ); } /** * 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. */ uint8 GetIndex()const{ return( (uint8)( (m_id & 0x00000ff0) >> 4 ) ); } /** * 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 ) ); } /** * Get a 64Bit Integer that represents this ValueID. This Integer is not guaranteed to be valid * across restarts of OpenZWave. * \return a uint64 integer */ uint64 GetId()const{ 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 ) { if( m_id == _other.m_id ) { return( m_id1 < _other.m_id1 ); } else { return( m_id < _other.m_id ); } } else { return( m_homeId < _other.m_homeId ); } } bool operator > ( ValueID const& _other )const { if( m_homeId == _other.m_homeId ) { if( m_id == _other.m_id ) { return( m_id1 > _other.m_id1 ); } else { return( m_id > _other.m_id ); } } else { return( m_homeId > _other.m_homeId ); } } /** * 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, uint8 const _valueIndex, ValueType const _type ): m_homeId( _homeId ) { m_id = (((uint32)_nodeId)<<24) | (((uint32)_genre)<<22) | (((uint32)_commandClassId)<<14) | (((uint32)_valueIndex)<<4) | ((uint32)_type); m_id1 = (((uint32)_instance)<<24); } /* 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 ){ m_id = ((uint32)_nodeId)<<24; } ValueID( uint32 const _homeId, uint8 const _nodeId, uint32 const _instance ): m_homeId( _homeId ) { m_id = (((uint32)_nodeId)<<24); m_id1 = (((uint32)_instance)<<24); } // 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 { return ( ( m_id & 0x003ffff0 ) | ( m_id1 & 0xff000000 ) ); } // Generate a key from its component parts static uint32 GetValueStoreKey( uint8 const _commandClassId, uint8 const _instance, uint8 const _valueIndex ) { uint32 key = (((uint32)_instance)<<24) | (((uint32)_commandClassId)<<14) | (((uint32)_valueIndex)<<4); return key; } // 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: 2 bits. Unused. // 04-11: 8 bits. Index of value within all the value created by the command class // instance (in configuration parameters, this is also the parameter ID). // 00-03: 4 bits. Type of value (bool, byte, string etc). uint32 m_id; // ID1 Packing: // Bits // 24-31 8 bits. Instance Index of the command class. uint32 m_id1; // Unique PC interface identifier uint32 m_homeId; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueInt.cpp000066400000000000000000000117711264474202400221230ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueInt.cpp // // Represents a 32-bit value // // 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 . // //----------------------------------------------------------------------------- #include #include #include "tinyxml.h" #include "value_classes/ValueInt.h" #include "Msg.h" #include "platform/Log.h" #include "Manager.h" #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueInt::ValueInt ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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_newValue( 0 ) { m_min = INT_MIN; m_max = INT_MAX; } //----------------------------------------------------------------------------- // // Constructor (from XML) //----------------------------------------------------------------------------- ValueInt::ValueInt ( ): Value(), m_value( 0 ), m_valueCheck( 0 ), m_newValue( 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 ); } //----------------------------------------------------------------------------- // // 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() ); } } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- void ValueInt::WriteXML ( TiXmlElement* _valueElement ) { Value::WriteXML( _valueElement ); 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; // Set the value in the device. bool ret = ((Value*)tempValue)->Set(); // clean up the temporary value delete tempValue; 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; } } open-zwave-1.5/cpp/src/value_classes/ValueInt.h000066400000000000000000000044161264474202400215660ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueInt.h // // Represents a 32-bit value // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueInt_H #define _ValueInt_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; /** \brief Integer value sent to/received from a node. */ class ValueInt: public Value { public: ValueInt( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int32 const _value, uint8 const _pollIntensity ); ValueInt(); virtual ~ValueInt(){} bool Set( int32 const _value ); void OnValueRefreshed( int32 const _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 ); 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) int32 m_newValue; // a new value to be set on the appropriate device }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueList.cpp000066400000000000000000000252371264474202400223060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueList.cpp // // Represents a list of items // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "value_classes/ValueList.h" #include "Msg.h" #include "platform/Log.h" #include "Manager.h" #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueList::ValueList ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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_newValueIdx( 0 ), m_size( _size ) { } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueList::ValueList ( ): Value(), m_items( ), m_valueIdx(), m_valueIdxCheck( 0 ), m_newValueIdx( 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_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() ); } } else { Log::Write( LogLevel_Info, "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() ); } // Read the items m_items.clear(); TiXmlElement const* itemElement = _valueElement->FirstChildElement(); while( itemElement ) { char const* str = itemElement->Value(); if( str && !strcmp( str, "Item" ) ) { char const* labelStr = itemElement->Attribute( "label" ); int value = 0; if (itemElement->QueryIntAttribute( "value", &value ) != TIXML_SUCCESS) { Log::Write( LogLevel_Info, "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_Info, "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 { Item item; item.m_label = labelStr; item.m_value = value; m_items.push_back( item ); } } itemElement = itemElement->NextSiblingElement(); } // 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_Info, "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_Info, "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_Info, "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 ); 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 ); 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 ); _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; // Set the value in the device. bool ret = ((Value*)tempValue)->Set(); // clean up the temporary value delete tempValue; 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; } 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; } 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 const ValueList::GetItemIdxByLabel ( string const& _label ) { for( int32 i=0; i<(int32)m_items.size(); ++i ) { if( _label == m_items[i].m_label ) { return i; } } return -1; } //----------------------------------------------------------------------------- // // Get the index of an item from its value //----------------------------------------------------------------------------- int32 const ValueList::GetItemIdxByValue ( int32 const _value ) { for( int32 i=0; i<(int32)m_items.size(); ++i ) { if( _value == m_items[i].m_value ) { return i; } } 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; } 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; } 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"); return NULL; } } open-zwave-1.5/cpp/src/value_classes/ValueList.h000066400000000000000000000056521264474202400217520ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueList.h // // Represents a list of items // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueList_H #define _ValueList_H #include #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; /** \brief List of values sent to/received from a node. */ 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, uint8 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 const GetItemIdxByLabel( string const& _label ); int32 const GetItemIdxByValue( int32 const _value ); bool GetItemLabels( vector* o_items ); bool GetItemValues( vector* o_values ); uint8 const 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) int32 m_newValueIdx; // a new value to be set on the appropriate device uint8 m_size; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueRaw.cpp000066400000000000000000000156401264474202400221210ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueRaw.cpp // // Represents a collection of 8-bit values // // Copyright (c) 2012 Greg Satz // // 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 "tinyxml.h" #include "value_classes/ValueRaw.h" #include "Msg.h" #include "platform/Log.h" #include "Manager.h" #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueRaw::ValueRaw ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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_newValue ( NULL ) { 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_valueCheck ( NULL ), m_newValue ( NULL ) { m_valueLength = 0; m_min = 0; m_max = 0; } //----------------------------------------------------------------------------- // // Destructor //----------------------------------------------------------------------------- ValueRaw::~ValueRaw ( ) { delete [] m_value; } 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; 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 ) { 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() ); } } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- 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 ); } //----------------------------------------------------------------------------- // // 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; // Set the value in the device. bool ret = ((Value*)tempValue)->Set(); // clean up the temporary value delete tempValue; 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, _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]; 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]; memcpy( m_value, _value, _length ); break; case 3: // all three values are different, so wait for next refresh to try again break; } } open-zwave-1.5/cpp/src/value_classes/ValueRaw.h000066400000000000000000000047221264474202400215650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueRaw.h // // Represents a collection of 8-bit values // // Copyright (c) 2013 Greg Satz // // 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 _ValueRaw_H #define _ValueRaw_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; /** \brief A collection of bytes sent to/received from a node. */ class ValueRaw: public Value { public: ValueRaw( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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(); bool Set( uint8 const* _value, uint8 const _length ); void OnValueRefreshed( uint8 const* _value, uint8 const _length ); // 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 ); 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_newValue; // a new value to be set on the appropriate device }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueSchedule.cpp000066400000000000000000000223611264474202400231220ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueSchedule.cpp // // A one day schedule for the Climate Control Schedule command class // // 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 . // //----------------------------------------------------------------------------- #include #include #include "tinyxml.h" #include "value_classes/ValueSchedule.h" #include "Msg.h" #include "platform/Log.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueSchedule::ValueSchedule ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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 ) { } //----------------------------------------------------------------------------- // // 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" ) ) { 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(); } } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- void ValueSchedule::WriteXML ( TiXmlElement* _valueElement ) { Value::WriteXML( _valueElement ); for( uint8 i=0; iLinkEndChild( switchPointElement ); 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", 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(); } //----------------------------------------------------------------------------- // // 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 */ 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; } 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; } // 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; } //----------------------------------------------------------------------------- // // A value in a device has changed //----------------------------------------------------------------------------- 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; } --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; } if( o_hours ) { *o_hours = m_switchPoints[_idx].m_hours; } if( o_minutes ) { *o_minutes = m_switchPoints[_idx].m_minutes; } if( o_setback ) { *o_setback = m_switchPoints[_idx].m_setback; } 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; } } // 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"; } open-zwave-1.5/cpp/src/value_classes/ValueSchedule.h000066400000000000000000000050601264474202400225640ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueSchedule.h // // A one day schedule for the Climate Control Schedule command class // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueSchedule_H #define _ValueSchedule_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; /** \brief Schedule sent to/received from a node. */ class ValueSchedule: public Value { public: ValueSchedule( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, uint8 const _pollIntensity ); ValueSchedule(); virtual ~ValueSchedule(){} 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; } bool Set(); void OnValueRefreshed(); virtual string const GetAsString() const; // From Value virtual void ReadXML( uint32 const _homeId, uint8 const _nodeId, uint8 const _commandClassId, TiXmlElement const* _valueElement ); virtual void WriteXML( TiXmlElement* _valueElement ); private: struct SwitchPoint { uint8 m_hours; uint8 m_minutes; int8 m_setback; }; SwitchPoint m_switchPoints[9]; uint8 m_numSwitchPoints; }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueShort.cpp000066400000000000000000000121261264474202400224630ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueShort.cpp // // Represents a 16-bit value // // 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 . // //----------------------------------------------------------------------------- #include #include #include "tinyxml.h" #include "value_classes/ValueShort.h" #include "Msg.h" #include "platform/Log.h" #include "Manager.h" #include using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueShort::ValueShort ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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_newValue( 0 ) { m_min = SHRT_MIN; m_max = SHRT_MAX; } //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueShort::ValueShort ( ): Value(), m_value( 0 ), m_valueCheck( 0 ), m_newValue( 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; } //----------------------------------------------------------------------------- // // 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() ); } } //----------------------------------------------------------------------------- // // Write ourselves to an XML document //----------------------------------------------------------------------------- void ValueShort::WriteXML ( TiXmlElement* _valueElement ) { Value::WriteXML( _valueElement ); 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; // Set the value in the device. bool ret = ((Value*)tempValue)->Set(); // clean up the temporary value delete tempValue; 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; } } open-zwave-1.5/cpp/src/value_classes/ValueShort.h000066400000000000000000000044321264474202400221310ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueShort.h // // Represents a 16-bit value // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueShort_H #define _ValueShort_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; /** \brief Short value sent to/received from a node. */ class ValueShort: public Value { public: ValueShort( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, int16 const _value, uint8 const _pollIntensity ); ValueShort(); virtual ~ValueShort(){} bool Set( int16 const _value ); void OnValueRefreshed( int16 const _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 ); 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) int16 m_newValue; // a new value to be set on the appropriate device }; } // namespace OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueStore.cpp000066400000000000000000000127651264474202400224710ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueStore.cpp // // Container for Value objects // // 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 . // //----------------------------------------------------------------------------- #include "value_classes/ValueStore.h" #include "value_classes/Value.h" #include "Manager.h" #include "Notification.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // 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(); } } //----------------------------------------------------------------------------- // // 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; } //----------------------------------------------------------------------------- // // 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; } ////----------------------------------------------------------------------------- //// //// Remove a value from the store ////----------------------------------------------------------------------------- //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() ) ) { 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; } } } //----------------------------------------------------------------------------- // // 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 open-zwave-1.5/cpp/src/value_classes/ValueStore.h000066400000000000000000000034261264474202400221300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueStore.h // // Container for Value objects // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueStore_H #define _ValueStore_H #include #include "Defs.h" #include "value_classes/ValueID.h" class TiXmlElement; namespace OpenZWave { class Value; /** \brief Container that holds all of the values associated with a given node. */ class ValueStore { public: typedef map::const_iterator Iterator; Iterator Begin(){ return m_values.begin(); } Iterator End(){ return m_values.end(); } ValueStore(){} ~ValueStore(); 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 OpenZWave #endif open-zwave-1.5/cpp/src/value_classes/ValueString.cpp000066400000000000000000000106031264474202400226300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueStore.cpp // // Represents a string value // // 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 . // //----------------------------------------------------------------------------- #include "tinyxml.h" #include "value_classes/ValueString.h" #include "Msg.h" #include "platform/Log.h" #include "Manager.h" using namespace OpenZWave; //----------------------------------------------------------------------------- // // Constructor //----------------------------------------------------------------------------- ValueString::ValueString ( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 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 ); 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() ); } //----------------------------------------------------------------------------- // // 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; // Set the value in the device. bool ret = ((Value*)tempValue)->Set(); // clean up the temporary value delete tempValue; 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; } } open-zwave-1.5/cpp/src/value_classes/ValueString.h000066400000000000000000000045321264474202400223010ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValueString.h // // Represents a string value // // 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 . // //----------------------------------------------------------------------------- #ifndef _ValueString_H #define _ValueString_H #include #include "Defs.h" #include "value_classes/Value.h" class TiXmlElement; namespace OpenZWave { class Msg; class Node; /** \brief String value sent to/received from a node. */ class ValueString: public Value { public: ValueString( uint32 const _homeId, uint8 const _nodeId, ValueID::ValueGenre const _genre, uint8 const _commandClassId, uint8 const _instance, uint8 const _index, string const& _label, string const& _units, bool const _readOnly, bool const _writeOnly, string const& _value, uint8 const _pollIntensity ); ValueString(){} virtual ~ValueString(){} 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; } 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 OpenZWave #endif open-zwave-1.5/cpp/tinyxml/000077500000000000000000000000001264474202400157455ustar00rootroot00000000000000open-zwave-1.5/cpp/tinyxml/Makefile000066400000000000000000000067101264474202400174110ustar00rootroot00000000000000#**************************************************************************** # # Makefile for TinyXml test. # Lee Thomason # www.grinninglizard.com # # This is a GNU make (gmake) makefile #**************************************************************************** # DEBUG can be set to YES to include debugging info, or NO otherwise DEBUG := YES # PROFILE can be set to YES to include profiling info, or NO otherwise PROFILE := NO # TINYXML_USE_STL can be used to turn on STL support. NO, then STL # will not be used. YES will include the STL files. TINYXML_USE_STL := YES #**************************************************************************** CC := gcc CXX := g++ LD := g++ AR := ar rc RANLIB := ranlib DEBUG_CFLAGS := -Wall -Wno-format -g -DDEBUG $(CPPFLAGS) RELEASE_CFLAGS := -Wall -Wno-unknown-pragmas -Wno-format -O3 $(CPPFLAGS) LIBS := DEBUG_CXXFLAGS := ${DEBUG_CFLAGS} RELEASE_CXXFLAGS := ${RELEASE_CFLAGS} DEBUG_LDFLAGS := -g RELEASE_LDFLAGS := ifeq (YES, ${DEBUG}) CFLAGS := ${DEBUG_CFLAGS} CXXFLAGS := ${DEBUG_CXXFLAGS} LDFLAGS := ${DEBUG_LDFLAGS} else CFLAGS := ${RELEASE_CFLAGS} CXXFLAGS := ${RELEASE_CXXFLAGS} LDFLAGS := ${RELEASE_LDFLAGS} endif ifeq (YES, ${PROFILE}) CFLAGS := ${CFLAGS} -pg -O3 CXXFLAGS := ${CXXFLAGS} -pg -O3 LDFLAGS := ${LDFLAGS} -pg endif #**************************************************************************** # Preprocessor directives #**************************************************************************** ifeq (YES, ${TINYXML_USE_STL}) DEFS := -DTIXML_USE_STL else DEFS := endif #**************************************************************************** # Include paths #**************************************************************************** #INCS := -I/usr/include/g++-2 -I/usr/local/include INCS := #**************************************************************************** # Makefile code common to all platforms #**************************************************************************** CFLAGS := ${CFLAGS} ${DEFS} CXXFLAGS := ${CXXFLAGS} ${DEFS} #**************************************************************************** # Targets of the build #**************************************************************************** OUTPUT := xmltest all: ${OUTPUT} #**************************************************************************** # Source files #**************************************************************************** SRCS := tinyxml.cpp tinyxmlparser.cpp xmltest.cpp tinyxmlerror.cpp tinystr.cpp # Add on the sources for libraries SRCS := ${SRCS} OBJS := $(addsuffix .o,$(basename ${SRCS})) #**************************************************************************** # Output #**************************************************************************** ${OUTPUT}: ${OBJS} ${LD} -o $@ ${LDFLAGS} ${OBJS} ${LIBS} ${EXTRA_LIBS} #**************************************************************************** # common rules #**************************************************************************** # Rules for compiling source files to object files %.o : %.cpp ${CXX} -c ${CXXFLAGS} ${INCS} $< -o $@ %.o : %.c ${CC} -c ${CFLAGS} ${INCS} $< -o $@ dist: bash makedistlinux clean: -rm -f core ${OBJS} ${OUTPUT} depend: #makedepend ${INCS} ${SRCS} tinyxml.o: tinyxml.h tinystr.h tinyxmlparser.o: tinyxml.h tinystr.h xmltest.o: tinyxml.h tinystr.h tinyxmlerror.o: tinyxml.h tinystr.h open-zwave-1.5/cpp/tinyxml/tinystr.cpp000066400000000000000000000050521264474202400201670ustar00rootroot00000000000000/* www.sourceforge.net/projects/tinyxml Original file by Yves Berquin. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* * THIS FILE WAS ALTERED BY Tyge Lvset, 7. April 2005. */ #ifndef TIXML_USE_STL #include "tinystr.h" // Error value for find primitive const TiXmlString::size_type TiXmlString::npos = static_cast< TiXmlString::size_type >(-1); // Null rep. TiXmlString::Rep TiXmlString::nullrep_ = { 0, 0, { '\0' } }; void TiXmlString::reserve (size_type cap) { if (cap > capacity()) { TiXmlString tmp; tmp.init(length(), cap); memcpy(tmp.start(), data(), length()); swap(tmp); } } TiXmlString& TiXmlString::assign(const char* str, size_type len) { size_type cap = capacity(); if (len > cap || cap > 3*(len + 8)) { TiXmlString tmp; tmp.init(len); memcpy(tmp.start(), str, len); swap(tmp); } else { memmove(start(), str, len); set_size(len); } return *this; } TiXmlString& TiXmlString::append(const char* str, size_type len) { size_type newsize = length() + len; if (newsize > capacity()) { reserve (newsize + capacity()); } memmove(finish(), str, len); set_size(newsize); return *this; } TiXmlString operator + (const TiXmlString & a, const TiXmlString & b) { TiXmlString tmp; tmp.reserve(a.length() + b.length()); tmp += a; tmp += b; return tmp; } TiXmlString operator + (const TiXmlString & a, const char* b) { TiXmlString tmp; TiXmlString::size_type b_len = static_cast( strlen(b) ); tmp.reserve(a.length() + b_len); tmp += a; tmp.append(b, b_len); return tmp; } TiXmlString operator + (const char* a, const TiXmlString & b) { TiXmlString tmp; TiXmlString::size_type a_len = static_cast( strlen(a) ); tmp.reserve(a_len + b.length()); tmp.append(a, a_len); tmp += b; return tmp; } #endif // TIXML_USE_STL open-zwave-1.5/cpp/tinyxml/tinystr.h000066400000000000000000000211111264474202400176260ustar00rootroot00000000000000/* www.sourceforge.net/projects/tinyxml Original file by Yves Berquin. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ /* * THIS FILE WAS ALTERED BY Tyge Lovset, 7. April 2005. * * - completely rewritten. compact, clean, and fast implementation. * - sizeof(TiXmlString) = pointer size (4 bytes on 32-bit systems) * - fixed reserve() to work as per specification. * - fixed buggy compares operator==(), operator<(), and operator>() * - fixed operator+=() to take a const ref argument, following spec. * - added "copy" constructor with length, and most compare operators. * - added swap(), clear(), size(), capacity(), operator+(). */ #ifndef TIXML_USE_STL #ifndef TIXML_STRING_INCLUDED #define TIXML_STRING_INCLUDED #include #include /* The support for explicit isn't that universal, and it isn't really required - it is used to check that the TiXmlString class isn't incorrectly used. Be nice to old compilers and macro it here: */ #if defined(_MSC_VER) && (_MSC_VER >= 1200 ) // Microsoft visual studio, version 6 and higher. #define TIXML_EXPLICIT explicit #elif defined(__GNUC__) && (__GNUC__ >= 3 ) // GCC version 3 and higher.s #define TIXML_EXPLICIT explicit #else #define TIXML_EXPLICIT #endif /* TiXmlString is an emulation of a subset of the std::string template. Its purpose is to allow compiling TinyXML on compilers with no or poor STL support. Only the member functions relevant to the TinyXML project have been implemented. The buffer allocation is made by a simplistic power of 2 like mechanism : if we increase a string and there's no more room, we allocate a buffer twice as big as we need. */ class TiXmlString { public : // The size type used typedef size_t size_type; // Error value for find primitive static const size_type npos; // = -1; // TiXmlString empty constructor TiXmlString () : rep_(&nullrep_) { } // TiXmlString copy constructor TiXmlString ( const TiXmlString & copy) : rep_(0) { init(copy.length()); memcpy(start(), copy.data(), length()); } // TiXmlString constructor, based on a string TIXML_EXPLICIT TiXmlString ( const char * copy) : rep_(0) { init( static_cast( strlen(copy) )); memcpy(start(), copy, length()); } // TiXmlString constructor, based on a string TIXML_EXPLICIT TiXmlString ( const char * str, size_type len) : rep_(0) { init(len); memcpy(start(), str, len); } // TiXmlString destructor ~TiXmlString () { quit(); } // = operator TiXmlString& operator = (const char * copy) { return assign( copy, (size_type)strlen(copy)); } // = operator TiXmlString& operator = (const TiXmlString & copy) { return assign(copy.start(), copy.length()); } // += operator. Maps to append TiXmlString& operator += (const char * suffix) { return append(suffix, static_cast( strlen(suffix) )); } // += operator. Maps to append TiXmlString& operator += (char single) { return append(&single, 1); } // += operator. Maps to append TiXmlString& operator += (const TiXmlString & suffix) { return append(suffix.data(), suffix.length()); } // Convert a TiXmlString into a null-terminated char * const char * c_str () const { return rep_->str; } // Convert a TiXmlString into a char * (need not be null terminated). const char * data () const { return rep_->str; } // Return the length of a TiXmlString size_type length () const { return rep_->size; } // Alias for length() size_type size () const { return rep_->size; } // Checks if a TiXmlString is empty bool empty () const { return rep_->size == 0; } // Return capacity of string size_type capacity () const { return rep_->capacity; } // single char extraction const char& at (size_type index) const { assert( index < length() ); return rep_->str[ index ]; } // [] operator char& operator [] (size_type index) const { assert( index < length() ); return rep_->str[ index ]; } // find a char in a string. Return TiXmlString::npos if not found size_type find (char lookup) const { return find(lookup, 0); } // find a char in a string from an offset. Return TiXmlString::npos if not found size_type find (char tofind, size_type offset) const { if (offset >= length()) return npos; for (const char* p = c_str() + offset; *p != '\0'; ++p) { if (*p == tofind) return static_cast< size_type >( p - c_str() ); } return npos; } void clear () { //Lee: //The original was just too strange, though correct: // TiXmlString().swap(*this); //Instead use the quit & re-init: quit(); init(0,0); } /* Function to reserve a big amount of data when we know we'll need it. Be aware that this function DOES NOT clear the content of the TiXmlString if any exists. */ void reserve (size_type cap); TiXmlString& assign (const char* str, size_type len); TiXmlString& append (const char* str, size_type len); void swap (TiXmlString& other) { Rep* r = rep_; rep_ = other.rep_; other.rep_ = r; } private: void init(size_type sz) { init(sz, sz); } void set_size(size_type sz) { rep_->str[ rep_->size = sz ] = '\0'; } char* start() const { return rep_->str; } char* finish() const { return rep_->str + rep_->size; } struct Rep { size_type size, capacity; char str[1]; }; void init(size_type sz, size_type cap) { if (cap) { // Lee: the original form: // rep_ = static_cast(operator new(sizeof(Rep) + cap)); // doesn't work in some cases of new being overloaded. Switching // to the normal allocation, although use an 'int' for systems // that are overly picky about structure alignment. const size_type bytesNeeded = sizeof(Rep) + cap; const size_type intsNeeded = ( bytesNeeded + sizeof(int) - 1 ) / sizeof( int ); rep_ = reinterpret_cast( new int[ intsNeeded ] ); rep_->str[ rep_->size = sz ] = '\0'; rep_->capacity = cap; } else { rep_ = &nullrep_; } } void quit() { if (rep_ != &nullrep_) { // The rep_ is really an array of ints. (see the allocator, above). // Cast it back before delete, so the compiler won't incorrectly call destructors. delete [] ( reinterpret_cast( rep_ ) ); } } Rep * rep_; static Rep nullrep_; } ; inline bool operator == (const TiXmlString & a, const TiXmlString & b) { return ( a.length() == b.length() ) // optimization on some platforms && ( strcmp(a.c_str(), b.c_str()) == 0 ); // actual compare } inline bool operator < (const TiXmlString & a, const TiXmlString & b) { return strcmp(a.c_str(), b.c_str()) < 0; } inline bool operator != (const TiXmlString & a, const TiXmlString & b) { return !(a == b); } inline bool operator > (const TiXmlString & a, const TiXmlString & b) { return b < a; } inline bool operator <= (const TiXmlString & a, const TiXmlString & b) { return !(b < a); } inline bool operator >= (const TiXmlString & a, const TiXmlString & b) { return !(a < b); } inline bool operator == (const TiXmlString & a, const char* b) { return strcmp(a.c_str(), b) == 0; } inline bool operator == (const char* a, const TiXmlString & b) { return b == a; } inline bool operator != (const TiXmlString & a, const char* b) { return !(a == b); } inline bool operator != (const char* a, const TiXmlString & b) { return !(b == a); } TiXmlString operator + (const TiXmlString & a, const TiXmlString & b); TiXmlString operator + (const TiXmlString & a, const char* b); TiXmlString operator + (const char* a, const TiXmlString & b); /* TiXmlOutStream is an emulation of std::ostream. It is based on TiXmlString. Only the operators that we need for TinyXML have been developped. */ class TiXmlOutStream : public TiXmlString { public : // TiXmlOutStream << operator. TiXmlOutStream & operator << (const TiXmlString & in) { *this += in; return *this; } // TiXmlOutStream << operator. TiXmlOutStream & operator << (const char * in) { *this += in; return *this; } } ; #endif // TIXML_STRING_INCLUDED #endif // TIXML_USE_STL open-zwave-1.5/cpp/tinyxml/tinyxml.cpp000066400000000000000000001103651264474202400201630ustar00rootroot00000000000000/* www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #include #ifdef TIXML_USE_STL #include #include #endif #include #include "tinyxml.h" bool TiXmlBase::condenseWhiteSpace = true; // Microsoft compiler security FILE* TiXmlFOpen( const char* filename, const char* mode ) { #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) FILE* fp = 0; errno_t err = fopen_s( &fp, filename, mode ); if ( !err && fp ) return fp; return 0; #else return fopen( filename, mode ); #endif } void TiXmlBase::EncodeString( const TIXML_STRING& str, TIXML_STRING* outString ) { int i=0; while( i<(int)str.length() ) { unsigned char c = (unsigned char) str[i]; if ( c == '&' && i < ( (int)str.length() - 2 ) && str[i+1] == '#' && str[i+2] == 'x' ) { // Hexadecimal character reference. // Pass through unchanged. // © -- copyright symbol, for example. // // The -1 is a bug fix from Rob Laveaux. It keeps // an overflow from happening if there is no ';'. // There are actually 2 ways to exit this loop - // while fails (error case) and break (semicolon found). // However, there is no mechanism (currently) for // this function to return an error. while ( i<(int)str.length()-1 ) { outString->append( str.c_str() + i, 1 ); ++i; if ( str[i] == ';' ) break; } } else if ( c == '&' ) { outString->append( entity[0].str, entity[0].strLength ); ++i; } else if ( c == '<' ) { outString->append( entity[1].str, entity[1].strLength ); ++i; } else if ( c == '>' ) { outString->append( entity[2].str, entity[2].strLength ); ++i; } else if ( c == '\"' ) { outString->append( entity[3].str, entity[3].strLength ); ++i; } else if ( c == '\'' ) { outString->append( entity[4].str, entity[4].strLength ); ++i; } else if ( c < 32 ) { // Easy pass at non-alpha/numeric/symbol // Below 32 is symbolic. char buf[ 32 ]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF( buf, sizeof(buf), "&#x%02X;", (unsigned) ( c & 0xff ) ); #else sprintf( buf, "&#x%02X;", (unsigned) ( c & 0xff ) ); #endif //*ME: warning C4267: convert 'size_t' to 'int' //*ME: Int-Cast to make compiler happy ... outString->append( buf, (int)strlen( buf ) ); ++i; } else { //char realc = (char) c; //outString->append( &realc, 1 ); *outString += (char) c; // somewhat more efficient function call. ++i; } } } TiXmlNode::TiXmlNode( NodeType _type ) : TiXmlBase() { parent = 0; type = _type; firstChild = 0; lastChild = 0; prev = 0; next = 0; } TiXmlNode::~TiXmlNode() { TiXmlNode* node = firstChild; TiXmlNode* temp = 0; while ( node ) { temp = node; node = node->next; delete temp; } } void TiXmlNode::CopyTo( TiXmlNode* target ) const { target->SetValue (value.c_str() ); target->userData = userData; } void TiXmlNode::Clear() { TiXmlNode* node = firstChild; TiXmlNode* temp = 0; while ( node ) { temp = node; node = node->next; delete temp; } firstChild = 0; lastChild = 0; } TiXmlNode* TiXmlNode::LinkEndChild( TiXmlNode* node ) { assert( node->parent == 0 || node->parent == this ); assert( node->GetDocument() == 0 || node->GetDocument() == this->GetDocument() ); if ( node->Type() == TiXmlNode::DOCUMENT ) { delete node; if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } node->parent = this; node->prev = lastChild; node->next = 0; if ( lastChild ) lastChild->next = node; else firstChild = node; // it was an empty list. lastChild = node; return node; } TiXmlNode* TiXmlNode::InsertEndChild( const TiXmlNode& addThis ) { if ( addThis.Type() == TiXmlNode::DOCUMENT ) { if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } TiXmlNode* node = addThis.Clone(); if ( !node ) return 0; return LinkEndChild( node ); } TiXmlNode* TiXmlNode::InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ) { if ( !beforeThis || beforeThis->parent != this ) { return 0; } if ( addThis.Type() == TiXmlNode::DOCUMENT ) { if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } TiXmlNode* node = addThis.Clone(); if ( !node ) return 0; node->parent = this; node->next = beforeThis; node->prev = beforeThis->prev; if ( beforeThis->prev ) { beforeThis->prev->next = node; } else { assert( firstChild == beforeThis ); firstChild = node; } beforeThis->prev = node; return node; } TiXmlNode* TiXmlNode::InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ) { if ( !afterThis || afterThis->parent != this ) { return 0; } if ( addThis.Type() == TiXmlNode::DOCUMENT ) { if ( GetDocument() ) GetDocument()->SetError( TIXML_ERROR_DOCUMENT_TOP_ONLY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } TiXmlNode* node = addThis.Clone(); if ( !node ) return 0; node->parent = this; node->prev = afterThis; node->next = afterThis->next; if ( afterThis->next ) { afterThis->next->prev = node; } else { assert( lastChild == afterThis ); lastChild = node; } afterThis->next = node; return node; } TiXmlNode* TiXmlNode::ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ) { if ( replaceThis->parent != this ) return 0; TiXmlNode* node = withThis.Clone(); if ( !node ) return 0; node->next = replaceThis->next; node->prev = replaceThis->prev; if ( replaceThis->next ) replaceThis->next->prev = node; else lastChild = node; if ( replaceThis->prev ) replaceThis->prev->next = node; else firstChild = node; delete replaceThis; node->parent = this; return node; } bool TiXmlNode::RemoveChild( TiXmlNode* removeThis ) { if ( removeThis->parent != this ) { assert( 0 ); return false; } if ( removeThis->next ) removeThis->next->prev = removeThis->prev; else lastChild = removeThis->prev; if ( removeThis->prev ) removeThis->prev->next = removeThis->next; else firstChild = removeThis->next; delete removeThis; return true; } const TiXmlNode* TiXmlNode::FirstChild( const char * _value ) const { const TiXmlNode* node; for ( node = firstChild; node; node = node->next ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } const TiXmlNode* TiXmlNode::LastChild( const char * _value ) const { const TiXmlNode* node; for ( node = lastChild; node; node = node->prev ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } const TiXmlNode* TiXmlNode::IterateChildren( const TiXmlNode* previous ) const { if ( !previous ) { return FirstChild(); } else { assert( previous->parent == this ); return previous->NextSibling(); } } const TiXmlNode* TiXmlNode::IterateChildren( const char * val, const TiXmlNode* previous ) const { if ( !previous ) { return FirstChild( val ); } else { assert( previous->parent == this ); return previous->NextSibling( val ); } } const TiXmlNode* TiXmlNode::NextSibling( const char * _value ) const { const TiXmlNode* node; for ( node = next; node; node = node->next ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } const TiXmlNode* TiXmlNode::PreviousSibling( const char * _value ) const { const TiXmlNode* node; for ( node = prev; node; node = node->prev ) { if ( strcmp( node->Value(), _value ) == 0 ) return node; } return 0; } void TiXmlElement::RemoveAttribute( const char * name ) { #ifdef TIXML_USE_STL TIXML_STRING str( name ); TiXmlAttribute* node = attributeSet.Find( str ); #else TiXmlAttribute* node = attributeSet.Find( name ); #endif if ( node ) { attributeSet.Remove( node ); delete node; } } const TiXmlElement* TiXmlNode::FirstChildElement() const { const TiXmlNode* node; for ( node = FirstChild(); node; node = node->NextSibling() ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } const TiXmlElement* TiXmlNode::FirstChildElement( const char * _value ) const { const TiXmlNode* node; for ( node = FirstChild( _value ); node; node = node->NextSibling( _value ) ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } const TiXmlElement* TiXmlNode::NextSiblingElement() const { const TiXmlNode* node; for ( node = NextSibling(); node; node = node->NextSibling() ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } const TiXmlElement* TiXmlNode::NextSiblingElement( const char * _value ) const { const TiXmlNode* node; for ( node = NextSibling( _value ); node; node = node->NextSibling( _value ) ) { if ( node->ToElement() ) return node->ToElement(); } return 0; } const TiXmlDocument* TiXmlNode::GetDocument() const { const TiXmlNode* node; for( node = this; node; node = node->parent ) { if ( node->ToDocument() ) return node->ToDocument(); } return 0; } TiXmlElement::TiXmlElement (const char * _value) : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; value = _value; } #ifdef TIXML_USE_STL TiXmlElement::TiXmlElement( const std::string& _value ) : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; value = _value; } #endif TiXmlElement::TiXmlElement( const TiXmlElement& copy) : TiXmlNode( TiXmlNode::ELEMENT ) { firstChild = lastChild = 0; copy.CopyTo( this ); } void TiXmlElement::operator=( const TiXmlElement& base ) { ClearThis(); base.CopyTo( this ); } TiXmlElement::~TiXmlElement() { ClearThis(); } void TiXmlElement::ClearThis() { Clear(); while( attributeSet.First() ) { TiXmlAttribute* node = attributeSet.First(); attributeSet.Remove( node ); delete node; } } const char* TiXmlElement::Attribute( const char* name ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( node ) return node->Value(); return 0; } #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( node ) return &node->ValueStr(); return 0; } #endif const char* TiXmlElement::Attribute( const char* name, int* i ) const { const char* s = Attribute( name ); if ( i ) { if ( s ) { *i = atoi( s ); } else { *i = 0; } } return s; } #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name, int* i ) const { const std::string* s = Attribute( name ); if ( i ) { if ( s ) { *i = atoi( s->c_str() ); } else { *i = 0; } } return s; } #endif const char* TiXmlElement::Attribute( const char* name, double* d ) const { const char* s = Attribute( name ); if ( d ) { if ( s ) { *d = atof( s ); } else { *d = 0; } } return s; } #ifdef TIXML_USE_STL const std::string* TiXmlElement::Attribute( const std::string& name, double* d ) const { const std::string* s = Attribute( name ); if ( d ) { if ( s ) { *d = atof( s->c_str() ); } else { *d = 0; } } return s; } #endif int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; return node->QueryIntValue( ival ); } #ifdef TIXML_USE_STL int TiXmlElement::QueryIntAttribute( const std::string& name, int* ival ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; return node->QueryIntValue( ival ); } #endif int TiXmlElement::QueryDoubleAttribute( const char* name, double* dval ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; return node->QueryDoubleValue( dval ); } #ifdef TIXML_USE_STL int TiXmlElement::QueryDoubleAttribute( const std::string& name, double* dval ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; return node->QueryDoubleValue( dval ); } #endif void TiXmlElement::SetAttribute( const char * name, int val ) { char buf[64]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF( buf, sizeof(buf), "%d", val ); #else sprintf( buf, "%d", val ); #endif SetAttribute( name, buf ); } #ifdef TIXML_USE_STL void TiXmlElement::SetAttribute( const std::string& name, int val ) { std::ostringstream oss; oss << val; SetAttribute( name, oss.str() ); } #endif void TiXmlElement::SetDoubleAttribute( const char * name, double val ) { char buf[256]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF( buf, sizeof(buf), "%f", val ); #else sprintf( buf, "%f", val ); #endif SetAttribute( name, buf ); } void TiXmlElement::SetAttribute( const char * cname, const char * cvalue ) { #ifdef TIXML_USE_STL TIXML_STRING _name( cname ); TIXML_STRING _value( cvalue ); #else const char* _name = cname; const char* _value = cvalue; #endif TiXmlAttribute* node = attributeSet.Find( _name ); if ( node ) { node->SetValue( _value ); return; } TiXmlAttribute* attrib = new (std::nothrow) TiXmlAttribute( cname, cvalue ); if ( attrib ) { attributeSet.Add( attrib ); } else { TiXmlDocument* document = GetDocument(); if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); } } #ifdef TIXML_USE_STL void TiXmlElement::SetAttribute( const std::string& name, const std::string& _value ) { TiXmlAttribute* node = attributeSet.Find( name ); if ( node ) { node->SetValue( _value ); return; } TiXmlAttribute* attrib = new (std::nothrow) TiXmlAttribute( name, _value ); if ( attrib ) { attributeSet.Add( attrib ); } else { TiXmlDocument* document = GetDocument(); if ( document ) document->SetError( TIXML_ERROR_OUT_OF_MEMORY, 0, 0, TIXML_ENCODING_UNKNOWN ); } } #endif void TiXmlElement::Print( FILE* cfile, int depth ) const { int i; assert( cfile ); for ( i=0; iNext() ) { fprintf( cfile, " " ); attrib->Print( cfile, depth ); } // There are 3 different formatting approaches: // 1) An element without children is printed as a node // 2) An element with only a text child is printed as text // 3) An element with children is printed on multiple lines. TiXmlNode* node; if ( !firstChild ) { fprintf( cfile, " />" ); } else if ( firstChild == lastChild && firstChild->ToText() ) { fprintf( cfile, ">" ); firstChild->Print( cfile, depth + 1 ); fprintf( cfile, "", value.c_str() ); } else { fprintf( cfile, ">" ); for ( node = firstChild; node; node=node->NextSibling() ) { if ( !node->ToText() ) { fprintf( cfile, "\n" ); } node->Print( cfile, depth+1 ); } fprintf( cfile, "\n" ); for( i=0; i", value.c_str() ); } } void TiXmlElement::CopyTo( TiXmlElement* target ) const { // superclass: TiXmlNode::CopyTo( target ); // Element class: // Clone the attributes, then clone the children. const TiXmlAttribute* attribute = 0; for( attribute = attributeSet.First(); attribute; attribute = attribute->Next() ) { target->SetAttribute( attribute->Name(), attribute->Value() ); } TiXmlNode* node = 0; for ( node = firstChild; node; node = node->NextSibling() ) { target->LinkEndChild( node->Clone() ); } } bool TiXmlElement::Accept( TiXmlVisitor* visitor ) const { if ( visitor->VisitEnter( *this, attributeSet.First() ) ) { for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) { if ( !node->Accept( visitor ) ) break; } } return visitor->VisitExit( *this ); } TiXmlNode* TiXmlElement::Clone() const { TiXmlElement* clone = new (std::nothrow) TiXmlElement( Value() ); if ( !clone ) return 0; CopyTo( clone ); return clone; } const char* TiXmlElement::GetText() const { const TiXmlNode* child = this->FirstChild(); if ( child ) { const TiXmlText* childText = child->ToText(); if ( childText ) { return childText->Value(); } } return 0; } TiXmlDocument::TiXmlDocument() : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; ClearError(); } TiXmlDocument::TiXmlDocument( const char * documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; value = documentName; ClearError(); } #ifdef TIXML_USE_STL TiXmlDocument::TiXmlDocument( const std::string& documentName ) : TiXmlNode( TiXmlNode::DOCUMENT ) { tabsize = 4; useMicrosoftBOM = false; value = documentName; ClearError(); } #endif TiXmlDocument::TiXmlDocument( const TiXmlDocument& copy ) : TiXmlNode( TiXmlNode::DOCUMENT ) { copy.CopyTo( this ); } void TiXmlDocument::operator=( const TiXmlDocument& copy ) { Clear(); copy.CopyTo( this ); } bool TiXmlDocument::LoadFile( TiXmlEncoding encoding ) { // See STL_STRING_BUG below. //StringToBuffer buf( value ); return LoadFile( Value(), encoding ); } bool TiXmlDocument::SaveFile() const { // See STL_STRING_BUG below. // StringToBuffer buf( value ); // // if ( buf.buffer && SaveFile( buf.buffer ) ) // return true; // // return false; return SaveFile( Value() ); } bool TiXmlDocument::LoadFile( const char* _filename, TiXmlEncoding encoding ) { // There was a really terrifying little bug here. The code: // value = filename // in the STL case, cause the assignment method of the std::string to // be called. What is strange, is that the std::string had the same // address as its c_str() method, and so bad things happen. Looks // like a bug in the Microsoft STL implementation. // Add an extra string to avoid the crash. TIXML_STRING filename( _filename ); value = filename; // reading in binary mode so that tinyxml can normalize the EOL FILE* file = TiXmlFOpen( value.c_str (), "rb" ); if ( file ) { bool result = LoadFile( file, encoding ); fclose( file ); return result; } else { SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); return false; } } bool TiXmlDocument::LoadFile( FILE* file, TiXmlEncoding encoding ) { if ( !file ) { SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); return false; } // Delete the existing data: Clear(); location.Clear(); // Get the file size, so we can pre-allocate the string. HUGE speed impact. long length = 0; fseek( file, 0, SEEK_END ); length = ftell( file ); fseek( file, 0, SEEK_SET ); // Strange case, but good to handle up front. if ( length <= 0 ) { SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); return false; } // If we have a file, assume it is all one big XML file, and read it in. // The document parser may decide the document ends sooner than the entire file, however. TIXML_STRING data; data.reserve( length ); // Subtle bug here. TinyXml did use fgets. But from the XML spec: // 2.11 End-of-Line Handling // // // ...the XML processor MUST behave as if it normalized all line breaks in external // parsed entities (including the document entity) on input, before parsing, by translating // both the two-character sequence #xD #xA and any #xD that is not followed by #xA to // a single #xA character. // // // It is not clear fgets does that, and certainly isn't clear it works cross platform. // Generally, you expect fgets to translate from the convention of the OS to the c/unix // convention, and not work generally. /* while( fgets( buf, sizeof(buf), file ) ) { data += buf; } */ char* buf = new char[ length+1 ]; buf[0] = 0; if ( fread( buf, length, 1, file ) != 1 ) { delete [] buf; SetError( TIXML_ERROR_OPENING_FILE, 0, 0, TIXML_ENCODING_UNKNOWN ); return false; } const char* lastPos = buf; const char* p = buf; buf[length] = 0; while( *p ) { assert( p < (buf+length) ); if ( *p == 0xa ) { // Newline character. No special rules for this. Append all the characters // since the last string, and include the newline. data.append( lastPos, (p-lastPos+1) ); // append, include the newline ++p; // move past the newline lastPos = p; // and point to the new buffer (may be 0) assert( p <= (buf+length) ); } else if ( *p == 0xd ) { // Carriage return. Append what we have so far, then // handle moving forward in the buffer. if ( (p-lastPos) > 0 ) { data.append( lastPos, p-lastPos ); // do not add the CR } data += (char)0xa; // a proper newline if ( *(p+1) == 0xa ) { // Carriage return - new line sequence p += 2; lastPos = p; assert( p <= (buf+length) ); } else { // it was followed by something else...that is presumably characters again. ++p; lastPos = p; assert( p <= (buf+length) ); } } else { ++p; } } // Handle any left over characters. if ( p-lastPos ) { data.append( lastPos, p-lastPos ); } delete [] buf; buf = 0; Parse( data.c_str(), 0, encoding ); if ( Error() ) return false; else return true; } bool TiXmlDocument::SaveFile( const char * filename ) const { // The old c stuff lives on... FILE* fp = TiXmlFOpen( filename, "w" ); if ( fp ) { bool result = SaveFile( fp ); fclose( fp ); return result; } return false; } bool TiXmlDocument::SaveFile( FILE* fp ) const { if ( useMicrosoftBOM ) { const unsigned char TIXML_UTF_LEAD_0 = 0xefU; const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; fputc( TIXML_UTF_LEAD_0, fp ); fputc( TIXML_UTF_LEAD_1, fp ); fputc( TIXML_UTF_LEAD_2, fp ); } Print( fp, 0 ); return (ferror(fp) == 0); } void TiXmlDocument::CopyTo( TiXmlDocument* target ) const { TiXmlNode::CopyTo( target ); target->error = error; target->errorId = errorId; target->errorDesc = errorDesc; target->tabsize = tabsize; target->errorLocation = errorLocation; target->useMicrosoftBOM = useMicrosoftBOM; TiXmlNode* node = 0; for ( node = firstChild; node; node = node->NextSibling() ) { TiXmlNode* clonedNode=node->Clone(); if (clonedNode!=NULL) target->LinkEndChild( clonedNode ); } } TiXmlNode* TiXmlDocument::Clone() const { TiXmlDocument* clone = new (std::nothrow) TiXmlDocument(); if ( !clone ) return 0; CopyTo( clone ); return clone; } void TiXmlDocument::Print( FILE* cfile, int depth ) const { assert( cfile ); for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) { node->Print( cfile, depth ); fprintf( cfile, "\n" ); } } bool TiXmlDocument::Accept( TiXmlVisitor* visitor ) const { if ( visitor->VisitEnter( *this ) ) { for ( const TiXmlNode* node=FirstChild(); node; node=node->NextSibling() ) { if ( !node->Accept( visitor ) ) break; } } return visitor->VisitExit( *this ); } const TiXmlAttribute* TiXmlAttribute::Next() const { // We are using knowledge of the sentinel. The sentinel // have a value or name. if ( next->value.empty() && next->name.empty() ) return 0; return next; } /* TiXmlAttribute* TiXmlAttribute::Next() { // We are using knowledge of the sentinel. The sentinel // have a value or name. if ( next->value.empty() && next->name.empty() ) return 0; return next; } */ const TiXmlAttribute* TiXmlAttribute::Previous() const { // We are using knowledge of the sentinel. The sentinel // have a value or name. if ( prev->value.empty() && prev->name.empty() ) return 0; return prev; } /* TiXmlAttribute* TiXmlAttribute::Previous() { // We are using knowledge of the sentinel. The sentinel // have a value or name. if ( prev->value.empty() && prev->name.empty() ) return 0; return prev; } */ void TiXmlAttribute::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const { TIXML_STRING n, v; EncodeString( name, &n ); EncodeString( value, &v ); if (value.find ('\"') == TIXML_STRING::npos) { if ( cfile ) { fprintf (cfile, "%s=\"%s\"", n.c_str(), v.c_str() ); } if ( str ) { (*str) += n; (*str) += "=\""; (*str) += v; (*str) += "\""; } } else { if ( cfile ) { fprintf (cfile, "%s='%s'", n.c_str(), v.c_str() ); } if ( str ) { (*str) += n; (*str) += "='"; (*str) += v; (*str) += "'"; } } } int TiXmlAttribute::QueryIntValue( int* ival ) const { if ( TIXML_SSCANF( value.c_str(), "%d", ival ) == 1 ) return TIXML_SUCCESS; return TIXML_WRONG_TYPE; } int TiXmlAttribute::QueryDoubleValue( double* dval ) const { if ( TIXML_SSCANF( value.c_str(), "%lf", dval ) == 1 ) return TIXML_SUCCESS; return TIXML_WRONG_TYPE; } void TiXmlAttribute::SetIntValue( int _value ) { char buf [64]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF(buf, sizeof(buf), "%d", _value); #else sprintf (buf, "%d", _value); #endif SetValue (buf); } void TiXmlAttribute::SetDoubleValue( double _value ) { char buf [256]; #if defined(TIXML_SNPRINTF) TIXML_SNPRINTF( buf, sizeof(buf), "%lf", _value); #else sprintf (buf, "%lf", _value); #endif SetValue (buf); } int TiXmlAttribute::IntValue() const { return atoi (value.c_str ()); } double TiXmlAttribute::DoubleValue() const { return atof (value.c_str ()); } TiXmlComment::TiXmlComment( const TiXmlComment& copy ) : TiXmlNode( TiXmlNode::COMMENT ) { copy.CopyTo( this ); } void TiXmlComment::operator=( const TiXmlComment& base ) { Clear(); base.CopyTo( this ); } void TiXmlComment::Print( FILE* cfile, int depth ) const { assert( cfile ); for ( int i=0; i", value.c_str() ); } void TiXmlComment::CopyTo( TiXmlComment* target ) const { TiXmlNode::CopyTo( target ); } bool TiXmlComment::Accept( TiXmlVisitor* visitor ) const { return visitor->Visit( *this ); } TiXmlNode* TiXmlComment::Clone() const { TiXmlComment* clone = new (std::nothrow) TiXmlComment(); if ( !clone ) return 0; CopyTo( clone ); return clone; } void TiXmlText::Print( FILE* cfile, int depth ) const { assert( cfile ); if ( cdata ) { int i; fprintf( cfile, "\n" ); for ( i=0; i\n", value.c_str() ); // unformatted output } else { TIXML_STRING buffer; EncodeString( value, &buffer ); fprintf( cfile, "%s", buffer.c_str() ); } } void TiXmlText::CopyTo( TiXmlText* target ) const { TiXmlNode::CopyTo( target ); target->cdata = cdata; } bool TiXmlText::Accept( TiXmlVisitor* visitor ) const { return visitor->Visit( *this ); } TiXmlNode* TiXmlText::Clone() const { TiXmlText* clone = 0; clone = new (std::nothrow) TiXmlText( "" ); if ( !clone ) return 0; CopyTo( clone ); return clone; } TiXmlDeclaration::TiXmlDeclaration( const char * _version, const char * _encoding, const char * _standalone ) : TiXmlNode( TiXmlNode::DECLARATION ) { version = _version; encoding = _encoding; standalone = _standalone; } #ifdef TIXML_USE_STL TiXmlDeclaration::TiXmlDeclaration( const std::string& _version, const std::string& _encoding, const std::string& _standalone ) : TiXmlNode( TiXmlNode::DECLARATION ) { version = _version; encoding = _encoding; standalone = _standalone; } #endif TiXmlDeclaration::TiXmlDeclaration( const TiXmlDeclaration& copy ) : TiXmlNode( TiXmlNode::DECLARATION ) { copy.CopyTo( this ); } void TiXmlDeclaration::operator=( const TiXmlDeclaration& copy ) { Clear(); copy.CopyTo( this ); } void TiXmlDeclaration::Print( FILE* cfile, int /*depth*/, TIXML_STRING* str ) const { if ( cfile ) fprintf( cfile, "" ); if ( str ) (*str) += "?>"; } void TiXmlDeclaration::CopyTo( TiXmlDeclaration* target ) const { TiXmlNode::CopyTo( target ); target->version = version; target->encoding = encoding; target->standalone = standalone; } bool TiXmlDeclaration::Accept( TiXmlVisitor* visitor ) const { return visitor->Visit( *this ); } TiXmlNode* TiXmlDeclaration::Clone() const { TiXmlDeclaration* clone = new (std::nothrow) TiXmlDeclaration(); if ( !clone ) return 0; CopyTo( clone ); return clone; } void TiXmlUnknown::Print( FILE* cfile, int depth ) const { for ( int i=0; i", value.c_str() ); } void TiXmlUnknown::CopyTo( TiXmlUnknown* target ) const { TiXmlNode::CopyTo( target ); } bool TiXmlUnknown::Accept( TiXmlVisitor* visitor ) const { return visitor->Visit( *this ); } TiXmlNode* TiXmlUnknown::Clone() const { TiXmlUnknown* clone = new (std::nothrow) TiXmlUnknown(); if ( !clone ) return 0; CopyTo( clone ); return clone; } TiXmlAttributeSet::TiXmlAttributeSet() { sentinel.next = &sentinel; sentinel.prev = &sentinel; } TiXmlAttributeSet::~TiXmlAttributeSet() { assert( sentinel.next == &sentinel ); assert( sentinel.prev == &sentinel ); } void TiXmlAttributeSet::Add( TiXmlAttribute* addMe ) { #ifdef TIXML_USE_STL assert( !Find( TIXML_STRING( addMe->Name() ) ) ); // Shouldn't be multiply adding to the set. #else assert( !Find( addMe->Name() ) ); // Shouldn't be multiply adding to the set. #endif addMe->next = &sentinel; addMe->prev = sentinel.prev; sentinel.prev->next = addMe; sentinel.prev = addMe; } void TiXmlAttributeSet::Remove( TiXmlAttribute* removeMe ) { TiXmlAttribute* node; for( node = sentinel.next; node != &sentinel; node = node->next ) { if ( node == removeMe ) { node->prev->next = node->next; node->next->prev = node->prev; node->next = 0; node->prev = 0; return; } } assert( 0 ); // we tried to remove a non-linked attribute. } #ifdef TIXML_USE_STL const TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) const { for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) { if ( node->name == name ) return node; } return 0; } /* TiXmlAttribute* TiXmlAttributeSet::Find( const std::string& name ) { for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) { if ( node->name == name ) return node; } return 0; } */ #endif const TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) const { for( const TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) { if ( strcmp( node->name.c_str(), name ) == 0 ) return node; } return 0; } /* TiXmlAttribute* TiXmlAttributeSet::Find( const char* name ) { for( TiXmlAttribute* node = sentinel.next; node != &sentinel; node = node->next ) { if ( strcmp( node->name.c_str(), name ) == 0 ) return node; } return 0; } */ #ifdef TIXML_USE_STL std::istream& operator>> (std::istream & in, TiXmlNode & base) { TIXML_STRING tag; tag.reserve( 8 * 1000 ); base.StreamIn( &in, &tag ); base.Parse( tag.c_str(), 0, TIXML_DEFAULT_ENCODING ); return in; } #endif #ifdef TIXML_USE_STL std::ostream& operator<< (std::ostream & out, const TiXmlNode & base) { TiXmlPrinter printer; printer.SetStreamPrinting(); base.Accept( &printer ); out << printer.Str(); return out; } std::string& operator<< (std::string& out, const TiXmlNode& base ) { TiXmlPrinter printer; printer.SetStreamPrinting(); base.Accept( &printer ); out.append( printer.Str() ); return out; } #endif TiXmlHandle TiXmlHandle::FirstChild() const { if ( node ) { TiXmlNode* child = node->FirstChild(); if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChild( const char * value ) const { if ( node ) { TiXmlNode* child = node->FirstChild( value ); if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChildElement() const { if ( node ) { TiXmlElement* child = node->FirstChildElement(); if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::FirstChildElement( const char * value ) const { if ( node ) { TiXmlElement* child = node->FirstChildElement( value ); if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::Child( int count ) const { if ( node ) { int i; TiXmlNode* child = node->FirstChild(); for ( i=0; child && iNextSibling(), ++i ) { // nothing } if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::Child( const char* value, int count ) const { if ( node ) { int i; TiXmlNode* child = node->FirstChild( value ); for ( i=0; child && iNextSibling( value ), ++i ) { // nothing } if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::ChildElement( int count ) const { if ( node ) { int i; TiXmlElement* child = node->FirstChildElement(); for ( i=0; child && iNextSiblingElement(), ++i ) { // nothing } if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } TiXmlHandle TiXmlHandle::ChildElement( const char* value, int count ) const { if ( node ) { int i; TiXmlElement* child = node->FirstChildElement( value ); for ( i=0; child && iNextSiblingElement( value ), ++i ) { // nothing } if ( child ) return TiXmlHandle( child ); } return TiXmlHandle( 0 ); } bool TiXmlPrinter::VisitEnter( const TiXmlDocument& ) { return true; } bool TiXmlPrinter::VisitExit( const TiXmlDocument& ) { return true; } bool TiXmlPrinter::VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ) { DoIndent(); buffer += "<"; buffer += element.Value(); for( const TiXmlAttribute* attrib = firstAttribute; attrib; attrib = attrib->Next() ) { buffer += " "; attrib->Print( 0, 0, &buffer ); } if ( !element.FirstChild() ) { buffer += " />"; DoLineBreak(); } else { buffer += ">"; if ( element.FirstChild()->ToText() && element.LastChild() == element.FirstChild() && element.FirstChild()->ToText()->CDATA() == false ) { simpleTextPrint = true; // no DoLineBreak()! } else { DoLineBreak(); } } ++depth; return true; } bool TiXmlPrinter::VisitExit( const TiXmlElement& element ) { --depth; if ( !element.FirstChild() ) { // nothing. } else { if ( simpleTextPrint ) { simpleTextPrint = false; } else { DoIndent(); } buffer += ""; DoLineBreak(); } return true; } bool TiXmlPrinter::Visit( const TiXmlText& text ) { if ( text.CDATA() ) { DoIndent(); buffer += ""; DoLineBreak(); } else if ( simpleTextPrint ) { TIXML_STRING str; TiXmlBase::EncodeString( text.ValueTStr(), &str ); buffer += str; } else { DoIndent(); TIXML_STRING str; TiXmlBase::EncodeString( text.ValueTStr(), &str ); buffer += str; DoLineBreak(); } return true; } bool TiXmlPrinter::Visit( const TiXmlDeclaration& declaration ) { DoIndent(); declaration.Print( 0, 0, &buffer ); DoLineBreak(); return true; } bool TiXmlPrinter::Visit( const TiXmlComment& comment ) { DoIndent(); buffer += ""; DoLineBreak(); return true; } bool TiXmlPrinter::Visit( const TiXmlUnknown& unknown ) { DoIndent(); buffer += "<"; buffer += unknown.Value(); buffer += ">"; DoLineBreak(); return true; } open-zwave-1.5/cpp/tinyxml/tinyxml.h000066400000000000000000001755001264474202400176320ustar00rootroot00000000000000/* www.sourceforge.net/projects/tinyxml Original code (2.0 and earlier )copyright (c) 2000-2006 Lee Thomason (www.grinninglizard.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #ifndef TINYXML_INCLUDED #define TINYXML_INCLUDED #ifdef _MSC_VER #pragma warning( push ) #pragma warning( disable : 4530 ) #pragma warning( disable : 4786 ) #endif #include #include #include #include #include // Help out windows: #if defined( _DEBUG ) && !defined( DEBUG ) #define DEBUG #endif #ifdef TIXML_USE_STL #include #include #include #define TIXML_STRING std::string #else #include "tinystr.h" #define TIXML_STRING TiXmlString #endif // Deprecated library function hell. Compilers want to use the // new safe versions. This probably doesn't fully address the problem, // but it gets closer. There are too many compilers for me to fully // test. If you get compilation troubles, undefine TIXML_SAFE #define TIXML_SAFE #ifdef TIXML_SAFE #if defined(_MSC_VER) && (_MSC_VER >= 1400 ) // Microsoft visual studio, version 2005 and higher. #define TIXML_SNPRINTF _snprintf_s #define TIXML_SNSCANF _snscanf_s #define TIXML_SSCANF sscanf_s #elif defined(_MSC_VER) && (_MSC_VER >= 1200 ) // Microsoft visual studio, version 6 and higher. //#pragma message( "Using _sn* functions." ) #define TIXML_SNPRINTF _snprintf #define TIXML_SNSCANF _snscanf #define TIXML_SSCANF sscanf #elif defined(__GNUC__) && (__GNUC__ >= 3 ) // GCC version 3 and higher.s //#warning( "Using sn* functions." ) #define TIXML_SNPRINTF snprintf #define TIXML_SNSCANF snscanf #define TIXML_SSCANF sscanf #else #define TIXML_SSCANF sscanf #endif #endif class TiXmlDocument; class TiXmlElement; class TiXmlComment; class TiXmlUnknown; class TiXmlAttribute; class TiXmlText; class TiXmlDeclaration; class TiXmlParsingData; const int TIXML_MAJOR_VERSION = 2; const int TIXML_MINOR_VERSION = 5; const int TIXML_PATCH_VERSION = 3; /* Internal structure for tracking location of items in the XML file. */ struct TiXmlCursor { TiXmlCursor() { Clear(); } void Clear() { row = col = -1; } int row; // 0 based. int col; // 0 based. }; /** If you call the Accept() method, it requires being passed a TiXmlVisitor class to handle callbacks. For nodes that contain other nodes (Document, Element) you will get called with a VisitEnter/VisitExit pair. Nodes that are always leaves are simple called with Visit(). If you return 'true' from a Visit method, recursive parsing will continue. If you return false, no children of this node or its sibilings will be Visited. All flavors of Visit methods have a default implementation that returns 'true' (continue visiting). You need to only override methods that are interesting to you. Generally Accept() is called on the TiXmlDocument, although all nodes suppert Visiting. You should never change the document from a callback. \see TiXmlNode::Accept() */ class TiXmlVisitor { public: virtual ~TiXmlVisitor() {} /// Visit a document. virtual bool VisitEnter( const TiXmlDocument& /*doc*/ ) { return true; } /// Visit a document. virtual bool VisitExit( const TiXmlDocument& /*doc*/ ) { return true; } /// Visit an element. virtual bool VisitEnter( const TiXmlElement& /*element*/, const TiXmlAttribute* /*firstAttribute*/ ) { return true; } /// Visit an element. virtual bool VisitExit( const TiXmlElement& /*element*/ ) { return true; } /// Visit a declaration virtual bool Visit( const TiXmlDeclaration& /*declaration*/ ) { return true; } /// Visit a text node virtual bool Visit( const TiXmlText& /*text*/ ) { return true; } /// Visit a comment node virtual bool Visit( const TiXmlComment& /*comment*/ ) { return true; } /// Visit an unknow node virtual bool Visit( const TiXmlUnknown& /*unknown*/ ) { return true; } }; // Only used by Attribute::Query functions enum { TIXML_SUCCESS, TIXML_NO_ATTRIBUTE, TIXML_WRONG_TYPE }; // Used by the parsing routines. enum TiXmlEncoding { TIXML_ENCODING_UNKNOWN, TIXML_ENCODING_UTF8, TIXML_ENCODING_LEGACY }; const TiXmlEncoding TIXML_DEFAULT_ENCODING = TIXML_ENCODING_UNKNOWN; /** TiXmlBase is a base class for every class in TinyXml. It does little except to establish that TinyXml classes can be printed and provide some utility functions. In XML, the document and elements can contain other elements and other types of nodes. \verbatim A Document can contain: Element (container or leaf) Comment (leaf) Unknown (leaf) Declaration( leaf ) An Element can contain: Element (container or leaf) Text (leaf) Attributes (not on tree) Comment (leaf) Unknown (leaf) A Decleration contains: Attributes (not on tree) \endverbatim */ class TiXmlBase { friend class TiXmlNode; friend class TiXmlElement; friend class TiXmlDocument; public: TiXmlBase() : userData(0) {} virtual ~TiXmlBase() {} /** All TinyXml classes can print themselves to a filestream or the string class (TiXmlString in non-STL mode, std::string in STL mode.) Either or both cfile and str can be null. This is a formatted print, and will insert tabs and newlines. (For an unformatted stream, use the << operator.) */ virtual void Print( FILE* cfile, int depth ) const = 0; /** The world does not agree on whether white space should be kept or not. In order to make everyone happy, these global, static functions are provided to set whether or not TinyXml will condense all white space into a single space or not. The default is to condense. Note changing this value is not thread safe. */ static void SetCondenseWhiteSpace( bool condense ) { condenseWhiteSpace = condense; } /// Return the current white space setting. static bool IsWhiteSpaceCondensed() { return condenseWhiteSpace; } /** Return the position, in the original source file, of this node or attribute. The row and column are 1-based. (That is the first row and first column is 1,1). If the returns values are 0 or less, then the parser does not have a row and column value. Generally, the row and column value will be set when the TiXmlDocument::Load(), TiXmlDocument::LoadFile(), or any TiXmlNode::Parse() is called. It will NOT be set when the DOM was created from operator>>. The values reflect the initial load. Once the DOM is modified programmatically (by adding or changing nodes and attributes) the new values will NOT update to reflect changes in the document. There is a minor performance cost to computing the row and column. Computation can be disabled if TiXmlDocument::SetTabSize() is called with 0 as the value. \see TiXmlDocument::SetTabSize() */ int Row() const { return location.row + 1; } int Column() const { return location.col + 1; } ///< See Row() void SetUserData( void* user ) { userData = user; } ///< Set a pointer to arbitrary user data. void* GetUserData() { return userData; } ///< Get a pointer to arbitrary user data. const void* GetUserData() const { return userData; } ///< Get a pointer to arbitrary user data. // Table that returs, for a given lead byte, the total number of bytes // in the UTF-8 sequence. static const int utf8ByteTable[256]; virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding /*= TIXML_ENCODING_UNKNOWN */ ) = 0; /** Expands entities in a string. Note this should not contian the tag's '<', '>', etc, or they will be transformed into entities! */ static void EncodeString( const TIXML_STRING& str, TIXML_STRING* out ); enum { TIXML_NO_ERROR = 0, TIXML_ERROR, TIXML_ERROR_OPENING_FILE, TIXML_ERROR_OUT_OF_MEMORY, TIXML_ERROR_PARSING_ELEMENT, TIXML_ERROR_FAILED_TO_READ_ELEMENT_NAME, TIXML_ERROR_READING_ELEMENT_VALUE, TIXML_ERROR_READING_ATTRIBUTES, TIXML_ERROR_PARSING_EMPTY, TIXML_ERROR_READING_END_TAG, TIXML_ERROR_PARSING_UNKNOWN, TIXML_ERROR_PARSING_COMMENT, TIXML_ERROR_PARSING_DECLARATION, TIXML_ERROR_DOCUMENT_EMPTY, TIXML_ERROR_EMBEDDED_NULL, TIXML_ERROR_PARSING_CDATA, TIXML_ERROR_DOCUMENT_TOP_ONLY, TIXML_ERROR_STRING_COUNT }; protected: static const char* SkipWhiteSpace( const char*, TiXmlEncoding encoding ); inline static bool IsWhiteSpace( char c ) { return ( isspace( (unsigned char) c ) || c == '\n' || c == '\r' ); } inline static bool IsWhiteSpace( int c ) { if ( c < 256 ) return IsWhiteSpace( (char) c ); return false; // Again, only truly correct for English/Latin...but usually works. } #ifdef TIXML_USE_STL static bool StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ); static bool StreamTo( std::istream * in, int character, TIXML_STRING * tag ); #endif /* Reads an XML name into the string provided. Returns a pointer just past the last character of the name, or 0 if the function has an error. */ static const char* ReadName( const char* p, TIXML_STRING* name, TiXmlEncoding encoding ); /* Reads text. Returns a pointer past the given end tag. Wickedly complex options, but it keeps the (sensitive) code in one place. */ static const char* ReadText( const char* in, // where to start TIXML_STRING* text, // the string read bool ignoreWhiteSpace, // whether to keep the white space const char* endTag, // what ends this text bool ignoreCase, // whether to ignore case in the end tag TiXmlEncoding encoding ); // the current encoding // If an entity has been found, transform it into a character. static const char* GetEntity( const char* in, char* value, int* length, TiXmlEncoding encoding ); // Get a character, while interpreting entities. // The length can be from 0 to 4 bytes. inline static const char* GetChar( const char* p, char* _value, int* length, TiXmlEncoding encoding ) { assert( p ); if ( encoding == TIXML_ENCODING_UTF8 ) { *length = utf8ByteTable[ *((const unsigned char*)p) ]; assert( *length >= 0 && *length < 5 ); } else { *length = 1; } if ( *length == 1 ) { if ( *p == '&' ) return GetEntity( p, _value, length, encoding ); *_value = *p; return p+1; } else if ( *length ) { //strncpy( _value, p, *length ); // lots of compilers don't like this function (unsafe), // and the null terminator isn't needed for( int i=0; p[i] && i<*length; ++i ) { _value[i] = p[i]; } return p + (*length); } else { // Not valid text. return 0; } } // Return true if the next characters in the stream are any of the endTag sequences. // Ignore case only works for english, and should only be relied on when comparing // to English words: StringEqual( p, "version", true ) is fine. static bool StringEqual( const char* p, const char* endTag, bool ignoreCase, TiXmlEncoding encoding ); static const char* errorString[ TIXML_ERROR_STRING_COUNT ]; TiXmlCursor location; /// Field containing a generic user pointer void* userData; // None of these methods are reliable for any language except English. // Good for approximation, not great for accuracy. static int IsAlpha( unsigned char anyByte, TiXmlEncoding encoding ); static int IsAlphaNum( unsigned char anyByte, TiXmlEncoding encoding ); inline static int ToLower( int v, TiXmlEncoding encoding ) { if ( encoding == TIXML_ENCODING_UTF8 ) { if ( v < 128 ) return tolower( v ); return v; } else { return tolower( v ); } } static void ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ); private: TiXmlBase( const TiXmlBase& ); // not implemented. void operator=( const TiXmlBase& base ); // not allowed. struct Entity { const char* str; unsigned int strLength; char chr; }; enum { NUM_ENTITY = 5, MAX_ENTITY_LENGTH = 6 }; static Entity entity[ NUM_ENTITY ]; static bool condenseWhiteSpace; }; /** The parent class for everything in the Document Object Model. (Except for attributes). Nodes have siblings, a parent, and children. A node can be in a document, or stand on its own. The type of a TiXmlNode can be queried, and it can be cast to its more defined type. */ class TiXmlNode : public TiXmlBase { friend class TiXmlDocument; friend class TiXmlElement; public: #ifdef TIXML_USE_STL /** An input stream operator, for every class. Tolerant of newlines and formatting, but doesn't expect them. */ friend std::istream& operator >> (std::istream& in, TiXmlNode& base); /** An output stream operator, for every class. Note that this outputs without any newlines or formatting, as opposed to Print(), which includes tabs and new lines. The operator<< and operator>> are not completely symmetric. Writing a node to a stream is very well defined. You'll get a nice stream of output, without any extra whitespace or newlines. But reading is not as well defined. (As it always is.) If you create a TiXmlElement (for example) and read that from an input stream, the text needs to define an element or junk will result. This is true of all input streams, but it's worth keeping in mind. A TiXmlDocument will read nodes until it reads a root element, and all the children of that root element. */ friend std::ostream& operator<< (std::ostream& out, const TiXmlNode& base); /// Appends the XML node or attribute to a std::string. friend std::string& operator<< (std::string& out, const TiXmlNode& base ); #endif /** The types of XML nodes supported by TinyXml. (All the unsupported types are picked up by UNKNOWN.) */ enum NodeType { DOCUMENT, ELEMENT, COMMENT, UNKNOWN, TEXT, DECLARATION, TYPECOUNT }; virtual ~TiXmlNode(); /** The meaning of 'value' changes for the specific type of TiXmlNode. \verbatim Document: filename of the xml file Element: name of the element Comment: the comment text Unknown: the tag contents Text: the text string \endverbatim The subclasses will wrap this function. */ const char *Value() const { return value.c_str (); } #ifdef TIXML_USE_STL /** Return Value() as a std::string. If you only use STL, this is more efficient than calling Value(). Only available in STL mode. */ const std::string& ValueStr() const { return value; } #endif const TIXML_STRING& ValueTStr() const { return value; } /** Changes the value of the node. Defined as: \verbatim Document: filename of the xml file Element: name of the element Comment: the comment text Unknown: the tag contents Text: the text string \endverbatim */ void SetValue(const char * _value) { value = _value;} #ifdef TIXML_USE_STL /// STL std::string form. void SetValue( const std::string& _value ) { value = _value; } #endif /// Delete all the children of this node. Does not affect 'this'. void Clear(); /// One step up the DOM. TiXmlNode* Parent() { return parent; } const TiXmlNode* Parent() const { return parent; } const TiXmlNode* FirstChild() const { return firstChild; } ///< The first child of this node. Will be null if there are no children. TiXmlNode* FirstChild() { return firstChild; } const TiXmlNode* FirstChild( const char * value ) const; ///< The first child of this node with the matching 'value'. Will be null if none found. /// The first child of this node with the matching 'value'. Will be null if none found. TiXmlNode* FirstChild( const char * _value ) { // Call through to the const version - safe since nothing is changed. Exiting syntax: cast this to a const (always safe) // call the method, cast the return back to non-const. return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->FirstChild( _value )); } const TiXmlNode* LastChild() const { return lastChild; } /// The last child of this node. Will be null if there are no children. TiXmlNode* LastChild() { return lastChild; } const TiXmlNode* LastChild( const char * value ) const; /// The last child of this node matching 'value'. Will be null if there are no children. TiXmlNode* LastChild( const char * _value ) { return const_cast< TiXmlNode* > ((const_cast< const TiXmlNode* >(this))->LastChild( _value )); } #ifdef TIXML_USE_STL const TiXmlNode* FirstChild( const std::string& _value ) const { return FirstChild (_value.c_str ()); } ///< STL std::string form. TiXmlNode* FirstChild( const std::string& _value ) { return FirstChild (_value.c_str ()); } ///< STL std::string form. const TiXmlNode* LastChild( const std::string& _value ) const { return LastChild (_value.c_str ()); } ///< STL std::string form. TiXmlNode* LastChild( const std::string& _value ) { return LastChild (_value.c_str ()); } ///< STL std::string form. #endif /** An alternate way to walk the children of a node. One way to iterate over nodes is: \verbatim for( child = parent->FirstChild(); child; child = child->NextSibling() ) \endverbatim IterateChildren does the same thing with the syntax: \verbatim child = 0; while( child = parent->IterateChildren( child ) ) \endverbatim IterateChildren takes the previous child as input and finds the next one. If the previous child is null, it returns the first. IterateChildren will return null when done. */ const TiXmlNode* IterateChildren( const TiXmlNode* previous ) const; TiXmlNode* IterateChildren( const TiXmlNode* previous ) { return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( previous ) ); } /// This flavor of IterateChildren searches for children with a particular 'value' const TiXmlNode* IterateChildren( const char * value, const TiXmlNode* previous ) const; TiXmlNode* IterateChildren( const char * _value, const TiXmlNode* previous ) { return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->IterateChildren( _value, previous ) ); } #ifdef TIXML_USE_STL const TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) const { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. TiXmlNode* IterateChildren( const std::string& _value, const TiXmlNode* previous ) { return IterateChildren (_value.c_str (), previous); } ///< STL std::string form. #endif /** Add a new node related to this. Adds a child past the LastChild. Returns a pointer to the new object or NULL if an error occured. */ TiXmlNode* InsertEndChild( const TiXmlNode& addThis ); /** Add a new node related to this. Adds a child past the LastChild. NOTE: the node to be added is passed by pointer, and will be henceforth owned (and deleted) by tinyXml. This method is efficient and avoids an extra copy, but should be used with care as it uses a different memory model than the other insert functions. \sa InsertEndChild */ TiXmlNode* LinkEndChild( TiXmlNode* addThis ); /** Add a new node related to this. Adds a child before the specified child. Returns a pointer to the new object or NULL if an error occured. */ TiXmlNode* InsertBeforeChild( TiXmlNode* beforeThis, const TiXmlNode& addThis ); /** Add a new node related to this. Adds a child after the specified child. Returns a pointer to the new object or NULL if an error occured. */ TiXmlNode* InsertAfterChild( TiXmlNode* afterThis, const TiXmlNode& addThis ); /** Replace a child of this node. Returns a pointer to the new object or NULL if an error occured. */ TiXmlNode* ReplaceChild( TiXmlNode* replaceThis, const TiXmlNode& withThis ); /// Delete a child of this node. bool RemoveChild( TiXmlNode* removeThis ); /// Navigate to a sibling node. const TiXmlNode* PreviousSibling() const { return prev; } TiXmlNode* PreviousSibling() { return prev; } /// Navigate to a sibling node. const TiXmlNode* PreviousSibling( const char * ) const; TiXmlNode* PreviousSibling( const char *_prev ) { return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->PreviousSibling( _prev ) ); } #ifdef TIXML_USE_STL const TiXmlNode* PreviousSibling( const std::string& _value ) const { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. TiXmlNode* PreviousSibling( const std::string& _value ) { return PreviousSibling (_value.c_str ()); } ///< STL std::string form. const TiXmlNode* NextSibling( const std::string& _value) const { return NextSibling (_value.c_str ()); } ///< STL std::string form. TiXmlNode* NextSibling( const std::string& _value) { return NextSibling (_value.c_str ()); } ///< STL std::string form. #endif /// Navigate to a sibling node. const TiXmlNode* NextSibling() const { return next; } TiXmlNode* NextSibling() { return next; } /// Navigate to a sibling node with the given 'value'. const TiXmlNode* NextSibling( const char * ) const; TiXmlNode* NextSibling( const char* _next ) { return const_cast< TiXmlNode* >( (const_cast< const TiXmlNode* >(this))->NextSibling( _next ) ); } /** Convenience function to get through elements. Calls NextSibling and ToElement. Will skip all non-Element nodes. Returns 0 if there is not another element. */ const TiXmlElement* NextSiblingElement() const; TiXmlElement* NextSiblingElement() { return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement() ); } /** Convenience function to get through elements. Calls NextSibling and ToElement. Will skip all non-Element nodes. Returns 0 if there is not another element. */ const TiXmlElement* NextSiblingElement( const char * ) const; TiXmlElement* NextSiblingElement( const char *_next ) { return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->NextSiblingElement( _next ) ); } #ifdef TIXML_USE_STL const TiXmlElement* NextSiblingElement( const std::string& _value) const { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. TiXmlElement* NextSiblingElement( const std::string& _value) { return NextSiblingElement (_value.c_str ()); } ///< STL std::string form. #endif /// Convenience function to get through elements. const TiXmlElement* FirstChildElement() const; TiXmlElement* FirstChildElement() { return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement() ); } /// Convenience function to get through elements. const TiXmlElement* FirstChildElement( const char * _value ) const; TiXmlElement* FirstChildElement( const char * _value ) { return const_cast< TiXmlElement* >( (const_cast< const TiXmlNode* >(this))->FirstChildElement( _value ) ); } #ifdef TIXML_USE_STL const TiXmlElement* FirstChildElement( const std::string& _value ) const { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. TiXmlElement* FirstChildElement( const std::string& _value ) { return FirstChildElement (_value.c_str ()); } ///< STL std::string form. #endif /** Query the type (as an enumerated value, above) of this node. The possible types are: DOCUMENT, ELEMENT, COMMENT, UNKNOWN, TEXT, and DECLARATION. */ int Type() const { return type; } /** Return a pointer to the Document this node lives in. Returns null if not in a document. */ const TiXmlDocument* GetDocument() const; TiXmlDocument* GetDocument() { return const_cast< TiXmlDocument* >( (const_cast< const TiXmlNode* >(this))->GetDocument() ); } /// Returns true if this node has no children. bool NoChildren() const { return !firstChild; } virtual const TiXmlDocument* ToDocument() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual const TiXmlElement* ToElement() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual const TiXmlComment* ToComment() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual const TiXmlUnknown* ToUnknown() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual const TiXmlText* ToText() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual const TiXmlDeclaration* ToDeclaration() const { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual TiXmlDocument* ToDocument() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual TiXmlElement* ToElement() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual TiXmlComment* ToComment() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual TiXmlUnknown* ToUnknown() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual TiXmlText* ToText() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. virtual TiXmlDeclaration* ToDeclaration() { return 0; } ///< Cast to a more defined type. Will return null if not of the requested type. /** Create an exact duplicate of this node and return it. The memory must be deleted by the caller. */ virtual TiXmlNode* Clone() const = 0; /** Accept a hierchical visit the nodes in the TinyXML DOM. Every node in the XML tree will be conditionally visited and the host will be called back via the TiXmlVisitor interface. This is essentially a SAX interface for TinyXML. (Note however it doesn't re-parse the XML for the callbacks, so the performance of TinyXML is unchanged by using this interface versus any other.) The interface has been based on ideas from: - http://www.saxproject.org/ - http://c2.com/cgi/wiki?HierarchicalVisitorPattern Which are both good references for "visiting". An example of using Accept(): \verbatim TiXmlPrinter printer; tinyxmlDoc.Accept( &printer ); const char* xmlcstr = printer.CStr(); \endverbatim */ virtual bool Accept( TiXmlVisitor* visitor ) const = 0; protected: TiXmlNode( NodeType _type ); // Copy to the allocated object. Shared functionality between Clone, Copy constructor, // and the assignment operator. void CopyTo( TiXmlNode* target ) const; #ifdef TIXML_USE_STL // The real work of the input operator. virtual void StreamIn( std::istream* in, TIXML_STRING* tag ) = 0; #endif // Figure out what is at *p, and parse it. Returns null if it is not an xml node. TiXmlNode* Identify( const char* start, TiXmlEncoding encoding ); TiXmlNode* parent; NodeType type; TiXmlNode* firstChild; TiXmlNode* lastChild; TIXML_STRING value; TiXmlNode* prev; TiXmlNode* next; private: TiXmlNode( const TiXmlNode& ); // not implemented. void operator=( const TiXmlNode& base ); // not allowed. }; /** An attribute is a name-value pair. Elements have an arbitrary number of attributes, each with a unique name. \note The attributes are not TiXmlNodes, since they are not part of the tinyXML document object model. There are other suggested ways to look at this problem. */ class TiXmlAttribute : public TiXmlBase { friend class TiXmlAttributeSet; public: /// Construct an empty attribute. TiXmlAttribute() : TiXmlBase() { document = 0; prev = next = 0; } #ifdef TIXML_USE_STL /// std::string constructor. TiXmlAttribute( const std::string& _name, const std::string& _value ) { name = _name; value = _value; document = 0; prev = next = 0; } #endif /// Construct an attribute with a name and value. TiXmlAttribute( const char * _name, const char * _value ) { name = _name; value = _value; document = 0; prev = next = 0; } const char* Name() const { return name.c_str(); } ///< Return the name of this attribute. const char* Value() const { return value.c_str(); } ///< Return the value of this attribute. #ifdef TIXML_USE_STL const std::string& ValueStr() const { return value; } ///< Return the value of this attribute. #endif int IntValue() const; ///< Return the value of this attribute, converted to an integer. double DoubleValue() const; ///< Return the value of this attribute, converted to a double. // Get the tinyxml string representation const TIXML_STRING& NameTStr() const { return name; } /** QueryIntValue examines the value string. It is an alternative to the IntValue() method with richer error checking. If the value is an integer, it is stored in 'value' and the call returns TIXML_SUCCESS. If it is not an integer, it returns TIXML_WRONG_TYPE. A specialized but useful call. Note that for success it returns 0, which is the opposite of almost all other TinyXml calls. */ int QueryIntValue( int* _value ) const; /// QueryDoubleValue examines the value string. See QueryIntValue(). int QueryDoubleValue( double* _value ) const; void SetName( const char* _name ) { name = _name; } ///< Set the name of this attribute. void SetValue( const char* _value ) { value = _value; } ///< Set the value. void SetIntValue( int _value ); ///< Set the value from an integer. void SetDoubleValue( double _value ); ///< Set the value from a double. #ifdef TIXML_USE_STL /// STL std::string form. void SetName( const std::string& _name ) { name = _name; } /// STL std::string form. void SetValue( const std::string& _value ) { value = _value; } #endif /// Get the next sibling attribute in the DOM. Returns null at end. const TiXmlAttribute* Next() const; TiXmlAttribute* Next() { return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Next() ); } /// Get the previous sibling attribute in the DOM. Returns null at beginning. const TiXmlAttribute* Previous() const; TiXmlAttribute* Previous() { return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttribute* >(this))->Previous() ); } bool operator==( const TiXmlAttribute& rhs ) const { return rhs.name == name; } bool operator<( const TiXmlAttribute& rhs ) const { return name < rhs.name; } bool operator>( const TiXmlAttribute& rhs ) const { return name > rhs.name; } /* Attribute parsing starts: first letter of the name returns: the next char after the value end quote */ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); // Prints this Attribute to a FILE stream. virtual void Print( FILE* cfile, int depth ) const { Print( cfile, depth, 0 ); } void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; // [internal use] // Set the document pointer so the attribute can report errors. void SetDocument( TiXmlDocument* doc ) { document = doc; } private: TiXmlAttribute( const TiXmlAttribute& ); // not implemented. void operator=( const TiXmlAttribute& base ); // not allowed. TiXmlDocument* document; // A pointer back to a document, for error reporting. TIXML_STRING name; TIXML_STRING value; TiXmlAttribute* prev; TiXmlAttribute* next; }; /* A class used to manage a group of attributes. It is only used internally, both by the ELEMENT and the DECLARATION. The set can be changed transparent to the Element and Declaration classes that use it, but NOT transparent to the Attribute which has to implement a next() and previous() method. Which makes it a bit problematic and prevents the use of STL. This version is implemented with circular lists because: - I like circular lists - it demonstrates some independence from the (typical) doubly linked list. */ class TiXmlAttributeSet { public: TiXmlAttributeSet(); ~TiXmlAttributeSet(); void Add( TiXmlAttribute* attribute ); void Remove( TiXmlAttribute* attribute ); const TiXmlAttribute* First() const { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } TiXmlAttribute* First() { return ( sentinel.next == &sentinel ) ? 0 : sentinel.next; } const TiXmlAttribute* Last() const { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } TiXmlAttribute* Last() { return ( sentinel.prev == &sentinel ) ? 0 : sentinel.prev; } const TiXmlAttribute* Find( const char* _name ) const; TiXmlAttribute* Find( const char* _name ) { return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); } #ifdef TIXML_USE_STL const TiXmlAttribute* Find( const std::string& _name ) const; TiXmlAttribute* Find( const std::string& _name ) { return const_cast< TiXmlAttribute* >( (const_cast< const TiXmlAttributeSet* >(this))->Find( _name ) ); } #endif private: //*ME: Because of hidden/disabled copy-construktor in TiXmlAttribute (sentinel-element), //*ME: this class must be also use a hidden/disabled copy-constructor !!! TiXmlAttributeSet( const TiXmlAttributeSet& ); // not allowed void operator=( const TiXmlAttributeSet& ); // not allowed (as TiXmlAttribute) TiXmlAttribute sentinel; }; /** The element is a container class. It has a value, the element name, and can contain other elements, text, comments, and unknowns. Elements also contain an arbitrary number of attributes. */ class TiXmlElement : public TiXmlNode { public: /// Construct an element. TiXmlElement (const char * in_value); #ifdef TIXML_USE_STL /// std::string constructor. TiXmlElement( const std::string& _value ); #endif TiXmlElement( const TiXmlElement& ); void operator=( const TiXmlElement& base ); virtual ~TiXmlElement(); /** Given an attribute name, Attribute() returns the value for the attribute of that name, or null if none exists. */ const char* Attribute( const char* name ) const; /** Given an attribute name, Attribute() returns the value for the attribute of that name, or null if none exists. If the attribute exists and can be converted to an integer, the integer value will be put in the return 'i', if 'i' is non-null. */ const char* Attribute( const char* name, int* i ) const; /** Given an attribute name, Attribute() returns the value for the attribute of that name, or null if none exists. If the attribute exists and can be converted to an double, the double value will be put in the return 'd', if 'd' is non-null. */ const char* Attribute( const char* name, double* d ) const; /** QueryIntAttribute examines the attribute - it is an alternative to the Attribute() method with richer error checking. If the attribute is an integer, it is stored in 'value' and the call returns TIXML_SUCCESS. If it is not an integer, it returns TIXML_WRONG_TYPE. If the attribute does not exist, then TIXML_NO_ATTRIBUTE is returned. */ int QueryIntAttribute( const char* name, int* _value ) const; /// QueryDoubleAttribute examines the attribute - see QueryIntAttribute(). int QueryDoubleAttribute( const char* name, double* _value ) const; /// QueryFloatAttribute examines the attribute - see QueryIntAttribute(). int QueryFloatAttribute( const char* name, float* _value ) const { double d; int result = QueryDoubleAttribute( name, &d ); if ( result == TIXML_SUCCESS ) { *_value = (float)d; } return result; } #ifdef TIXML_USE_STL /** Template form of the attribute query which will try to read the attribute into the specified type. Very easy, very powerful, but be careful to make sure to call this with the correct type. NOTE: This method doesn't work correctly for 'string' types. \return TIXML_SUCCESS, TIXML_WRONG_TYPE, or TIXML_NO_ATTRIBUTE */ template< typename T > int QueryValueAttribute( const std::string& name, T* outValue ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; std::stringstream sstream( node->ValueStr() ); sstream >> *outValue; if ( !sstream.fail() ) return TIXML_SUCCESS; return TIXML_WRONG_TYPE; } /* This is - in theory - a bug fix for "QueryValueAtribute returns truncated std::string" but template specialization is hard to get working cross-compiler. Leaving the bug for now. // The above will fail for std::string because the space character is used as a seperator. // Specialize for strings. Bug [ 1695429 ] QueryValueAtribute returns truncated std::string template<> int QueryValueAttribute( const std::string& name, std::string* outValue ) const { const TiXmlAttribute* node = attributeSet.Find( name ); if ( !node ) return TIXML_NO_ATTRIBUTE; *outValue = node->ValueStr(); return TIXML_SUCCESS; } */ #endif /** Sets an attribute of name to a given value. The attribute will be created if it does not exist, or changed if it does. */ void SetAttribute( const char* name, const char * _value ); #ifdef TIXML_USE_STL const std::string* Attribute( const std::string& name ) const; const std::string* Attribute( const std::string& name, int* i ) const; const std::string* Attribute( const std::string& name, double* d ) const; int QueryIntAttribute( const std::string& name, int* _value ) const; int QueryDoubleAttribute( const std::string& name, double* _value ) const; /// STL std::string form. void SetAttribute( const std::string& name, const std::string& _value ); ///< STL std::string form. void SetAttribute( const std::string& name, int _value ); #endif /** Sets an attribute of name to a given value. The attribute will be created if it does not exist, or changed if it does. */ void SetAttribute( const char * name, int value ); /** Sets an attribute of name to a given value. The attribute will be created if it does not exist, or changed if it does. */ void SetDoubleAttribute( const char * name, double value ); /** Deletes an attribute with the given name. */ void RemoveAttribute( const char * name ); #ifdef TIXML_USE_STL void RemoveAttribute( const std::string& name ) { RemoveAttribute (name.c_str ()); } ///< STL std::string form. #endif const TiXmlAttribute* FirstAttribute() const { return attributeSet.First(); } ///< Access the first attribute in this element. TiXmlAttribute* FirstAttribute() { return attributeSet.First(); } const TiXmlAttribute* LastAttribute() const { return attributeSet.Last(); } ///< Access the last attribute in this element. TiXmlAttribute* LastAttribute() { return attributeSet.Last(); } /** Convenience function for easy access to the text inside an element. Although easy and concise, GetText() is limited compared to getting the TiXmlText child and accessing it directly. If the first child of 'this' is a TiXmlText, the GetText() returns the character string of the Text node, else null is returned. This is a convenient method for getting the text of simple contained text: \verbatim This is text const char* str = fooElement->GetText(); \endverbatim 'str' will be a pointer to "This is text". Note that this function can be misleading. If the element foo was created from this XML: \verbatim This is text \endverbatim then the value of str would be null. The first child node isn't a text node, it is another element. From this XML: \verbatim This is text \endverbatim GetText() will return "This is ". WARNING: GetText() accesses a child node - don't become confused with the similarly named TiXmlHandle::Text() and TiXmlNode::ToText() which are safe type casts on the referenced node. */ const char* GetText() const; /// Creates a new Element and returns it - the returned element is a copy. virtual TiXmlNode* Clone() const; // Print the Element to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; /* Attribtue parsing starts: next char past '<' returns: next char past '>' */ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); virtual const TiXmlElement* ToElement() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. virtual TiXmlElement* ToElement() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ virtual bool Accept( TiXmlVisitor* visitor ) const; protected: void CopyTo( TiXmlElement* target ) const; void ClearThis(); // like clear, but initializes 'this' object as well // Used to be public [internal use] #ifdef TIXML_USE_STL virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif /* [internal use] Reads the "value" of the element -- another element, or text. This should terminate with the current end tag. */ const char* ReadValue( const char* in, TiXmlParsingData* prevData, TiXmlEncoding encoding ); private: TiXmlAttributeSet attributeSet; }; /** An XML comment. */ class TiXmlComment : public TiXmlNode { public: /// Constructs an empty comment. TiXmlComment() : TiXmlNode( TiXmlNode::COMMENT ) {} /// Construct a comment from text. TiXmlComment( const char* _value ) : TiXmlNode( TiXmlNode::COMMENT ) { SetValue( _value ); } TiXmlComment( const TiXmlComment& ); void operator=( const TiXmlComment& base ); virtual ~TiXmlComment() {} /// Returns a copy of this Comment. virtual TiXmlNode* Clone() const; // Write this Comment to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; /* Attribtue parsing starts: at the ! of the !-- returns: next char past '>' */ virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); virtual const TiXmlComment* ToComment() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. virtual TiXmlComment* ToComment() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ virtual bool Accept( TiXmlVisitor* visitor ) const; protected: void CopyTo( TiXmlComment* target ) const; // used to be public #ifdef TIXML_USE_STL virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif // virtual void StreamOut( TIXML_OSTREAM * out ) const; private: }; /** XML text. A text node can have 2 ways to output the next. "normal" output and CDATA. It will default to the mode it was parsed from the XML file and you generally want to leave it alone, but you can change the output mode with SetCDATA() and query it with CDATA(). */ class TiXmlText : public TiXmlNode { friend class TiXmlElement; public: /** Constructor for text element. By default, it is treated as normal, encoded text. If you want it be output as a CDATA text element, set the parameter _cdata to 'true' */ TiXmlText (const char * initValue ) : TiXmlNode (TiXmlNode::TEXT) { SetValue( initValue ); cdata = false; } virtual ~TiXmlText() {} #ifdef TIXML_USE_STL /// Constructor. TiXmlText( const std::string& initValue ) : TiXmlNode (TiXmlNode::TEXT) { SetValue( initValue ); cdata = false; } #endif TiXmlText( const TiXmlText& copy ) : TiXmlNode( TiXmlNode::TEXT ) { copy.CopyTo( this ); } void operator=( const TiXmlText& base ) { base.CopyTo( this ); } // Write this text object to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; /// Queries whether this represents text using a CDATA section. bool CDATA() const { return cdata; } /// Turns on or off a CDATA representation of text. void SetCDATA( bool _cdata ) { cdata = _cdata; } virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); virtual const TiXmlText* ToText() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. virtual TiXmlText* ToText() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ virtual bool Accept( TiXmlVisitor* content ) const; protected : /// [internal use] Creates a new Element and returns it. virtual TiXmlNode* Clone() const; void CopyTo( TiXmlText* target ) const; bool Blank() const; // returns true if all white space and new lines // [internal use] #ifdef TIXML_USE_STL virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif private: bool cdata; // true if this should be input and output as a CDATA style text element }; /** In correct XML the declaration is the first entry in the file. \verbatim \endverbatim TinyXml will happily read or write files without a declaration, however. There are 3 possible attributes to the declaration: version, encoding, and standalone. Note: In this version of the code, the attributes are handled as special cases, not generic attributes, simply because there can only be at most 3 and they are always the same. */ class TiXmlDeclaration : public TiXmlNode { public: /// Construct an empty declaration. TiXmlDeclaration() : TiXmlNode( TiXmlNode::DECLARATION ) {} #ifdef TIXML_USE_STL /// Constructor. TiXmlDeclaration( const std::string& _version, const std::string& _encoding, const std::string& _standalone ); #endif /// Construct. TiXmlDeclaration( const char* _version, const char* _encoding, const char* _standalone ); TiXmlDeclaration( const TiXmlDeclaration& copy ); void operator=( const TiXmlDeclaration& copy ); virtual ~TiXmlDeclaration() {} /// Version. Will return an empty string if none was found. const char *Version() const { return version.c_str (); } /// Encoding. Will return an empty string if none was found. const char *Encoding() const { return encoding.c_str (); } /// Is this a standalone document? const char *Standalone() const { return standalone.c_str (); } /// Creates a copy of this Declaration and returns it. virtual TiXmlNode* Clone() const; // Print this declaration to a FILE stream. virtual void Print( FILE* cfile, int depth, TIXML_STRING* str ) const; virtual void Print( FILE* cfile, int depth ) const { Print( cfile, depth, 0 ); } virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); virtual const TiXmlDeclaration* ToDeclaration() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. virtual TiXmlDeclaration* ToDeclaration() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ virtual bool Accept( TiXmlVisitor* visitor ) const; protected: void CopyTo( TiXmlDeclaration* target ) const; // used to be public #ifdef TIXML_USE_STL virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif private: TIXML_STRING version; TIXML_STRING encoding; TIXML_STRING standalone; }; /** Any tag that tinyXml doesn't recognize is saved as an unknown. It is a tag of text, but should not be modified. It will be written back to the XML, unchanged, when the file is saved. DTD tags get thrown into TiXmlUnknowns. */ class TiXmlUnknown : public TiXmlNode { public: TiXmlUnknown() : TiXmlNode( TiXmlNode::UNKNOWN ) {} virtual ~TiXmlUnknown() {} TiXmlUnknown( const TiXmlUnknown& copy ) : TiXmlNode( TiXmlNode::UNKNOWN ) { copy.CopyTo( this ); } void operator=( const TiXmlUnknown& copy ) { copy.CopyTo( this ); } /// Creates a copy of this Unknown and returns it. virtual TiXmlNode* Clone() const; // Print this Unknown to a FILE stream. virtual void Print( FILE* cfile, int depth ) const; virtual const char* Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ); virtual const TiXmlUnknown* ToUnknown() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. virtual TiXmlUnknown* ToUnknown() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ virtual bool Accept( TiXmlVisitor* content ) const; protected: void CopyTo( TiXmlUnknown* target ) const; #ifdef TIXML_USE_STL virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif private: }; /** Always the top level node. A document binds together all the XML pieces. It can be saved, loaded, and printed to the screen. The 'value' of a document node is the xml file name. */ class TiXmlDocument : public TiXmlNode { public: /// Create an empty document, that has no name. TiXmlDocument(); /// Create a document with a name. The name of the document is also the filename of the xml. TiXmlDocument( const char * documentName ); #ifdef TIXML_USE_STL /// Constructor. TiXmlDocument( const std::string& documentName ); #endif TiXmlDocument( const TiXmlDocument& copy ); void operator=( const TiXmlDocument& copy ); virtual ~TiXmlDocument() {} /** Load a file using the current document value. Returns true if successful. Will delete any existing document data before loading. */ bool LoadFile( TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); /// Save a file using the current document value. Returns true if successful. bool SaveFile() const; /// Load a file using the given filename. Returns true if successful. bool LoadFile( const char * filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); /// Save a file using the given filename. Returns true if successful. bool SaveFile( const char * filename ) const; /** Load a file using the given FILE*. Returns true if successful. Note that this method doesn't stream - the entire object pointed at by the FILE* will be interpreted as an XML file. TinyXML doesn't stream in XML from the current file location. Streaming may be added in the future. */ bool LoadFile( FILE*, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); /// Save a file using the given FILE*. Returns true if successful. bool SaveFile( FILE* ) const; #ifdef TIXML_USE_STL bool LoadFile( const std::string& filename, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ) ///< STL std::string version. { // StringToBuffer f( filename ); // return ( f.buffer && LoadFile( f.buffer, encoding )); return LoadFile( filename.c_str(), encoding ); } bool SaveFile( const std::string& filename ) const ///< STL std::string version. { // StringToBuffer f( filename ); // return ( f.buffer && SaveFile( f.buffer )); return SaveFile( filename.c_str() ); } #endif /** Parse the given null terminated block of xml data. Passing in an encoding to this method (either TIXML_ENCODING_LEGACY or TIXML_ENCODING_UTF8 will force TinyXml to use that encoding, regardless of what TinyXml might otherwise try to detect. */ virtual const char* Parse( const char* p, TiXmlParsingData* data = 0, TiXmlEncoding encoding = TIXML_DEFAULT_ENCODING ); /** Get the root element -- the only top level element -- of the document. In well formed XML, there should only be one. TinyXml is tolerant of multiple elements at the document level. */ const TiXmlElement* RootElement() const { return FirstChildElement(); } TiXmlElement* RootElement() { return FirstChildElement(); } /** If an error occurs, Error will be set to true. Also, - The ErrorId() will contain the integer identifier of the error (not generally useful) - The ErrorDesc() method will return the name of the error. (very useful) - The ErrorRow() and ErrorCol() will return the location of the error (if known) */ bool Error() const { return error; } /// Contains a textual (english) description of the error if one occurs. const char * ErrorDesc() const { return errorDesc.c_str (); } /** Generally, you probably want the error string ( ErrorDesc() ). But if you prefer the ErrorId, this function will fetch it. */ int ErrorId() const { return errorId; } /** Returns the location (if known) of the error. The first column is column 1, and the first row is row 1. A value of 0 means the row and column wasn't applicable (memory errors, for example, have no row/column) or the parser lost the error. (An error in the error reporting, in that case.) \see SetTabSize, Row, Column */ int ErrorRow() const { return errorLocation.row+1; } int ErrorCol() const { return errorLocation.col+1; } ///< The column where the error occured. See ErrorRow() /** SetTabSize() allows the error reporting functions (ErrorRow() and ErrorCol()) to report the correct values for row and column. It does not change the output or input in any way. By calling this method, with a tab size greater than 0, the row and column of each node and attribute is stored when the file is loaded. Very useful for tracking the DOM back in to the source file. The tab size is required for calculating the location of nodes. If not set, the default of 4 is used. The tabsize is set per document. Setting the tabsize to 0 disables row/column tracking. Note that row and column tracking is not supported when using operator>>. The tab size needs to be enabled before the parse or load. Correct usage: \verbatim TiXmlDocument doc; doc.SetTabSize( 8 ); doc.Load( "myfile.xml" ); \endverbatim \see Row, Column */ void SetTabSize( int _tabsize ) { tabsize = _tabsize; } int TabSize() const { return tabsize; } /** If you have handled the error, it can be reset with this call. The error state is automatically cleared if you Parse a new XML block. */ void ClearError() { error = false; errorId = 0; errorDesc = ""; errorLocation.row = errorLocation.col = 0; //errorLocation.last = 0; } /** Write the document to standard out using formatted printing ("pretty print"). */ void Print() const { Print( stdout, 0 ); } /* Write the document to a string using formatted printing ("pretty print"). This will allocate a character array (new char[]) and return it as a pointer. The calling code pust call delete[] on the return char* to avoid a memory leak. */ //char* PrintToMemory() const; /// Print this Document to a FILE stream. virtual void Print( FILE* cfile, int depth = 0 ) const; // [internal use] void SetError( int err, const char* errorLocation, TiXmlParsingData* prevData, TiXmlEncoding encoding ); virtual const TiXmlDocument* ToDocument() const { return this; } ///< Cast to a more defined type. Will return null not of the requested type. virtual TiXmlDocument* ToDocument() { return this; } ///< Cast to a more defined type. Will return null not of the requested type. /** Walk the XML tree visiting this node and all of its children. */ virtual bool Accept( TiXmlVisitor* content ) const; protected : // [internal use] virtual TiXmlNode* Clone() const; #ifdef TIXML_USE_STL virtual void StreamIn( std::istream * in, TIXML_STRING * tag ); #endif private: void CopyTo( TiXmlDocument* target ) const; bool error; int errorId; TIXML_STRING errorDesc; int tabsize; TiXmlCursor errorLocation; bool useMicrosoftBOM; // the UTF-8 BOM were found when read. Note this, and try to write. }; /** A TiXmlHandle is a class that wraps a node pointer with null checks; this is an incredibly useful thing. Note that TiXmlHandle is not part of the TinyXml DOM structure. It is a separate utility class. Take an example: \verbatim \endverbatim Assuming you want the value of "attributeB" in the 2nd "Child" element, it's very easy to write a *lot* of code that looks like: \verbatim TiXmlElement* root = document.FirstChildElement( "Document" ); if ( root ) { TiXmlElement* element = root->FirstChildElement( "Element" ); if ( element ) { TiXmlElement* child = element->FirstChildElement( "Child" ); if ( child ) { TiXmlElement* child2 = child->NextSiblingElement( "Child" ); if ( child2 ) { // Finally do something useful. \endverbatim And that doesn't even cover "else" cases. TiXmlHandle addresses the verbosity of such code. A TiXmlHandle checks for null pointers so it is perfectly safe and correct to use: \verbatim TiXmlHandle docHandle( &document ); TiXmlElement* child2 = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", 1 ).ToElement(); if ( child2 ) { // do something useful \endverbatim Which is MUCH more concise and useful. It is also safe to copy handles - internally they are nothing more than node pointers. \verbatim TiXmlHandle handleCopy = handle; \endverbatim What they should not be used for is iteration: \verbatim int i=0; while ( true ) { TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).Child( "Child", i ).ToElement(); if ( !child ) break; // do something ++i; } \endverbatim It seems reasonable, but it is in fact two embedded while loops. The Child method is a linear walk to find the element, so this code would iterate much more than it needs to. Instead, prefer: \verbatim TiXmlElement* child = docHandle.FirstChild( "Document" ).FirstChild( "Element" ).FirstChild( "Child" ).ToElement(); for( child; child; child=child->NextSiblingElement() ) { // do something } \endverbatim */ class TiXmlHandle { public: /// Create a handle from any node (at any depth of the tree.) This can be a null pointer. TiXmlHandle( TiXmlNode* _node ) { this->node = _node; } /// Copy constructor TiXmlHandle( const TiXmlHandle& ref ) { this->node = ref.node; } TiXmlHandle operator=( const TiXmlHandle& ref ) { this->node = ref.node; return *this; } /// Return a handle to the first child node. TiXmlHandle FirstChild() const; /// Return a handle to the first child node with the given name. TiXmlHandle FirstChild( const char * value ) const; /// Return a handle to the first child element. TiXmlHandle FirstChildElement() const; /// Return a handle to the first child element with the given name. TiXmlHandle FirstChildElement( const char * value ) const; /** Return a handle to the "index" child with the given name. The first child is 0, the second 1, etc. */ TiXmlHandle Child( const char* value, int index ) const; /** Return a handle to the "index" child. The first child is 0, the second 1, etc. */ TiXmlHandle Child( int index ) const; /** Return a handle to the "index" child element with the given name. The first child element is 0, the second 1, etc. Note that only TiXmlElements are indexed: other types are not counted. */ TiXmlHandle ChildElement( const char* value, int index ) const; /** Return a handle to the "index" child element. The first child element is 0, the second 1, etc. Note that only TiXmlElements are indexed: other types are not counted. */ TiXmlHandle ChildElement( int index ) const; #ifdef TIXML_USE_STL TiXmlHandle FirstChild( const std::string& _value ) const { return FirstChild( _value.c_str() ); } TiXmlHandle FirstChildElement( const std::string& _value ) const { return FirstChildElement( _value.c_str() ); } TiXmlHandle Child( const std::string& _value, int index ) const { return Child( _value.c_str(), index ); } TiXmlHandle ChildElement( const std::string& _value, int index ) const { return ChildElement( _value.c_str(), index ); } #endif /** Return the handle as a TiXmlNode. This may return null. */ TiXmlNode* ToNode() const { return node; } /** Return the handle as a TiXmlElement. This may return null. */ TiXmlElement* ToElement() const { return ( ( node && node->ToElement() ) ? node->ToElement() : 0 ); } /** Return the handle as a TiXmlText. This may return null. */ TiXmlText* ToText() const { return ( ( node && node->ToText() ) ? node->ToText() : 0 ); } /** Return the handle as a TiXmlUnknown. This may return null. */ TiXmlUnknown* ToUnknown() const { return ( ( node && node->ToUnknown() ) ? node->ToUnknown() : 0 ); } /** \deprecated use ToNode. Return the handle as a TiXmlNode. This may return null. */ TiXmlNode* Node() const { return ToNode(); } /** \deprecated use ToElement. Return the handle as a TiXmlElement. This may return null. */ TiXmlElement* Element() const { return ToElement(); } /** \deprecated use ToText() Return the handle as a TiXmlText. This may return null. */ TiXmlText* Text() const { return ToText(); } /** \deprecated use ToUnknown() Return the handle as a TiXmlUnknown. This may return null. */ TiXmlUnknown* Unknown() const { return ToUnknown(); } private: TiXmlNode* node; }; /** Print to memory functionality. The TiXmlPrinter is useful when you need to: -# Print to memory (especially in non-STL mode) -# Control formatting (line endings, etc.) When constructed, the TiXmlPrinter is in its default "pretty printing" mode. Before calling Accept() you can call methods to control the printing of the XML document. After TiXmlNode::Accept() is called, the printed document can be accessed via the CStr(), Str(), and Size() methods. TiXmlPrinter uses the Visitor API. \verbatim TiXmlPrinter printer; printer.SetIndent( "\t" ); doc.Accept( &printer ); fprintf( stdout, "%s", printer.CStr() ); \endverbatim */ class TiXmlPrinter : public TiXmlVisitor { public: TiXmlPrinter() : depth( 0 ), simpleTextPrint( false ), buffer(), indent( " " ), lineBreak( "\n" ) {} virtual bool VisitEnter( const TiXmlDocument& doc ); virtual bool VisitExit( const TiXmlDocument& doc ); virtual bool VisitEnter( const TiXmlElement& element, const TiXmlAttribute* firstAttribute ); virtual bool VisitExit( const TiXmlElement& element ); virtual bool Visit( const TiXmlDeclaration& declaration ); virtual bool Visit( const TiXmlText& text ); virtual bool Visit( const TiXmlComment& comment ); virtual bool Visit( const TiXmlUnknown& unknown ); /** Set the indent characters for printing. By default 4 spaces but tab (\t) is also useful, or null/empty string for no indentation. */ void SetIndent( const char* _indent ) { indent = _indent ? _indent : "" ; } /// Query the indention string. const char* Indent() { return indent.c_str(); } /** Set the line breaking string. By default set to newline (\n). Some operating systems prefer other characters, or can be set to the null/empty string for no indenation. */ void SetLineBreak( const char* _lineBreak ) { lineBreak = _lineBreak ? _lineBreak : ""; } /// Query the current line breaking string. const char* LineBreak() { return lineBreak.c_str(); } /** Switch over to "stream printing" which is the most dense formatting without linebreaks. Common when the XML is needed for network transmission. */ void SetStreamPrinting() { indent = ""; lineBreak = ""; } /// Return the result. const char* CStr() { return buffer.c_str(); } /// Return the length of the result string. size_t Size() { return buffer.size(); } #ifdef TIXML_USE_STL /// Return the result. const std::string& Str() { return buffer; } #endif private: void DoIndent() { for( int i=0; i #include #include #include "tinyxml.h" //#define DEBUG_PARSER #if defined( DEBUG_PARSER ) # if defined( DEBUG ) && defined( _MSC_VER ) # include # define TIXML_LOG OutputDebugString # else # define TIXML_LOG printf # endif #endif // Note tha "PutString" hardcodes the same list. This // is less flexible than it appears. Changing the entries // or order will break putstring. TiXmlBase::Entity TiXmlBase::entity[ NUM_ENTITY ] = { { "&", 5, '&' }, { "<", 4, '<' }, { ">", 4, '>' }, { """, 6, '\"' }, { "'", 6, '\'' } }; // Bunch of unicode info at: // http://www.unicode.org/faq/utf_bom.html // Including the basic of this table, which determines the #bytes in the // sequence from the lead byte. 1 placed for invalid sequences -- // although the result will be junk, pass it through as much as possible. // Beware of the non-characters in UTF-8: // ef bb bf (Microsoft "lead bytes") // ef bf be // ef bf bf const unsigned char TIXML_UTF_LEAD_0 = 0xefU; const unsigned char TIXML_UTF_LEAD_1 = 0xbbU; const unsigned char TIXML_UTF_LEAD_2 = 0xbfU; const int TiXmlBase::utf8ByteTable[256] = { // 0 1 2 3 4 5 6 7 8 9 a b c d e f 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x00 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x10 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x20 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x30 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x50 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x70 End of ASCII range 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x80 0x80 to 0xc1 invalid 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x90 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xa0 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0xb0 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xc0 0xc2 to 0xdf 2 byte 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // 0xd0 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xe0 0xe0 to 0xef 3 byte 4, 4, 4, 4, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // 0xf0 0xf0 to 0xf4 4 byte, 0xf5 and higher invalid }; void TiXmlBase::ConvertUTF32ToUTF8( unsigned long input, char* output, int* length ) { const unsigned long BYTE_MASK = 0xBF; const unsigned long BYTE_MARK = 0x80; const unsigned long FIRST_BYTE_MARK[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; if (input < 0x80) *length = 1; else if ( input < 0x800 ) *length = 2; else if ( input < 0x10000 ) *length = 3; else if ( input < 0x200000 ) *length = 4; else { *length = 0; return; } // This code won't covert this correctly anyway. output += *length; // Scary scary fall throughs. switch (*length) { case 4: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 3: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 2: --output; *output = (char)((input | BYTE_MARK) & BYTE_MASK); input >>= 6; case 1: --output; *output = (char)(input | FIRST_BYTE_MARK[*length]); } } /*static*/ int TiXmlBase::IsAlpha( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) { // This will only work for low-ascii, everything else is assumed to be a valid // letter. I'm not sure this is the best approach, but it is quite tricky trying // to figure out alhabetical vs. not across encoding. So take a very // conservative approach. // if ( encoding == TIXML_ENCODING_UTF8 ) // { if ( anyByte < 127 ) return isalpha( anyByte ); else return 1; // What else to do? The unicode set is huge...get the english ones right. // } // else // { // return isalpha( anyByte ); // } } /*static*/ int TiXmlBase::IsAlphaNum( unsigned char anyByte, TiXmlEncoding /*encoding*/ ) { // This will only work for low-ascii, everything else is assumed to be a valid // letter. I'm not sure this is the best approach, but it is quite tricky trying // to figure out alhabetical vs. not across encoding. So take a very // conservative approach. // if ( encoding == TIXML_ENCODING_UTF8 ) // { if ( anyByte < 127 ) return isalnum( anyByte ); else return 1; // What else to do? The unicode set is huge...get the english ones right. // } // else // { // return isalnum( anyByte ); // } } class TiXmlParsingData { friend class TiXmlDocument; public: void Stamp( const char* now, TiXmlEncoding encoding ); const TiXmlCursor& Cursor() { return cursor; } private: // Only used by the document! TiXmlParsingData( const char* start, int _tabsize, int row, int col ) { assert( start ); stamp = start; tabsize = _tabsize; cursor.row = row; cursor.col = col; } TiXmlCursor cursor; const char* stamp; int tabsize; }; void TiXmlParsingData::Stamp( const char* now, TiXmlEncoding encoding ) { assert( now ); // Do nothing if the tabsize is 0. if ( tabsize < 1 ) { return; } // Get the current row, column. int row = cursor.row; int col = cursor.col; const char* p = stamp; assert( p ); while ( p < now ) { // Treat p as unsigned, so we have a happy compiler. const unsigned char* pU = (const unsigned char*)p; // Code contributed by Fletcher Dunn: (modified by lee) switch (*pU) { case 0: // We *should* never get here, but in case we do, don't // advance past the terminating null character, ever return; case '\r': // bump down to the next line ++row; col = 0; // Eat the character ++p; // Check for \r\n sequence, and treat this as a single character if (*p == '\n') { ++p; } break; case '\n': // bump down to the next line ++row; col = 0; // Eat the character ++p; // Check for \n\r sequence, and treat this as a single // character. (Yes, this bizarre thing does occur still // on some arcane platforms...) if (*p == '\r') { ++p; } break; case '\t': // Eat the character ++p; // Skip to next tab stop col = (col / tabsize + 1) * tabsize; break; case TIXML_UTF_LEAD_0: if ( encoding == TIXML_ENCODING_UTF8 ) { if ( *(p+1) && *(p+2) ) { // In these cases, don't advance the column. These are // 0-width spaces. if ( *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) p += 3; else if ( *(pU+1)==0xbfU && *(pU+2)==0xbeU ) p += 3; else if ( *(pU+1)==0xbfU && *(pU+2)==0xbfU ) p += 3; else { p +=3; ++col; } // A normal character. } } else { ++p; ++col; } break; default: if ( encoding == TIXML_ENCODING_UTF8 ) { // Eat the 1 to 4 byte utf8 character. int step = TiXmlBase::utf8ByteTable[*((const unsigned char*)p)]; if ( step == 0 ) step = 1; // Error case from bad encoding, but handle gracefully. p += step; // Just advance one column, of course. ++col; } else { ++p; ++col; } break; } } cursor.row = row; cursor.col = col; assert( cursor.row >= -1 ); assert( cursor.col >= -1 ); stamp = p; assert( stamp ); } const char* TiXmlBase::SkipWhiteSpace( const char* p, TiXmlEncoding encoding ) { if ( !p || !*p ) { return 0; } if ( encoding == TIXML_ENCODING_UTF8 ) { while ( *p ) { const unsigned char* pU = (const unsigned char*)p; // Skip the stupid Microsoft UTF-8 Byte order marks if ( *(pU+0)==TIXML_UTF_LEAD_0 && *(pU+1)==TIXML_UTF_LEAD_1 && *(pU+2)==TIXML_UTF_LEAD_2 ) { p += 3; continue; } else if(*(pU+0)==TIXML_UTF_LEAD_0 && *(pU+1)==0xbfU && *(pU+2)==0xbeU ) { p += 3; continue; } else if(*(pU+0)==TIXML_UTF_LEAD_0 && *(pU+1)==0xbfU && *(pU+2)==0xbfU ) { p += 3; continue; } if ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) // Still using old rules for white space. ++p; else break; } } else { while ( (*p) && ( IsWhiteSpace( *p ) || *p == '\n' || *p =='\r' ) ) ++p; } return p; } #ifdef TIXML_USE_STL /*static*/ bool TiXmlBase::StreamWhiteSpace( std::istream * in, TIXML_STRING * tag ) { for( ;; ) { if ( !in->good() ) return false; int c = in->peek(); // At this scope, we can't get to a document. So fail silently. if ( !IsWhiteSpace( c ) || c <= 0 ) return true; *tag += (char) in->get(); } } /*static*/ bool TiXmlBase::StreamTo( std::istream * in, int character, TIXML_STRING * tag ) { //assert( character > 0 && character < 128 ); // else it won't work in utf-8 while ( in->good() ) { int c = in->peek(); if ( c == character ) return true; if ( c <= 0 ) // Silent failure: can't get document at this scope return false; in->get(); *tag += (char) c; } return false; } #endif // One of TinyXML's more performance demanding functions. Try to keep the memory overhead down. The // "assign" optimization removes over 10% of the execution time. // const char* TiXmlBase::ReadName( const char* p, TIXML_STRING * name, TiXmlEncoding encoding ) { // Oddly, not supported on some comilers, //name->clear(); // So use this: *name = ""; assert( p ); // Names start with letters or underscores. // Of course, in unicode, tinyxml has no idea what a letter *is*. The // algorithm is generous. // // After that, they can be letters, underscores, numbers, // hyphens, or colons. (Colons are valid ony for namespaces, // but tinyxml can't tell namespaces from names.) if ( p && *p && ( IsAlpha( (unsigned char) *p, encoding ) || *p == '_' ) ) { const char* start = p; while( p && *p && ( IsAlphaNum( (unsigned char ) *p, encoding ) || *p == '_' || *p == '-' || *p == '.' || *p == ':' ) ) { //(*name) += *p; // expensive ++p; } if ( p-start > 0 ) { name->assign( start, p-start ); } return p; } return 0; } const char* TiXmlBase::GetEntity( const char* p, char* value, int* length, TiXmlEncoding encoding ) { // Presume an entity, and pull it out. TIXML_STRING ent; int i; *length = 0; if ( *(p+1) && *(p+1) == '#' && *(p+2) ) { unsigned long ucs = 0; ptrdiff_t delta = 0; unsigned mult = 1; if ( *(p+2) == 'x' ) { // Hexadecimal. if ( !*(p+3) ) return 0; const char* q = p+3; q = strchr( q, ';' ); if ( !q || !*q ) return 0; delta = q-p; --q; while ( *q != 'x' ) { if ( *q >= '0' && *q <= '9' ) ucs += mult * (*q - '0'); else if ( *q >= 'a' && *q <= 'f' ) ucs += mult * (*q - 'a' + 10); else if ( *q >= 'A' && *q <= 'F' ) ucs += mult * (*q - 'A' + 10 ); else return 0; mult *= 16; --q; } } else { // Decimal. if ( !*(p+2) ) return 0; const char* q = p+2; q = strchr( q, ';' ); if ( !q || !*q ) return 0; delta = q-p; --q; while ( *q != '#' ) { if ( *q >= '0' && *q <= '9' ) ucs += mult * (*q - '0'); else return 0; mult *= 10; --q; } } if ( encoding == TIXML_ENCODING_UTF8 ) { // convert the UCS to UTF-8 ConvertUTF32ToUTF8( ucs, value, length ); } else { *value = (char)ucs; *length = 1; } return p + delta + 1; } // Now try to match it. for( i=0; iappend( cArr, len ); } } else { bool whitespace = false; // Remove leading white space: p = SkipWhiteSpace( p, encoding ); while ( p && *p && !StringEqual( p, endTag, caseInsensitive, encoding ) ) { if ( *p == '\r' || *p == '\n' ) { whitespace = true; ++p; } else if ( IsWhiteSpace( *p ) ) { whitespace = true; ++p; } else { // If we've found whitespace, add it before the // new character. Any whitespace just becomes a space. if ( whitespace ) { (*text) += ' '; whitespace = false; } int len; char cArr[4] = { 0, 0, 0, 0 }; p = GetChar( p, cArr, &len, encoding ); if ( len == 1 ) (*text) += cArr[0]; // more efficient else text->append( cArr, len ); } } } if ( p ) p += strlen( endTag ); return p; } #ifdef TIXML_USE_STL void TiXmlDocument::StreamIn( std::istream * in, TIXML_STRING * tag ) { // The basic issue with a document is that we don't know what we're // streaming. Read something presumed to be a tag (and hope), then // identify it, and call the appropriate stream method on the tag. // // This "pre-streaming" will never read the closing ">" so the // sub-tag can orient itself. if ( !StreamTo( in, '<', tag ) ) { SetError( TIXML_ERROR_PARSING_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } while ( in->good() ) { int tagIndex = (int) tag->length(); while ( in->good() && in->peek() != '>' ) { int c = in->get(); if ( c <= 0 ) { SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); break; } (*tag) += (char) c; } if ( in->good() ) { // We now have something we presume to be a node of // some sort. Identify it, and call the node to // continue streaming. TiXmlNode* node = Identify( tag->c_str() + tagIndex, TIXML_DEFAULT_ENCODING ); if ( node ) { node->StreamIn( in, tag ); bool isElement = node->ToElement() != 0; delete node; node = 0; // If this is the root element, we're done. Parsing will be // done by the >> operator. if ( isElement ) { return; } } else { SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } } } // We should have returned sooner. SetError( TIXML_ERROR, 0, 0, TIXML_ENCODING_UNKNOWN ); } #endif const char* TiXmlDocument::Parse( const char* p, TiXmlParsingData* prevData, TiXmlEncoding encoding ) { ClearError(); // Parse away, at the document level. Since a document // contains nothing but other tags, most of what happens // here is skipping white space. if ( !p || !*p ) { SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } // Note that, for a document, this needs to come // before the while space skip, so that parsing // starts from the pointer we are given. location.Clear(); if ( prevData ) { location.row = prevData->cursor.row; location.col = prevData->cursor.col; } else { location.row = 0; location.col = 0; } TiXmlParsingData data( p, TabSize(), location.row, location.col ); location = data.Cursor(); if ( encoding == TIXML_ENCODING_UNKNOWN ) { // Check for the Microsoft UTF-8 lead bytes. const unsigned char* pU = (const unsigned char*)p; if ( *(pU+0) && *(pU+0) == TIXML_UTF_LEAD_0 && *(pU+1) && *(pU+1) == TIXML_UTF_LEAD_1 && *(pU+2) && *(pU+2) == TIXML_UTF_LEAD_2 ) { encoding = TIXML_ENCODING_UTF8; useMicrosoftBOM = true; } } p = SkipWhiteSpace( p, encoding ); if ( !p ) { SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, TIXML_ENCODING_UNKNOWN ); return 0; } while ( p && *p ) { TiXmlNode* node = Identify( p, encoding ); if ( node ) { p = node->Parse( p, &data, encoding ); LinkEndChild( node ); } else { break; } // Did we get encoding info? if ( encoding == TIXML_ENCODING_UNKNOWN && node->ToDeclaration() ) { TiXmlDeclaration* dec = node->ToDeclaration(); const char* enc = dec->Encoding(); assert( enc ); if ( *enc == 0 ) encoding = TIXML_ENCODING_UTF8; else if ( StringEqual( enc, "UTF-8", true, TIXML_ENCODING_UNKNOWN ) ) encoding = TIXML_ENCODING_UTF8; else if ( StringEqual( enc, "UTF8", true, TIXML_ENCODING_UNKNOWN ) ) encoding = TIXML_ENCODING_UTF8; // incorrect, but be nice else encoding = TIXML_ENCODING_LEGACY; } p = SkipWhiteSpace( p, encoding ); } // Was this empty? if ( !firstChild ) { SetError( TIXML_ERROR_DOCUMENT_EMPTY, 0, 0, encoding ); return 0; } // All is well. return p; } void TiXmlDocument::SetError( int err, const char* pError, TiXmlParsingData* data, TiXmlEncoding encoding ) { // The first error in a chain is more accurate - don't set again! if ( error ) return; assert( err > 0 && err < TIXML_ERROR_STRING_COUNT ); error = true; errorId = err; errorDesc = errorString[ errorId ]; errorLocation.Clear(); if ( pError && data ) { data->Stamp( pError, encoding ); errorLocation = data->Cursor(); } } TiXmlNode* TiXmlNode::Identify( const char* p, TiXmlEncoding encoding ) { TiXmlNode* returnNode = 0; p = SkipWhiteSpace( p, encoding ); if( !p || !*p || *p != '<' ) { return 0; } TiXmlDocument* doc = GetDocument(); p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) { return 0; } // What is this thing? // - Elements start with a letter or underscore, but xml is reserved. // - Comments: "; if ( !StringEqual( p, startTag, false, encoding ) ) { document->SetError( TIXML_ERROR_PARSING_COMMENT, p, data, encoding ); return 0; } p += strlen( startTag ); // [ 1475201 ] TinyXML parses entities in comments // Oops - ReadText doesn't work, because we don't want to parse the entities. // p = ReadText( p, &value, false, endTag, false, encoding ); // // from the XML spec: /* [Definition: Comments may appear anywhere in a document outside other markup; in addition, they may appear within the document type declaration at places allowed by the grammar. They are not part of the document's character data; an XML processor MAY, but need not, make it possible for an application to retrieve the text of comments. For compatibility, the string "--" (double-hyphen) MUST NOT occur within comments.] Parameter entity references MUST NOT be recognized within comments. An example of a comment: */ value = ""; // Keep all the white space. while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) { value.append( p, 1 ); ++p; } if ( p ) p += strlen( endTag ); return p; } const char* TiXmlAttribute::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) return 0; // int tabsize = 4; // if ( document ) // tabsize = document->TabSize(); if ( data ) { data->Stamp( p, encoding ); location = data->Cursor(); } // Read the name, the '=' and the value. const char* pErr = p; p = ReadName( p, &name, encoding ); if ( !p || !*p ) { if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, pErr, data, encoding ); return 0; } p = SkipWhiteSpace( p, encoding ); if ( !p || !*p || *p != '=' ) { if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); return 0; } ++p; // skip '=' p = SkipWhiteSpace( p, encoding ); if ( !p || !*p ) { if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); return 0; } const char* end; const char SINGLE_QUOTE = '\''; const char DOUBLE_QUOTE = '\"'; if ( *p == SINGLE_QUOTE ) { ++p; end = "\'"; // single quote in string p = ReadText( p, &value, false, end, false, encoding ); } else if ( *p == DOUBLE_QUOTE ) { ++p; end = "\""; // double quote in string p = ReadText( p, &value, false, end, false, encoding ); } else { // All attribute values should be in single or double quotes. // But this is such a common error that the parser will try // its best, even without them. value = ""; while ( p && *p // existence && !IsWhiteSpace( *p ) && *p != '\n' && *p != '\r' // whitespace && *p != '/' && *p != '>' ) // tag end { if ( *p == SINGLE_QUOTE || *p == DOUBLE_QUOTE ) { // [ 1451649 ] Attribute values with trailing quotes not handled correctly // We did not have an opening quote but seem to have a // closing one. Give up and throw an error. if ( document ) document->SetError( TIXML_ERROR_READING_ATTRIBUTES, p, data, encoding ); return 0; } value += *p; ++p; } } return p; } #ifdef TIXML_USE_STL void TiXmlText::StreamIn( std::istream * in, TIXML_STRING * tag ) { while ( in->good() ) { int c = in->peek(); if ( !cdata && (c == '<' ) ) { return; } if ( c <= 0 ) { TiXmlDocument* document = GetDocument(); if ( document ) document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } (*tag) += (char) c; in->get(); // "commits" the peek made above if ( cdata && c == '>' && tag->size() >= 3 ) { size_t len = tag->size(); if ( (*tag)[len-2] == ']' && (*tag)[len-3] == ']' ) { // terminator of cdata. return; } } } } #endif const char* TiXmlText::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding encoding ) { value = ""; TiXmlDocument* document = GetDocument(); if ( data ) { data->Stamp( p, encoding ); location = data->Cursor(); } const char* const startTag = ""; if ( cdata || StringEqual( p, startTag, false, encoding ) ) { cdata = true; if ( !StringEqual( p, startTag, false, encoding ) ) { document->SetError( TIXML_ERROR_PARSING_CDATA, p, data, encoding ); return 0; } p += strlen( startTag ); // Keep all the white space, ignore the encoding, etc. while ( p && *p && !StringEqual( p, endTag, false, encoding ) ) { value += *p; ++p; } TIXML_STRING dummy; p = ReadText( p, &dummy, false, endTag, false, encoding ); return p; } else { bool ignoreWhite = true; const char* end = "<"; p = ReadText( p, &value, ignoreWhite, end, false, encoding ); if ( p ) return p-1; // don't truncate the '<' return 0; } } #ifdef TIXML_USE_STL void TiXmlDeclaration::StreamIn( std::istream * in, TIXML_STRING * tag ) { while ( in->good() ) { int c = in->get(); if ( c <= 0 ) { TiXmlDocument* document = GetDocument(); if ( document ) document->SetError( TIXML_ERROR_EMBEDDED_NULL, 0, 0, TIXML_ENCODING_UNKNOWN ); return; } (*tag) += (char) c; if ( c == '>' ) { // All is well. return; } } } #endif const char* TiXmlDeclaration::Parse( const char* p, TiXmlParsingData* data, TiXmlEncoding _encoding ) { p = SkipWhiteSpace( p, _encoding ); // Find the beginning, find the end, and look for // the stuff in-between. TiXmlDocument* document = GetDocument(); if ( !p || !*p || !StringEqual( p, "SetError( TIXML_ERROR_PARSING_DECLARATION, 0, 0, _encoding ); return 0; } if ( data ) { data->Stamp( p, _encoding ); location = data->Cursor(); } p += 5; version = ""; encoding = ""; standalone = ""; while ( p && *p ) { if ( *p == '>' ) { ++p; return p; } p = SkipWhiteSpace( p, _encoding ); if ( StringEqual( p, "version", true, _encoding ) ) { TiXmlAttribute attrib; p = attrib.Parse( p, data, _encoding ); version = attrib.Value(); } else if ( StringEqual( p, "encoding", true, _encoding ) ) { TiXmlAttribute attrib; p = attrib.Parse( p, data, _encoding ); encoding = attrib.Value(); } else if ( StringEqual( p, "standalone", true, _encoding ) ) { TiXmlAttribute attrib; p = attrib.Parse( p, data, _encoding ); standalone = attrib.Value(); } else { // Read over whatever it is. while( p && *p && *p != '>' && !IsWhiteSpace( *p ) ) ++p; } } return 0; } bool TiXmlText::Blank() const { for ( unsigned i=0; i$(distdir).tar.gz .PHONY: dist-gzip # FIXME: gnu tar dependency dist-bzip2: distdir tar chof - $(distdir) | bzip2 -9 -c >$(distdir).tar.bz2 .PHONY: dist-bzip2 dist-zip: distdir rm -f $(distdir).zip zip -rq $(distdir).zip $(distdir) .PHONY: dist-zip dist: $(addprefix dist-,$(DIST_FORMATS)) $(if $(DIST_FORMATS),,$(error DIST_FORMATS is empty)) $(am__remove_distdir) .PHONY: dist distcheck-hook: echo $(BUILDDIR) mkdir -p ../$(BUILDDIR)/cpp/build/ mkdir -p ../$(BUILDDIR)/cpp/examples/MinOZW/ cp Makefile ../$(BUILDDIR) cp cpp/build/support.mk ../$(BUILDDIR)/cpp/build/ cp cpp/build/Makefile ../$(BUILDDIR)/cpp/build/ cp dist.mk ../$(BUILDDIR) cp distfiles.mk ../$(BUILDDIR) cp cpp/examples/MinOZW/Makefile ../$(BUILDDIR)/cpp/examples/MinOZW/ .PHONY: distcheck-hook DISTCHECK_CONFIGURE_FLAGS ?= # FIXME: should 'make dvi' in the check. should copy over commentary # from automake. # FIXME: support DIST_ARCHIVES stuff from automake as well distcheck: $(MAKE) DIST_FORMATS=bzip2 dist bunzip2 -c $(distdir).tar.bz2 | tar xf - chmod -R a-w $(distdir); chmod a+w $(distdir) mkdir $(distdir)/_build mkdir $(distdir)/_inst chmod a-w $(distdir) dc_install_base=`cd $(distdir)/_inst && pwd | sed -e 's,^[^:\\/]:[\\/],/,'` \ && dc_destdir="$${TMPDIR-/tmp}/am-dc-$$$$/" \ && $(MAKE) distcheck-hook \ && cd $(distdir)/_build \ && $(MAKE) -C ../ \ && chmod -R a-w "$$dc_install_base" \ && rm -rf "$$dc_destdir" \ && $(MAKE) DIST_FORMATS=bzip2 dist \ && rm -rf $(distdir).tar.bz2 \ && $(MAKE) distcleancheck $(am__remove_distdir) @(echo "$(distdir).tar.bz2 archive ready for distribution" .PHONY: distcheck distuninstallcheck_listfiles = find . -type f -print distuninstallcheck: @cd $(distuninstallcheck_dir) \ && test `$(distuninstallcheck_listfiles) | wc -l` -le 1 \ || { echo "ERROR: files left after uninstall:" ; \ if test -n "$(DESTDIR)"; then \ echo " (check DESTDIR support)"; \ fi ; \ $(distuninstallcheck_listfiles) ; \ exit 1; } >&2 .PHONY: distuninstallcheck distcleancheck_listfiles = find . -type f -print distcleancheck: distclean @if test '$(srcdir)' = . ; then \ echo "ERROR: distcleancheck can only run from a VPATH build" ; \ exit 1 ; \ fi @test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ || { echo "ERROR: files left in build directory after distclean:" ; \ $(distcleancheck_listfiles) ; \ exit 1; } >&2 .PHONY: distcleancheck open-zwave-1.5/distfiles.mk000066400000000000000000000535701264474202400160100ustar00rootroot00000000000000# This File is automatically generated by make dist-update # Any Edits on this file will be lost next time dist-update is run DISTFILES = .gitignore \ ChangeLog \ INSTALL \ Makefile \ README.md \ config/2gig/ct100.xml \ config/2gig/ct101.xml \ config/2gig/ct30.xml \ config/BeNext/1poleswitch.xml \ config/BeNext/2poleswitch.xml \ config/BeNext/AlarmSound.xml \ config/BeNext/BuiltinDimmer.xml \ config/BeNext/DoorSensor.xml \ config/BeNext/EnergySwitch.xml \ config/BeNext/HeatingControl.xml \ config/BeNext/Molite.xml \ config/BeNext/PluginDimmer.xml \ config/BeNext/SceneController.xml \ config/BeNext/TagReader.xml \ config/POP009303.xml \ config/act/lfm20.xml \ config/act/zdm230.xml \ config/act/zdw103.xml \ config/act/zdw232.xml \ config/act/zir010.xml \ config/act/zrp110.xml \ config/act/zrw103.xml \ config/aeotec/alms.xml \ config/aeotec/doorbell_gen5.xml \ config/aeotec/doorwindow.xml \ config/aeotec/drycontactsensor.xml \ config/aeotec/dsd31.xml \ config/aeotec/hdss_gen5.xml \ config/aeotec/hem.xml \ config/aeotec/hemg2.xml \ config/aeotec/keyfob.xml \ config/aeotec/keyfob2.xml \ config/aeotec/ledbulb.xml \ config/aeotec/minimote.xml \ config/aeotec/msesv2.xml \ config/aeotec/multisensor6.xml \ config/aeotec/multisensor_gen5.xml \ config/aeotec/panicbtn.xml \ config/aeotec/recessed_doorsensor.xml \ config/aeotec/recessed_doorsensor_gen5.xml \ config/aeotec/sd6.xml \ config/aeotec/ses.xml \ config/aeotec/ses2.xml \ config/aeotec/ss6.xml \ config/aeotec/watersensor.xml \ config/aeotec/zstickgen5.xml \ config/assa_abloy/RealLivingCapTouch.xml \ config/cooper/RF9505-T.xml \ config/cooper/RF9540-N.xml \ config/danfoss/living.xml \ config/danfoss/z.xml \ config/device_classes.xml \ config/device_classes.xsd \ config/device_configuration.xsd \ config/dlink/dch-z110.xml \ config/dragontech/wd-100.xml \ config/duwi/ZWES1000.xml \ config/duwi/ZWESJ300.xml \ config/enerwave/zwn-sc7.xml \ config/eurotronic/eur_cometz.xml \ config/eurotronic/eur_stellaz.xml \ config/everspring/ad146.xml \ config/everspring/ad147.xml \ config/everspring/an145.xml \ config/everspring/an158.xml \ config/everspring/an179.xml \ config/everspring/an180.xml \ config/everspring/hsp02.xml \ config/everspring/se812.xml \ config/everspring/sf812.xml \ config/everspring/sm103.xml \ config/everspring/sp103.xml \ config/everspring/sp814.xml \ config/everspring/st812.xml \ config/everspring/st814.xml \ config/everspring/st815.xml \ config/everspring/tse03.xml \ config/everspringct/hsm02.xml \ config/evolve/lrm-as.xml \ config/evolve/lsm-15.xml \ config/evolve/ltm-5.xml \ config/fibaro/fgbs001.xml \ config/fibaro/fgd211.xml \ config/fibaro/fgd212.xml \ config/fibaro/fgfs101.xml \ config/fibaro/fgk001.xml \ config/fibaro/fgms.xml \ config/fibaro/fgr221.xml \ config/fibaro/fgrgbwm441.xml \ config/fibaro/fgrm222.xml \ config/fibaro/fgs211.xml \ config/fibaro/fgs212.xml \ config/fibaro/fgs221.xml \ config/fibaro/fgs222.xml \ config/fibaro/fgsd002.xml \ config/fibaro/fgss101.xml \ config/fibaro/fgwpe.xml \ config/fortrezz/mimolite.xml \ config/frostdale/fdn2nxx.xml \ config/ge/dimmer.xml \ config/ge/dimmer_module.xml \ config/ge/relay.xml \ config/greenwave/powernode1.xml \ config/greenwave/powernode6.xml \ config/homeseer/ezmotionplus.xml \ config/homeseer/hsm100.xml \ config/homeseer/hsm200.xml \ config/homeseer/ztroller.xml \ config/honeywell/th8320zw1000.xml \ config/horstmann/hrt4zw.xml \ config/intermatic/ca8900.xml \ config/iris/rangeextender.xml \ config/leviton/rzi10.xml \ config/leviton/vrcpg.xml \ config/leviton/vrf01.xml \ config/leviton/vri06.xml \ config/leviton/vri10.xml \ config/linear/PD300Z-2.xml \ config/linear/WD500Z-1.xml \ config/manufacturer_specific.xml \ config/manufacturer_specific.xsd \ config/mcohome/mhs311.xml \ config/mcohome/mhs312.xml \ config/mcohome/mhs314.xml \ config/mcohome/mhs411.xml \ config/mcohome/mhs412.xml \ config/mcohome/mhs513.xml \ config/merten/507801.xml \ config/merten/50x5xx.xml \ config/nodon/asp3100SmartPlug.xml \ config/nodon/crc3100OctanRemote.xml \ config/nodon/cws3101wallswitch.xml \ config/northq/nq92021.xml \ config/options.xml \ config/options.xsd \ config/philio/pan04.xml \ config/philio/psm02.xml \ config/philio/pst02-1c.xml \ config/philio/pst02-b.xml \ config/philio/pst02.xml \ config/polycontrol/doorlock.xml \ config/polycontrol/keypad.xml \ config/polycontrol/polylock.xml \ config/popp/123580.xml \ config/popp/123601.xml \ config/popp/123658.xml \ config/popp/POPE009105.xml \ config/qees/reto-plugin-switch.xml \ config/qubino/ZMNHAA2.xml \ config/qubino/ZMNHAD1.xml \ config/qubino/ZMNHBA2.xml \ config/qubino/ZMNHBD2.xml \ config/qubino/ZMNHCA2.xml \ config/qubino/ZMNHCD.xml \ config/qubino/ZMNHDA2.xml \ config/qubino/ZMNHDD1.xml \ config/qubino/ZMNHIA2.xml \ config/qubino/ZMNHJA2.xml \ config/qubino/ZMNHJD1.xml \ config/qubino/ZMNHND1.xml \ config/rcs/em52-zw.xml \ config/rcs/pm12-zw.xml \ config/rcs/therm0005.xml \ config/rcs/therm0007.xml \ config/rcs/therm0009.xml \ config/remotec/zfm-80.xml \ config/remotec/zurc.xml \ config/remotec/zxt-120.xml \ config/schlage/BE469NXCEN.xml \ config/schlagelink/itemp.xml \ config/schlagelink/minikeypad.xml \ config/sensative/strips-mazw.xml \ config/swiid/swiidinter.xml \ config/swiid/swiidplug.xml \ config/thermofloor/multireg.xml \ config/trane/TZEMT400AB32MAA.xml \ config/trane/TZEMT400BB32MAA.xml \ config/vision/zd2102.xml \ config/vision/zm1601eu.xml \ config/vision/zm1602eu.xml \ config/vision/zp3102.xml \ config/vision/zs5101eu.xml \ config/vitrum/vitrumBS.xml \ config/waynedalton/WDTC-20.xml \ config/wenzhou/sm103.xml \ config/wenzhou/tsp01.xml \ config/wenzhou/tz65d.xml \ config/wenzhou/tz66d.xml \ config/wenzhou/tz67.xml \ config/wenzhou/tz68.xml \ config/wenzhou/tz88.xml \ config/widom/UBS104.xml \ config/widom/UME304C_S.xml \ config/zipato/MiniKeypad.xml \ config/zipato/RGBBulb.xml \ config/zwave.me/ZME_05431.xml \ config/zwave.me/ZME_06433.xml \ config/zwave.me/ZME_06436.xml \ config/zwave.me/ZME_064381.xml \ config/zwave.me/ZME_064435.xml \ config/zwave.me/ZME_KFOB-S.xml \ config/zwave.me/ZME_WALLC-S.xml \ config/zwave.me/ZME_WCD2.xml \ config/zwave.me/iTemp.xml \ config/zwave.me/kfob.xml \ config/zwcfg.xsd \ config/zwscene.xsd \ cpp/build/Makefile \ cpp/build/OZW_RunTests.sh \ cpp/build/libopenzwave.pc.in \ cpp/build/ozw_config.in \ cpp/build/sh2ju.sh \ cpp/build/support.mk \ cpp/build/winRT/vs2015/OpenZWave.sln \ cpp/build/winRT/vs2015/OpenZWave.vcxproj \ cpp/build/winRT/vs2015/OpenZWave.vcxproj.filters \ cpp/build/windows/GIT-VS-VERSION-GEN.bat \ cpp/build/windows/installer/buildall.bat \ cpp/build/windows/installer/openzwave.nsi \ 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 \ cpp/build/windows/winversion.tmpl \ cpp/examples/MinOZW/Main.cpp \ 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 \ cpp/hidapi/AUTHORS.txt \ cpp/hidapi/HACKING.txt \ cpp/hidapi/LICENSE-bsd.txt \ cpp/hidapi/LICENSE-gpl3.txt \ cpp/hidapi/LICENSE-orig.txt \ cpp/hidapi/LICENSE.txt \ cpp/hidapi/Makefile.am \ cpp/hidapi/README.txt \ cpp/hidapi/bootstrap \ cpp/hidapi/configure.ac \ cpp/hidapi/doxygen/Doxyfile \ cpp/hidapi/hidapi/hidapi.h \ cpp/hidapi/libusb/Makefile-manual \ cpp/hidapi/libusb/Makefile.am \ cpp/hidapi/libusb/Makefile.freebsd \ cpp/hidapi/libusb/Makefile.linux \ cpp/hidapi/libusb/hid.c \ cpp/hidapi/linux/.gitignore \ cpp/hidapi/linux/Makefile-manual \ cpp/hidapi/linux/Makefile.am \ cpp/hidapi/linux/README.txt \ cpp/hidapi/linux/hid.c \ cpp/hidapi/m4/ax_pthread.m4 \ cpp/hidapi/m4/pkg.m4 \ cpp/hidapi/mac/.gitignore \ cpp/hidapi/mac/Makefile-manual \ cpp/hidapi/mac/Makefile.am \ cpp/hidapi/mac/hid.c \ cpp/hidapi/pc/hidapi-hidraw.pc.in \ cpp/hidapi/pc/hidapi-libusb.pc.in \ cpp/hidapi/pc/hidapi.pc.in \ cpp/hidapi/udev/99-hid.rules \ cpp/hidapi/windows/.gitignore \ cpp/hidapi/windows/Makefile-manual \ cpp/hidapi/windows/Makefile.am \ cpp/hidapi/windows/Makefile.mingw \ cpp/hidapi/windows/ddk_build/.gitignore \ cpp/hidapi/windows/ddk_build/hidapi.def \ cpp/hidapi/windows/ddk_build/makefile \ cpp/hidapi/windows/ddk_build/sources \ cpp/hidapi/windows/hid.cpp \ cpp/hidapi/windows/hidapi.sln \ cpp/hidapi/windows/hidapi.vcproj \ cpp/hidapi/windows/hidtest.vcproj \ cpp/src/Bitfield.h \ cpp/src/Defs.h \ cpp/src/DoxygenMain.h \ cpp/src/Driver.cpp \ cpp/src/Driver.h \ cpp/src/Group.cpp \ cpp/src/Group.h \ cpp/src/Manager.cpp \ cpp/src/Manager.h \ cpp/src/Msg.cpp \ cpp/src/Msg.h \ cpp/src/Node.cpp \ cpp/src/Node.h \ cpp/src/Notification.cpp \ cpp/src/Notification.h \ cpp/src/OZWException.h \ cpp/src/Options.cpp \ cpp/src/Options.h \ cpp/src/Scene.cpp \ cpp/src/Scene.h \ cpp/src/Utils.cpp \ cpp/src/Utils.h \ cpp/src/ZWSecurity.cpp \ cpp/src/ZWSecurity.h \ cpp/src/aes/aes.h \ cpp/src/aes/aes.txt \ cpp/src/aes/aes_modes.c \ cpp/src/aes/aescpp.h \ cpp/src/aes/aescrypt.c \ cpp/src/aes/aeskey.c \ cpp/src/aes/aesopt.h \ cpp/src/aes/aestab.c \ cpp/src/aes/aestab.h \ cpp/src/aes/brg_endian.h \ cpp/src/aes/brg_types.h \ cpp/src/command_classes/Alarm.cpp \ cpp/src/command_classes/Alarm.h \ cpp/src/command_classes/ApplicationStatus.cpp \ cpp/src/command_classes/ApplicationStatus.h \ cpp/src/command_classes/Association.cpp \ cpp/src/command_classes/Association.h \ cpp/src/command_classes/AssociationCommandConfiguration.cpp \ cpp/src/command_classes/AssociationCommandConfiguration.h \ cpp/src/command_classes/Basic.cpp \ cpp/src/command_classes/Basic.h \ cpp/src/command_classes/BasicWindowCovering.cpp \ cpp/src/command_classes/BasicWindowCovering.h \ cpp/src/command_classes/Battery.cpp \ cpp/src/command_classes/Battery.h \ cpp/src/command_classes/CRC16Encap.cpp \ cpp/src/command_classes/CRC16Encap.h \ cpp/src/command_classes/CentralScene.cpp \ cpp/src/command_classes/CentralScene.h \ cpp/src/command_classes/ClimateControlSchedule.cpp \ cpp/src/command_classes/ClimateControlSchedule.h \ cpp/src/command_classes/Clock.cpp \ cpp/src/command_classes/Clock.h \ cpp/src/command_classes/Color.cpp \ cpp/src/command_classes/Color.h \ cpp/src/command_classes/CommandClass.cpp \ cpp/src/command_classes/CommandClass.h \ cpp/src/command_classes/CommandClasses.cpp \ cpp/src/command_classes/CommandClasses.h \ cpp/src/command_classes/Configuration.cpp \ cpp/src/command_classes/Configuration.h \ cpp/src/command_classes/ControllerReplication.cpp \ cpp/src/command_classes/ControllerReplication.h \ cpp/src/command_classes/DeviceResetLocally.cpp \ cpp/src/command_classes/DeviceResetLocally.h \ cpp/src/command_classes/DoorLock.cpp \ cpp/src/command_classes/DoorLock.h \ cpp/src/command_classes/DoorLockLogging.cpp \ cpp/src/command_classes/DoorLockLogging.h \ cpp/src/command_classes/EnergyProduction.cpp \ cpp/src/command_classes/EnergyProduction.h \ cpp/src/command_classes/Hail.cpp \ cpp/src/command_classes/Hail.h \ cpp/src/command_classes/Indicator.cpp \ cpp/src/command_classes/Indicator.h \ cpp/src/command_classes/Language.cpp \ cpp/src/command_classes/Language.h \ cpp/src/command_classes/Lock.cpp \ cpp/src/command_classes/Lock.h \ cpp/src/command_classes/ManufacturerSpecific.cpp \ cpp/src/command_classes/ManufacturerSpecific.h \ cpp/src/command_classes/Meter.cpp \ cpp/src/command_classes/Meter.h \ cpp/src/command_classes/MeterPulse.cpp \ cpp/src/command_classes/MeterPulse.h \ cpp/src/command_classes/MultiCmd.cpp \ cpp/src/command_classes/MultiCmd.h \ cpp/src/command_classes/MultiInstance.cpp \ cpp/src/command_classes/MultiInstance.h \ cpp/src/command_classes/MultiInstanceAssociation.cpp \ cpp/src/command_classes/MultiInstanceAssociation.h \ cpp/src/command_classes/NoOperation.cpp \ cpp/src/command_classes/NoOperation.h \ cpp/src/command_classes/NodeNaming.cpp \ cpp/src/command_classes/NodeNaming.h \ cpp/src/command_classes/Powerlevel.cpp \ cpp/src/command_classes/Powerlevel.h \ cpp/src/command_classes/Proprietary.cpp \ cpp/src/command_classes/Proprietary.h \ cpp/src/command_classes/Protection.cpp \ cpp/src/command_classes/Protection.h \ cpp/src/command_classes/SceneActivation.cpp \ cpp/src/command_classes/SceneActivation.h \ cpp/src/command_classes/Security.cpp \ cpp/src/command_classes/Security.h \ cpp/src/command_classes/SensorAlarm.cpp \ cpp/src/command_classes/SensorAlarm.h \ cpp/src/command_classes/SensorBinary.cpp \ cpp/src/command_classes/SensorBinary.h \ cpp/src/command_classes/SensorMultilevel.cpp \ cpp/src/command_classes/SensorMultilevel.h \ cpp/src/command_classes/SwitchAll.cpp \ cpp/src/command_classes/SwitchAll.h \ cpp/src/command_classes/SwitchBinary.cpp \ cpp/src/command_classes/SwitchBinary.h \ cpp/src/command_classes/SwitchMultilevel.cpp \ cpp/src/command_classes/SwitchMultilevel.h \ cpp/src/command_classes/SwitchToggleBinary.cpp \ cpp/src/command_classes/SwitchToggleBinary.h \ cpp/src/command_classes/SwitchToggleMultilevel.cpp \ cpp/src/command_classes/SwitchToggleMultilevel.h \ cpp/src/command_classes/ThermostatFanMode.cpp \ cpp/src/command_classes/ThermostatFanMode.h \ cpp/src/command_classes/ThermostatFanState.cpp \ cpp/src/command_classes/ThermostatFanState.h \ cpp/src/command_classes/ThermostatMode.cpp \ cpp/src/command_classes/ThermostatMode.h \ cpp/src/command_classes/ThermostatOperatingState.cpp \ cpp/src/command_classes/ThermostatOperatingState.h \ cpp/src/command_classes/ThermostatSetpoint.cpp \ cpp/src/command_classes/ThermostatSetpoint.h \ cpp/src/command_classes/TimeParameters.cpp \ cpp/src/command_classes/TimeParameters.h \ cpp/src/command_classes/UserCode.cpp \ cpp/src/command_classes/UserCode.h \ cpp/src/command_classes/Version.cpp \ cpp/src/command_classes/Version.h \ cpp/src/command_classes/WakeUp.cpp \ cpp/src/command_classes/WakeUp.h \ cpp/src/command_classes/ZWavePlusInfo.cpp \ cpp/src/command_classes/ZWavePlusInfo.h \ cpp/src/platform/Controller.cpp \ cpp/src/platform/Controller.h \ cpp/src/platform/Event.cpp \ cpp/src/platform/Event.h \ cpp/src/platform/FileOps.cpp \ cpp/src/platform/FileOps.h \ cpp/src/platform/HidController.cpp \ cpp/src/platform/HidController.h \ cpp/src/platform/Log.cpp \ cpp/src/platform/Log.h \ cpp/src/platform/Mutex.cpp \ cpp/src/platform/Mutex.h \ cpp/src/platform/Ref.h \ cpp/src/platform/SerialController.cpp \ cpp/src/platform/SerialController.h \ cpp/src/platform/Stream.cpp \ cpp/src/platform/Stream.h \ cpp/src/platform/Thread.cpp \ cpp/src/platform/Thread.h \ cpp/src/platform/TimeStamp.cpp \ cpp/src/platform/TimeStamp.h \ cpp/src/platform/Wait.cpp \ cpp/src/platform/Wait.h \ cpp/src/platform/unix/EventImpl.cpp \ cpp/src/platform/unix/EventImpl.h \ cpp/src/platform/unix/FileOpsImpl.cpp \ cpp/src/platform/unix/FileOpsImpl.h \ cpp/src/platform/unix/LogImpl.cpp \ cpp/src/platform/unix/LogImpl.h \ cpp/src/platform/unix/MutexImpl.cpp \ cpp/src/platform/unix/MutexImpl.h \ cpp/src/platform/unix/SerialControllerImpl.cpp \ cpp/src/platform/unix/SerialControllerImpl.h \ cpp/src/platform/unix/ThreadImpl.cpp \ cpp/src/platform/unix/ThreadImpl.h \ cpp/src/platform/unix/TimeStampImpl.cpp \ cpp/src/platform/unix/TimeStampImpl.h \ cpp/src/platform/unix/WaitImpl.cpp \ cpp/src/platform/unix/WaitImpl.h \ cpp/src/platform/winRT/EventImpl.cpp \ cpp/src/platform/winRT/EventImpl.h \ cpp/src/platform/winRT/FileOpsImpl.cpp \ cpp/src/platform/winRT/FileOpsImpl.h \ cpp/src/platform/winRT/HidControllerWinRT.cpp \ cpp/src/platform/winRT/HidControllerWinRT.h \ cpp/src/platform/winRT/LogImpl.cpp \ cpp/src/platform/winRT/LogImpl.h \ cpp/src/platform/winRT/MutexImpl.cpp \ cpp/src/platform/winRT/MutexImpl.h \ cpp/src/platform/winRT/SerialControllerImpl.cpp \ cpp/src/platform/winRT/SerialControllerImpl.h \ cpp/src/platform/winRT/ThreadImpl.cpp \ cpp/src/platform/winRT/ThreadImpl.h \ cpp/src/platform/winRT/TimeStampImpl.cpp \ cpp/src/platform/winRT/TimeStampImpl.h \ cpp/src/platform/winRT/WaitImpl.cpp \ cpp/src/platform/winRT/WaitImpl.h \ cpp/src/platform/windows/EventImpl.cpp \ cpp/src/platform/windows/EventImpl.h \ cpp/src/platform/windows/FileOpsImpl.cpp \ cpp/src/platform/windows/FileOpsImpl.h \ cpp/src/platform/windows/LogImpl.cpp \ cpp/src/platform/windows/LogImpl.h \ cpp/src/platform/windows/MutexImpl.cpp \ cpp/src/platform/windows/MutexImpl.h \ cpp/src/platform/windows/SerialControllerImpl.cpp \ cpp/src/platform/windows/SerialControllerImpl.h \ cpp/src/platform/windows/ThreadImpl.cpp \ cpp/src/platform/windows/ThreadImpl.h \ cpp/src/platform/windows/TimeStampImpl.cpp \ cpp/src/platform/windows/TimeStampImpl.h \ cpp/src/platform/windows/WaitImpl.cpp \ cpp/src/platform/windows/WaitImpl.h \ cpp/src/value_classes/Value.cpp \ cpp/src/value_classes/Value.h \ cpp/src/value_classes/ValueBool.cpp \ cpp/src/value_classes/ValueBool.h \ cpp/src/value_classes/ValueButton.cpp \ cpp/src/value_classes/ValueButton.h \ cpp/src/value_classes/ValueByte.cpp \ cpp/src/value_classes/ValueByte.h \ cpp/src/value_classes/ValueDecimal.cpp \ cpp/src/value_classes/ValueDecimal.h \ cpp/src/value_classes/ValueID.h \ cpp/src/value_classes/ValueInt.cpp \ cpp/src/value_classes/ValueInt.h \ cpp/src/value_classes/ValueList.cpp \ cpp/src/value_classes/ValueList.h \ cpp/src/value_classes/ValueRaw.cpp \ cpp/src/value_classes/ValueRaw.h \ cpp/src/value_classes/ValueSchedule.cpp \ cpp/src/value_classes/ValueSchedule.h \ cpp/src/value_classes/ValueShort.cpp \ cpp/src/value_classes/ValueShort.h \ cpp/src/value_classes/ValueStore.cpp \ cpp/src/value_classes/ValueStore.h \ cpp/src/value_classes/ValueString.cpp \ cpp/src/value_classes/ValueString.h \ cpp/tinyxml/Makefile \ cpp/tinyxml/tinystr.cpp \ cpp/tinyxml/tinystr.h \ cpp/tinyxml/tinyxml.cpp \ cpp/tinyxml/tinyxml.h \ cpp/tinyxml/tinyxmlerror.cpp \ cpp/tinyxml/tinyxmlparser.cpp \ debian/MinOZW.1 \ debian/TODO \ debian/changelog \ debian/compat \ debian/control \ debian/copyright \ debian/libopenzwave-doc.doc-base \ debian/libopenzwave1.3-dev.install \ debian/libopenzwave1.3.install \ debian/libopenzwave1.3.lintian-overrides \ debian/openzwave.install \ debian/openzwave.manpages \ debian/rules \ debian/source/format \ dist.mk \ distfiles.mk \ docs/Doxyfile.in \ docs/default.htm \ docs/general/DoxygenStepByStep.html \ docs/general/GettingHelp.html \ docs/general/Index.htm \ docs/general/MakingDocumentation.html \ docs/general/Notifications.html \ docs/images+css/Doxywizard1.JPG \ docs/images+css/Doxywizard2.JPG \ docs/images+css/Doxywizard3.JPG \ docs/images+css/Doxywizard4.JPG \ docs/images+css/Doxywizard5.JPG \ docs/images+css/OpenZWave.css \ docs/images+css/image003.gif \ dotnet/build/vs2008/OpenZWaveDotNet.sln \ dotnet/build/vs2008/OpenZWaveDotNet.vcproj \ dotnet/build/vs2010/OpenZWaveDotNet.sln \ dotnet/build/vs2010/OpenZWaveDotNet.vcxproj \ dotnet/build/vs2010/OpenZWaveDotNet.vcxproj.filters \ dotnet/examples/OZWForm/CopyFilesVS2008.cmd \ dotnet/examples/OZWForm/CopyFilesVS2010.cmd \ dotnet/examples/OZWForm/README.TXT \ dotnet/examples/OZWForm/build/vs2008/OZWForm.csproj \ dotnet/examples/OZWForm/build/vs2008/OZWForm.sln \ dotnet/examples/OZWForm/build/vs2010/OZWForm.csproj \ dotnet/examples/OZWForm/build/vs2010/OZWForm.sln \ dotnet/examples/OZWForm/src/ConfigurationWakeUpDlg.Designer.cs \ dotnet/examples/OZWForm/src/ConfigurationWakeUpDlg.cs \ dotnet/examples/OZWForm/src/ConfigurationWakeUpDlg.resx \ dotnet/examples/OZWForm/src/ControllerCommandDlg.Designer.cs \ dotnet/examples/OZWForm/src/ControllerCommandDlg.cs \ dotnet/examples/OZWForm/src/ControllerCommandDlg.resx \ dotnet/examples/OZWForm/src/MainForm.Designer.cs \ dotnet/examples/OZWForm/src/MainForm.cs \ dotnet/examples/OZWForm/src/MainForm.resx \ dotnet/examples/OZWForm/src/Node.cs \ dotnet/examples/OZWForm/src/NodeForm.Designer.cs \ dotnet/examples/OZWForm/src/NodeForm.cs \ dotnet/examples/OZWForm/src/NodeForm.resx \ dotnet/examples/OZWForm/src/Program.cs \ dotnet/examples/OZWForm/src/Properties/AssemblyInfo.cs \ dotnet/examples/OZWForm/src/Properties/Resources.Designer.cs \ dotnet/examples/OZWForm/src/Properties/Resources.resx \ dotnet/examples/OZWForm/src/Properties/Settings.Designer.cs \ dotnet/examples/OZWForm/src/Properties/Settings.settings \ dotnet/examples/OZWForm/src/ValuePanel.Designer.cs \ dotnet/examples/OZWForm/src/ValuePanel.cs \ dotnet/examples/OZWForm/src/ValuePanel.resx \ dotnet/examples/OZWForm/src/ValuePanelBool.cs \ dotnet/examples/OZWForm/src/ValuePanelBool.resx \ dotnet/examples/OZWForm/src/ValuePanelButton.cs \ dotnet/examples/OZWForm/src/ValuePanelButton.resx \ dotnet/examples/OZWForm/src/ValuePanelByte.cs \ dotnet/examples/OZWForm/src/ValuePanelByte.resx \ dotnet/examples/OZWForm/src/ValuePanelDecimal.cs \ dotnet/examples/OZWForm/src/ValuePanelDecimal.resx \ dotnet/examples/OZWForm/src/ValuePanelInt.cs \ dotnet/examples/OZWForm/src/ValuePanelInt.resx \ dotnet/examples/OZWForm/src/ValuePanelList.cs \ dotnet/examples/OZWForm/src/ValuePanelList.resx \ dotnet/examples/OZWForm/src/ValuePanelShort.cs \ dotnet/examples/OZWForm/src/ValuePanelShort.resx \ dotnet/examples/OZWForm/src/ValuePanelString.cs \ dotnet/examples/OZWForm/src/ValuePanelString.resx \ dotnet/examples/OZWForm/src/app.config \ dotnet/src/AssemblyInfo.cpp \ dotnet/src/ZWManager.cpp \ dotnet/src/ZWManager.h \ dotnet/src/ZWNotification.h \ dotnet/src/ZWOptions.cpp \ dotnet/src/ZWOptions.h \ dotnet/src/ZWValueID.h \ dotnet/src/app.ico \ dotnet/src/app.rc \ dotnet/src/resource.h \ license/Apache-License-2.0.txt \ license/gpl.txt \ license/lgpl.txt \ license/license.txt \ makedist \ openzwave.dsc \ openzwave.spec \ cpp/src/vers.cpp open-zwave-1.5/docs/000077500000000000000000000000001264474202400144075ustar00rootroot00000000000000open-zwave-1.5/docs/Doxyfile.in000066400000000000000000003021411264474202400165230ustar00rootroot00000000000000# Doxyfile 1.8.5 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # # All text after a double hash (##) is considered a comment and is placed in # front of the TAG it is preceding. # # All text after a single hash (#) is considered a comment and will be ignored. # The format is: # TAG = value [value, ...] # For lists, items can also be appended using: # TAG += value [value, ...] # Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file # that follow. The default is UTF-8 which is also the encoding used for all text # before the first occurrence of this tag. Doxygen uses libiconv (or the iconv # built into libc) for the transcoding. See http://www.gnu.org/software/libiconv # for the list of possible encodings. # The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 # The PROJECT_NAME tag is a single word (or a sequence of words surrounded by # double-quotes, unless you are using Doxywizard) that should identify the # project for which the documentation is generated. This name is used in the # title of most generated pages and in a few other places. # The default value is: My Project. PROJECT_NAME = "OpenZWave Library" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version # control system is used. PROJECT_NUMBER = @VERSION@ # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = # With the PROJECT_LOGO tag one can specify an logo or icon that is included in # the documentation. The maximum height of the logo should not exceed 55 pixels # and the maximum width should not exceed 200 pixels. Doxygen will copy the logo # to the output directory. PROJECT_LOGO = @TOPSRC_DIR@/docs/images+css/image003.gif # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. OUTPUT_DIRECTORY = @OUTPUT_DIR@ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where # putting all generated files in the same directory would otherwise causes # performance problems for the file system. # The default value is: NO. CREATE_SUBDIRS = NO # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. # Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- # Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, # Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, # Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, # Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, # Turkish, Ukrainian and Vietnamese. # The default value is: English. OUTPUT_LANGUAGE = English # If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES # If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. # The default value is: YES. REPEAT_BRIEF = YES # This tag implements a quasi-intelligent brief description abbreviator that is # used to form the text in various listings. Each string in this list, if found # as the leading text of the brief description, will be stripped from the text # and the result, after processing the whole list, is used as the annotated # text. Otherwise, the brief description is used as-is. If left blank, the # following values are used ($name is automatically replaced with the name of # the entity):The $name class, The $name widget, The $name file, is, provides, # specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then # doxygen will generate a detailed section even if there is only a brief # description. # The default value is: NO. ALWAYS_DETAILED_SEC = NO # If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. # The default value is: NO. INLINE_INHERITED_MEMB = NO # If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. FULL_PATH_NAMES = No # The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. # Stripping is only done if one of the specified strings matches the left-hand # part of the path. The tag can be used to show relative paths in the file list. # If left blank the directory from which doxygen is run is used as the path to # strip. # # Note that you can specify absolute paths here, but also relative paths, which # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which # header file to include in order to use a class. If left blank only the name of # the header file containing the class definition is used. Otherwise one should # specify the list of include paths that are normally passed to the compiler # using the -I flag. STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't # support long names like on DOS, Mac, or CD-ROM. # The default value is: NO. SHORT_NAMES = NO # If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the # first line (until the first dot) of a Javadoc-style comment as the brief # description. If set to NO, the Javadoc-style will behave just like regular Qt- # style comments (thus requiring an explicit @brief command for a brief # description.) # The default value is: NO. JAVADOC_AUTOBRIEF = NO # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first # line (until the first dot) of a Qt-style comment as the brief description. If # set to NO, the Qt-style will behave just like regular Qt-style comments (thus # requiring an explicit \brief command for a brief description.) # The default value is: NO. QT_AUTOBRIEF = NO # The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a # multi-line C++ special comment block (i.e. a block of //! or /// comments) as # a brief description. This used to be the default behavior. The new default is # to treat a multi-line C++ comment block as a detailed description. Set this # tag to YES if you prefer the old behavior instead. # # Note that setting this tag to YES also means that rational rose comments are # not recognized any more. # The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the # documentation from any documented member that it re-implements. # The default value is: YES. INHERIT_DOCS = YES # If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a # new page for each member. If set to NO, the documentation of a member will be # part of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO # The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen # uses this value to replace tabs by spaces in code fragments. # Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 4 # This tag can be used to specify a number of aliases that act as commands in # the documentation. An alias has the form: # name=value # For example adding # "sideeffect=@par Side Effects:\n" # will allow you to put the command \sideeffect (or @sideeffect) in the # documentation, which will result in a user-defined paragraph with heading # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For # instance, some of the names that are used will be different. The list of all # members will be omitted, etc. # The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = NO # Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or # Python sources only. Doxygen will then generate output that is more tailored # for that language. For instance, namespaces will be presented as packages, # qualified scopes will look different, etc. # The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran # sources. Doxygen will then generate output that is tailored for Fortran. # The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL # sources. Doxygen will then generate output that is tailored for VHDL. # The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it # parses. With this tag you can assign which parser to use for a given # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, # C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make # doxygen treat .inc files as Fortran files (default is PHP), and .f files as C # (default is Fortran), use: inc=Fortran f=C. # # Note For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. # The output of markdown processing is further processed by doxygen, so you can # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in # case of backward compatibilities issues. # The default value is: YES. MARKDOWN_SUPPORT = YES # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can # be prevented in individual cases by by putting a % sign in front of the word # or globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want # to include (a tag file for) the STL sources as input, then you should set this # tag to YES in order to let doxygen match functions declarations and # definitions whose arguments contain STL classes (e.g. func(std::string); # versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. # The default value is: NO. BUILTIN_STL_SUPPORT = YES # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. # The default value is: NO. CPP_CLI_SUPPORT = NO # Set the SIP_SUPPORT tag to YES if your project consists of sip (see: # http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen # will parse them like normal C++ but will assume all classes use public instead # of private inheritance when no explicit protection keyword is present. # The default value is: NO. SIP_SUPPORT = NO # For Microsoft's IDL there are propget and propput attributes to indicate # getter and setter methods for a property. Setting this option to YES will make # doxygen to replace the get and set methods by a property in the documentation. # This will only work if the methods are indeed getting or setting a simple # type. If this is not the case, or you want to show the methods anyway, you # should set this option to NO. # The default value is: YES. IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent # subgrouping. Alternatively, this can be done per class using the # \nosubgrouping command. # The default value is: YES. SUBGROUPING = YES # When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions # are shown inside the group in which they are included (e.g. using \ingroup) # instead of on a separate page (for HTML and Man pages) or section (for LaTeX # and RTF). # # Note that this feature does not work in combination with # SEPARATE_MEMBER_PAGES. # The default value is: NO. INLINE_GROUPED_CLASSES = NO # When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions # with only public data fields or simple typedef fields will be shown inline in # the documentation of the scope in which they are defined (i.e. file, # namespace, or group documentation), provided this scope is documented. If set # to NO, structs, classes, and unions are shown on a separate page (for HTML and # Man pages) or section (for LaTeX and RTF). # The default value is: NO. INLINE_SIMPLE_STRUCTS = NO # When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or # enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, # namespace, or class. And the struct will be named TypeS. This can typically be # useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. # The default value is: NO. TYPEDEF_HIDES_STRUCT = NO # The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This # cache is used to resolve symbols given their name and scope. Since this can be # an expensive process and often the same symbol appears multiple times in the # code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small # doxygen will become slower. If the cache is too large, memory is wasted. The # cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range # is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 # symbols. At the end of a run doxygen will report the cache usage and suggest # the optimal cache size from a speed point of view. # Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. # Note: This will also disable the warnings about undocumented members that are # normally produced when WARNINGS is set to YES. # The default value is: NO. EXTRACT_ALL = YES # If the EXTRACT_PRIVATE tag is set to YES all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = NO # If the EXTRACT_PACKAGE tag is set to YES all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined # locally in source files will be included in the documentation. If set to NO # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = NO # This flag is only useful for Objective-C code. When set to YES local methods, # which are defined in the implementation section but not in the interface are # included in the documentation. If set to NO only methods in the interface are # included. # The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called # 'anonymous_namespace{file}', where file will be replaced with the base name of # the file that contains the anonymous namespace. By default anonymous namespace # are hidden. # The default value is: NO. EXTRACT_ANON_NSPACES = NO # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all # undocumented members inside documented classes or files. If set to NO these # members will be included in the various overviews, but no documentation # section is generated. This option has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set # to NO these classes will be included in the various overviews. This option has # no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend # (class|struct|union) declarations. If set to NO these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any # documentation blocks found inside the body of a function. If set to NO these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. HIDE_IN_BODY_DOCS = NO # The INTERNAL_DOCS tag determines if documentation that is typed after a # \internal command is included. If the tag is set to NO then the documentation # will be excluded. Set it to YES to include the internal documentation. # The default value is: NO. INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file # names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. # The default value is: system dependent. CASE_SENSE_NAMES = YES # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with # their full class and namespace scopes in the documentation. If set to YES the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. SHOW_INCLUDE_FILES = YES # If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include # files with double quotes in the documentation rather than with sharp brackets. # The default value is: NO. FORCE_LOCAL_INCLUDES = NO # If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the # documentation for inline members. # The default value is: YES. INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member # name. If set to NO the members will appear in declaration order. # The default value is: NO. SORT_BRIEF_DOCS = NO # If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the # (brief and detailed) documentation of class members so that constructors and # destructors are listed first. If set to NO the constructors will appear in the # respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. # Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief # member documentation. # Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting # detailed member documentation. # The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO # If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy # of group names into alphabetical order. If set to NO the group names will # appear in their defined order. # The default value is: NO. SORT_GROUP_NAMES = NO # If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by # fully-qualified names, including namespaces. If set to NO, the class list will # be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. # Note: This option applies only to the class list, not to the alphabetical # list. # The default value is: NO. SORT_BY_SCOPE_NAME = NO # If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper # type resolution of all parameters of a function it will reject a match between # the prototype and the implementation of a member function even if there is # only one candidate or it is obvious which candidate to choose by doing a # simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still # accept a match between prototype and implementation in such cases. # The default value is: NO. STRICT_PROTO_MATCHING = NO # The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the # todo list. This list is created by putting \todo commands in the # documentation. # The default value is: YES. GENERATE_TODOLIST = YES # The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the # test list. This list is created by putting \test commands in the # documentation. # The default value is: YES. GENERATE_TESTLIST = YES # The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES # The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. GENERATE_DEPRECATEDLIST= YES # The ENABLED_SECTIONS tag can be used to enable conditional documentation # sections, marked by \if ... \endif and \cond # ... \endcond blocks. ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the # documentation. If the initializer consists of more lines than specified here # it will be hidden. Use a value of 0 to hide initializers completely. The # appearance of the value of individual variables and macros / defines can be # controlled using \showinitializer or \hideinitializer command in the # documentation regardless of this setting. # Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at # the bottom of the documentation of classes and structs. If set to YES the list # will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES # Set the SHOW_FILES tag to NO to disable the generation of the Files page. This # will remove the Files entry from the Quick Index and from the Folder Tree View # (if specified). # The default value is: YES. SHOW_FILES = YES # Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces # page. This will remove the Namespaces entry from the Quick Index and from the # Folder Tree View (if specified). # The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via # popen()) the command command input-file, where command is the value of the # FILE_VERSION_FILTER tag, and input-file is the name of an input file provided # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file # that represents doxygen's defaults, run doxygen with the -l option. You can # optionally specify a file name after the option, if omitted DoxygenLayout.xml # will be used as the name of the layout file. # # Note that if you run doxygen from a directory containing a file called # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib # extension is automatically appended if omitted. This requires the bibtex tool # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the # search path. Do not use file names with spaces, bibtex cannot handle them. See # also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages #--------------------------------------------------------------------------- # The QUIET tag can be used to turn on/off the messages that are generated to # standard output by doxygen. If QUIET is set to YES this implies that the # messages are off. # The default value is: NO. QUIET = YES # The WARNINGS tag can be used to turn on/off the warning messages that are # generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. # The default value is: YES. WARNINGS = NO # If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. WARN_IF_UNDOCUMENTED = NO # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for # potential errors in the documentation, such as not documenting some parameters # in a documented function, or documenting parameters that don't exist or using # markup commands wrongly. # The default value is: YES. WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return # value. If set to NO doxygen will only warn about wrong or incomplete parameter # documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated # and the warning text. Optionally the format may contain $version, which will # be replaced by the version of the file (if it could be obtained via # FILE_VERSION_FILTER) # The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" # The WARN_LOGFILE tag can be used to specify a file to which warning and error # messages should be written. If left blank the output is written to standard # error (stderr). WARN_LOGFILE = doxygen.log #--------------------------------------------------------------------------- # Configuration options related to the input files #--------------------------------------------------------------------------- # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with # spaces. # Note: If this tag is empty the current directory is searched. INPUT = @TOPSRC_DIR@/cpp/src/ # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # libiconv (or the iconv built into libc) for the transcoding. See the libiconv # documentation (see: http://www.gnu.org/software/libiconv) for the list of # possible encodings. # The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank the # following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, # *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, # *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, # *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, # *.qsf, *.as and *.js. FILE_PATTERNS = # The RECURSIVE tag can be used to specify whether or not subdirectories should # be searched for input files as well. # The default value is: NO. RECURSIVE = YES # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. # # Note that relative paths are relative to the directory from which doxygen is # run. EXCLUDE = @TOPSRC_DIR@/cpp/src/platform/unix/ @(TOPSRC_DIR)/cpp/src/platform/windows/ # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. # The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude # certain files from those directories. # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test # # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). EXAMPLE_PATH = @(TOPSRC_DIR)/cpp/examples/ # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and # *.h) to filter out the source-files in the directories. If left blank all # files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be # searched for input files to be used with the \include or \dontinclude commands # irrespective of the value of the RECURSIVE tag. # The default value is: NO. EXAMPLE_RECURSIVE = YES # The IMAGE_PATH tag can be used to specify one or more files or directories # that contain images that are to be included in the documentation (see the # \image command). IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program # by executing (via popen()) the command: # # # # where is the value of the INPUT_FILTER tag, and is the # name of an input file. Doxygen will then use the output that the filter # program writes to standard output. If FILTER_PATTERNS is specified, this tag # will be ignored. # # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the # filter if there is a match. The filters are a list of the form: pattern=filter # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using # INPUT_FILTER ) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file # pattern. A pattern will override the setting for FILTER_PATTERN (if any) and # it is also possible to disable source filtering for a specific pattern using # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing #--------------------------------------------------------------------------- # If the SOURCE_BROWSER tag is set to YES then a list of source files will be # generated. Documented entities will be cross-referenced with these sources. # # Note: To get rid of all source code in the generated output, make sure that # also VERBATIM_HEADERS is set to NO. # The default value is: NO. SOURCE_BROWSER = NO # Setting the INLINE_SOURCES tag to YES will include the body of functions, # classes and enums directly into the documentation. # The default value is: NO. INLINE_SOURCES = NO # Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any # special comment blocks from generated source code fragments. Normal C, C++ and # Fortran comments will always remain visible. # The default value is: YES. STRIP_CODE_COMMENTS = YES # If the REFERENCED_BY_RELATION tag is set to YES then for each documented # function all documented functions referencing it will be listed. # The default value is: NO. REFERENCED_BY_RELATION = NO # If the REFERENCES_RELATION tag is set to YES then for each documented function # all documented entities called/used by that function will be listed. # The default value is: NO. REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set # to YES, then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. REFERENCES_LINK_SOURCE = YES # If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the # source code will show a tooltip with additional information such as prototype, # brief description and links to the definition and documentation. Since this # will make the HTML file larger and loading of large files a bit slower, you # can opt to disable this feature. # The default value is: YES. # This tag requires that the tag SOURCE_BROWSER is set to YES. # SOURCE_TOOLTIPS = YES # If the USE_HTAGS tag is set to YES then the references to source code will # point to the HTML generated by the htags(1) tool instead of doxygen built-in # source browser. The htags tool is part of GNU's global source tagging system # (see http://www.gnu.org/software/global/global.html). You will need version # 4.8.6 or higher. # # To use it do the following: # - Install the latest version of global # - Enable SOURCE_BROWSER and USE_HTAGS in the config file # - Make sure the INPUT points to the root of the source tree # - Run doxygen as normal # # Doxygen will invoke htags (and that will in turn invoke gtags), so these # tools must be available from the command line (i.e. in the search path). # # The result: instead of the source browser generated by doxygen, the links to # source code will now point to the output of htags. # The default value is: NO. # This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO # If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a # verbatim copy of the header file for each class for which an include is # specified. Set to NO to disable this. # See also: Section \class. # The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- # If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all # compounds will be generated. Enable this if the project contains a lot of # classes, structs, unions or interfaces. # The default value is: YES. ALPHABETICAL_INDEX = YES # The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in # which the alphabetical index list will be split. # Minimum value: 1, maximum value: 20, default value: 5. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 # In case all classes in a project start with a common prefix, all classes will # be put under the same header in the alphabetical index. The IGNORE_PREFIX tag # can be used to specify a prefix (or a list of prefixes) that should be ignored # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- # If the GENERATE_HTML tag is set to YES doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES # The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a # relative path is entered the value of OUTPUT_DIRECTORY will be put in front of # it. # The default directory is: html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # generated HTML page (for example: .htm, .php, .asp). # The default value is: .html. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html # The HTML_HEADER tag can be used to specify a user-defined HTML header file for # each generated HTML page. If the tag is left blank doxygen will generate a # standard header. # # To get valid HTML the header file that includes any scripts and style sheets # that doxygen needs, which is dependent on the configuration options used (e.g. # the setting GENERATE_TREEVIEW). It is highly recommended to start with a # default header using # doxygen -w html new_header.html new_footer.html new_stylesheet.css # YourConfigFile # and then modify the file new_header.html. See also section "Doxygen usage" # for information on how to generate the default header that doxygen normally # uses. # Note: The header is subject to change so you typically have to regenerate the # default header when upgrading to a newer version of doxygen. For a description # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard # footer. See HTML_HEADER for more information on how to generate a default # footer and what special commands can be used inside the footer. See also # section "Doxygen usage" for information on how to generate the default footer # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of # the HTML output. If left blank doxygen will generate a default style sheet. # See also section "Doxygen usage" for information on how to generate the style # sheet that doxygen normally uses. # Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as # it is more robust and this tag (HTML_STYLESHEET) will in the future become # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = # The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- # defined cascading style sheet that is included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the # standard style sheet and is therefor more robust against future updates. # Doxygen will copy the style sheet file to the output directory. For an example # see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the # $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these # files. In the HTML_STYLESHEET file, use the file name only. Also note that the # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen # will adjust the colors in the stylesheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 # purple, and 360 is red again. # Minimum value: 0, maximum value: 359, default value: 220. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors # in the HTML output. For a value of 0 the output will use grayscales only. A # value of 255 will produce the most vivid colors. # Minimum value: 0, maximum value: 255, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 # The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the # luminance component of the colors in the HTML output. Values below 100 # gradually make the output lighter, whereas values above 100 make the output # darker. The value divided by 100 is the actual gamma applied, so 80 represents # a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not # change the gamma. # Minimum value: 40, maximum value: 240, default value: 80. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this # to NO can help when comparing the output of multiple runs. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = YES # With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries # shown in the various tree structured indices initially; the user can expand # and collapse entries dynamically later on. Doxygen will expand the tree to # such a level that at most the specified number of entries are visible (unless # a fully collapsed tree already exceeds this amount). So setting the number of # entries 1 will produce a full collapsed tree by default. 0 is a special value # representing an infinite number of entries and will result in a full expanded # tree by default. # Minimum value: 0, maximum value: 9999, default value: 100. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 # If the GENERATE_DOCSET tag is set to YES, additional index files will be # generated that can be used as input for Apple's Xcode 3 integrated development # environment (see: http://developer.apple.com/tools/xcode/), introduced with # OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a # Makefile in the HTML output directory. Running make will produce the docset in # that directory and running make install will install the docset in # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at # startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO # This tag determines the name of the docset feed. A documentation feed provides # an umbrella under which multiple documentation sets from a single provider # (such as a company or product suite) can be grouped. # The default value is: Doxygen generated docs. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" # This tag specifies a string that should uniquely identify the documentation # set bundle. This should be a reverse domain-name style string, e.g. # com.mycompany.MyDocSet. Doxygen will append .docset to the name. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project # The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. # The default value is: org.doxygen.Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher # The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. # The default value is: Publisher. # This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three # additional HTML index files: index.hhp, index.hhc, and index.hhk. The # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop # (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on # Windows. # # The HTML Help Workshop contains a compiler that can convert all HTML output # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML # files are now used as the Windows 98 help format, and will replace the old # Windows help format (.hlp) on all Windows platforms in the future. Compressed # HTML files also contain an index, a table of contents, and you can search for # words in the documentation. The HTML workshop also contains a viewer for # compressed HTML files. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = NO # The CHM_FILE tag can be used to specify the file name of the resulting .chm # file. You can add a path in front of the file if the result should not be # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path # including file name) of the HTML help compiler ( hhc.exe). If non-empty # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = # The GENERATE_CHI flag controls if a separate .chi index file is generated ( # YES) or that it should be included in the master .chm file ( NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO # The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = # The BINARY_TOC flag controls whether a binary table of contents is generated ( # YES) or a normal table of contents ( NO) in the .chm file. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = NO # The TOC_EXPAND flag can be set to YES to add extra items for group members to # the table of contents of the HTML help documentation and to the tree view. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = NO # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and # QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that # can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help # (.qch) of the generated HTML documentation. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO # If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify # the file name of the resulting .qch file. The path specified is relative to # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace # (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt # Help Project output. For more information please see Qt Help Project / Virtual # Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- # folders). # The default value is: doc. # This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom # filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom # Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- # filters). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To # install this plugin and make it available under the help contents menu in # Eclipse, the contents of the directory containing the HTML and XML files needs # to be copied into the plugins directory of eclipse. The name of the directory # within the plugins directory should be the same as the ECLIPSE_DOC_ID value. # After copying Eclipse needs to be restarted before the help appears. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO # A unique identifier for the Eclipse help plugin. When installing the plugin # the directory name containing the HTML and XML files should also have this # name. Each documentation set should have its own identifier. # The default value is: org.doxygen.Project. # This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project # If you want full control over the layout of the generated HTML pages it might # be necessary to disable the index and replace it with your own. The # DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top # of each HTML page. A value of NO enables the index and the value YES disables # it. Since the tabs in the index contain the same information as the navigation # tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index # structure should be generated to display hierarchical information. If the tag # value is set to YES, a side panel will be generated containing a tree-like # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the # HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has # the same information as the tab index, you could consider setting # DISABLE_INDEX to YES when enabling this option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_TREEVIEW = NO # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. # # Note that a value of 0 will completely suppress the enum values from appearing # in the overview section. # Minimum value: 0, maximum value: 20, default value: 4. # This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 # If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used # to set the initial width (in pixels) of the frame in which the tree is shown. # Minimum value: 0, maximum value: 1500, default value: 250. # This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 # When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO # Use this tag to change the font size of LaTeX formulas included as images in # the HTML documentation. When you change the font size after a successful # doxygen run you need to manually remove any form_*.png images from the HTML # output directory to force them to be regenerated. # Minimum value: 8, maximum value: 50, default value: 10. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images # generated for formulas are transparent PNGs. Transparent PNGs are not # supported properly for IE 6.0, but are supported on all modern browsers. # # Note that when changing this option you need to delete any form_*.png files in # the HTML output directory before the changes have effect. # The default value is: YES. # This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering # instead of using prerendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO # When MathJax is enabled you can set the default output format to be used for # the MathJax output. See the MathJax site (see: # http://docs.mathjax.org/en/latest/output.html) for more details. # Possible values are: HTML-CSS (which is slower, but has the best # compatibility), NativeMML (i.e. MathML) and SVG. # The default value is: HTML-CSS. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_FORMAT = HTML-CSS # When MathJax is enabled you need to specify the location relative to the HTML # output directory using the MATHJAX_RELPATH option. The destination directory # should contain the MathJax.js script. For instance, if the mathjax directory # is located at the same level as the HTML output directory, then # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax # Content Delivery Network so you can quickly see the result without installing # MathJax. However, it is strongly recommended to install a local copy of # MathJax from http://www.mathjax.org before deployment. # The default value is: http://cdn.mathjax.org/mathjax/latest. # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax # extension names that should be enabled during MathJax rendering. For example # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site # (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. # MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and # should work on any modern browser. Note that when using HTML help # (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) # there is already a search function so this one should typically be disabled. # For large projects the javascript based search engine can be slow, then # enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to # search using the keyboard; to jump to the search box use + S # (what the is depends on the OS and browser, but it is typically # , /

Logo Introduction

Purpose

OpenZWave is a library which provides an API for applications to access and control a Z-Wave controller connected to the PC via a serial or HID connection.

Documentation

Although the project is still in too early a stage to produce user documentation, the source code for OpenZWave and OpenZWaveDotNet contains comments that can be converted into HTML documentation.

Instructions for how to generate this documentation, as well as other links to information that may be useful to developers using OpenZWave may be found here: OpenZWave Documents

Project Directory Structure

   
config XML files that provide device- and manufacturer-specific information, as well as the Z-Wave command class codes.
cpp The OpenZWave library project.
  cpp/build Makefiles and Visual Studio project/solution files for building the library under linux, Mac and Windows (VS2008 and VS2010).
  cpp/examples A minimal console application (MinOZW) that can be built under linux, Mac and Windows. It is a useful example of how to start up the library and can be used to generate a log file (OZWlog.txt) to diagnose startup or other problems with the library and/or Z-Wave devices.
  cpp/hidapi Files related to implementation of a "Human Interface Device" (HID) connection between the PC and the Z-Wave controller. While many controllers use a serial interface, others (the ThinkStick, for example) use HID via USB.
  cpp/lib Essentially empty.
  cpp/src The source code for the OpenZWave Library. The top-level code is in this directory; subdirectories contain files to implement the command classes, the value classes and platform-specific code (linux, Mac and Windows).
  cpp/tinyxml The TinyXML class code. TinyXML is used to read and write XML files for persistent storage.
documents Draft documentation for the library and example applications.
dotnet A .NET wrapper for the OpenZWave library.
  dotnet/build Project/Solution files for building OpenZWaveDotNet under VS2008 and VS2010.
  dotnet/examples Code for OZWForm, a .NET application that demonstrates use of OpenZWaveDotNet to connect to a controller, read information about nodes, process notifications, etc.
  dotnet/src The OpenZWaveDotNet wrapper code.
license License documents.
open-zwave-1.5/docs/general/000077500000000000000000000000001264474202400160245ustar00rootroot00000000000000open-zwave-1.5/docs/general/DoxygenStepByStep.html000066400000000000000000000101151264474202400223100ustar00rootroot00000000000000 Creating OpenZWave Documentation
Logo Doxygen Step-by-Step

Introduction

To produce simple doxygen documentation for the OpenZWave libary, follow the steps below.  Once you've successfully produced the base documentation, you may want to use doxygen's Expert mode to customize the output.

Using Doxygen to generate OpenZWave documentation: Step 1

Once Doxygen has been downloaded and installed, run Doxywizard.exe. Here is a screen shot of the first step of the Wizard completed.  

  • Make sure the source code directory points to the OpenZWave cpp/src directory on your system.

  • Select the destination directory of your choice.

Using Doxygen to generate OpenZWave documentation: Step 2

The Mode selections allow you to control how much information is generated and to customize the output for a variety of programming languages. 

You can reduce the amount of documentation generated by selecting "Documented entities only" and de-selecting the "Include cross-referenced..." check box.  If you are using Doxygen to produce documentation for OpenZWaveDotNet, you might prefer "Optimize for C++/CLI output."

a


Using Doxygen to generate OpenZWave documentation: Step 3

The Output step determines what form the generated documentation should take. I generally prefer HTML with a navigation tree, searchable, but others are available.  

a


Using Doxygen to generate OpenZWave documentation: Step 4

The Diagrams step determines whether Doxygen will produce class diagrams.  

a


Using Doxygen to generate OpenZWave documentation: Step 5

That's it!  Select the Run tab, then Run doxygen to produce the documentation files.

a

That's it! You should now have a version of OpenZWave documentation in your destination directory.  Navigate into the .../html directory and load index.htm to display the top level of the documentation.

open-zwave-1.5/docs/general/GettingHelp.html000066400000000000000000000136131264474202400211300ustar00rootroot00000000000000 Getting Help with OpenZWave
Logo Getting Help
With OpenZWave

Need Help?

Since the OpenZWave library is still in early stages of development, you should not be surprised if it doesn't work as you might expect (despite our continuing efforts to stamp out bugs and add features). 

In particular, given the wide variety of Z-Wave devices and the fact that the developers of OpenZWave do not have access to the full protocol, certain portions of the code have not been tested with actual devices, so some problems are (unfortunately) inevitable. However, with more users testing the library with new Z-Wave devices, we should be able to identify and eliminate any faulty assumptions or logical (or careless) errors.

Based on the questions raised in the OpenZWave forum (link), here are some pointers to getting your questions answered.

I.  Generate and Review the Documentation

Although OpenZWave doesn't have user documentation as yet, the source code has been commented in a way that will allow an external program, Doxygen, to produce HTML documentation for the library.  Here is a description of how to generate this documentation.

II.  Isolate the Problem Using the MinOZW or OZWForm Examples

Some users' issues with OpenZWave have proven to be related to either their own (calling) code or a misunderstanding about how the library is supposed to work.  The documentation (see I above) should help reduce misunderstandings.  And reproducing the problem using small changes to the example code will help other developers and users try to replicate the issue.  Once you can reproduce the problem, post a forum message identifying:

  1. The nature of the problem (what's wrong?)
  2. What changes you made to MinOZW or OZWForm to replicate the issue (if they're substantial, you may want to attach the modified source code file(s) to your post)
  3. What hardware is involved (in particular, the Z-Wave controller attached to the PC and the device/node in question)--manufacturer and model number
  4. Where the problem is evident in an OZWlog.txt file (and attaching the log file to your post--see below)

III.  The OpenZWave Execution Log: OZWlog.txt

The OpenZWave library generates an execution log whenever it is run. (The library has been designed to allow this feature to be turned off, but at this early stage in development it should always be produced.)  The log file can be very helpful in diagnosing problems with OpenZWave.  It identifies the startup steps, communication between the OpenZWave library and the controller (and, through the controller, with the various nodes on the Z-Wave network).  It can help identify whether there is a problem with the library, the controller or a Z-Wave node).

So, if you're having a problem, try the following:

  1. Stop the OpenZWave application (if one is running)
  2. Locate and delete any copies of the zwcfg*.xml file. (The actual file name will have the Z-Wave network's HomeID in place of the '*' in the file name.)  This will cause the OpenZWave library to identify each node on the network as "New" and poll each device for its capabilities, settings, etc.
  3. Run the application using OpenZWave until the problem occurs.
  4. Exit the program and review the OZWlog.txt file that was created. Are there any unusual errors on startup?  Do the Z-Wave devices report the capabilities (command classes handled) that you expect?  Do the static, session and dynamic values look right?  Can you identify where execution went "off track" (sent a new command? unexpected response received? no response received to a command?)?
  5. Review of the log file may help you identify what went wrong with your code (or what's wrong with the OpenZWave library).
  6. If you can't figure out what's going wrong from the review of the log and the other suggestions outlined on this page, consider posting a message to the discussion forum and attach a copy of the OZWlog.txt file.  But keep in mind, it is often very helpful to have a "clean" log file to work with...one that shows the nodes in the network as "New," and not as "Known."  (See Step 2 above.)
open-zwave-1.5/docs/general/Index.htm000066400000000000000000000033641264474202400176130ustar00rootroot00000000000000 Other OpenZWave Documents
Logo OpenZWave Information

The following pages provide additional information about the ZWave protocol and the OpenZWave library.

General

Getting Help with OpenZWave

Generating OpenZWave Documentation

OpenZWave Architecture and Use

Notification Messages and Sequence

The Z-Wave Protocol

 

Z-Wave Devices

 

External Links to Other Z-Wave Information

 

open-zwave-1.5/docs/general/MakingDocumentation.html000066400000000000000000000070271264474202400226600ustar00rootroot00000000000000 Creating OpenZWave Documentation
Logo Creating OpenZWave
Documentation

Introduction

OpenZWave is still under development, and new features, bug fixes and interface changes are being made on a frequent basis.  So it's premature to focus too much energy on producing user documentation at this point.  However, several users have asked whether there is documentation available.

So here is a guide to producing your own version of the documentation (such as it is).

Doxygen-style comments

Much of the source code for the OpenZWave library and the OpenZWaveDotNet wrapper has been documented via comments in the .h header files associated with these projects.  So, if you're working with OpenZWave in a development environment (which most users will be, since only source code is available at this point), you can find many functions documented in these files.

The format of the comments is designed to allow an external program, called Doxygen, to produce documentation (for example, a series of .html files) by scanning the project files, interpreting these comments and producing the .html code to organize and display the documentation in a sensible manner. So, to produce the most up-to-date copy of the documentation, a user can run Doxygen on the project folder in question (OpenZWave or OpenZWaveDotNet).

Getting and Using Doxygen

The Doxygen program can be downloaded from http://www.doxygen.org.  Versions of Doxygen are available for Windows, linux and Mac operating systems (as well as source code).

Once Doxygen has been downloaded and installed you can produce documentation by running Doxywizard.exe.  If you're new to Doxygen, here are some step-by-step instructions for creating OpenZWave documentation.

Other Documentation Sources

In addition to the documentation that can be generated with Doxygen, there are a variety of other sources of information on OpenZWave and on the ZWave protocol more generally. Some of these are linked here.

 

open-zwave-1.5/docs/general/Notifications.html000066400000000000000000000322061264474202400215260ustar00rootroot00000000000000 Notification Messages and Sequence
Logo Notification Messages
and Sequence

Purpose

Several questions from developers using the OpenZWave library have suggested confusion about the meaning of notifications sent by the library. This document is intended to clarify and document the notifications sent by the library and to indicate what information is “known” at the time the notifications are sent. This will, hopefully, assist developers in designing the actions to take upon receipt of each notification.

Important Note

You should be aware that notifications are blocking. That is, when a notification is sent to an application, the OpenZWave library will wait until the callback function returns. So, for example, if you put a modal dialog box (for Windows users) in the notification handler in your application, OpenZWave will essentially stop communicating with the Z-Wave controller until the dialog box is dismissed and the notification handler returns.

This "feature" may be changed in the future, but for now developers must be aware of this issue.


Format

The table presented below lists notifications in the order they might typically be received, and grouped into a few logically related categories.  Of course, given the variety of ZWave controllers, devices and network configurations the actual sequence will vary (somewhat).  The descriptions below the notification name (in square brackets) identify whether the notification is always sent (unless there’s a significant error in the network or software) or potentially sent during the execution sequence.


Driver Initialization Notification

The notification below is sent when OpenZWave has successfully connected to a physical ZWave controller.

DriverReady
[always sent]
Sent when the driver (representing a connection between OpenZWave and a Z-Wave controller attached to the specified serial (or HID) port) has been initialized.

At the time this notification is sent, only certain information about the controller itself is known:
  • Controller Z-Wave version
  • Network HomeID
  • Controller capabilities
  • Controller Application Version & Manufacturer/Product ID
  • Nodes included in the network

Node Initialization Notifications

As OpenZWave starts, it identifies and reads information about each node in the network. The following notifications may be sent during the initialization process.

NodeNew
[potentially sent]
Sent when a new node has been identified as part of the Z-Wave network. It is not sent if the node was identified in a prior execution of the OpenZWave library and stored in the zwcfg*.xml file.

At the time this notification is sent, very little is known about the node itself...only that it is new to OpenZWave. This message is sent once for each new node identified.
   
NodeAdded
[always sent (for each node associated with the controller)]
Sent when a node has been added to OpenZWaves list of nodes. It can be triggered either as the zwcfg*.xml file is being read, when a new node is found on startup (see NodeNew notification above), or if a new node is included in the network while OpenZWave is running.

As with NodeNew, very little is known about the node at the time the notification is sentjust the fact that a new node has been identified and its assigned NodeID.
 
NodeProtocolInfo
[potentially sent]
Sent after a nodes protocol information has been successfully read from the controller.

At the time this notification is sent, only certain information about the node is known:
  • Whether it is a listening or sleeping device
  • Whether the node is capable of routing messages
  • Maximum baud rate for communication
  • Version number
  • Security byte
NodeNaming
[potentially sent]
Sent when a nodes name has been set or changed (although it may be set to or NULL).
ValueAdded
[potentially sent]
Sent when a new value has been associated with the node.

At the time this notification is sent, the new value may or may not have live data associated with it. It may be populated, but it may alternatively just be a placeholder for a value that has not been read at the time the notification is sent.
NodeQueriesComplete
[always sent (for each node associated with the controller that has been successfully queried)]
Sent when a nodes values and attributes have been fully queried. At the time this notification is sent, the nodes information has been fully read at least once. So this notification might trigger full display of the nodes information, values, etc. If this notification is not sent, it indicates that there has been a problem initializing the device. The most common issue is that the node is a sleeping device. The NodeQueriesComplete notification will be sent when the node wakes up and the query process completes.

Initialization Complete Notifications

As indicated above, when OpenZWave starts it reads certain information from a file, from the controller and from the network. The following notifications identify when this initialization/querying process is complete.

AwakeNodesQueried
[always sent]
Sent when all listeningalways-ondevices have been queried successfully. It also indicates, by implication, that there are some sleeping nodes that will not complete their queries until they wake up. This notification should be sent relatively quickly after start-up. (Of course, it depends on the number of devices on the ZWave network and whether there are any messages that time out without a proper response.)
AllNodesQueried
[potentially sent]
Sent when all nodes have been successfully queried.

This notification should be sent relatively quickly if there are no sleeping nodes. But it might be sent quite a while after start-up if there are sleeping nodes and at least one of these nodes has a long wake-up interval.

Other Notifications

In addition to the notifications described above, which are primarily initialization notifications that are sent during program start-up, the following notifications may be sent as a result of user actions, external program control, etc.

ValueChanged Sent when a value associated with a node has changed. Receipt of this notification indicates that it may be a good time to read the new value and display or otherwise process it accordingly.
ValueRemoved Sent when a value associated with a node has been removed.
Group Sent when a nodes group association has changed.
NodeRemoved Sent when a node has been removed from the ZWave network.
NodeEvent Sent when a node sends a Basic_Set command to the controller.  This notification can be generated by certain sensors, for example, motion detectors, to indicate that an event has been sensed.
PollingEnabled Sent when node/value polling has been enabled.
PollingDisabled Sent when node/value polling has been disabled.
DriverReset Sent to indicate when a controller has been reset. This notification is intended to replace the potentially hundreds of notifications representing each value and node removed from the network.
open-zwave-1.5/docs/images+css/000077500000000000000000000000001264474202400164405ustar00rootroot00000000000000open-zwave-1.5/docs/images+css/Doxywizard1.JPG000066400000000000000000002042731264474202400212370ustar00rootroot00000000000000JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222B" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?.UM<;iOkVFv s'1XZx"oM4 -S[0 ҽ3:e,c{%nqTԓR۹Ko)R|Ш'*'u>'''zط4wzљ-6Z7 }\aO_ƺΔk=}/xJ^f__m~QϝFōGj.#,08!p1H^%<љbQ zWW5>̱ߡG_m~Wm/PIfnVH#eC pw0\h\p,~d G4sSٿ2o( ?;o* 4J+e&vewF g݅({ih=phN oJ/B( ]OU o4DuM=SFOѴA.ԍH9''vsbU趢l׮o4g_m~Qϝ=tI̿؏h|>\n:G'ԴKV\%ĎeGcrjc({Dӿ[5-E.V"_m~Qϝ]F(`]>83>WipqIԢRiivWp``qO[S'ҋ|УJ/BӼ)ZzRөaPdp;gԁި.7>˶%go!CjUJM~VcJ/B( =#Rŧ]Re` ݌c ֏vQߡQͥ4 }RYv堆-U>{J|s'D:-QX|DFo9zVF;T˷㱟ߡG_m~YuQeisUN*RъtefOߡG_m~A6[>w %A9 9)蚬"!1 ngtzUsSr%ҋ|УJ/BE\Z=6W2[!!H2A`009UfF/wϩM*AnBlf)ӋIݾcT( ?;o*֣[:Fwu??mI:u$NeFIerfǟ&VznϽJj;YӋ|УN/BDe$G^ XntJhYYK4KuLY|>(JQ}I7N/B8 }Mox+n`o0@*VuE6ͦ^ Fݴ33iSKߡG_m~C64i2z$py}j9{XoRLBFM8={6;o(Ӌ|Ше{sJ'w8299ZkF?r)Re J+q#vTi:C>uQeisVo4 k+}HQSӵRo_m~qϝVMYg!(>*φ5k]/MSX@17WG:qvm\)5ur?8 ?;o)_5hG%įFCFXE&Ѭl-&Ԥ{T[my0.pcYʽE_ r\b8 ?;o*^r-:}ԟj}v|M"\FM:o{7ZӋ|УN/BDa]2'&9O~tu/$M>鮢 rR槽{9y?;o(Ӌ|Щ k:Cc:e h䉃 ,ݗ*M#Ɵ2bY=K'<Qz0MKK~;=I4z_8 ?;o*IY4OKes$/3e dhNFm#8U=Teɿ;o(Ӌ|Ш&uy}>)n1灴QҜ\2ukk8$6YAZj}lN/B8  J\_*v ǯ9|"=.Ztn7dc#<9s0Lok~>gN/BJ/B.~j"Y7Ky}q^:Ҷ$D+$8;cE7Xҋ}-УJ/B׶_,-ܞtlV˫=rM9n9'H`$́d7xu){QM!ҋ}-УJ/BjӼCi6j b$14j gOf[אK5D3#2ԁJqSVÕEYҋ}-УJ/B{^Ig:Zړll`{Wҭ_ڋ%$)=(s{TAQϥiE>US·~ca 7ww6޴1Xm dmYFDIi'+tp} *2QϥiE>T2ڜmrL8`]>P86%ܶx!**pA8ߙ7_k~QϥVm:+"T*?БTz>aNB i{7MZߡG_k~h?V;˻ƊKXwG)(7;vU.=p^ŨZPq q$iTD_QϥiE>Tj1e&trR>5/$M>鮢 rVׇtgߙ?_k~Qϥ-%_RvȑGVYD׭^VvoM6ݑǍ௾3X1,=#2( ?K_*]bkAK(WǞ͓/7wYW]6Sωw#tҩ;_b E( ?K_+3cڶF|Uis`4C${ԇF[]/ vVŕX7Wp>ӭZ{%Ԣo*X[X`IIcힵf=StJ &?*y`_)  oWMNy!gi# GcJت'gc7N0o9TX},[BFzqךTEVW4#E'd\VtJ2rm[OU= ibsn>  _?WwdAtсlX|c K!&Zd%P M,negGpܒi y[E]k"AuSEgԾ#_?Ȋ?/ͷ2gns oO8.޼_r<&lK,EJwI;=#Qo$#F2'!tqWۋd kzZ}D\q_Gf/***?}UFKyjbi_323,E|裠um" qv]f;yIW@g;9 f >i1u02JJ;j53qƤ'枟M/Sw%͔ڞPF7%Qa+xvqu5$,V &iWqךL_Uxbg-emM3wO_GFo,smn^XI-mHWԠHG.L_ypD[;TArx+N&KIjymAQAOb";IPʩr\󣄔w>-Fur=M #z}\7䶲P@+<q\ׄ)a]Ll6J`n8 L_Uu9j$y8{?/-&_h:oŴ֍:eT*0V#= [Qu>#9#1ۡmFT{?oQG&/**JJVU'}gV5e9K͉Жe1l]ܞ;KxM/#fmϒkL_Uxb骪KߐI57M_4c3~L]c[r3h^ k±Iv[hBȐ ^]B]팞Yxb#ſ?YJtٯu$U1][d Ayܹ1lՎH曣xO|5w -Qr2?zcG&/*B<[@s1TO.YKsj~` K˗ۦA:x'*3j7ojOڼLاf L_Uϛ_.51~_szoi%Xı$\Wu[}ZhΚGX"JolZxb#ſ?][)H+nGGgGg̈́O..c> x F+.]j+qkת ^[f+}'L*st>ߵō7p4xb⫑< mʲTݟkĖvMk2[MiWE`ҫ; @f_x]N0[?9;񌏿$A8V5StB<[@s1T pܹe.SŨ_W$F=S+0殝nkkCj6y\+᳴!/%m'k{Y`_,Fg%I_*!-9?oVpE햷KRW%ogۣkY;6s6qo<H#MNgWagoi-xME[rG$2&Te, $_ -1?oQr5핝m~o#]vt.{ 1E7#<A[@c1T ^k |MK5%M2|Ѯ6K+ ^X|;iDlJH#F8!8&_w,ř"XI$IyR˖>Y_+5qJn4cuk=[D絞yiۗb;HL3 ֬kVh/IkͶyvH` *~m Uſ?G -1//VT<ػ{7}3j%ޔ{iigj69xܱߎWSKt/k=,^I)qb69݃1ޤſ?G -1px5%]]u`IY4k#ZݴY6rR>9b xKKI P\0"2dp 8bſ?J?PU}[uIt=?/5&//Ak+Fi#* j[hw)npj$Vhh}2ѭ^L fst}j -1?oT{,*Eo}\g}%ЋrItj\ KT7jxF٫o퍓2͕*7s֪ L_U>Lu_^k'"\Yi>д|Q ƱC .. ך uqQſ?G -1#O/\֟BuqmɅ=P᤻eC:aP3c= ^|Oc6YŎ 7D|ToQ? &/*Q˥U{ۮ>boɗ5G\SZ: &y2'av<`FmhBw}Dj z.qUO9!9Tof/*A[@o6ܫ'w_$쭱7դR^@4դԮ<1]%c\eF0+*XQTg6"Nn˿!nW &bſɘ! 1]Jx;?t7+˫xmIf,;dCP7=Q5&̛ ] |Zg -7LQ? 1U4eYi*uqޟIyiwm0*Vmni\'S,n|Wmg{a.e?@~>RxUOA[@o&bKeUG6-Zwj^-. BmGWg@6 :fvD5Qb!ܥTRI=A[@o&b%K.Il^_B\ck{y3W×ˤi:{}2i/,oearDlv#<k6Oh_YvFP,ʾQB|= aH_J̋`|ngsR7pmg;`C[*ZxYI5}:=ZV5RRR,xZӤQh*,j92 /!k]xVzޜy9X [r=bU@`s/ -7LV$-?ŷ?j_ծQj5>#[f< l1HҴ!u? 閌P])hJ͵X0$yⰿof/*5MmY!r0p8&8Bv(Υ*o~/{iv6V]GoZK}J2|P%p~n*?H>Ӯ;F8e[YM@͏>I< XE¨E*w -7LPe˫N/== 7ִè,7ZIm9Të1)HW+;:ԣoZu2-LE d3of/*A[@oK(:ɧMn3rK{X~Zj:wgY10՗ *$+ 1gYki6QB\7-bhFp{/XI= U?A[@o&bQY.W^^w槺6^Ey!h lf`nw>[[G$ImpyIG9 qſɘ?of/*V; hg֔k[˧ko\<b$A'+jW7&@%RL9;nq6weWsڣEKe[c>gڭ}1&;#9C+YwwbK$A#3lpkҼuma^jǴ8~_cr~o _,tFkI?g>mՂMv 1jc)&Fr\ ^N fDp'u򲭇_ܯz~-'P&q,KyH0K('"Dy`e\q.ZD U3_<]XyN?m_gs&ڽX\Adt6?+eO2ȳ3僩`!O!M㿴KVe< q8 :w=QѴҴ,仚DZi ,Fpf 8ɽHf43^K/6ZqWIRl},ӼzW4FMB{Ee \PNt|zTsX-wi[99qqߎ_LwmOIQKq.Fb#B"SF_ ^/xƖ:};3[4#J[$IW x7RItۋ1ooWdJpywT;QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEr?@>ԯ_־"F|}/y|v9ci"C̞ק}_O&xAKӭi<HyO䍰_?͉i?>/|L4M7_ݦdIe(>GcV:fgS5bxm㸷%Ueu# 8 ٥h4?MCkzNjjvV>n|\$[qG*W4?MfgSF}f;F̹y|&i][ Ie@J(` 7 Mi?>/|V*jvJcs;E *,o*G^(fgS5bi?>/|V* {Vk6F8' ՙG'٥h4?MH'eC2*FnUbB:J}Ҥ fgS5biڝg݅O 8+Eu<*ppp€i?>/|V*1٥h4?MX+_O&K?)#ԭeԥw{Wtbb/vgv8[ fgS5bi?>/|J5ɛbIL˅9ɍ/qOx20 28 @_O&K?)^[6֒y1,>܌h%ԦF ʌyP}_O&K?)Պ(٥h4?MX+_O&K?)Պi@Je@B$;Gi?>/|PZ͆lttK-ƒHPE^ fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V(?$2'56k\0x |xk/ HjW˭־%sO>KgCx-~m5Ě28{yV'(N0QrG _<5!rשד~HB nKHŨ Z}%e 貼otcib5rbUPP*(sjlRfQaor|p""@ :H"y"Gx[|l F\CaBGzt@sI @~id{]+!ٌ[V O :)aH&c Հ;2=[# r&wJ}M5U(,[{Q!s8$pϠ˫ɬM%iclMDa9 2Ф1$hY(xI$E(8{{\?yvL˝dry|€82֝{%M\i3Y4|j`$'uE bO cZo\2MsiDѺtWVR4,UYf_&>"[ ̋LPhD%"艚;_!з@M-֋u6-jKTU/l>H#B(\W.OQEkkZ#@.Ugfh(X~]f5*lZ:IˮĖwKKl 5 +EZڐzTk [[}BжA2 r=۾a?*o;7PYʗ,zйGt7/<ˌW`_k>i 5VkuaA+$%YcP82:F!vW;[?y?l?Z][\}2]AD-nJٮ|ZY&iB$Dq9W7|C 3!<*^OEYG-<\UWK=*MFkCsHiG.v91+4jumqu8*fkdk$򪝥$h\7:>\ߑs-Xm{UV=]1%YE@Zs$k,7hrݙX{*-<\Uy\^ H#K+f}l.k̟ۖPۜe ΟΎYAZ318bUj>+c7ڭpy,n.T,RTC\FIǘIvGO鶶\M,0DKQ@$sEiB&vDy. l( +]nעuYK^hg02]IˉI[p@Oi1jWQZsQqӬ~";S H8vGaǠ6q }FQyT6*g{gO?/\bMkMgynM*E Ulk:ψ .佻MD.X0lט̢, 7MifTFA6#&J3Z@]ܝ'yķ-Ve&bn c>Lw\,UbnmJ?skZ2Jmޫ.?=._*|%oXkQZZ&{EPr=~oRTG.4oi|uh\K ts(>\ߠ ڟlnt},%XA"F1q# /radnbQgO?/^+}tYD?f/07n67/oC(+{kj:m4"6Lt[8٥9$S诗,͸V7ʎ\)rcWc:;|s\i%Ը/S|(gK>RG۟K[.e|k by_ 'f$ #ҵkY.de~0[+|qXų 3T/D.@U[&b X\gⵚ7(2}=adtضrTbW:m28n|xy.$e`ќ""p7?xTbWM5̦e\I USI,Tų ._*}*StMux47F"#bR5A=adgbQgO?/ZQvF-<\UضrUEadgbQgO?/ZQvF-<\UضrUEadgbQgO?/ZQvF-<\UضrUEadgbQgO?/ZQvF-<\UضrUEadgbQgO?/ZQvF-<\UضrUEadgbQgO?/ZQvF-<\UضrUEadgbQgO?/ZQvF-<\UضrUEadgbQgO?/ZQvF-<\UضrUEadgbQgO?/ZQvF-<\UضrUEadgbU#ZKV|'~UX?Ф-QDfHI'2TsgA{` $ʪ($&s~:Jj};\Ţp\` lI$9B_qT~\kݷ-n/?eԢMM)9<|{RI.Ǣ%{SR&O5mXYO<ma`,Ky wiJn;YQ9/mB]A%,ڕ,f Q.WQT|gqKg4קvNFg̍epF7dqϣ+Î)s˸rDZGڗ nTXk mOVJ71$݃k\'>2?F\P]B5c+?:/}#ȃ}"ѩ_.?ZLQ9+6{?܇^0Mm4(\PAF^zW| CuNمG#\Gʕds{;Տ+tW/[S?QGa/[Sd)eg*1>$$}{Fi_ϕ7J|)E<[[qq*E J^I$`I$xm㸷%Ueu# 8 {FWmM9.fx^]24mrfQr>Vn+t3p$@̅apAv =R_+u[]2N U$';n>(9Eҿ+o o7Qusuo-ƙe4I#rF ǂ(9Eҿ+o o7G[SJ(9FMusr',@^r2e<0Ri_ϕ7hÔ_+ti_ϕ7)^TTwHl8e8 (9Eҿ+o o7Qusuo-ƙe4I#rF ǂ(9Eҿ+o o7Q{, eRJ| 1OhÔ_+ti_ϕ7+x-IaC$l]H #IGa/[S?ROOI*##V` `z+z{Q \!xeI3!d`@e%XqA"hÔJ|)G=ռeJ$I+ #S0J|)WmM(0J|)G ͲL IʂŘRĒ{M>=Q>VnxxIQf][Xڤ0*M\cKB* G}\m xb [x(`GsTP0<x<ҤhYP39IRQr>Vn+tQr>Vn+tQr>Vn+u&{u ȪaU H*=JhÔ_+ti_ϕ7($TGFl8V80%ҿ+o o7G[SJ(9Eҿ+o o7G[SJ(9Eҿ+o o7G[SJ%JgVuʤ u \ۇч)/[S?QGa/[S?QGa/[S?QGa/[S?QGa/[S?ROOI*##V` `z+z{T{Fi_ϕ7J|)%G\qo*K 9#`FApA9I>Vn=Q>Vn=Q>Vn=Q>Vn=Q>Vn=Q>Vn=Q n&xtiT,s5VS5 v}BůbHEt1|^_kǫ^~Ӻ/fdl-__=GίBկEvÕ2?ugWjעh~a: WQеkG]0}̏_kǩt/d;oi̇qH2c=+ZKXuW?:/}#ȃ}"ѩ_.?ZQ86{?܇]b"³AZfd̡ `7 2+s Cu>_6|6y}ܖ7je(tX-I"1% gK "./<]e-DPmG˴rp^P\YMk4S4'$mrv+ʹsgWo섯B 8YU ʢ2IlMG4{[xQpֺnmx:(}CgѺO7;]|yAv qui@ywVnWnU. uE./ukxr;f,^WkyEݗ߱Æ)5IB^ʰ[j5W8p(P30n3:;;}>-gĒrY嘒IbI$I&qQ ,b%a!E<Ӎm㗾N4y.SKvO9܀[8@d e[:j-< l-l/J !V]y>\5e QM^4[n)$c5ZGh4& Bt}=&p ,I'%Y$$I$h-͝kS]@ŅB7+,6qITqY7  q?5kU#R}qiI,aO'pRGwN'W^Ѭ) Mes{@$(qsTkټ<d_ZN1弖Xiĭ /˹Qp<ZZݭ em"HW{go\[\ʙ#r0 G^SuQq*.H 0w3q>}p\ZUuߧ!e&Pr@Ŏ=N.\xcGxOEtWvrBv GS_:kl/( 0)JeH# ѫݍ`aHSVr!>|Q#?+n( 0RԜ<X&Hp&4@,!At^źm6/XMԌ$R)&\9 SLY\mbϘp(_A\>bO-jfNڬpGnY-&̅A ]+W7sAszW&[ ~$w$`ARqs5#%" 1Fܬ ;N(g5F%Ծ$ >m?܃ (dF 7ƂIolS\xK%et!Z2@Hl샕L(aR?u(!s3m"ٗvef׾&U4?[xEE$=*Yo81WmEί5W8p(P30n3;:(,I]1fy%GtH xזF` r(Fʒz?nmUmZzݴ8"MGF.u[77Wzu-NY|罸UXţ5T',R)%ݵ/2K. ʟh_1wlf*|ܸp޿smIka5;+k]7#4ée܄cO^Z6k h[HMa$0є0U+H^ -Ώgy I!۲3q'9V1n!/Qtc{.5`&阮՜mDg0<{.FۯZkzuCPټt $Jf(Uy~\%ӧaX%cgr,&C3e%Y5kU#R}qiI,aO'pRGwN'p[-kP]^;Ad΄+FH) ݐrnsZlVҭ(<ne`P%mt#'fSǦnm 'T.rNhxVԧ<0G F>qlqBIX2`H>ELeQcK/؁ln3=2.œi:T3^"md[xHfi%e(U3dW{&_}SXe].X&;bڪAaXrHV \>M^W4MyuR. |y068a×A{\ȬrAQu{Z襣?R0^m.kI㾕D!fS>`o.6zڝRV[RSwSo vŞww/$A-eծ]q,h+ #'"UV&t]o7U!ce Yu_`o.^\,:y?][^OwQ|.u4O_Pu{Ƹ[#$fG!oPP66K9Et_ nφَwCm;s'=h]]GLȔJVM=eڒ"CWvsKfXύ_+g7DW>ǻLclc_cjAROuc%ƒeo&m)K|Ia>6KsD,x$MgrNa~d"ߕY̰oGeߥ |?%j5qZĚ|>Ϋ`C(6 /Jؑҗ2|mٖm~)sDve;3[?J1YA8wb; ͵e 3K)f,DžI$L̰oGeߥ 9dP\lrڣk_w4KfXύ_X+Z k<._&a>6KCֿ%hZ fXύ_2|m^Cֿ%hZ fXύ_2|m^Cֿ%hZ fXύ_2|m^Cֿ%hZ fXύ_2|m^Cֿ%hZ fXύ_2|m^Cֿ%hZ fXύ_IG-'R{Ŀk_w4}KѥưKT0m(+v /Gx]$MmO٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OIt71\&pTzB+fSC:tO2JGTER]o~uO_5+_Q?' |y/9ku$>/9ku$/8W0+Z^i6o{akr6H4*UW#Â; sz:tE"[Qm)P|9rP 2Ѽٿ/`]FKkSk 29Ҽu+Cj)(c-E>zaU\' Ĥj NHM}+b<.Ln&˂xV[L3)>焿ɢY} G4EVY&/h[gxK|>焿ɠ 4Uo/hY&,U焿ɣgxK|EVY&/h[gxK|>焿ɠ 4Uo/hY&,U焿ɣgxK|EVY&/h[gxK|>焿ɠ 4Uo/hY&,U焿ɣgxK|EVY&/hEsG<%M5< a €%_S֭0ZSO5nVvJxM.lkQ.OtcN JudJӼw"4V{fݒH d.X\^#mme-nt.]'ZH0梄8-o(Qeձ4T;V"ipVXXmӥc"2eɛ`Gx-h%@WR2#5%yqÖ1kE Ӂ% o UB> Jcvug.j;-XBE,` d2 ^X'.,V^RI#m"y.0N6ͽu*ْ!&/7"/pƶm}rDž܏++(@Pz}.|-5Z}[Q Xijzvs>=:Ξme!1BP>-|n3=>S Y3h$#`p? \umKBqqk9gH%yc~6Ba߽A}}X4PC£. f0\j>T~~I=F+̥vG|6Iri@H]P3PY*{ ܐ*JWŷWKksA ^0kKjȂ[re#V]p" nfF+FW^0N/4}K{-Ȏtv]|׉/H6li(,U^&yPybgȐĩ;r3'[[]qΡ[4$NtQEU6nj$nb.]?ؚ83I溔 oS)>7ӴvW݆+h#OJ*@"Z 6Bm6zc+hPdFݕ]i^aa>弁Y~‘,qۉiZBA,  \H ZxXWIKV7 pV ʥ8Sr@.K4׉kYPΈXT E/,&k̵o/ r\li>!5~>'#I1˩8o_&;+%wg muTՖ MopVP*DnpxF$7lɿKȋ,hm}rDž܏++(@Pz}.kzl yn< ^c|)%/I绷S?8l i]L n ^am zAЮ&gm_Jy}y,EU.%rd7OPim a;UNt@EQ@Q@Q@Q@Q@Q@a'u/-+vSC:tOGTER]o~uO_5+_M?'|y/9ku$>/9ku$/8W0DdB*(F%8d3<55k7h-''h2pÜuǽr lbu ^tQYJ&1# IFr\m2^kmq2+`GU4diKYLНmrv+9'qO]v wKHD& 0ߗNɯM=&9"[.GuX9HD[@K!8PiWrZx$`s p@-X~~bMM+z4FЖJ.#IȦ07(:m\C'4 (-4-m4J|0ڇ Fq8x#M[wtjӏN# WNޜVؤ~f ?b>'4X\EYO)?UIb9X\EYO)?UIb9X\EYO)?UIb9X\EYO)?UIb9X\EYO)?UIb9X\EYO)?UIb9X\Ŀ1nt*OQs(ȭ[UݓQTEPEPEPEPEPEPEPEPEPEP{{+{I=]&'{Xʊ8X 7qsK!bąU$f8lQE^L,mXaME(֬Q@Q@Q@Q@Q@Q@ H##F8e ڠtM&ݡIw.,,6˻ptU((((((($Υ]EngRҦ{#ȃ}"ѩ_.?Z?:/}Kg C:zfW| C:zfW~F_utiF$w3?ݱQB1-3 =1}_a&̇߉U?W<+n-þkzN&~&-ծone ;0cmC^YzotZᠳFpD/fP%NWB^~a-K2NmWoK*F+a)#rɎ~Z͝Cv+kOiqwp+_\XTcϧ*U{{I!M]am'{iʌyX((((((((((((( ;7jج{'}MZ--fE0 њ(4f((((((Z* kQ2K0QԁԊw? W.QTs@/..rOw? ]︿,.QTs@/..rSw? ]︿,*w}qtYtUO.w? 誟k]Gw}f-U>s@/..rSw? ]︿,-U>s@/..rSw? ]︿,-U>s@/..r-S]︿>s@/.˔U?.w? (k]R܋<ЏUU`=RԿ购O _?ZT`[uO_5+_Q|GTER]o~/qW7~lYQ"JYQ"J~H :fny鎧Eķ̀~U~tu%jzC]2I-@7M\vI>3OM˒+K<$sK%(-wUl*k'=[i-ϕn[npqc85%;Mjw!yhl?:_szkNyl-˻OkYb^ھkG򛘛eˋ3:^WR-;DBe`$x@FH\#I[x$X̸` Ty{]5k^EfSҴ1Mg4R6<}[5d{zjnbo2@+=[.{wQg )2,c]otp$~/I]ȾRnĖ?Pdpȹev@bnQUob,㺅'H8#pt9ҬPEPEPEPEPEPEPEPEPEPEPEPEPޓѭZakVJ݂QTEPEPg5) jOge5k %K"Q\収|^Yek3a 2A,_J-]VChe:yo%$dJ/4oY)"ql }$o,ӯxp(˅S*NF7DK|Em[e|)19P7r+<4y%i @xC'd9,p(Okc:[a+wRF7EȎ}i=ԖyV\ĘG,w F%VRO-_U[cjv*}"0< evm۷(5*jwh8V7cs!%ڬ<" 97Ʌ_|R]Iq}aifJV6o]L7ZxJ;{h/-$' .B u$S_,aIY(%^XR4/7Lr-ZY/$K }2cX oR!UW#> 6Ե),il KdTB.3. J_Q\vGOip6W_i'F9o6>w]w1-n!kfIq(?(88~RXnԼ|W:vep r|%;C9 $n 73"M klZ58ȸ 1E ` `Ҁ02ieX.6\"!c<$ˀA!AܷwImlpJHcR y2?+=>+-F'obiUʴO1Y]nɧSM_Hx]K*UvUQ? DN%.Fxmd7LĐf8a"oۍXrW9vm74o8 aAkk3mB-H]S &),hNHʑ|o`1O/ zŕ1n1L!XT@ؽ񦟦k:nE%DUd bC#.VQb+}ORM= b)B @pM }7wŤ>Qy1f,FVQIM񮛨YX_I݅Cs| DG gF@X]}N<|I/p$pkfaxR4AG.`q2`£hU]%QEQEQEQEQEQEQEQEǴ?zѬ7=k.)(1k ?3-+nC:Ҧ{ uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :ϼbsxW%&fǪsS#e֒[yvoB qskQ8&XLmha8)vs ňW >mEgY%Won|o]]JC|~ςWڴ.<,n1_}Mw2o\ٴs!aEgk<ROy${O<Ř3m†f!@2t( ( ( ( ( ( ( ( ( ( ( ( (0~7j֬5V0[!h EVm [hi$Ƌ+=J..;&@$0(ko-ĩ !y$($w(h['tgH ̪@bRezԔRQ@ EE[qo*M9#`FApAJZ)*9*D;b%=z6 &.fIMBzpdOՊZ)(KSc46ꮹ5['M}_ԲmC:%Ar8&O?;}ztm77 mRm.-O~ ou'2&/$w!J[9 lPd{ m*zS?'M}_'M}_+{TJFA6#ԟ6߻/"i~W(i~W*_odU6߻/"i~W)tߕ &/GM2_*tߕ ?tߕ &/GM2_*tߕ ?tߕ &/GM2_*tߕ ?tߕ &/GM2_*tߕ O7¥ɶKQm ao"/77¥ɶKQm ao"/77¥ɶKQm ao"/77¥ɶKQm ao"/77¥ɶKQm ao"/7—#M}_?mwTd~%⨿[ȏ#M}_#M}_?mwTd~%⨿[ȏ#M}_1C#z*(~ɶKTznE)gm̀80OR{n5rJ*F-bG!Gi[U5EL9 HjW˭־"F|xk_7'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcOFjUY?oթS-RQL []x}"\И6DřAX8ֲu<_g-ƣtr7f/# bb]WGVO rp3j5A5X3 1 pG9XkZ__i6cٶO~I~<~xojkf OhCw5.3"7d|ܚqiζBwGpm0K+lc3. qfj(ʵ8SH_Z{{;V~ϲS/AJy?k}e]"gu8 =!X%!~?僀Ph!vn_iM\Төϝ7:S,4(_iMN>vn +?:S>өϝ7sBN>vn_iM\Төϝ7:S,4(_iMN>vn +?:S>өϝ7sBN>vn_iM\Төϝ7:S,4(_iMN>vn +?:S>өϝ7sBN>vn_iM\Ь;=kөϝ7!+0A#I$#-3҇u,IEIB,OXcQ}?ZT`G?DSJu_A>ԯ[}>K(5_=xjCA7xjCA7F3_4Φ(< ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0z_S֭J˱'}MZ~3FiQFhQ3@fE% Z)(Z)(Z)(Z)(Z)(Z)(Z)(Z)(Z)(-PIE-P4OXcQ}?ZTa"F|xk/ HjW˭־%tN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V=dkVeѭZu?is>x{QiX_@:UҰoGOF?UҰoGOF?UҰoGOF?UҰoG:]O+4iX_{sxtSJmVmWj?TҰoG:77@??a?ƭo΍O+4iX_{ƍ@??a?ƭo77TҰoGh4SJmVmWjsxO+4iX_{?UҰoG:77@?a?ƭno΍_+4iX_[sxtWJmVmWj?UҰoG:77@??a?ƭo΍O+4iX_{sxtSJmVmWj?TҰoG:77@?a?ƭno΍_+4iX_[sxtWJmK o]K: '& ǏCҵ"? j?JR?:/}#ȃ}"ѩ_.?Z|Q8k6{?܇^Ǩvo%y?܇^Ǩvo%yyg$iw_?͝MQ^yQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEaXѭZueOFi} dfjӮ-aD1Шg&GE.0iS_ŦfӤ!+iEcA#K ;x-Bxx9*0Rʐ|3x]i79lԬ'S oXʐ npX=sHVb`6!633[:JռwX%ޝp Ժqn*?q aGmY[..s?y v,m'͂#O.s toAL֏^ ;]ېzF5He {O)H+B IN2H*Gi4*Fem)kheƆic\cn0wu?{,Vzeth^4{AKrCn]'(tȵ9u94dWMt'nxW [{J{}i=|$<Hq Cwcq!ԧ;T, d50AA\Vƃsmijh.Rw~P p]#z^k-̗6+˲f΁8+ngp[kcZ=WNSLS|2Qx9^H=k| vQԗNdB4[̿vA"(nj /QD[{+\ȉ 7ۂ|Ov]B^o\Ѵc-B3"[,dUtK&)*0b(xYb]Xӵk=:)kY |Z21\hvwbi˧5o n-v 6e2`%EY y2 R ,0;\udHnG#3+18?  :YGWw(F!K$ aFY1ڐ~Z5jwz$ miCmmuP1&LɍNp6WN-L\Im2ȡ RFpGohJ֜]L[mII`㑊X?ڶ[,Ӵ&dCf#n6  k0pq8?cW궷21ugr@'DX7xM䣑#o W?y@z+lbwH~ς[#Ovuy/4K=6ި64dʄ,'w׏UӦx+YUIYY<#F=`6OnmeVHY.!n3[CFy]Whh=ĈJfhxݳ%W@jt:ZdLiJ*+rcQkFKaG$x.H@A嶂끞kuMGW4?S;v3[*Z@"+܎7(Mkz~!:=BY-۴R*%eR~3se@:ttnw9r5KsN)U/^oGݳvq+-ܶVe3:V+N_CF;Tmm\۫$&g5l6m 9P#m [hi$ƠMsH5[Om !y .9pk.AtյyWFg)@ۻ ?(T@.WKԮd[gHD`)6,?/ˆ_>/J_"UCO%RX$l?hvP][IA tlpy~MjLӧ6ImX-J]E- 9RxgHHđOupgVkAiN8A@8tRQ@ E%RQ@ E%QEQEQEQEQEQEQEQE5EkDO#"F|xk/ HjW˭־%tN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V_ѭZUe-?oեQ-QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEEkVD_OA>ԯ[}EDSJuO_%~ dž?Zg=G+Ͼ dž?Zg=G+?c?U#L/lhΐ(((((((((((((((( Z5F}MZj> (X|qXKYCKdll9ٴƘz+ϣ=妕6Ge%Ww%,n|;uncY񞣧x\pj NkllILݱ0\Ƹ4֗N{kxn$Yd;iQ;gbiZżw_m$Ƭ€&vbA)02psauح_6ݭܼr}Z]뜾y Őֵ'NPyhlX|T(ɐ<|PƖ>'֗Imm*Ng1-$61Ry˄>>n4iR7 4 +L,0 l wTW[xUk {W-d $YJ K\ ''ZMsqp4IVy h#T1r\XMwO ^"jV1FsMyÈg5b:*@a; eEpH)Ǒ6geI4Q`bspTac͗w_EٲNN=WZ<7>oBkBƑ'1μ 22N\xW_(ԭ5ͦ]ژ`Č./㉃!qU9ǢfA;/"'y|WmgĺF z͌L^Wj\,vZ^XGDV8=O'w|Wug݁iZ+Ȓ\)Z!PNUTd As(2~%cM+P>iPw\Eq/;A3̑kU|Q|pzW5kךǓOݑ/٧o,yw|r.?LMF=Kj-%__*",s+G*V. c)bHrc?%POw6ʲQEAꢹcɦ}^%Ʒwg%؆(ŅR\b21Pr]$dYS )_E{r)[[\ pڤ89<ĒTko 64iJ:&-ZDѬ6fGh_3Z/.'{sQ|ڤxY\2̱@hzDat>Ǻٱy||ڽ1zTssCEӦ Iq%4vXWǧ+Nwiڅŵ텭֯IWh[ SAEi7V]>!Ql eX}O[(>Iwuv]\aмѐGle 8"$t}ZSn@}kNݭiv+sie@\08ѩhzFjv7V|[3p8*6-'Ǝ0f~H;&2]2=NM>g-ڠێY1~UҴ zG_<gIgizBV:B¨#W`HԀjBGtLw-s/NU."~(,: m$H#*$xN_^Qu%\±O͏GH7B/%]33081j;W?eRQG7[̏N_^Qu^X' "$M90yq뚹EAo2?9y}E//?憎9dr2N_^Qu%syi,q3_x.8d}ȅʌyX=:H'd܌a&FA=*syeG J( yi@/.9y}EԔQ#ӗ_]r2(-SIcQtu4Q#D.TcG,rj0߶xnHc} yƟQ)sA^$r;;"2q==sEuyI )3&L:( yi@/.y.lЧb41׳Յ[o!X+d㸱ӵawq*<r̎J ) kk*uBB&-<5uo{>6- tMsnaNH穮Š=Ü}慦đXj83"Nd+.i+8L_ŦKEYf-䧕~Uһ:(|i_! _==y:MFOD!~p|#f>Wn15QE K9Iv7H'iƝ`7] {-/ݴ" ey$kZ)7wqe`/-+Zb贩`|GTER]o~u?_5+_Q??' |y/9ku$>/9ku$/8W0+:B(((((((((((((((( +/k_S֭β7jѨL(nEb$W&Dd R?@^VYu5m*!,gOv8~=vc~n/4%وΓ .W@@$4;_n+?HoYdEIYB89cVvwW4袊C ( ( *8&[x@$@$#<TPjZ:]\NۀYV5<\g=zP( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ɋBҵ&/ ?JR:?Aԯ}EDSJudoO_%~ dž?Zg=G+Ͼ dž?Zg=G+?c?U#L/lhΐ(((((((((((((((( Z5F}MZj>0EqoisOw լ}]fidH._)Cˁf`glzGMs4we^ '#?f uQH(((((((((((((((((((b购jɋBҔuO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭lYTV(e.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~c EW??]]AP.~cԑ,˟6Xde1ԔPY1_Q}?ZVd!}GiJ[S?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ǩvo%y?܇^Ǩvo%yyg$iw_?͝MQ^yQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEaY_FhukVG`FtKQ)2(XcB 0ٍ~O*+KUŰmuag R5%v]2ܦlîԴ=#Yt+>_ڭ]qg^:Ew 5+Dj$2E-jtVo\Si7ŕΗZPIbcf%VfyDBcꚇtN{fi# zmks1&3Cv^=HVbo6۠Ns3;zZ-t="comk}65鴝Yt@i`yeFT|NC5(+.9%:n@G-\ tlm5+GLoxã`23ujSEd)&J#u7gXÐ0`ReӸεf&[Qnx.)_, WhbrBe+]H~ǥ?꼛tO/?z7dJӡ㰵MBd-¢W^8gHW{J(a[MX[fYHjf8nl9$mc\OҮ:wmິ W#mC )8tm㷷ta]Gv `8֤C Xt乕fEm@7 zDίmGK , [q!c!L^.kit> +,"@"8UI&7+|iЍa6gyۢbPŘ]js-p BrXUr;S{ogBk1p|h8; -V4N[Z%̓&H@bwniZr۽Z^m^1 hT n>zDwWoصF vYp@imk;-!AWyq,aDDvr[bi'LkyZ{e DB+3wHFޕj3Zy&]l$eNTr=koZ¯cdP# 0#8's@C=Hů}il4Le&/(~a_j#I^G Ȓ-[}nK[H6-0&mF'(w;Ϟ9qsO5}^Yۓ`މn?lu%7xm`aTgnQq~EqAPEKq,:]r\ʳNn"v |=h^.<=tzekGhTKg悤FLYǦSk[#cKFlCp \׺D_v7Q({tp9m.zcZ}C]v7mn%G=rb20I# y}[X>C&Y9w,AJ7Wql1[oKKt-kT-8ʅ=ڣ:E߈?젹X$#wuhV̇$_J|OE<uq HfU"ܭGRC98m{_ >F?wXӆaFx?}ݿzqRCia O(mRXw c'#i{:ƹv3ftwX-". UFr.xCֹqo&mI1*0 eG \Ҵ- pB(C1=.: -4;OI *3d,rǓ}h ŚͭkSG.Ia2Q0'g-ڠێY1~UҀ9P|$[n-|,bIu~mݒ7OI#>y B{.ek'1mv^h 9~b>oJӭæAakQڤ*lNF9ɪw??K}q~f6یnb񎯨cTX[XXyhWCf#UR6v忭k^-д籇>&yvWLDz:94:mN-NK W!M]4*eE|d>ߧu#;gшh_sXmaVV(c;62$e o 6gxWio.?5eb-~ab mRzD֍i.c%E- [CdЮ1I$%QH(b购jɋBҔuO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭l(aEPEPEPEPEPEPEeH!y;QgrhU_/9ku$/8W0+:B(((((((((((((((( +/k_S֭β7jѨL+3YF,lnf<0BI@w: u.uEk4ᢹWS`2s =;I 64Y|RT'! ω +^.aY+1(xFs'M`P{h)S"lm`Xɀ75uY\A6I(O >V)e%۳`tGT3ɬfQ.E vs *ع&C7TO{}8Ǘϝ=G``j-o|ayq;X?iF|h|34wm:M<a?+"q:iz/e:1$N^Ywg P$s'%^?hd~_7g:OI4ֱY.3HV+ǴQ Oxij(ׯHe=0C(bC Ĝ֟j^W0y~^7on9LV.-/U VwqsrI{N  (135r5Gbr\H$87~V{N-cYfS(;1^SmImno`f}BMCA0XeX Zh:妓,:sF7nV &O$y*\#}Rnm"3\BrOWNrol󷜸C2{Ƹ_ھ])l%.ZW$)p=ESr~`N.Cui6vof {Xal [ S 9HGx_d F pp{{Ogj$V\RE̾a!j5_׼ ОQkΝiH-M?$ǵI.*GRKatJaXNY,L@ IctHR,&X&9g,kd'lŹYW`+˼DeR0bnfIg]Eu:bY3  J .l ˠˑi'i|[Ŧܼɳf,eӉ#?0d\ޛCzMm Zd6%R2'F Puk{8cx,4LHXǐP%߈5$4,4Cj-'i`"6s`@;Tc[;쿵,էwu܁9}N>V_D𞱡cV7H'ӜȐƈ*od.NrTy(w oE~LjYҿmnxe1Km/ 8_w$1)і~Dcj%0p&j=S?-ݵ:/%Ѽf2֬? 4yFJew# dYKef!x+<Y>QWxV_-g_hxdmd2]F*(܏3Fqfs.4˫]F ֳi&X$01b?hsiqZsn HpϜ/]xSEe$s8]Dy5vaXnڕZv[G"A6st&Uxʤhf T#V'WԮ;$5 69$D7t0+miˬoj ̓,WB1nߕnqu;տl}>|?]9Ԯi #8yex_@2bW@K[US𠬘/-+Zb贬]L HjW˭־"F|xk2_G'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEe-oգY_ѭZ5iQ@Š((((((,IQU*qY~>EϸY~>EϸY~>EϸY~>EϸY~>EϸY~>EϸY~>EϸY~>EϸY~>EϸY~>EϸY~T%I7N8gПάG3AXrxefI*Z 6+K`(6Y$'$~f)7r ɋBҵ&/ ?JlL HjW˭־"F|xk2_7'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEe-oգY_ѭZ5iQ@Š(((((((((((((((((((((((((b购jɋBҔu?_5+_QGSER\o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭l(aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPY1_Q}?ZVd!}GiJ[S?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ǩvo%y?܇^Ǩvo%yyg$iw_?͝MQ^yQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEaY_FhukVG`AEFmyQO`)j@ɨ~o?b[_ؠ ~o?b[_ؠ ~o?b[_ؠ ~o?b9((((((((((((((((l$Q0TQX ,i4[MEba4 O Z>Iv<{TV/&KOL|3Ci4rKsǹEbc4 O RmXg 3jş]Fqcs1:~@%9Ӭ/-+Zb质u0>#ȃ}"ѩ_.?Z?:/}Kg C:zfW| C:zfW~F_uE!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPkVgY_Fh} dCl繑Fm7tԆST0Fo DH`F=\v]]&]V7monJVs R_#큆z#vDs" Mbsvie'*w&XI:)G;!A$*ԯ[}FK(5_=xjCA7xjCAqxt]bd $W~F_/Φ3o(3o+F 5?fQ 5?fQfڢ&L?&L,ÙTV/$֟ɛ9G$֟ɛ9Es#j3o(3o(dmQXZs&mZs&ma̍+kOͿkOͿ9EbMiMiY26_I?6rI?6r0F 5?fQ 5?fQfڢ&L?&L,ÙTV/$֟ɛ9G$֟ɛ9Es#j3o(3o(dmQXZs&mZs&ma̍+kOͿkOͿ9EbMiMiY26_I?6rI?6r0C,}MZkQKXM$Z2@gf=?Ƣi臈B\d 9=.ۏ?UGBBҰIz~Fۏ?UGBB`&ۏ?Un?_UA OGA OEn?_Tm߳Tz-?z-? m߳Sʌ.I9$ܓPi4i4X.Zi4i4-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,-QUZ?Z,ɪX5J"Ht`yPk7/C?>Z?ZiKIee ?,?Zz-?z-?>gU3+/X~wOc!ih!ih}_2EA?t?_=?Ə=?ƎgU3+/_X~h:Źx'dʷ1d`˖27=;VA OGA OG3rd!}GiW?Zm$sjW$lFݨ+9lR"F|xk/ HjW˭־%tN/͞_<5!rר+0zNF?௟_ʏ<((#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#_ʤ#ԯ[}EDSJudoO7~lNcNA,A>Fl/>? /\SRPTdV8JRI͝M?,?_&ߨbԿGG)2\, XKރqL̞@`&d^_0?Z 6-RWib: ϭ־*R\_3[83xPާsxtQ^2 ѹ:(sxtnoΊ(?77F袀 ѹ:(sz΍:(sz΍:(sz΍:(sxtnoSEtnoSEsxtQ@?tQ@?77F袀 ѹOEnoSѹOEno΍EsxtQ@?POF?POF?POF?P:77袀 :77袀 :77Eno΍EsxtQ@?P:77Eno΍EsxtQ@?P:77Eno΍EsxtQ@?P:77Eno΍EtnoSEtnoΊ(?77F袀 ѹ:(sxtnoΊ(?77IEopen-zwave-1.5/docs/images+css/Doxywizard2.JPG000066400000000000000000001772461264474202400212510ustar00rootroot00000000000000JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222B" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?׼_smFYIl"W$o9< `UXbQ+ OZ:fᥱKwWFqp^ӌyOd>rJj[w9Cm~0Qϝe^ٞ[B&Z3%f1F0#q+)U<]ҍgϥ QTtkҋ|УJ/Bv]8h\äe&3)KDg3,J!b]?r8S1 :4́y=j}{7MߡG_m~A&Ez,B9ی£^Om!MBG t-iE>vQߡSˣY2jA=^|0Am效.AGh6%ߞھQ@)g$z VJWWmۣ-{ҋ|УJ/B /yogˍ>GHj @]]ؑŒsMLq4%hwf47ֿWҋ|УJ/B K|xX81i:WM>.4,0 +~j}џ~dQϝiE>vTw5KZJ[u2b6*ll;ҵQvĬ6"#~>R= JI]ÏJ׳,iE>vQߡPGjSY뷶 X̰1LA;dDžvVTn$]AFjYa h半:ᔎ 5O%( ?;o*9oK.ߴܴŷ g` Qnu$]%*4y{/(Ôwg#JUw8jvv3;o(ҋ|Ы:{mF//|?fa]َ@H`3H^+>m'QgJ<,.xA*եR*Qz1N;o(ҋ|Ш&5+uӮҗ`$'#G=:=UzD&!mntJjv>^dQϝiE>vUhGKd$<RH,?J>hey)H-<@-,:qi7jߡG_m~Z|+Yh5; #GNҳL܉,SDM|)M^/0Gt?qϝi>vTQ蚬"!1 ݞuS+)fQ n[/J;/)=i>vQߡP6v/em rJ.&ٴp9۶8q}M>j}н;o(Ӌ|Шfѵ;xm68`FO@Ď#G6{okw[WH)fr_m~qϝnciWљdn{FG'=M|]*LIPw\p7N2gUٿܥFodqϝi>vVx6[ RIﯴmKQnݼF1\ӯMߋ;yM呜pSM,E??F9SkN/B8 m'QgJ<,.xA*yyeckv-voIT#*9z5~Қv>[Ӌ|УN/BאK5D3#2ԁ^ƭk麃Jb 821H✧N.ͫ&GߡG_m~?K;mh䴸hh8蠞$5ڔ/qjm@&ߎ }k9W(QKlAߡG_m~VK.EO[ϲ>n߽Ґ_+h")^>܏f_qϝi>vTRh71K^0g @ΘN%i5C2BtW\g/2_m~qϝ6MgRlgYl3M0ac%Ix^X㸆LK=XǷ!ܩw$瀪2x5F Iiob㇩&O_ЫߡG_m~I6k&uw]ZLdEl U[Sӣ_ivʹ42z$u ?1J7_m~qϝNo4ϧE-͒i>vQߡZv[Y\6K[EWQX5^SтNPyR&dg<}np׿ɛ}Ro>RiE>UeoM]DX] &pbo/1ZVҵhd?6T101s p9Z;fQϥiE>U[:eŷ΍pԼ9ugI=$ ِ1\ .4oq2i?QϥiE>U_wu &ABd _$ |}2 f(dxfT8)N*qjr(V?QϥiE>UWӯcK,KW;Rv1 {jU"[Qux$``ą'toJ3J/B( xVO,l!;ֆ8|[ +(^Si8$Z!RFQvoJ/B( ]SXMI< GֆѵD{o%^SR'<|}&ҋ}-УJ/Bͧ^u=VeG0 GԬ"ivhY>#;úfɿK_(ҋ}-Эywx@ t"E|p=j߇kصKP1Jܮ9#ޱ"54xjWhJ/B( F;@ @аvqКF%i5C2BtW'ҋ}-УJ/BeCNQy(]7ț{z>N R۲7sYKF2籤pӒ_ZߡG_k~]|1kMqt7e XٲsFk*KӶ}xy2ndsNZU>kLS8|HZߡG_k~fcڌ{Vܨϔ4B.cӬFHb=@vzڀk}㕽%8x@NҼuOd;^V[[ >k=  ")=7lc=֬ǣjrB;N]CVpGUo6\c 0Way$6$c$8(Q[RD_t)ѵFm*76 OecKw(HN:^>=jh22 kuj޺SNQrqkV9`I7*m3LCnmчcQշ՗܈.0-}u6R5vy\X=}̡|S?M?3Ս: he3ِa'oث[X`φ~wͥZ#əa)bkFo[dRTtS<J4j# 1pO^,LkEqm@2Oֱ7:թ:]JϚxʺOT&b⫯2STd]~F&.0##l`ޠյ'_b32;ojށDaU@N3L_Uxb%mZoorڹy]=іuoY^3I؛H] fXC!~U̳Wt٘K1 b6m& `=qVoQG&/*_ n_ľͭ.SSt>3F?7=60 (Yܧ#?Zv /Kּ+o5ot.T*UG&/*B<[@s1UI[-[LSnȿiq)@tn˓F̜|Xdi7t'ZLjzHP\.LeY##`F9_xb#ſ?JT^1Ʈ1?iv}dmLs;灜RxK_Ҭm#6vψ!ʟ+y+G&/*B<[@s1U2Ҷtqvqvz^I*kl..3@0Tb֢ y@I}\X' 3IG&/*ܫ-no:oI%My|Igi6-֛u{dV * n5e չӛ˳Hec\e8J#ſ?G!-9 ˙]~5:vk=QiB;NNJmI-o#g3jnʱĉ4 ),T^Nyx{vv+G$^5*rC"eF[nrMe L_U-^Y ۧ7{m/<gLg1 @sY$l|2lWo+xvnP&fF* 5km:h%PB h둃5xqƱB*QZVulRZRwgj\xL-Ą'L@!s9qL_,;[`Iv1d/(#^Cr3Pſ?G -1S˔e{1^#{7x =a_ 7'i]2]_Y$H- MT V9IoQ? &/*⬫.\cw2Mo F,h3^d8pb`ތVM])cHI {R L_UhR^|kmD#,ﬤӬ&kf}I]DQ|dw#]V >ݤ[<\M'ml,k3Ko$4a#j%/q;Y%Kdz, c핕ҽݾ] W/fN:VմK:]>{Yg!͹v*0=j͖moim.YH[՚#m,w*AE#듚/`weɺ#&I'3j? &/*A[@c1TWe_XOٽ#ZiBkH&9B0ƥrvEiq6-hvg=qG֪ L_UGˬV_Ͼٚor\M1/Ji 6 p(%Cvgk -jI=3,Rp(q=j -1?oS˭gY5%Ryz?/*Ŗ O7<k0a2p0y:͖~'?ltΑ HR6b.YFRx<3? &/*/0ȱp5#xK fc[F5jJ=rYէZ7Ӫ/եcZu+%*oO2NJ|OeY_:KuZZNҢƣ!)@"jƹ׌oGk!` 39o*]1qR_Uky|RJ˼_ڌL[-Z#[i5`cV+O7^3h-қK$Um@'+ &bH<[YlJ# #h0+Gn~^[Œ|RoG&caiv=դT3+.!UW:m#Z5+ɁO8T,54\*T\_U _S}kIm:{e[4ӕK:;pA%y⳼#i}J9UY!1(D$X H=7&bſɘzn37,]Խ׵妣xjus Yp"B1AVuOFou(upNh+fg 7$АSſɘ?of/*aGJs9A[@o&b⫵c֏xjiM&{kֶg+_2Da;Rx±i6qsrdU zC䑠ecm|#8<  %}5/j(sGMbKmq]T^5vlF b¶OE=:O gk[%)1 V d3TN[X7>$ʹ8殦#?{GϝNX}Zmc{.bcV 䐬 Y6z|/a/$To"Ɩ>O%Y)̋X#'d^([o(eU;u=Pmfc O^?!` 3)<\:ً?s0u!O_i/$Wfq k/:9+%|zTq{Y{h9s۟|$o l‡Q3Id-EK%>d hȨvj… [)Tt~k[֮#lt&He8 AAoU$Z}w52\A%tT8-lpdDM Kt[$i%2٭ /ʀFK30v:Mj~̻l|B)k|vUqW9yݪ:ZW]핶3}"cr:c2WqXݿxv$RI$Jb36Wܜ|+Vڟ_ڶ7{LS'V7'/^xeNmfCsX$`F&<"dl'%*H+Oޛ0dMgRwZ+*~eay?釠2ulgʰt۫:/Ѫ$qR/tG\1& :ULW@ n޸EQ</CՍǙ=q|X: R;DfX8çqSN}+JKMŦً1bbʹgbԆa^xI5Re7utU O;ǥxMl$/ װA+((^TVX`1\gN-7׮O7?h|7}χvm͌ ldm51f"4"%8eU"iciwڝ㽞 s9KYEsK8O4@OK(]Epu+M*)6[paH0T8GuCQHaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP+#D SJu}k/ jHjW˯_Y?'7~lo7f,$?p/< zw٥k~ ǎJM:ﮡ@8cב~H؟fgS4SO}m APx=23v5ni?>/|V*8';yRXePWR2#@_O&K?):WecUE7d~bPK?)i?Tgl-i˗`FհTK6޹#pfgS5b6dliF73[>`Ҡrˑ FBui?>/|V( fgS5bfdm,p~y"=Y~<}_O&K?)ԂxT3"aV$)#`}*Ji?>/|V*jq\𺣂@dW\ʒ (fgS5bn] 7*!I@%[@_O&K?)Պ(٥h4?M2=J]J]>7wwI&( fw`պi?>/|V( fgS4ynX$DSg *H #)*ÎA٥h4?M-徣am}i'mspy֋{YaM]Ja`:|ǟO'٥h4?MX+_O&K?)Պ(٥h4?MX+t4T ,*{@ PfgS5kvqOD2~i*:uUi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5b"C"xSfm־"F|xk2_7'D6{?܇]׉v\IC,Okbr,|ݎ pPr-zy9O䍰_?͞t 伽ԌZէZ &P+F6#W(6%U76/u-vm.}EkyI,w 2"$ ߏS)^'$w̠l8f$w*I>j4&GR]Ű`\nQt🃢Na8dbh:[:X ռ2.)g{K.Z{UXɥ*\Qw3C@rIiS | ȼV6,!m/$1Ƒ:4M MYz 0En!#BQ@crI$$xI3{GRww[KZw#g9XOYkmZ=>y)hül8TcIc qQEؒas/5YȴϵtH"]/ވu | 4hSj2޶/HRFO44 2 l}rE\:,.F4 xeV.ݖhcRFţOZhĚIkgtTr s\Ҵ\孩1`N\שK/Oշ4* d#*r#Qp1Mk|3~V~ͻ|s{lԘIx,~l8c%d Ld^'K)Ss_q-{΋`#@ePQ %y}ǭ 'I{sD^82&?~^4Qp<-o5{;}2C=bWR]Eך OC3 r>HٰMBOOboK >y.V,2 sЄ+lj]EGDq"<;FU`.O¨Ϡo75GǓ1#g1 ,T}u;T;{sdBo1b/Kg CF&I1 nzP+ dž?Z!;z~H 6Exn.cϴ_pn?ꟁd<7iw}=:s\L?v[6嵼_a9o| ꖳ6UiַV]JX5pS#$bhx.΋#ų ._*Leյ%LԪem|Oʪv"LOs}\i0?ʒ¨]bUtҤfY.M1G4TrNwc^}3O֮.lmVLPQ3[Rk0IA?*P2Fϟssj#ϥͭ2yyDZ<[n3]YZ 52F ?iav-ٕ8bWe4l-7>i^fl% PYOs}\i0?ʒ¨]\YVC<)%ܦf;#HG ʌyXų 36^%4OWq#ٵŅ"xK$, #P2KՋF#ṯbB=H?>[cd9EYgO?/G-<\UyvZM+p<-8%\f.3}RuB%D?[l5lyadz$nko-H^I$U Il9Z&!kmgdGPXFn€⸽_E|=z-UT{Z3%ߑ / d ]ݖu5^,:7;gr#U<advlzn^+i-uC`FpAǸضrU$ִۛVw-dҡ{T[XeV˹yp[pv QC\`"K۴I-ʼn<ȉ_=yݞ|. t۫x-h%@쌮dC`9il/ K4>ȕdil/ڬp;{WiK{.yqjYOxmn&Y0Bf//3ʭ'u\&KѦԣ]6U$xk~#( #?l]GVuֵBkW^5 ;ї鑚)HDrSO=VIJHLw2qmݽ y 𮭩O^[Db$cW0R*I.vF-<\UضrU"EKMsZ;VbA9S CxLcrT1!VfMm#it˚].?l1p4tEw^ɹU Hݐ V}+4VrJP_8Jmr[/4>FyX.XXҷhXy<{Ù6 hJ/f$vGI-׆->u-$L쌀 ]kS._*=k6wr흭rXF+21pcsw>zYTLY[;9. Iqx(T*3.[?yGqj c8EQx ,g{8|WX_yZ{{;V~ͲS/AJy?6ᫍJN\[-Gqw7Iy;X9]7-ݜڴSZ$lȑ(=>F5pik\=)]nUbB7dU=J ^-hvŦj;QK&I%f]?gBIe-QgmFXln.2mЃ # V?*Y-<\UضrUE_?;MYc-bI1ΊxB_ۉ-n5m3ڦ_Gkk-q}¶j$10(?7<74]3hIjqr,l>_>fY8N 0s3hbWZVL-8o,hϐI*ı֥$}W$>m7'O]g>d?-( #ų gI`\bi3|œ&7q??#͗:u2]K7N76pTعnu-D}"[/76'xz}bK:;=+PHY!'3 +Yr+ wIovGAgO?/G-<\Uqk>iΣ-..#=!)G2KV B"'}s7/Mf+E{Xf[ەğ@P[]e;p.O[?y?l⫗Ҭ;]GO/Z7P 㺵 >3%mZ2+=[R\V` u޺ n޺ nO}MԶq|Mzq*NOof{;{kiVng,}3NIFW+aؑޟEч(WmMҿ+o o7IQ(9Eҿ+o o7G[S ⹷TT=Q>Vn=Qp\!H4(9T,Y,I'$0J|)WmM)''$m0=N==J=RѥΖ4-.]<"wUѰnj qV L$q9UE#qI*F; 1 H%ч(WmMҿ+o o7IEч(WmMҿ+o o7IEч(WmMҿ+o o7Q kYP̊цXi(9Eҿ+o o7G[SJII%DydjvlSc@Oj=R_+ti_ϕ7hÔ_+ti_ϕ7hÔ_+ti_ϕ7-[&ugX ̪@bRezri_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)E$D$<Ͳ5f`±Ǡ'IGa/[S?TpOͼwʡ6 dGޏhÔJ|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)@kng(FI 9*?SQI͵`1nSPg-,Z+xdDWCHAAOZz;rfGίBl-__=ZQo9_s#gWj?uz(е: WV{EWZzJMNS)8`Yw&1ҵԺG[~#ȃ}"ѩ_.?Z?:/}Kg Cx->m"!jZ}+8+m6H`p";q\o?܇^^NwS#lWg]asy}6R7NT)/NRPq* /!-RQiߤOZA>p !4q|K 'ŝֳM-e3BrF(O~WaϯҼ'6u{F >J$ NcP#$Fp~Onn k[gQ)l |ͣk? Wؿ6}s߷ۻoǙT\0ojPwViT ufvePᑂ lTQp-`ҳ]ıYF-+4RX4A\V*UF ;{x(bPTP0RQp9}SU,]B8}R F9 ?_ѮͮeΙl\˯gd?,;O\z\Q5[6Yp,"RDeaדpV_" cMŶ’F3]wm3L2`~xt!Nڋ;;}>-gĒrY嘒IbI$I&\ڭ5 X[+ Crg@wpr3#\ֵ[5+)L$lVq$w|r{(u%Ÿ`o$^W9a 7.B9eF,7EŭQj[e,JۈEίosy!'jg$(8:\h}D5sMm=Ʊ Yپ>ҁ$T2 ˦ f-n;g"y˅"0sHj +IY[[hD`CNO\m<[ ClAl쥄H! E"` 9heÒ:(}axhtřq%̶,] eʓ-dkQƧkM $vrݢlT`rz(osw4:xkհСYGxRK !X+<\?~]A!.aYi-KpckxS\o]KO`6cm1 "Lm~ h-5˨.lj/@dV[B$ 9\ (_y ++oR݂36آ,mxkVm{m%SANlTRCrp3EvQp< z_Ba#Ϲ ^ e4-ќ$2NtGT73s\E_XY#G q }߸Q3 8#zt_FhTxlDQydfw"l 笼Cvѵ_إG[]H,dxlrQHَpI(NsuwGR_Eώ{ۅUZ3ZL>heA|u"a^MXmR.dJ- |v~fb ˎΊ. 66Sr>o#@L:&]@_8>$%3kp֋q4Is mCXN%]Ow\ #7y9Sc Ab@yv7Y k["mNxmYȆDFsǸDjH7\5 }ɷHmIon+4YQFor|^.zΩ]:{v[(mn!;qg"d1*36\a2Ux#\ֵ[5+)L$lVq$w|r{(gXئu% J|Bd"}+QxBu=Jtp=Ԣ#,w3÷`Ͷ($>[f^> (߉#gaƳ%b_ީ$[VAZF7/3^Cvyw1Ŧkm*͟i_1V DpnW$#*A* Qp<"1VVgc.fmDY!2,ֳq@өϫicU4yf8#(yY6C>(nVK=DlFa"VRYc1>lEwm 58FU9c-$f',bQEo5{=3LDך|Q [iqǓ cnΐ9yq}̖+c!N`072NV6ERQEQEQEQEQEQEQEGTER]o~uO_5+_Y??'_%~ dž?ZgS!B5Pr-zsCO*X{;~Hh͌y#s*+5 /mfh;5Y`amHw#r<?R35{y#scj6s#[F>q-J 3.l=:΍Zck*q _^sFs ""΄HHeT4l6q)}f#AUGV\[9#]H s,K \k)·SYvC 7+Q_'UZ?/!&T;]Me;/9c뚽 v]W< ѫSnЅ%h/ſu%7y>y?]`o. YwwzH]ZeܷƁ2P11r%_jiK}Cz=MK+?_bf6W0U v;u3̖Zdf$~#dPO ` %Cݷ'N2K 12F1^r?)7dJ-(0(((((((((((((((((((((((((((((((((("F|xk/ HjW˭־%tO>Kg C! ?zYQ"Js$kl騬/KfXύ_;fa>6Ks7h/KfXύ_V l2VXRE'UKٖm~(̰oCXYEѻjͿ͘{>ٓ1=rs֍_Iutn̰oGeߥ \ 2z,atEc{?f1&6Lt$iwV2Xi&[9\iѻIR$͟^zԟٖm~(̰oG4B̟A?K}$mvN,-UKfXύ_YhG6—4GfSsqF#[R ;9TAfbx^II4KfXύ_!fE.Yyw/,? O /M̰oGeߥ OﵯI>ֿ%iٖm~(̰oJ;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ d}q;Rq/QK /Gx]$M\k yHT@+VRAwkk_w4}K k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ Cso H8"k?3DiS($ uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H 2uf/dBU^p28 8#7xJӯOR+U1 xb0.˃%.=͛}.? l.ln.$6܌##=+GYj"t:6"2ܴQN^여aQp|JA8`*֩iaj?YDkqdҸ (`?̸'n͛}.? <ٿ |ٿ͛}.? @MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PzTlq~S]6CiqF‹7j٬M-Re$~n[V( +6V6ue-k In#,+ ]Hż6s%Uwr9*G8*)$%+sVX%^DYAJ r?1TW,jVxXFFu(<1HQB78ٯEb&^e7&8@uC{<8ޓ%Y5MKS7~b4*}h_6c;t9e[xI+ˇ m\+yh7Lc'F{-+vmT/?Ow{unӢHꠒ@b8O'0ijt1M,?]P#|<|pGQKVNۇ2\i>v涍~Ӆ鞢6Zl"k{XP[׃Ssv9r ]..Ev>\P|GvgU!eެv pȀV&s$sV/W~Ӷe>F3_CTz?,QkGuB< 2zS{ smTVӒ{g-{x̳DfP aOjZ&k {Eu A8I+>e{\EPlj-u;)VeEp]`@ @E=5m:_z?i2#~^Ӓ w.QX)g좳[Gr)Z? ?1fhDeE Gߑ*rāI=(((((((((((((($Υ]En gRҢ{9 HjW˭־"F|xk_7'Do?Pr-zٿDPr-zٿD1|6u5]c`U_SEķ̀~U~t>(ԧ^ػEsk4.X) uǽs־#n KYmNc(< QV(B z>jbH x;iKI|69FG|VRj"%RvlOMxwKH22` ;y!q/S-}sZ%Yd(cBT P/bCPQ^Kgm} ox|A 9A K6Y7I\VtFW gR_-G,C'R>U}^?eӴ[6zZ($L6FM3Oq^X%:۵1ί̫bĿ]r0~%^>>[Sez^:#|S?u|?slWa2ފ=W/??>)x׹OG0}oEq➀ql{d_dtkG'#{j̾󷢸O@8KO}z^:#=?_y\@~%^>=W/??zڟ/ |S?u|?sl➀ql{dosmOvW>)x׹AO@8KO}}^?;z+_dtkG ~%^>>[Sez^:#|S?u|?slWa2ފ=W/??>)x׹OG0}oEq➀ql{d_dtkG'#{j̾󷢸O@8KO}z^:#=?_y\@~%^>=W/??zڟ/۰_S֭.R;4(ld ެ*q$GcYm7t_n5@Ec`FV+>}0$]OrC4uǚF {J+J1] J2wg7f{wtXfk宦r8qoHݓW\[jVZQ nӲRظc/p+j%- RAhm:qs,&Q.) :߇nu \:!s%; VDbpr3tR"qҋbx/q69#[o\.5 IM!jSZ8>j bAݜyh L]o^q[gwa-o&ݒ&ceo(.W$g+bo K _w(ʃr/ u4SxX^'?u(tk왵eXϸ;+3%s.O^Y[1#erw'/q9gvO7%.:~CQ~Bhm1ƁXo. U,|oҴ[ݥg-2+fȉVL Tp@']"oaqgڴ,O${,igP|]H!2p!E^t[PQ>UrZq~aev2/]utUn:^,TְB24CWyYZ*4wG'mlaimEkB3`t ΢ֺ|5e[Yd ~7~nԽO/5[BmRhēHE(VϚ`pwg9^w9[V;8-VY MI'`v lELy^Í8܋fOK[jZ+B/'4}?/ohEtƏ5-XΟޗtƥ>ΟޗԴQ`":z_G,_fOK[h2z_REfOK[jZ(}?/oKE/'4}?/ohEdƓME'4}?/o񩨢~̟ޗdƦ +IବŁVjK]B5Կ购O _?ZT`[uO_5+_Q|GTER]o~/qW7~lYQ"JYQ"J~H :b6ԃ ${g*(F%8d3Kn'?us5Iy)F<twگG?>S?(ԪwGQ^~h?xϸC@9_}=jQT,{|?q|fsmW{ԣR5E{)YU>گG?>SPO$%69Ep9=}sS yb:\Mq#鍨Wp1Henuscj>&qXJmr[/4>FyX.Xz/m G"܃Xl|kz -Z%׮\Ү kX-M8f/,X%jZޟksڮ3iMGzwifn+N8Xt{5mb[?BDGKԣiY %`Ȼ@Hվ<;kmjAi.,6ys !%[m f<$ZOn֡ImOR89ױ4RQ@ E%RQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@-%RQ@ E% T?!RgRҷ+ ?3DiS=nsA>ԯ[}EDSJudoO_%~ dž?Zg=G+Ͼ dž?Zg=G+?c?U#L/ljFi;  (_U:[#c2WgyQִ<9 to$lޅ7`c=sۚ&K}>M7.Kxq,,@2U6gQ؞o' >V!mq[xh5;K;3TiP`'T~lo(5d{zjnbo2@./ ϯXjz4v7s1\jyHhuY 8eY!s&)ni;{Ic2~2;eQt\׶uy]NsJm5J΢2cnhIo@/h 컴Ƶv%ꝫ)v_H;hFnd!G4ȱ)vfQf=_ C&qw"I[ʌ0RAò"!EWP#|OQaӸJ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@vzOFkEޓѭZ+v dTFP%8#[6v!˼q*9jZ:eP"<~Y^mGL6:N$򇬃n'ЖSrȬsKR[?Yz6*T8fB:斚lڔAe !-|௿lTvkqj+i-YT6*HP*_YH$̀lCz`u;Q %DFx6H͌mˮ>,QEQEQEQE&K3:#"HTnUb zJG}ҟ3@ E&h-4RfEPEPEPEPEPIE-PIE-PIE-PIEEsBn?iԿOX!GiJ{ uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :ϼbsxW%&fǪsS#e֒[yvoB qskQ8&XLmha8)vs ňW >mEgY%Won|o]]JC|~ςWڴ.<,n1_}Mw2o\ٴs!aEgk<ROy${O<Ř3m†f!@2t( ( ( ( ( ( ( ( ( ( ( ( (0~7j֬5V0[!jG?jZQ`dkZKs"Lݢ$>ib[>&uuE vq&ǯl1}b20jei+mgo oc&J [im,d‘BMy=ޟЮc麒\%shkq2W&%O$v`R8;~MS }3ond#2y[v)s*VjL/y)!\iy=5?+H7R ڊ@yv{yq˱gH,Y$t& Fʯmai4$k 9VK%`, g??szGE(5D[_Y5V0 hBmDžEG_RJ(hJ(hJ(hJ(hJ(hJ(hJ(hJ(hJ(hJ(+C'*jP #Σ购ŏCҦ{ uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((ñ'}MZk*Ǭ7jԩLZQ}#RV`gjݝ7O5(B6IJK]܊n 8pNyY{Y+Bi׊T%ӭ3Bu)5u4_~i(2R#VU@ Z%dmJ9c;ҧԭ i3h$A#̶ ҧp#ӡvTOj4-Y&n![<-h,` qu06*5%fѬ]=:OfˍpN^GTAǫ2lX=-b]`j;)[˨є$blץ,U5qeu0NMh&+&1,Zh1Fd%xX"{KszvzeQy[*d#ܭ%>\Qt5Q5wFK_% nKyYJn>˩mr}p H ^]dVᐨg ͺٿ?.,>'~'ۡ|@tzuiɬ]]mISP ḻ0ߘeלּDmKp][CĐByvHbVr R#!ًvwŵ{qD1(%P\$dU> fn-m{y;M=Ta$+)e8]-|X`KkG[ni6|"+n@=j|lo źYĶ3ڄ)A|L\vz-^iQͬy4-y-SacďUU{{Y!M]am'{g#*1::6ݭe5ϙ&L}1x‡͸ป:CŬ>v3-Ko*a+,Ќ͒AP\ &˿O0;>5H!nw#kMV "Q"\r7Q\5Ϩȁڣ%/%󼬈%7V[}]>YfO vN|ev{o Ihic5$ko-ĩ !y$($w%Y&]m5Ҟ=^{8i H$)ʬ r 65GE+֣su{[O?(EG3v ?( SlmQ[w[>ߘ2*+ 2'^Nk+]Be֯YH) pΊjoo]>xp"6j  1\4W7Xmu*/{w#ffA w]udm<Fw8uu3p%@셑Xq0 ^ksyXh:眺5$:?HyE=ZMHelG<1iO7!{ĴDy,^WpA[0?"Q<7(^ RTY0 UA7y˭^iRC0O4-ה[`-SďVO ! GxJ&iL%$1n(5tRQ@ E%RQ@ E%RQ@ŢZ)(?B5Cqhk? j?J٬h1-*e#"F|xk/ HjW˭־%tN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@v=dkVeѭZu?i Q[?j\t2]|X&Kg-nWۜgtT_?9OƏ9OƩM.)Q C iQTD*Qy>~k4y>~k57-'G'E__&_}h_}hQP>~k4y>~k4\ |y?5<y?5.T>kϼsϼj*9OƏ9OƋ5'G'E__MEC??p&}h}hQP>~k4y>~k4\ |y?5<y?5.C3ĎWfsϼsϼj*9OƏ9OƝ__p&}h}hQP>k4y>k4\ |y5<y5.T>sϼsϼ5'G'E__-BdE0ff# O@ XcQ}?ZVc!GiJ[ uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((±'}MZ+.Ǭ7jөLZyخx&vM= xZCnEXK,pBM"GjY rI'[煯7Fk U)_u(}<-!EW}<-!7 _EX+7 _EX+7 _EX+7 _EJeLJYP@$A~c֟L 煯o"Rk QxZCfxZCnEY+nE煯7Vh ۯ煯7Fk U(k QxZCb$¡K* $=;\ _o"Rk QxZCbxZCoEJ#H"3F\+TCЊ};_}(}<-!|V^o"ʐ'8hi_u(}<-!E!_ _o"P}u*_u(}<-!EW}<-!7_ _o"Q@_ _o"P}u*`؜}6UJ(k? j?J׬1-)K`9 HjW˭־"F|xk_G'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcOFieY?oէQ-T"YG*VxtYҮ)F<,B 5mR zkQc{/72GnLC*C2]J 'a*-gk;:kYfA4 0븬gsHT]wIįunx~ܫ[rU'ppkä- nOK_'/bVcT;jeYhʋo$6,qf26TQXc }|Pmښ)1j7VbgZq1yB2|'[rioao}gZA?)9fz$ ^d=_iڏ.ݬΈ!H8SsNPBtk)jcxixa](u ye]BqbVfjz֢[cxfvbsS9ʋ2{|њ}Sܯ}/]Ces>WSMb"A[LfIW* 4~(,"7%ҝ6=|,!y epbTu3W]L%wP^A&<$A# { [[Qdsc o{[8<ƌFId ?efWwZi ڟ WG6Ar g# olE3*ݘ.$B9Ҧ(!5(*"( p4y] Ss>".uSihUJȟhmcsʜ!*|n/!SԳ8.~񋇏t`/P8#5)C]5_qj J8 谆O흯,pqKdiF,I 6os+D_+m0݌KyvGPƺhnXM$d:=A*lֿY?]HRnp: wi ԥ9$0«',g#*>!͓YH7WٙȤ(;@Q}4f"?=no9-7V.Tjn4]$ʊ˃.:1}OMȿ9/yׇelAudF"l--Ih%atPq|Az(En[l?'{Fq-<= ι-Sw'[$!6s p kxjUԚPFcY[5.K4 בqݿ霑r\^(]u6og6FX7շ4hKf\)y-OXuv 6|ԯ[}FK(5_=xjCA7xjCA7F3_4Φ(< ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0}MZk:Z5F0[ VԵdko/46BE #>q> K}ZI[t/(qt"j|Z 6|`2ߓ94j:?41#G'#mZjfmne$I\b^(R{@aPˢ. zyK3l*n]53Gw1#w:D[b9eA;'lg#qmf}LM:TKK Uh%&!p*uk7P`NIEMsw1Cok$D +YAtoZ^ovy%bvϑ"G*[o h.D!vFi#8pXI+C=~\$ o_if^YܵK}-g;TFWڅ_ ]5,2HD[lV2۽}-QӾ;#mل`TF>'$;Di巙};qm2ͅpAI/4 a٢t\dvF=PEeev/7|p]$-NɒvJJ|5=y{ ϐ[|by$m}6[uYyzmjV6i"OPdsUE+O_Aܼ/7ܕp6=7u8!s]O5kvs!mp@n_ hkGYwv'MjY=䖈Aʃ1U'z^+ Dh839'rX}U@QEQEQEQEQEQEQEQEQEQEQEQEQEE?BV?OTVL_OY1_Q}?ZR"F|xk/ HjW˭־%tN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V_ѭZ5e-oգQ-TP?jZgЍ%'&[WrVזIärxy 柦HaPb3wԷ%k0XB\"` G=GB*WR} z*pzm̱ +յ/]+_3YKDIiny\ʡ2&@P1c wdӼcφm^{v|ϵB, #ceʼn<[Pi> D#GWgDwӥ0!P`DԲc_JH$6Ĩ%+zAHwHhtb`F* #\X|?i<-" d-**  bEPEPEPEPEPEPEPEPEPEPEPEPEPS*ZcЅK@d!}GiZՓE)lL HjW˭־"F|xk2_7'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEe-oգY_ѭZ5iEFV3#^Cyy-n<ǘv(5-i&;imмOQЊij0,r3<O~OTү/AB{La-i[^M3’2$ErxKIi4B..),Cavv ``Vd>`Ρ&*Ďm-UlǍ=24[KQ-.^UkdtEŒ~x f׍CQm9%I5g q.sppH9eѼiz%7{$vۙ渕sg>G̊FF !m%ZGU6[jvTk<|t^j{;+{hY&#q9y>8 [MoأX\Ng"Q4V͑!R>l#T~ӭ+^|"v\ d >5 s6N'uxlw\3)#b %gӜab!dlBņ2ػq@NJuJK;[k bgM2F1u,8m )Fv rIcI'IH(((((((((((((V?OT ɋBҵ&/ ?JR:A>ԯ[}EDSJudoO_%~ dž?Zg=G+Ͼ dž?Zg=G+?c?U#L/lhΐ(((((((((((((((( Z5F}MZj> gЍKQAddk}BWi#8tUbP! c;J F}}DMf ^ P 㧨EZCoEVM3’2$ErxKIi4B..),CavM;+Ϯ% 0$oݶATǗYY]GE Ɵ@,O4~21I  WУ7P^^#LH@B HzMLX\63Z\lXw/PcfNKmh*yӴ"Wn4AVbK+\Œ8X2.ܝ*iUV;]r9U7|mB Owssku{c~fx@f,c'*StZwmZiu7K88+|ʎwfTیn`Er^6PSqlmYe[f pEμCA7.fsj:iid%dE;`8v3ghw4W+ehu ;{'5f[`T\ܜ<jzY 7K)7ySē4ER((((((((((((()ՏB-E?Bb购jɋBҔuO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭lY}#RP?hŨoh')=?SJA 3C?4zHrr=k\ oY][^[$gʬWJIhKIY!uq6T$vHlG9l'{d͝:*J9V[yGkkXݧ1s|Ȭd`ʩZ+%n䶝H(-J_9$L K h6fIn' 6r1=I<'L$J#O-Λlɖl, Vjߴy)!ɍ?/sYxKEmx5{`"ȫ"$ v&PAEWi%hN69FBx}}qU5麭y$̙'d||sEfK6k"D*NȒ3;,ЎC%5}KhxI]E`IwG Wi@m/ls [\;K4Afb-49ׁeyFgY"mdE]Ӆ%sUI I|%qNI %*c-0F+%O*M:MBht[{{ǘb #,j!~NxQL I|%qNI %*c-0F+%O442Jk{4x/ci]>ځ\([Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Oj)ՏB-EkVL_Ou0>#ȃ}"ѩ_.?Z?:/}Kg C:zfW| C:zfW~F_uE!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPkVgY_Fh} dY}#@̍y 柦HaPb3wԷ%k0XB\"` G=GB*桧Ũoh')=?SJA 3C?4zHrr=kHmo{O{6XrK H ڗ./Hu' E \"p1 ¦؁YMS:p8{Hgs;gsE#YT~fr76g˄ӭm.D xeVmRb  2^6u F Y$7C6H!@r OF>|}ngV+iA2+(rEIhy-i.$f9#7dD3rI ̖eokk坽]$-쯸b߁s@!ay}[x]}]\A3,M$ͰEc* u.m;y#6ݘNAVNmc{xOH"IF[yӱ71/,Y7$ @)OoHl&L mlUVVWoQCq2K_ 'Ld(fRCOZVjߴy)!ɍ?/sYxKEmx5{`"ȫ"$ v&PAjE܅"O13pU46pjO;xYwm>UPKo91yKC9nRl.-bhfMnF0pOJ=Bk3E2>!r82?(=]{byMv0!} #’)|7{q5̞d{;@Gs* UG54+ tXɚbEH\2i VKH}V6bKr}M`^8M[KG arDMl3MD?g FN"QU)O?$1][ g:;]q% $՘3n`w6`O6_/3ɨ<ɳ~ݒ4Ӊ$)@:FHI-;K%1 'ExOxS,- -&I!; bM@9ni m y.)q#*&؅Ƨl EH ѓm,^gQyf$i H>R2&7@QEQEQEQEQEQEQEQEQEQEQEQEQEQEE?BV?OTVL_OY1_Q}?ZR"F|xk/ HjW˭־%tN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V_ѭZ5e-oգQ-T6t̮$G!ƌ}J@Q}(4?PT_fx|>-٠1"A-٠1"A-٠1"A-٠1"A-٠1"A-٠1"A/9ku$/8W0+:B(((((((((((((((( +/k_S֭β7jѨL(QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEEkVL_Ou0>#ȃ"ѩ_.?Z?:/}Kg C:zfW| C:zfW~F_uE!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPkVgY_Fh} dVmt]:"V4ꍏ5_ ZRAsEu6_L<5Ci4a4 O]=ͪ+#f /i?1 g'. `?)?ƏL|3CI4rKsǹEbxhi[ȓFFцU)8OaQE!Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@$Hi$`%ϋ4 X#iKsj_0iG&K|.x6_L<5Ci4g /h`sn?0iG&>L9%9ۢ?1 g'Ջ?h -Zb2#uvKsGY1_Q}?ZVd!}GiQ-`|GTER]o~uO_5+_Q?' |y/9ku$>/9ku$/8W0+:B(((((((((((((((( +/k_S֭β7jѨLҮ%%4"(䙧Tu`)܁@<5Ʃ^-V+Cm%m#I3:^2etc*=;)a3gPK` =O4םk/-;ulwqC\q9KLoyB~ԵZC_Čn9K)2d+(QNp=G4yZӵ=wPڤq4VqjU7,|m2#r QMk[Ek [ƒGhaF @zLQp4L1#"*^ݢUnd`k|<- i?J_ܟQPXQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEI6I/u؂Et¨U0\?ma/)7U_b>,jVnsw'mmM38I߀r_~#e ֯A OGA OG3*/,?G_;ji4i4s>߀r'J:=i$)R8wv.N)z-?z-?&VԵEU!ih!iiXz-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? t,եx$NJ:0e<(5!鏟Zz-?z-?4V%2GA?t?_=?Ə=?Ɵ3*?,?G_;ji4i4s>߀r_~"e ֯A OGA OG3*/,?H4Jz2M[٘0e[OO_OO_H9Qjb贫z-?Q9+bu6tãu)na|GTER]o~uO_5+_Q??' |y/9kY= yw?܇^^FwS#lWdgyGkTWu濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕9QPaTN9_ HjW˭־"F|xk2_7'D6{?܇^^1zNawv #6vx~u (SmiO+ Zi%)$ΦcxOK /^o1_ #}h[?,?_&?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy_Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>Kގ4FIj/S1 /Q? )_f+usG~/}KXA FVfO y{02/~[}oxUggc1B`uINk_MQK R./ugռ]_noSѹ:(M?P:77Eno΍EsxtQ@?POF?POF?POF?P:77袀 :77袀 ѹ:(sz΍:(sz΍EsxtQ@ާ77ާ77F袀 ѹ:(sxtnoΊ(ާszΊ(ާszΊ(ާszΊ(?tQ@?tQ@?77F袀 ѹ:(sxtnoΊ(?77F袀 ѹ:(sxtnoΊ(?77F袀 ѹ:(sxtnoΊ(?77F袀 :77袀 :77Eno΍EsxtQ@?P:77Eno΍E󤢊Lhopen-zwave-1.5/docs/images+css/Doxywizard3.JPG000066400000000000000000001772651264474202400212530ustar00rootroot00000000000000JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222B" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?׼_smFYIl"W$o9< `UXbQ+ OZ:fᥱKwWFqp^ӌyOd>rJj[w9Cm~0Qϝe^ٞ[B&Z3%f1F0#q+)U<]ҍgϥ QTtkҋ|УJ/Bv]8h\äe&3)KDg3,J!b]?r8S1 :4́y=j}{7MߡG_m~A&Ez,B9ی£^Om!MBG t-iE>vQߡSˣY2jA=^|0Am效.AGh6%ߞھQ@)g$z VJWWmۣ-{ҋ|УJ/B /yogˍ>GHj @]]ؑŒsMLq4%hwf47ֿWҋ|УJ/B K|xX81i:WM>.4,0 +~j}џ~dQϝiE>vTw5KZJ[u2b6*ll;ҵQvĬ6"#~>R= JI]ÏJ׳,iE>vQߡPGjSY뷶 X̰1LA;dDžvVTn$]AFjYa h半:ᔎ 5O%( ?;o*9oK.ߴܴŷ g` Qnu$]%*4y{/(Ôwg#JUw8jvv3;o(ҋ|Ы:{mF//|?fa]َ@H`3H^+>m'QgJ<,.xA*եR*Qz1N;o(ҋ|Ш&5+uӮҗ`$'#G=:=UzD&!mntJjv>^dQϝiE>vUhGKd$<RH,?J>hey)H-<@-,:qi7jߡG_m~Z|+Yh5; #GNҳL܉,SDM|)M^/0Gt?qϝi>vTQ蚬"!1 ݞuS+)fQ n[/J;/)=i>vQߡP6v/em rJ.&ٴp9۶8q}M>j}н;o(Ӌ|Шfѵ;xm68`FO@Ď#G6{okw[WH)fr_m~qϝnciWљdn{FG'=M|]*LIPw\p7N2gUٿܥFodqϝi>vVx6[ RIﯴmKQnݼF1\ӯMߋ;yM呜pSM,E??F9SkN/B8 m'QgJ<,.xA*yyeckv-voIT#*9z5~Қv>[Ӌ|УN/BאK5D3#2ԁ^ƭk麃Jb 821H✧N.ͫ&GߡG_m~?K;mh䴸hh8蠞$5ڔ/qjm@&ߎ }k9W(QKlAߡG_m~VK.EO[ϲ>n߽Ґ_+h")^>܏f_qϝi>vTRh71K^0g @ΘN%i5C2BtW\g/2_m~qϝ6MgRlgYl3M0ac%Ix^X㸆LK=XǷ!ܩw$瀪2x5F Iiob㇩&O_ЫߡG_m~I6k&uw]ZLdEl U[Sӣ_ivʹ42z$u ?1J7_m~qϝNo4ϧE-͒i>vQߡZv[Y\6K[EWQX5^SтNPyR&dg<}np׿ɛ}Ro>RiE>UeoM]DX] &pbo/1ZVҵhd?6T101s p9Z;fQϥiE>U[:eŷ΍pԼ9ugI=$ ِ1\ .4oq2i?QϥiE>U_wu &ABd _$ |}2 f(dxfT8)N*qjr(V?QϥiE>UWӯcK,KW;Rv1 {jU"[Qux$``ą'toJ3J/B( xVO,l!;ֆ8|[ +(^Si8$Z!RFQvoJ/B( ]SXMI< GֆѵD{o%^SR'<|}&ҋ}-УJ/Bͧ^u=VeG0 GԬ"ivhY>#;úfɿK_(ҋ}-Эywx@ t"E|p=j߇kصKP1Jܮ9#ޱ"54xjWhJ/B( F;@ @аvqКF%i5C2BtW'ҋ}-УJ/BeCNQy(]7ț{z>N R۲7sYKF2籤pӒ_ZߡG_k~]|1kMqt7e XٲsFk*KӶ}xy2ndsNZU>kLS8|HZߡG_k~fcڌ{Vܨϔ4B.cӬFHb=@vzڀk}㕽%8x@NҼuOd;^V[[ >k=  ")=7lc=֬ǣjrB;N]CVpGUo6\c 0Way$6$c$8(Q[RD_t)ѵFm*76 OecKw(HN:^>=jh22 kuj޺SNQrqkV9`I7*m3LCnmчcQշ՗܈.0-}u6R5vy\X=}̡|S?M?3Ս: he3ِa'oث[X`φ~wͥZ#əa)bkFo[dRTtS<J4j# 1pO^,LkEqm@2Oֱ7:թ:]JϚxʺOT&b⫯2STd]~F&.0##l`ޠյ'_b32;ojށDaU@N3L_Uxb%mZoorڹy]=іuoY^3I؛H] fXC!~U̳Wt٘K1 b6m& `=qVoQG&/*_ n_ľͭ.SSt>3F?7=60 (Yܧ#?Zv /Kּ+o5ot.T*UG&/*B<[@s1UI[-[LSnȿiq)@tn˓F̜|Xdi7t'ZLjzHP\.LeY##`F9_xb#ſ?JT^1Ʈ1?iv}dmLs;灜RxK_Ҭm#6vψ!ʟ+y+G&/*B<[@s1U2Ҷtqvqvz^I*kl..3@0Tb֢ y@I}\X' 3IG&/*ܫ-no:oI%My|Igi6-֛u{dV * n5e չӛ˳Hec\e8J#ſ?G!-9 ˙]~5:vk=QiB;NNJmI-o#g3jnʱĉ4 ),T^Nyx{vv+G$^5*rC"eF[nrMe L_U-^Y ۧ7{m/<gLg1 @sY$l|2lWo+xvnP&fF* 5km:h%PB h둃5xqƱB*QZVulRZRwgj\xL-Ą'L@!s9qL_,;[`Iv1d/(#^Cr3Pſ?G -1S˔e{1^#{7x =a_ 7'i]2]_Y$H- MT V9IoQ? &/*⬫.\cw2Mo F,h3^d8pb`ތVM])cHI {R L_UhR^|kmD#,ﬤӬ&kf}I]DQ|dw#]V >ݤ[<\M'ml,k3Ko$4a#j%/q;Y%Kdz, c핕ҽݾ] W/fN:VմK:]>{Yg!͹v*0=j͖moim.YH[՚#m,w*AE#듚/`weɺ#&I'3j? &/*A[@c1TWe_XOٽ#ZiBkH&9B0ƥrvEiq6-hvg=qG֪ L_UGˬV_Ͼٚor\M1/Ji 6 p(%Cvgk -jI=3,Rp(q=j -1?oS˭gY5%Ryz?/*Ŗ O7<k0a2p0y:͖~'?ltΑ HR6b.YFRx<3? &/*/0ȱp5#xK fc[F5jJ=rYէZ7Ӫ/եcZu+%*oO2NJ|OeY_:KuZZNҢƣ!)@"jƹ׌oGk!` 39o*]1qR_Uky|RJ˼_ڌL[-Z#[i5`cV+O7^3h-қK$Um@'+ &bH<[YlJ# #h0+Gn~^[Œ|RoG&caiv=դT3+.!UW:m#Z5+ɁO8T,54\*T\_U _S}kIm:{e[4ӕK:;pA%y⳼#i}J9UY!1(D$X H=7&bſɘzn37,]Խ׵妣xjus Yp"B1AVuOFou(upNh+fg 7$АSſɘ?of/*aGJs9A[@o&b⫵c֏xjiM&{kֶg+_2Da;Rx±i6qsrdU zC䑠ecm|#8<  %}5/j(sGMbKmq]T^5vlF b¶OE=:O gk[%)1 V d3TN[X7>$ʹ8殦#?{GϝNX}Zmc{.bcV 䐬 Y6z|/a/$To"Ɩ>O%Y)̋X#'d^([o(eU;u=Pmfc O^?!` 3)<\:ً?s0u!O_i/$Wfq k/:9+%|zTq{Y{h9s۟|$o l‡Q3Id-EK%>d hȨvj… [)Tt~k[֮#lt&He8 AAoU$Z}w52\A%tT8-lpdDM Kt[$i%2٭ /ʀFK30v:Mj~̻l|B)k|vUqW9yݪ:ZW]핶3}"cr:c2WqXݿxv$RI$Jb36Wܜ|+Vڟ_ڶ7{LS'V7'/^xeNmfCsX$`F&<"dl'%*H+Oޛ0dMgRwZ+*~eay?釠2ulgʰt۫:/Ѫ$qR/tG\1& :ULW@ n޸EQ</CՍǙ=q|X: R;DfX8çqSN}+JKMŦً1bbʹgbԆa^xI5Re7utU O;ǥxMl$/ װA+((^TVX`1\gN-7׮O7?h|7}χvm͌ ldm51f"4"%8eU"iciwڝ㽞 s9KYEsK8O4@OK(]Epu+M*)6[paH0T8GuCQHaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP+#D SJu}k/ jHjW˯_Y?'7~lo7f,$?p/< zw٥k~ ǎJM:ﮡ@8cב~H؟fgS4SO}m APx=23v5ni?>/|V*8';yRXePWR2#@_O&K?):WecUE7d~bPK?)i?Tgl-i˗`FհTK6޹#pfgS5b6dliF73[>`Ҡrˑ FBui?>/|V( fgS5bfdm,p~y"=Y~<}_O&K?)ԂxT3"aV$)#`}*Ji?>/|V*jq\𺣂@dW\ʒ (fgS5bn] 7*!I@%[@_O&K?)Պ(٥h4?M2=J]J]>7wwI&( fw`պi?>/|V( fgS4ynX$DSg *H #)*ÎA٥h4?M-徣am}i'mspy֋{YaM]Ja`:|ǟO'٥h4?MX+_O&K?)Պ(٥h4?MX+t4T ,*{@ PfgS5kvqOD2~i*:uUi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5b"C"xSfm־"F|xk2_7'D6{?܇]׉v\IC,Okbr,|ݎ pPr-zy9O䍰_?͞t 伽ԌZէZ &P+F6#W(6%U76/u-vm.}EkyI,w 2"$ ߏS)^'$w̠l8f$w*I>j4&GR]Ű`\nQt🃢Na8dbh:[:X ռ2.)g{K.Z{UXɥ*\Qw3C@rIiS | ȼV6,!m/$1Ƒ:4M MYz 0En!#BQ@crI$$xI3{GRww[KZw#g9XOYkmZ=>y)hül8TcIc qQEؒas/5YȴϵtH"]/ވu | 4hSj2޶/HRFO44 2 l}rE\:,.F4 xeV.ݖhcRFţOZhĚIkgtTr s\Ҵ\孩1`N\שK/Oշ4* d#*r#Qp1Mk|3~V~ͻ|s{lԘIx,~l8c%d Ld^'K)Ss_q-{΋`#@ePQ %y}ǭ 'I{sD^82&?~^4Qp<-o5{;}2C=bWR]Eך OC3 r>HٰMBOOboK >y.V,2 sЄ+lj]EGDq"<;FU`.O¨Ϡo75GǓ1#g1 ,T}u;T;{sdBo1b/Kg CF&I1 nzP+ dž?Z!;z~H 6Exn.cϴ_pn?ꟁd<7iw}=:s\L?v[6嵼_a9o| ꖳ6UiַV]JX5pS#$bhx.΋#ų ._*Leյ%LԪem|Oʪv"LOs}\i0?ʒ¨]bUtҤfY.M1G4TrNwc^}3O֮.lmVLPQ3[Rk0IA?*P2Fϟssj#ϥͭ2yyDZ<[n3]YZ 52F ?iav-ٕ8bWe4l-7>i^fl% PYOs}\i0?ʒ¨]\YVC<)%ܦf;#HG ʌyXų 36^%4OWq#ٵŅ"xK$, #P2KՋF#ṯbB=H?>[cd9EYgO?/G-<\UyvZM+p<-8%\f.3}RuB%D?[l5lyadz$nko-H^I$U Il9Z&!kmgdGPXFn€⸽_E|=z-UT{Z3%ߑ / d ]ݖu5^,:7;gr#U<advlzn^+i-uC`FpAǸضrU$ִۛVw-dҡ{T[XeV˹yp[pv QC\`"K۴I-ʼn<ȉ_=yݞ|. t۫x-h%@쌮dC`9il/ K4>ȕdil/ڬp;{WiK{.yqjYOxmn&Y0Bf//3ʭ'u\&KѦԣ]6U$xk~#( #?l]GVuֵBkW^5 ;ї鑚)HDrSO=VIJHLw2qmݽ y 𮭩O^[Db$cW0R*I.vF-<\UضrU"EKMsZ;VbA9S CxLcrT1!VfMm#it˚].?l1p4tEw^ɹU Hݐ V}+4VrJP_8Jmr[/4>FyX.XXҷhXy<{Ù6 hJ/f$vGI-׆->u-$L쌀 ]kS._*=k6wr흭rXF+21pcsw>zYTLY[;9. Iqx(T*3.[?yGqj c8EQx ,g{8|WX_yZ{{;V~ͲS/AJy?6ᫍJN\[-Gqw7Iy;X9]7-ݜڴSZ$lȑ(=>F5pik\=)]nUbB7dU=J ^-hvŦj;QK&I%f]?gBIe-QgmFXln.2mЃ # V?*Y-<\UضrUE_?;MYc-bI1ΊxB_ۉ-n5m3ڦ_Gkk-q}¶j$10(?7<74]3hIjqr,l>_>fY8N 0s3hbWZVL-8o,hϐI*ı֥$}W$>m7'O]g>d?-( #ų gI`\bi3|œ&7q??#͗:u2]K7N76pTعnu-D}"[/76'xz}bK:;=+PHY!'3 +Yr+ wIovGAgO?/G-<\Uqk>iΣ-..#=!)G2KV B"'}s7/Mf+E{Xf[ەğ@P[]e;p.O[?y?l⫗Ҭ;]GO/Z7P 㺵 >3%mZ2+=[R\V` u޺ n޺ nO}MԶq|Mzq*NOof{;{kiVng,}3NIFW+aؑޟEч(WmMҿ+o o7IQ(9Eҿ+o o7G[S ⹷TT=Q>Vn=Qp\!H4(9T,Y,I'$0J|)WmM)''$m0=N==J=RѥΖ4-.]<"wUѰnj qV L$q9UE#qI*F; 1 H%ч(WmMҿ+o o7IEч(WmMҿ+o o7IEч(WmMҿ+o o7Q kYP̊цXi(9Eҿ+o o7G[SJII%DydjvlSc@Oj=R_+ti_ϕ7hÔ_+ti_ϕ7hÔ_+ti_ϕ7-[&ugX ̪@bRezri_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)E$D$<Ͳ5f`±Ǡ'IGa/[S?TpOͼwʡ6 dGޏhÔJ|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)@kng(FI 9*?SQI͵`1nSPg-,Z+xdDWCHAAOZz;rfGίBl-__=ZQo9_s#gWj?uz(е: WV{EWZzJMNS)8`Yw&1ҵԺG[~#ȃ}"ѩ_.?Z?:/}Kg Cx->m"!jZ}+8+m6H`p";q\o?܇^^NwS#lWg]asy}6R7NT)/NRPq* /!-RQiߤOZA>p !4q|K 'ŝֳM-e3BrF(O~WaϯҼ'6u{F >J$ NcP#$Fp~Onn k[gQ)l |ͣk? Wؿ6}s߷ۻoǙT\0ojPwViT ufvePᑂ lTQp-`ҳ]ıYF-+4RX4A\V*UF ;{x(bPTP0RQp9}SU,]B8}R F9 ?_ѮͮeΙl\˯gd?,;O\z\Q5[6Yp,"RDeaדpV_" cMŶ’F3]wm3L2`~xt!Nڋ;;}>-gĒrY嘒IbI$I&\ڭ5 X[+ Crg@wpr3#\ֵ[5+)L$lVq$w|r{(u%Ÿ`o$^W9a 7.B9eF,7EŭQj[e,JۈEίosy!'jg$(8:\h}D5sMm=Ʊ Yپ>ҁ$T2 ˦ f-n;g"y˅"0sHj +IY[[hD`CNO\m<[ ClAl쥄H! E"` 9heÒ:(}axhtřq%̶,] eʓ-dkQƧkM $vrݢlT`rz(osw4:xkհСYGxRK !X+<\?~]A!.aYi-KpckxS\o]KO`6cm1 "Lm~ h-5˨.lj/@dV[B$ 9\ (_y ++oR݂36آ,mxkVm{m%SANlTRCrp3EvQp< z_Ba#Ϲ ^ e4-ќ$2NtGT73s\E_XY#G q }߸Q3 8#zt_FhTxlDQydfw"l 笼Cvѵ_إG[]H,dxlrQHَpI(NsuwGR_Eώ{ۅUZ3ZL>heA|u"a^MXmR.dJ- |v~fb ˎΊ. 66Sr>o#@L:&]@_8>$%3kp֋q4Is mCXN%]Ow\ #7y9Sc Ab@yv7Y k["mNxmYȆDFsǸDjH7\5 }ɷHmIon+4YQFor|^.zΩ]:{v[(mn!;qg"d1*36\a2Ux#\ֵ[5+)L$lVq$w|r{(gXئu% J|Bd"}+QxBu=Jtp=Ԣ#,w3÷`Ͷ($>[f^> (߉#gaƳ%b_ީ$[VAZF7/3^Cvyw1Ŧkm*͟i_1V DpnW$#*A* Qp<"1VVgc.fmDY!2,ֳq@өϫicU4yf8#(yY6C>(nVK=DlFa"VRYc1>lEwm 58FU9c-$f',bQEo5{=3LDך|Q [iqǓ cnΐ9yq}̖+c!N`072NV6ERQEQEQEQEQEQEQEGTER]o~uO_5+_Y??'_%~ dž?ZgS!B5Pr-zsCO*X{;~Hh͌y#s*+5 /mfh;5Y`amHw#r<?R35{y#scj6s#[F>q-J 3.l=:΍Zck*q _^sFs ""΄HHeT4l6q)}f#AUGV\[9#]H s,K \k)·SYvC 7+Q_'UZ?/!&T;]Me;/9c뚽 v]W< ѫSnЅ%h/ſu%7y>y?]`o. YwwzH]ZeܷƁ2P11r%_jiK}Cz=MK+?_bf6W0U v;u3̖Zdf$~#dPO ` %Cݷ'N2K 12F1^r?)7dJ-(0(((((((((((((((((((((((((((((((((("F|xk/ HjW˭־%tO>Kg C! ?zYQ"Js$kl騬/KfXύ_;fa>6Ks7h/KfXύ_V l2VXRE'UKٖm~(̰oCXYEѻjͿ͘{>ٓ1=rs֍_Iutn̰oGeߥ \ 2z,atEc{?f1&6Lt$iwV2Xi&[9\iѻIR$͟^zԟٖm~(̰oG4B̟A?K}$mvN,-UKfXύ_YhG6—4GfSsqF#[R ;9TAfbx^II4KfXύ_!fE.Yyw/,? O /M̰oGeߥ OﵯI>ֿ%iٖm~(̰oJ;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ d}q;Rq/QK /Gx]$M\k yHT@+VRAwkk_w4}K k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ Cso H8"k?3DiS($ uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H 2uf/dBU^p28 8#7xJӯOR+U1 xb0.˃%.=͛}.? l.ln.$6܌##=+GYj"t:6"2ܴQN^여aQp|JA8`*֩iaj?YDkqdҸ (`?̸'n͛}.? <ٿ |ٿ͛}.? @MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PzTlq~S]6CiqF‹7j٬M-Re$~n[V(j }%$'P"WLgs2>^jآNJtۙtZ0_^Mkr2$ܕ'>?[BKT[ӟOKvHbF|x' J+K>jW}][lcʄG*I1*32oZOkXjRf#6>N4.qPWEgɮlc\ Nq/;~5-[MT-l`g]L)lXqh]wRf@6Hvc0:+ǾѬFth.[ȑ27̀w @%]uRf@6Hvc0:+Z==hծfG=FT tV4٬4u=ݒm9>D)@^ ׉t+gִtG- 'FhR}wGMVm%0\p<|_&l%bsdI%*M yr0U}7({oYMT .Rp6Hڻ[&<71BѢ\eѰ7P$Й,u4at`H `gjnnic8EeK` c@(ty/-m#lZ!=+p挂C,qIjWZ֛soupN\Rr}jQY= |eìgiW`:T_X6i*Y\Eov!4bI01@Vzk<-swBFA!s\r8օQEQEQEQEQEQEQEQEQEQEQEQEQEԿ购O _?ZTO`G?DSJu_A>ԯ[}6K(U_=xjCA7xjCA7F3_4ΦsL Z@Au zx Xʾ?װΓ'> 5hmt?e8azzVAk6Zͩ,e@A?*\A_zuͅ~eO ɸzQqcow=ǾKILlr};}VMrް3ֳ>S  VnݤET~TG{#u\w4 alF [ qrK=3z.K]:7J=ܑF#lc0(f=Y:kxdO eeX0mK_ÓO[ 9YM}6uʢ-$q$TofjS~u+UlXWMydkeS7Bsp|7XVk'E<:rɐeYS.he -iCuht>hb8q"wKQTz[}'RX3ZDegPg? 6[,kf߇kNu#d}j+ɡ&b %?0Ul~#CƱll}o#a]3ר!53ccǧ q~=9?QEyq~=9ōc}1_}j+Gōc}1>,kf߇kNOG+T{gQ^B>,kf߇kNAcX66>?__zrg?_Z=zcX66>?__zrcӓ?0WcӐ|X8͍W֨^|X8͍Ʊll}o/>Gz#Ʊll}o53ccǧ'~#a=3ר!53ccǧ q~=9?QEyq~=9ōc}1_}j+Gōc}1>,kf߇kNOG+T{gQ^B>,kf߇kNAcX66>?__zrg?_Z=zcX66>?__zrcӓ?0Vyoձ\n^Knm2\Ot5ľ't-fII]vϧ֤7t5-f)q+'/L~=TP_ ()o1?.FKko} ṱiFFD!:c:MoV(n;O "tfW1%@h~KN;ܷӰ:(|cf$_"c![yXW_lQ[{uX-5 $r}26dy8s:s*:{{t-:U_t?['tWчBsXGOosJ94ksPΊ0Z9t3AдsV'=fo~??9_F G9Εbs=h:s*:{{}C߇:+áh9ҬNzBsXGOos?{|E}t-:U_t?Z9t3G?~O诣J94 G9Εbs=h> aдsV'=fh9ҬNz?>s:s*:{{t-:U_t?['tWчBsXGOosJ94ksPΊ0Z9t3AдsV'=fo~??9_F G9Εbs=h:s*:{{}C߇g:ss>NEYBT`+[肢T#RVtV&4gA+.!!!HIe3ZtKԺJI9έ%ԖC] :TJ8kKӦdkSt-~Y|O18ڊ$ΗwQBW|3Ss v))̊?ym {.m->>,<|c̏~qppEq?6}mg>_ۼvn?/]hw6zlc,HLmw>sNFhojRvb8q1am­:cp~PEPEPEPI3@ E&h-4RfEPEPEPEPEPIE-PIE-PIE-PIEEsBn?iԿOX!GiJ{ uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :ϼbsxW%&fǪsS#e֒[yvoB qskQ8&XLmha8)vs ňW >mEgY%Won|o]]JC|~ςWڴ.<,n1_}Mw2o\ٴs!aEgk<ROy${O<Ř3m†f!@2t( ( ( ( ( ( ( ( ( ( ( ( (0~7j֬5V0[!jG?jZQ`V4MEA.2G##*A T5M䖖6$G d/?#[TU)4'UTEE*; _mH;˻ {h )ᕒ=dg>_-I=#9Tf[SdH㲵cxheTR# 6YrsZzw,&I/Om> ϕ-`rxz(#?2+CC;3?iO],}P$$t #kQ@:DŽl5gYdqk+e`[́O#͐Iײ8fEg w'NOE-PIE-PIE-PIE-PIE-PIE-PIE-PIE-PIE-PIE-PWtOT ]B--bG!Gi[U5EL9 HjW˭־"F|xk_7'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcOFjUY?oթS- F՟B4%k=2u U#%+daѢ{-B 8cB8ľn{nh.2 q9AfvΖv\2c Վ;Weqk#^_ijVxPX;.1?DVr]Ty<ؙy3Ҫ" °m[}ˇe{Scol_׭IzﴕaBvqʀsۊ@Tѵ>smI-[qП/9WN}č3Q ,V@cN G R^Tl"Szc8'>gxB({_Qd{ '@5̇;y?mOdثk#Wol N,"潲[Ve UGi:C+ OR^ڿc}c_>|?>Ǚ'+$`~yaslWWL H#  uGՍՄYZɄ{ n"'4麯/tH]䧟 #FS<:u [B(grAV_IFms}4Vggk73Jv.p9$ AmN[s:W.8B */\ =#_&&dW13FP ۷w4.|m鐾70I|cay1MO{=P(6ˍBH!Oj?Kz[]ܙR?,#zH(l);F,\(&鶗OiD<$1ɕ2Lxy>  #fG_0o pu %ī1#poɠgyCs}j2Z' ,˰ ܋wP "Cnnu[i,cԯmWX- !u*q+W+r_g&,XfUWW{HQezr }ς$3]Ib\ "#V9P(|?$c88۴ T=JRod[%V9T"4U>)nrHP5/^M_Oi 6jC7K.ېJcjr^YZL$,L߰3NvYJ_>:4`qOx㙧7|@ !s#e}WRyq 1@O2%F` FAk0[ɝuUuдrlhJˏ3՜P!rE2HY,}$ hE%RQ@ E%RQ@ E%Z)(Z)(-PIEEqcЅK@ XcQ}?ZVcG!GiS-uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((ñ'}MZ+.Ǭ7jөLZY}#R桷V2j+]yn,%xED$7d) ,j6qb5. ;N~p{Iu!GEEW}کU%)~E Z^iQOjrRI{bw<ʜ1 %\R_=r x$ (Roc܊7}+&k[<^I_YG-j6_@K0a!TltW)Jn,`{ ʱ[Ȏ, GUC'|yPNt#`3qR_g&,XfUWW{HQezr Q|ye0[]3Q,1H9ieNyQ#֖΍o}ZRINY^\.w(fP-~%藖aW{Eow4 bH>\3d 2m.M:OJZ",sE]认 ` ?&DeT,W:Jb,R3ttpGY񫵳ot b'sgn>pΊu_j[}$ icRn$\Mѐ`7^ϻVxH%K WIZGUVVy`KI$`}ފ<=_YXnm"aWdWP7vH]n.)R14SԚGl[m%fIeg < kQ@^g[=EoTrZ!f%|;>Pqs`RԮ%Y)IUhvJxܒE 8K6ci0s )rn>lcN]/GJAy q!;pFРVS\iU0*[>>VӸvn<y| \WFy--ZX+Asd)52ĭqj^( hB|#rH (IMAht8_4<

'_Kmy+~p8GU%O6IⷉABsV -<#>c6W-<+L ϵFX >R1FkBM:dZ ImxH.KDpyVi2%$AӢ1!මյi-yDBs|Nσ4k[4x;,ʹy8-ro M6t/*eʩ8O;ݍXZG[D›ڊQ=Z)(Z)(Z)(Z)(Z)(Z)(?ՏB-Cqhk? j?J׬1-)K`9 HjW˭־"F|xk_G'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEcOFieY?oէQ-TVV)u)5 H/&1h9g60xsTm촽M ]\6ĥIUxq۞:5+]@w04.}F֢U hl-"˕MA,O'G: eds2s"$՜d)>J5R+!8'ʺRheI!K>MF06]v<ѬӴ=>b-pCJg[?H>t)ͻ/1"ؿCD6mL;;gaaq"yc1ZBXf@ڧ'%izn.-fG1ܰW7u(r a$y{ zW03$3Cq!]7nӢX՟ϸԑ,m#)g9aG:Yh']>yDVW5%;( Hnhv,Wg~'@eГ8sUko[VX̥_cI,|i<X!kSi{*bwc_Aj&}{{'+o(nv[HNOusŻR^Tl"Szc8'>PqkQjzyJ'@5̇8KOA\mc_\K/JR 8݇QKdi^:m#E',h~!kdO-jy kxV <%O)´M!†P6ml7$<a[Bo/;( Z?T vh2V TQf<X҄9Y#k7'uiZCimjX㵹)Fҳ #ʑnԚwmMu3uus|RUy1*%@ oM'F).yirˡmnrTeaqy<QC#M³L"&mą9 |OZkiX_jZѵ0ƭ"KH42ݗa m7ͷ#Xof2Hge*F&px>.jXk=>aQ.mY?Մr¨P ,Fbn oGo ռ}e K+HπTM"}@4SOƛ[ip{-^{RC]H7upL[˞C!lGՔ7\g ɸ$ga"A>R9ˎX.}w p0yՋKlޭFUm *tӡXդ-u$m HGel~ W&ϳOg}w7n_?{]^uw?te~' ͽMn#dW3n>t<ս+NGtv6QBp9-. 䅚FYA1H.o . _oia=ue=E$3[yr1Dp_(ORVjZip r"NpvbLve]5 jjb$K&(ee$Īw0F#4mnBMIJّ-Lw埘J#tk'Mxuy@sDk2Xaeuj:gUxhoo#h+",Măe8##5m|m Kij6wy 3$ ,4Ҁc(oH1\x{6Ic.5׌"1>nGha jNN/E-?\̱G}qc°Eަ|-^J"92/[Im;P.$G=dhhYNDeds/ C2-&~OWt{Է#̒huV {$Hܷlx3>kuut"v"ylvȇ xfβgI,-$22*ޠ,qʤ [tz`о ^P!2E|m#' M65Kiҵd"38u26.m!z_b yP>\ſ|̍u_3:Qo.A3,J֪ dD`$}\PPP)2ܺC?*Uǒ > &(O"Ma:Fֿh[`6dX)IlG!>bz_b yP>\ſ|̍u_7騅\GrdhhdF8ˆw$, &/o.h.xOʪqBH,I@O6NkY&Qdc=o݁Vetݴo}{p7-%CTp257`nٸIJ(((((X}?!RW ȏCҵ"? j?JRGTER]o~uO_5+_O??' |y/9ku$>/9ku$/8W0+:B(((((((((((((((( +/i_S֭*Ͳ7jҨL*+r lHKQ4(_ *g2Z*/!=d4y 'o h7'ƀ%OGOY?BzO@Qy ?BzO@Qy ?BzO@Qy ?BzO@Qy ?BzO@Qy ?BzO@Qy ?BzO@Qy ?BzO@Qy ?BzO@Qy ?BzO@Qy ?BzOH hƏ!?'o hƏ!?'o hƏ!?'oT^BzOGޓ7T^BzOGޓ7T^BzOGޓ7T^BzOGޓ7T^BzOGޓ7T^BzOGޓ7T^BzOGޓ7p@A=dLBXt,(/-+Z"败-"F|xk/ HjW˭־%tN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V_ѭZ5e-oգQ-Rn]w ;□P>fv P3[/sX3]_F*`*XƤtӭ Q4A#ޥt[U{˨.VX_&4<%`B=IEG?У0xRQ@(L?TPi{G} >%`B=IEG?У0hRQ@(L?TPi{G} >%`B=IEG?У0hRQ@(L?TPi{G} >%`B=IEG?У0hRQ@(L?TPi{G} >%`BA=IEG?УhRQ@(D?TPRX8I`iŒ#W\L M@ Y_Q}?ZVd!}GiJ[DSJu_A>ԯ[}FK(5_=xjCA7xjCA7F3_4Φ(< ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0}MZk:Z5F0[ VԵKE1؂3ޫp3>濳O#} y978^ U[=B̰Hᑣ=ry񝤏jekH wڄWU5(3(P01x/=jgr' qr#2Ȩwp>EWnϙ ^_]J

VH%gs -m٭{yY˲UW "-'zCXlay#`6[2"aeUf!ѮŽb7k(B]L9dz]4H1pX @ӀI=Xu=;ϼo.m&VDX.w3J qizsAEdiNyQŋEDmJ\*5źI~L,evv!n3]%NkA<.#1^HX;ݜ17c^:U84;}1K=ٝBr,)=S9lsEeOTs#ݛQ""DU2zFrNy<)2IcZ֢9/#L)'{.U1 i*pA<hӹr\hFYW2ƱG<&<0vێ:J(fL{x +]L ,7>StK(ڣϺ$bE/ohE`hx%d ~$w͹+ԯ[}FK(5_=xjCA7xjCA7F3_4Φ(< ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0}MZk:Z5F0[ VԵ9؂3ޚVDNFJcP2Q7L He 9dT f~˸ >V3ޝ_CSEAFsD2c+M}*_|lsA@cuExJX/8~O]5m/ (FU`(-ܺ\0O:p+`pgc8p3TΉsM20oT<3gF{dpzPٴBpfMnu;#қa5me!cj@)Gf<\HXvm+83̺Lq&ld)|:eXךmJ-RmՔʡ9*Uxib7,&@pI+>EQ ibH>VH%gs -m٭{yY˲UW "-$R-FV>Yy\ƆB!O p$ z Rk LflXf70@Ty`J(((((((((((((V?OT ɋBҵ&/ ?JR:A>ԯ[}EDSJudoO_%~ dž?Zg=G+Ͼ dž?Zg=G+?c?U#L/lhΐ(((((((((((((((( Z5F}MZj> gЍKQAdS*=d@[/J?JE!0P-.oĀXwzt=} XwKeh]u*I`5684K*V[lp?QZQEQEQEQEQEQEQEQEQEQEQE X}?!RY1_Q}?ZVd!}GiJ[S?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ǩvo%y?܇^Ǩvo%yyg$iw_?͝MQ^yQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEaY_FhukVG`AQAj(?՟B4 YYdF=A C)pUt.hE {$epV"U28u J(5y[)]>883tKi}^8|3#ҷ 6Rk2.B 1~Pz`tI34zd֍28OLz]uIx\V1s$+$K39l=Jy~X*q퓽Esi߬60Ȱ}-PG*3`슐b1Mn.L& }G=x{$zTqY8,@ D$:gh6Y@"q,r;YҸ4 9㠢2n4{h<Ţ6.FFC$o?jH2;n;Aߐ oɮao5$nwA*}坾Ј%Ώ!E9 9آ2]'*9n(W ʑ" *=jFWJ\dgH|:y9ڢ04뙞nv#XD{<Ϝ6OTuqSEe{nHm|.c )?1޵ ;}2d0mb[Q@z%FSlf(VU?֟?wߍ((((((((((((V?OT ɋBҵ&/ ?JR:A>ԯ[}EDSJudoO_%~ dž?Zg=G+Ͼ dž?Zg=G+?c?U#L/lhΐ(((((((((((((((( Z5F}MZj> Dccjj—YԟRӭeU5FXۏKscl?ƍHǗU-V)n%h|`zպ~u* O2FrhqhL~g߳4ȯ' .m𤀼[WrW#bȶ=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?h=#gh?hLNIU9ګ榢+&/ ?J֬/-)K``|GTER]o~uO_5+_Q?' |y/9ku$>/9ku$/8W0+:B(((((((((((((((( +/k_S֭β7jѨL+J~>xkjt.|n[tfl 3 qI>x=DG*&h?i&|e nͷ+N/hpLCiGKTH@֝6լ'{ҵ].Si!ϨZ6Zā%.JM"UV nʩ!{Kf0n`Jyd(,؂n$%w'_hǦ5^)ao?'ԊĚy5( q[\M±3DfR FP!kḧȒXh($YimksŭI]4~`NС![ RlXS{!m}d9Xƒp$ya LxTTu[M+N.n,-m}C L'.@Z@QH((((((((((((((((((((b购jɋBҔuO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭lu'ԯmlYcb2Mxі&4~6jݬ]*-ƺ%ᫍ},2]WXX,(Yve$T+KQtn5;[(Y,3,j[ gjGHY)no<I 0GskFj6>n|\$[qG*uoż42x䍃+wA5ƑARrUI=&kXuIdԯO+ͻE߲bO+d_+v$!<|@$$<ϲ%fm-8V8=i7Xpo3g*,&#/kH-F?usqoe^H{k㰼skmd":c?!E[qo*M 9#`FApAJc!ך366e( w=~p;v:!p.5(=uz妛wە-t Fb Q<3< U(CaNbzV-Rjiߟm/ ċ4${9U1?ö߁ [˛f-F=^ŕaa[trT~dQ^xFemD]MߴnۜA# .G֝m okEpPaȋ]FyldMNou<:ƭɵ#ȒAvϰݯ{Ym5,dWfaoxth5,ͳʄ^GSj'pe#r1֯^6uk&8%JA )VTAwM/gnڔN>U‹kpN^2 >&xg]/Tpj"KXs$z(EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPY1_Q}?ZVd!}GiJ[S?:/}#ȃ"ѩ_.7?ZQ8k6{?܇^Ǩvo%y?܇^Ǩvo%yyg$iw_?͝MQ^yQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEaY_FhukVG`AY:{pZM>7I-36IhVΤk,vFI2ƏF|uUԵ48&IѴ千#r pkNuU[2`y⅚;f_2E@@1pXd^$TGDm 'BJ*:qzl࿵#9&Vp8 ؂:cڢon`},ifPx'IE( ( ( (#Bp Q 72%A=HRQECkoI 1 HB(v((((((((((((((((((b购jɋBҔu?_5+_QGSER\o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭lt>AnIg%Ff#=J'ۤDJb&k+kkH^pTe F>soG,#l+V"4:6dt@TA imZw< zĶvZ,Y[X=]m +&FO of/3 NĠ_7"E$dd^EIAER((((((((((((((((((((((/-+Zb败-DOJu_A>ԯ[}FK(5_=xjCA7xjCA7F3_4Φ(< ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0}MZk:Z5F0[ o ֟ME[TV/&K?0 _asǹEba4 O?0iG$<{tV'&>L?1 g'. `?)?ƬYEgYj733 ]=:ɋBҵ&/ ?JlWS?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ǩvo%y?܇^Ǩvo%yyg$iw_?͝MQ^yQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEaY_FhukVG`FGq.Iwۉgoy 4yJs~& (YK gD@KYcI#,FP+k_x[\iI,,G$: IO0Iɮ5H~ozjZi-m>IIդFb,[% W(Y9Hлѝ<*XIRy^ymۯe[:7FZf|XOS𞥨B= .$d uΰYI YB'vK>i5Z֝뺅#;W6RcFlx `wJk]+Xf4;E+ 0PBzbeH <,aRs {+]5oI_U-?v6Š((((((((((((((( _L1IgfV0>+BjQ oLug5^RtqaB6eN=88Myvmj}j $2K6nfˍpXfG_I,R\C[UJTOVS C8]Oi7úi06ooMFkw\FPHkWubFJb3YY1_Q}?ZVd!}GiYbA>ԯ[}EDSJudO_%~ dž?Zg=G+Ͼ dž?ZggE(.FL2rEyyg$ilh_I?6rI?6r,ΎdmQXZs&mZs&ma̍+kOͿkOͿ9EbMiMiY26_I?6rI?6r0F 5?fQ 5?fQfڢ&L?&L,ÙTV/$֟ɛ9G$֟ɛ9Es#j3o(3o(dmQXZs&mZs&ma̍+kOͿkOͿ9EbMiMiY26_I?6rI?6r0F 5?fQ 5?fQfڢ&L?&L,ÙTV/$֟ɛ9G$֟ɛ9Es#j3o(3o(d2Z5FI#$va1 _!ij,ƞei0[I+\YJf ĞGz_wOc!ih!ijʌwOc?GA?WOO_OO_Lt?/_X~Z?Z9o9W̯wOc?EA?WOO_OO_L:Wl1?M/OM+N$iJw v8bqN!ih!ii6ڰ$*A OGA OJ\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\EU!ih!ih\f&`֭+w"rQу)A?lL|!ih!iiұ-'?,?G_;ji4i4o9W̯wOc?EA?WOO_OO_Lt?/_X~Z?Z9o9W̯wOcAW7So*].XZz-?z-?AʋUE\!ijͩ_vKs ?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ȯ0k˾ dž?Z:3/`#_ʤ5?ZlJX^Zq|un8έCsz΍Ezl77F袀 ѹ:(sxtnoΊ(?77F袀 :77袀 :77袀 :77袀 ѹOEnoSѹOEno΍EtnoSEtnoΊ(?77F?POF?P:77Eno΍EsxtQ@?tQ@?tQ@?tQ@ާ77ާ77?P:77Eno΍EsxtQ@?P:77Eno΍EsxtQ@?P:77Eno΍EsxtQ@?P:77EnoSѹOEnoSѹ:(sxtnoΊ(?77F袀 ѹ:(sxtnoΊ(?%RcGopen-zwave-1.5/docs/images+css/Doxywizard4.JPG000066400000000000000000001666031264474202400212460ustar00rootroot00000000000000JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222B" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?׼_smFYIl"W$o9< `UXbQ+ OZ:fᥱKwWFqp^ӌyOd>rJj[w9Cm~0Qϝe^ٞ[B&Z3%f1F0#q+)U<]ҍgϥ QTtkҋ|УJ/Bv]8h\äe&3)KDg3,J!b]?r8S1 :4́y=j}{7MߡG_m~A&Ez,B9ی£^Om!MBG t-iE>vQߡSˣY2jA=^|0Am效.AGh6%ߞھQ@)g$z VJWWmۣ-{ҋ|УJ/B /yogˍ>GHj @]]ؑŒsMLq4%hwf47ֿWҋ|УJ/B K|xX81i:WM>.4,0 +~j}џ~dQϝiE>vTw5KZJ[u2b6*ll;ҵQvĬ6"#~>R= JI]ÏJ׳,iE>vQߡPGjSY뷶 X̰1LA;dDžvVTn$]AFjYa h半:ᔎ 5O%( ?;o*9oK.ߴܴŷ g` Qnu$]%*4y{/(Ôwg#JUw8jvv3;o(ҋ|Ы:{mF//|?fa]َ@H`3H^+>m'QgJ<,.xA*եR*Qz1N;o(ҋ|Ш&5+uӮҗ`$'#G=:=UzD&!mntJjv>^dQϝiE>vUhGKd$<RH,?J>hey)H-<@-,:qi7jߡG_m~Z|+Yh5; #GNҳL܉,SDM|)M^/0Gt?qϝi>vTQ蚬"!1 ݞuS+)fQ n[/J;/)=i>vQߡP6v/em rJ.&ٴp9۶8q}M>j}н;o(Ӌ|Шfѵ;xm68`FO@Ď#G6{okw[WH)fr_m~qϝnciWљdn{FG'=M|]*LIPw\p7N2gUٿܥFodqϝi>vVx6[ RIﯴmKQnݼF1\ӯMߋ;yM呜pSM,E??F9SkN/B8 m'QgJ<,.xA*yyeckv-voIT#*9z5~Қv>[Ӌ|УN/BאK5D3#2ԁ^ƭk麃Jb 821H✧N.ͫ&GߡG_m~?K;mh䴸hh8蠞$5ڔ/qjm@&ߎ }k9W(QKlAߡG_m~VK.EO[ϲ>n߽Ґ_+h")^>܏f_qϝi>vTRh71K^0g @ΘN%i5C2BtW\g/2_m~qϝ6MgRlgYl3M0ac%Ix^X㸆LK=XǷ!ܩw$瀪2x5F Iiob㇩&O_ЫߡG_m~I6k&uw]ZLdEl U[Sӣ_ivʹ42z$u ?1J7_m~qϝNo4ϧE-͒i>vQߡZv[Y\6K[EWQX5^SтNPyR&dg<}np׿ɛ}Ro>RiE>UeoM]DX] &pbo/1ZVҵhd?6T101s p9Z;fQϥiE>U[:eŷ΍pԼ9ugI=$ ِ1\ .4oq2i?QϥiE>U_wu &ABd _$ |}2 f(dxfT8)N*qjr(V?QϥiE>UWӯcK,KW;Rv1 {jU"[Qux$``ą'toJ3J/B( xVO,l!;ֆ8|[ +(^Si8$Z!RFQvoJ/B( ]SXMI< GֆѵD{o%^SR'<|}&ҋ}-УJ/Bͧ^u=VeG0 GԬ"ivhY>#;úfɿK_(ҋ}-Эywx@ t"E|p=j߇kصKP1Jܮ9#ޱ"54xjWhJ/B( F;@ @аvqКF%i5C2BtW'ҋ}-УJ/BeCNQy(]7ț{z>N R۲7sYKF2籤pӒ_ZߡG_k~]|1kMqt7e XٲsFk*KӶ}xy2ndsNZU>kLS8|HZߡG_k~fcڌ{Vܨϔ4B.cӬFHb=@vzڀk}㕽%8x@NҼuOd;^V[[ >k=  ")=7lc=֬ǣjrB;N]CVpGUo6\c 0Way$6$c$8(Q[RD_t)ѵFm*76 OecKw(HN:^>=jh22 kuj޺SNQrqkV9`I7*m3LCnmчcQշ՗܈.0-}u6R5vy\X=}̡|S?M?3Ս: he3ِa'oث[X`φ~wͥZ#əa)bkFo[dRTtS<J4j# 1pO^,LkEqm@2Oֱ7:թ:]JϚxʺOT&b⫯2STd]~F&.0##l`ޠյ'_b32;ojށDaU@N3L_Uxb%mZoorڹy]=іuoY^3I؛H] fXC!~U̳Wt٘K1 b6m& `=qVoQG&/*_ n_ľͭ.SSt>3F?7=60 (Yܧ#?Zv /Kּ+o5ot.T*UG&/*B<[@s1UI[-[LSnȿiq)@tn˓F̜|Xdi7t'ZLjzHP\.LeY##`F9_xb#ſ?JT^1Ʈ1?iv}dmLs;灜RxK_Ҭm#6vψ!ʟ+y+G&/*B<[@s1U2Ҷtqvqvz^I*kl..3@0Tb֢ y@I}\X' 3IG&/*ܫ-no:oI%My|Igi6-֛u{dV * n5e չӛ˳Hec\e8J#ſ?G!-9 ˙]~5:vk=QiB;NNJmI-o#g3jnʱĉ4 ),T^Nyx{vv+G$^5*rC"eF[nrMe L_U-^Y ۧ7{m/<gLg1 @sY$l|2lWo+xvnP&fF* 5km:h%PB h둃5xqƱB*QZVulRZRwgj\xL-Ą'L@!s9qL_,;[`Iv1d/(#^Cr3Pſ?G -1S˔e{1^#{7x =a_ 7'i]2]_Y$H- MT V9IoQ? &/*⬫.\cw2Mo F,h3^d8pb`ތVM])cHI {R L_UhR^|kmD#,ﬤӬ&kf}I]DQ|dw#]V >ݤ[<\M'ml,k3Ko$4a#j%/q;Y%Kdz, c핕ҽݾ] W/fN:VմK:]>{Yg!͹v*0=j͖moim.YH[՚#m,w*AE#듚/`weɺ#&I'3j? &/*A[@c1TWe_XOٽ#ZiBkH&9B0ƥrvEiq6-hvg=qG֪ L_UGˬV_Ͼٚor\M1/Ji 6 p(%Cvgk -jI=3,Rp(q=j -1?oS˭gY5%Ryz?/*Ŗ O7<k0a2p0y:͖~'?ltΑ HR6b.YFRx<3? &/*/0ȱp5#xK fc[F5jJ=rYէZ7Ӫ/եcZu+%*oO2NJ|OeY_:KuZZNҢƣ!)@"jƹ׌oGk!` 39o*]1qR_Uky|RJ˼_ڌL[-Z#[i5`cV+O7^3h-қK$Um@'+ &bH<[YlJ# #h0+Gn~^[Œ|RoG&caiv=դT3+.!UW:m#Z5+ɁO8T,54\*T\_U _S}kIm:{e[4ӕK:;pA%y⳼#i}J9UY!1(D$X H=7&bſɘzn37,]Խ׵妣xjus Yp"B1AVuOFou(upNh+fg 7$АSſɘ?of/*aGJs9A[@o&b⫵c֏xjiM&{kֶg+_2Da;Rx±i6qsrdU zC䑠ecm|#8<  %}5/j(sGMbKmq]T^5vlF b¶OE=:O gk[%)1 V d3TN[X7>$ʹ8殦#?{GϝNX}Zmc{.bcV 䐬 Y6z|/a/$To"Ɩ>O%Y)̋X#'d^([o(eU;u=Pmfc O^?!` 3)<\:ً?s0u!O_i/$Wfq k/:9+%|zTq{Y{h9s۟|$o l‡Q3Id-EK%>d hȨvj… [)Tt~k[֮#lt&He8 AAoU$Z}w52\A%tT8-lpdDM Kt[$i%2٭ /ʀFK30v:Mj~̻l|B)k|vUqW9yݪ:ZW]핶3}"cr:c2WqXݿxv$RI$Jb36Wܜ|+Vڟ_ڶ7{LS'V7'/^xeNmfCsX$`F&<"dl'%*H+Oޛ0dMgRwZ+*~eay?釠2ulgʰt۫:/Ѫ$qR/tG\1& :ULW@ n޸EQ</CՍǙ=q|X: R;DfX8çqSN}+JKMŦً1bbʹgbԆa^xI5Re7utU O;ǥxMl$/ װA+((^TVX`1\gN-7׮O7?h|7}χvm͌ ldm51f"4"%8eU"iciwڝ㽞 s9KYEsK8O4@OK(]Epu+M*)6[paH0T8GuCQHaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP+#D SJu}k/ jHjW˯_Y?'7~lo7f,$?p/< zw٥k~ ǎJM:ﮡ@8cב~H؟fgS4SO}m APx=23v5ni?>/|V*8';yRXePWR2#@_O&K?):WecUE7d~bPK?)i?Tgl-i˗`FհTK6޹#pfgS5b6dliF73[>`Ҡrˑ FBui?>/|V( fgS5bfdm,p~y"=Y~<}_O&K?)ԂxT3"aV$)#`}*Ji?>/|V*jq\𺣂@dW\ʒ (fgS5bn] 7*!I@%[@_O&K?)Պ(٥h4?M2=J]J]>7wwI&( fw`պi?>/|V( fgS4ynX$DSg *H #)*ÎA٥h4?M-徣am}i'mspy֋{YaM]Ja`:|ǟO'٥h4?MX+_O&K?)Պ(٥h4?MX+t4T ,*{@ PfgS5kvqOD2~i*:uUi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5b"C"xSfm־"F|xk2_7'D6{?܇]׉v\IC,Okbr,|ݎ pPr-zy9O䍰_?͞t 伽ԌZէZ &P+F6#W(6%U76/u-vm.}EkyI,w 2"$ ߏS)^'$w̠l8f$w*I>j4&GR]Ű`\nQt🃢Na8dbh:[:X ռ2.)g{K.Z{UXɥ*\Qw3C@rIiS | ȼV6,!m/$1Ƒ:4M MYz 0En!#BQ@crI$$xI3{GRww[KZw#g9XOYkmZ=>y)hül8TcIc qQEؒas/5YȴϵtH"]/ވu | 4hSj2޶/HRFO44 2 l}rE\:,.F4 xeV.ݖhcRFţOZhĚIkgtTr s\Ҵ\孩1`N\שK/Oշ4* d#*r#Qp1Mk|3~V~ͻ|s{lԘIx,~l8c%d Ld^'K)Ss_q-{΋`#@ePQ %y}ǭ 'I{sD^82&?~^4Qp<-o5{;}2C=bWR]Eך OC3 r>HٰMBOOboK >y.V,2 sЄ+lj]EGDq"<;FU`.O¨Ϡo75GǓ1#g1 ,T}u;T;{sdBo1b/Kg CF&I1 nzP+ dž?Z!;z~H 6Exn.cϴ_pn?ꟁd<7iw}=:s\L?v[6嵼_a9o| ꖳ6UiַV]JX5pS#$bhx.΋#ų ._*Leյ%LԪem|Oʪv"LOs}\i0?ʒ¨]bUtҤfY.M1G4TrNwc^}3O֮.lmVLPQ3[Rk0IA?*P2Fϟssj#ϥͭ2yyDZ<[n3]YZ 52F ?iav-ٕ8bWe4l-7>i^fl% PYOs}\i0?ʒ¨]\YVC<)%ܦf;#HG ʌyXų 36^%4OWq#ٵŅ"xK$, #P2KՋF#ṯbB=H?>[cd9EYgO?/G-<\UyvZM+p<-8%\f.3}RuB%D?[l5lyadz$nko-H^I$U Il9Z&!kmgdGPXFn€⸽_E|=z-UT{Z3%ߑ / d ]ݖu5^,:7;gr#U<advlzn^+i-uC`FpAǸضrU$ִۛVw-dҡ{T[XeV˹yp[pv QC\`"K۴I-ʼn<ȉ_=yݞ|. t۫x-h%@쌮dC`9il/ K4>ȕdil/ڬp;{WiK{.yqjYOxmn&Y0Bf//3ʭ'u\&KѦԣ]6U$xk~#( #?l]GVuֵBkW^5 ;ї鑚)HDrSO=VIJHLw2qmݽ y 𮭩O^[Db$cW0R*I.vF-<\UضrU"EKMsZ;VbA9S CxLcrT1!VfMm#it˚].?l1p4tEw^ɹU Hݐ V}+4VrJP_8Jmr[/4>FyX.XXҷhXy<{Ù6 hJ/f$vGI-׆->u-$L쌀 ]kS._*=k6wr흭rXF+21pcsw>zYTLY[;9. Iqx(T*3.[?yGqj c8EQx ,g{8|WX_yZ{{;V~ͲS/AJy?6ᫍJN\[-Gqw7Iy;X9]7-ݜڴSZ$lȑ(=>F5pik\=)]nUbB7dU=J ^-hvŦj;QK&I%f]?gBIe-QgmFXln.2mЃ # V?*Y-<\UضrUE_?;MYc-bI1ΊxB_ۉ-n5m3ڦ_Gkk-q}¶j$10(?7<74]3hIjqr,l>_>fY8N 0s3hbWZVL-8o,hϐI*ı֥$}W$>m7'O]g>d?-( #ų gI`\bi3|œ&7q??#͗:u2]K7N76pTعnu-D}"[/76'xz}bK:;=+PHY!'3 +Yr+ wIovGAgO?/G-<\Uqk>iΣ-..#=!)G2KV B"'}s7/Mf+E{Xf[ەğ@P[]e;p.O[?y?l⫗Ҭ;]GO/Z7P 㺵 >3%mZ2+=[R\V` u޺ n޺ nO}MԶq|Mzq*NOof{;{kiVng,}3NIFW+aؑޟEч(WmMҿ+o o7IQ(9Eҿ+o o7G[S ⹷TT=Q>Vn=Qp\!H4(9T,Y,I'$0J|)WmM)''$m0=N==J=RѥΖ4-.]<"wUѰnj qV L$q9UE#qI*F; 1 H%ч(WmMҿ+o o7IEч(WmMҿ+o o7IEч(WmMҿ+o o7Q kYP̊цXi(9Eҿ+o o7G[SJII%DydjvlSc@Oj=R_+ti_ϕ7hÔ_+ti_ϕ7hÔ_+ti_ϕ7-[&ugX ̪@bRezri_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)E$D$<Ͳ5f`±Ǡ'IGa/[S?TpOͼwʡ6 dGޏhÔJ|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)@kng(FI 9*?SQI͵`1nSPg-,Z+xdDWCHAAOZz;rfGίBl-__=ZQo9_s#gWj?uz(е: WV{EWZzJMNS)8`Yw&1ҵԺG[~#ȃ}"ѩ_.?Z?:/}Kg Cx->m"!jZ}+8+m6H`p";q\o?܇^^NwS#lWg]asy}6R7NT)/NRPq* /!-RQiߤOZA>p !4q|K 'ŝֳM-e3BrF(O~WaϯҼ'6u{F >J$ NcP#$Fp~Onn k[gQ)l |ͣk? Wؿ6}s߷ۻoǙT\0ojPwViT ufvePᑂ lTQp-`ҳ]ıYF-+4RX4A\V*UF ;{x(bPTP0RQp9}SU,]B8}R F9 ?_ѮͮeΙl\˯gd?,;O\z\Q5[6Yp,"RDeaדpV_" cMŶ’F3]wm3L2`~xt!Nڋ;;}>-gĒrY嘒IbI$I&\ڭ5 X[+ Crg@wpr3#\ֵ[5+)L$lVq$w|r{(u%Ÿ`o$^W9a 7.B9eF,7EŭQj[e,JۈEίosy!'jg$(8:\h}D5sMm=Ʊ Yپ>ҁ$T2 ˦ f-n;g"y˅"0sHj +IY[[hD`CNO\m<[ ClAl쥄H! E"` 9heÒ:(}axhtřq%̶,] eʓ-dkQƧkM $vrݢlT`rz(osw4:xkհСYGxRK !X+<\?~]A!.aYi-KpckxS\o]KO`6cm1 "Lm~ h-5˨.lj/@dV[B$ 9\ (_y ++oR݂36آ,mxkVm{m%SANlTRCrp3EvQp< z_Ba#Ϲ ^ e4-ќ$2NtGT73s\E_XY#G q }߸Q3 8#zt_FhTxlDQydfw"l 笼Cvѵ_إG[]H,dxlrQHَpI(NsuwGR_Eώ{ۅUZ3ZL>heA|u"a^MXmR.dJ- |v~fb ˎΊ. 66Sr>o#@L:&]@_8>$%3kp֋q4Is mCXN%]Ow\ #7y9Sc Ab@yv7Y k["mNxmYȆDFsǸDjH7\5 }ɷHmIon+4YQFor|^.zΩ]:{v[(mn!;qg"d1*36\a2Ux#\ֵ[5+)L$lVq$w|r{(gXئu% J|Bd"}+QxBu=Jtp=Ԣ#,w3÷`Ͷ($>[f^> (߉#gaƳ%b_ީ$[VAZF7/3^Cvyw1Ŧkm*͟i_1V DpnW$#*A* Qp<"1VVgc.fmDY!2,ֳq@өϫicU4yf8#(yY6C>(nVK=DlFa"VRYc1>lEwm 58FU9c-$f',bQEo5{=3LDך|Q [iqǓ cnΐ9yq}̖+c!N`072NV6ERQEQEQEQEQEQEQEGTER]o~uO_5+_Y??'_%~ dž?ZgS!B5Pr-zsCO*X{;~Hh͌y#s*+5 /mfh;5Y`amHw#r<?R35{y#scj6s#[F>q-J 3.l=:΍Zck*q _^sFs ""΄HHeT4l6q)}f#AUGV\[9#]H s,K \k)·SYvC 7+Q_'UZ?/!&T;]Me;/9c뚽 v]W< ѫSnЅ%h/ſu%7y>y?]`o. YwwzH]ZeܷƁ2P11r%_jiK}Cz=MK+?_bf6W0U v;u3̖Zdf$~#dPO ` %Cݷ'N2K 12F1^r?)7dJ-(0(((((((((((((((((((((((((((((((((("F|xk/ HjW˭־%tO>Kg C! ?zYQ"Js$kl騬/KfXύ_;fa>6Ks7h/KfXύ_V l2VXRE'UKٖm~(̰oCXYEѻjͿ͘{>ٓ1=rs֍_Iutn̰oGeߥ \ 2z,atEc{?f1&6Lt$iwV2Xi&[9\iѻIR$͟^zԟٖm~(̰oG4B̟A?K}$mvN,-UKfXύ_YhG6—4GfSsqF#[R ;9TAfbx^II4KfXύ_!fE.Yyw/,? O /M̰oGeߥ OﵯI>ֿ%iٖm~(̰oJ;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ ?,?/Qh;k<._&Ioeߥ d}q;Rq/QK /Gx]$M\k yHT@+VRAwkk_w4}K k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ k<._&٠1>ֿ%hZ (h.OI>ֿ%kn= k<._&IۢfZ Cso H8"k?3DiS($ uO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H 2uf/dBU^p28 8#7xJӯOR+U1 xb0.˃%.=͛}.? l.ln.$6܌##=+GYj"t:6"2ܴQN^여aQp|JA8`*֩iaj?YDkqdҸ (`?̸'n͛}.? <ٿ |ٿ͛}.? @MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PT>lq~Q>MEC>lq~PzTlq~S]6CiqF‹7j٬M-Re$~n[V(?wt&}ki,㾟d$hYrBUg,k* }ws\Һ- 0<#G4GM kl绅K!tm0˜p{:Ԣ]伵UkЭ2 & e/;B]#3 : jQTm7P-ng}2B#ʜ>Ҳk$͒I V2,%q]۟zO {{.#]1GIʦ07ʘצ |O i}vڛh`gg O|#l&A'1m#HƩ}: y ˈoN+r ( ( ( ( ( ( ( ( ( ( ( ( (0>5b>5b݂r~6/=1uY5% yKkС*|wz)0#^Cx.#̃R$mEmiv2\OʗKգ(;N^pX zk5Mv)X[Kgg[GtSĔvDSUiV=x,[v!YHz8_Sk9 hڎo-$qYi5*LCd|nU wHZ6}"M24Y"LXD0s@>_}7ߤI#n[e9gOU/9ku$/8W0,lH2I;{( px\I(%'VΖ[vj.p1l<[jZWѵ]1nt-ҥMT;ᶷ,T>qZj%UG }ӭas'#0P*AVV;qEPEPEPIE-PIE-PEPEPEPEPEPEPEPEPEPKIE-PIE-PgRҷ+ ?3DiS=nsA>ԯ[}EDSJudoO_%~ dž?Zg=G+Ͼ dž?Zg=G+?c?U#L/ljFi;  (_U:[#c2WgyQִ<9 to$lޅ7`c=sۚ&K}>M7.Kxq,,@2U6c{q|icMdחxFyS֮#i+yCі6qAR#nCq K *M/*W:}[F'<eݧ5s/T_5MMH V/F{f+^O)X!28VFdO>z*?s}7ooaqM~A}-V1?{{x_ݽh*?s}7ooa?w_igдWCZNo?_S@V1?{{[>O>z*?s}7ooaqM~A}-V1?{{;(Mfu7'v4J@eD{"e%vutW[-F֒]-ŦI;CF: 3/ tzq^ {inCFn#s=ץ bѧEsF }^jV(3FHo܇I&t2e7Fw±gWErSEqiu>kK,"-Ǚ#`6Ƨ '5xz]IRudl;3޹_w ܒ:z+<]{6Y1o{["Fag<Ѽo$d2 Nrp@:+sVV\3s"$? EشzGż|2`%l{x\Hʅve9pFA^gzK][7hu\EY7;}oWJN!Xc ZfVIa2I]m]Zx ]4X5h]"o/b#(]8#V/]&+ymeX:ANϞD]+`j׿dv2H1!s(̓TTsae9k+ӄimþC/( @:+!#{Z[Ok+| b1 C'|I;anH$,eYAq˸i:m.Oki$dfh#JHp kۛ8tԽ=-{> ^_Am,v["Fޒ6QEaQEQEQEQEQE-PIE-PIE-PIE-PIE-au/Em"gQ}?ZTa"F|xk/ HjW˭־%sN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSQxYc,NwJCҤugwu K3o۰qӅY,kSDHGgh‡br+.Tʒt#9s6y&zhU#_ ]P,l ln]oIҴPx"X)Gai؀J) v ec_jͿ!]}\W_5(>M}0oocz?+v_ԩgGºI OQA3k?{{WдQ[>O>z>M}0ooczu_qLJݗa*}3k?{{P|+Ě`-jVSϞu_qL]|g$?hRe}Jv||+Ě` ?&7=E} Eڕ/T]|g$?W_5+Z(ԭ~?Rݟ= ?&7=EºI OQ_BGn0>W_5(>M}0oocz?+v_ԩg+DUd ++Ar'ƺJɱ'}MZk[l2v7B:pLs(3FO8Y G9'#oeԑ"X$B|0QI[H Q@^ UQk y0F :?//oX"Wu@B#DS$ZSvK5mOQ#Ռ[-IQH3 ƹfcyG/ Hɿv 2i"HpIXX/p]Erޝ.qLU0Yc1ŪB.7CcqvK5}OQ#ٌ[-IQH; ƹfcyuTPE,nv/mi3fP\kWlxmeh H-<9Z]^jڍŭǟ4`=q!@/Im5-F"Di&XdF}@#1` ya "VE)j X^x#F>ڒ9c0-)zu__*ȷJJsFDh}SݖZ)(Z)(Z)(Z)(Z)(Z)(Z)(H3-+jcƣ贩G?DSJu_A>ԯ[}>K(5_=xjCA7xjCA7F3_4Φ(< ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0z_S֭Zʱ'}MZ*~Z֮mfw0;.[\2:g={tuy\ :X$ ITg> px\Y2E&Mk[m$9ڥ8RsӋ6Eq;[[cs|uMMT;ᶷ,nf8muZu[t$ȌdeS8dQ&F&A>s"$eA2rIQQGnCx R$Ae R2M~t]eb'~uͭ2]qs$V@ C29FIg;=6xw}gdQ{d\"!f  8V IEOx}G"-n-t.XD[mW178P9Ǯx4+S]ʦ `I0`&IUarxV w_0e> |lc̓~cp1 ӮhOteG$+*2Yx.@Xׯt ǩǥ][Bl1" fJbtIaN,|؆P2b-ͣ i׷W.-ۈQ"87 L*6>7FqsyA.g I\ yQ!U;˂f^\YٵVKIX=1PVe7A&;3lwͥizP' dO'w!xqXg-nсkr(H@YI Kl/ $|9gkNږ ϱpW#uq .cmh#麏 ƈm-8YdVpa .U<4f@%""+y svldcy6s-BSm#}JH2[{FҥBڪI$./5[-"%Y 7o%٘z~i^U{}1ECw˔VQ$d^KLm'{;H{@IY| WPko ˋX|Dc(Y " $ [hE^]X[G0yOK#<l/I/!Kd.c[,ē~H0yewd7k-&i]+&h s6d%ڻ2IpN+_ pwpqqc#U.3#$o=vA"![iftg Jp!=I$t;J $l/b{i?-UL$D)UrYTI{=?L4/PK[䈪=yHdc+(w`G wWz}\,MQ2Cp6JGX1A捺ƪ 7PK)U#cfFYOǮ sv~mKmǥ۵ sb&B +w']XG%{RpP@NI$]-PIE-PIEJ(hJ(hE%RQ@ E%5El4O2GTER]o~uO_5+_O??' |y/9ku$>/9ku$/8W0+:B(((((((((((((((( ;5Rz_S֭:l?hR7o0&Q\Is+O.4sc}GEW5Ww±Miksjа2I [ f)R~C _oc?jWEsZF{c-VT-8] D ś,prg=*}z\I2i3EQnKI$y#9##;i7$U]j*,$& qATM R;|7D덋nuWt5l7):\] ?3$,}m-/VbdƊ̑[}svfN\~p j7~ݤvZTw/j7l 2v@1SiVQYZu֟|K 1N&#E۴r~k4y>~k4\ |y?5<y?5.T>sϼsϼj*9OƏ9OƋ5'G'E__p&}h}i\ |y5<y5.T>sϼsϼj*9_Ə9_Ƌ5/G'EMEC??p&}h}hQPUx=>ZƏCҶ+? j?Jl4sA>ԯ[}EDSJuO_%~ dž?Zg=G+Ͼ dž?Zg=G+?c?U#L/lhΐ(((((((((((((((( Ǭ7jԬ5N0[!j+gЍIQ[?hVuyŅQc˚HU0r0d`O}>Kݯ#]pу"x OEW<ʻAkok(| yh{qԟZ1A_+ytQ-[A ārrpMMIEKmahC ( ( ( )(Z)(Z)(Z)(Z)(Z)(X}?!R7 ƣ购zȏCҔ"F|xk/ HjW˭־%tN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V=dkVfYuѭZuiEoj+gЍ1E燚5+M.+kHdLnO,aF8_ĝ%Q3c҈HV"Nsrz7ڤ R1 .N?*u.m -Ű <) žn =xM̨u#!0FQU?_ :FR6${@?tV#m`GϷŅC]iI˧tIhc8?wv;#1GY Wh"*p2>l [F8 ځLorNpE&IgexK%V)t rkg<zt[([ifMD#rgt2Oi)7ܧ1f!)KEu(|fvܧ2>19kr)Dk4jۿ#ӯu]>&I"myʣV`ǃ[U.t)'Ӊk $29K0چoLyy3y[xq~Z$fL#m?d`qjQKۉ)8]iw\gp?P=z$mHˉ#0f؎?M/|򼳲ԸQ ѴFq{]4fLњZ(3Fhњ(4f (Z)(Z)((((((((+cЅKQ\*Z+"? j?J׬1-)K`G?DSJu_A>ԯ[}>K(5_=xjCA7xjCA7F3_4Φ(< ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0}MZ6Z5J0[ VԵc%E燚5AW֒6H!1I<}Lܥ`@ќ*Gv`w$/\(B5p'ER|qFGܔ?8uc5oCmc +4k %逤Kmя8!RHRWč)1q *+ }{m-,r Yc,i'i'RZkOdq8UTG)U+;צ7uZdѧ΋·$mcn^O\ R $FG␕ 7 o\@7.hйm7IqyP8kkOv*<#l2q VM߈l綘6i0[jo (mÀy`yqm/gX @+2;I`F8x J*ѼyDdm 3 Պ(((((((((((((((cЅKQOh/-+Z"败-"F|xk/ HjW˭־%tN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V_ѭZ5e-oգQ-Tp?jJgЍ|ĝ%Q3G'+)4)@mTu:#,4r_]I4r*۸@kB:JI#ȃ}"ѩ_.?Z?:/}Kg C:zfW| C:zfW~F_uE!EPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPkVgY_Fh} dY}#@ĐE燚5+IY]$V֐Ș$XŒp>!t5V²͎{J"y BZŠI8L ,su brqUioo, =G2͸$vwgyx)[y]|d0*4eK<+3"$㌱'瓔{~YO+G,  HPvܑ^-nP"I_tbB2r!g9E[PJfD qFpœTn,cg{t(k}>_.htrqJr'LF;w m-k< $RʪAI(Gs0i讌u{w;ț 7$L IXqZVsC2gdrr pA3Q{.|.YRF/V\TGj;ʛ#'qBN[]=\:f7 (YM˷~6#GLw暚@@4pg !r 9n qg 4E5(LDs$tncHeX&&Ȭ+qˎҳӒi25|d hq~!:%=5>G!Z6%V/(]TGFugTU%,0 EZZFI4K*q猀G4IBnnZ~LelaX(d'.II xѥi"Mdt+r:}h8uFC$qUf@-0QCmȑKk"{PE;P;z3hi(As<kL.AܤsONZ4SI.$rϿ iR  ;{ՊY}"eJ~i<=®z*ڮPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPS*ZcЅK@d!}GiZՓE)lL HjW˭־"F|xk2_G'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEe-oգY_ѭZ5iEFV2Z*^xyY!*BEmi I(~P@UCieddgk7`GoGwq, HF}OLnQY7Z6J1Ec~Q $!텽%"4K&ErEiQ\$ik%нH"GTG9bO/Oq&d\H &TGO^({X@fYLVhƂWU7`)MǏq۶< 'pXǻpInǐ:{jQXY2QIUF9"iwoe q-ᑾ}F@7(Y|QEqq fc;Y bPܐyuV.Pfb!GiQT" Q&Gw |#Y,aGޘʜc##hVXhf[E,w~1p~:PyP_ 2nq 8h\Cn!o˓cq=95EeeL#ATqn?v^MZ&YcxhVpW9lG9Z2˵fϜ`]ywvz1:JI4M,(@ G$N: lQ@SMXeH*?U8L*2ԯ[}FK(5_=xjCA7xjCA7F3_4Φ(< ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( (0}MZk:Z5F0[ VԵ$/<<Ѭ_ZH"D$c?Ilu#QRI?`Gs#eW1 qVUa[yİ*q#==30X|Ž#۽18FF?1T"Эⱖ;hYc P $hɶUE/ʎgwv tl-e)P \ Pp 2()IBY~8& UĂLw,SbB ur ~]F].N i<_HK{ E22rž_?xklKM`OnpP18Aɢvo9cqU\lۏݧlדNFnnc̎W2nŁoPpFqI Y+$Rir\EsDžzt2L洯L ɷ$ m=j;%/.$gD%hnI}TYlԮc&Տh <P@uRHCmK0 7:eNNNU ׃bUV|f3^i'R{(4icHn #(Z>b[{{£䫲El.ӯ' Lj-T 9h$xє Oq$Z᝭Ɵi„˪wᣪ)tK7B+'EwA@#ˉ'rK;َO'Z9_,w0[< xe~mM`{~R'۷9mO^4A@nY!˷BS˷1皵\Gp2#rx+2<70{H{pI IqCiR  ;{{-%4bTUhҲ@ۜWs&e1)˸_G j"A؆TC Ua*E(bNM>okymkpi#ʖ8 T6|phR3d #;yj0KdޟII xѥi"Mdt+r:}hIc Zd\FLљ#VÁc{Z:Am9gd.c cmS'clwR-q*c.d5bE\$KO*9RG9sTQEQEQEQEQEQEQEQEQEQEQEQEQEE?BV?OTVL_OY1_Q}?ZR"F|xk/ HjW˭־%sN/͞_<5!rנ??ݛDI^}_<5!rנ??ݛDI^^q#agSEWtQ@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@V_ѭZ5e-oգQ-TP?jZgЍ%G-k$j Z+_v**K=H6c@\~TŒ9o%1$lTHT9l22BH W7/ ֍c.J#.7) GXyMmsw0vLdB:"ɔEo!F8,usq B" A<$BifMb]̧?6[8ElQX؊)Z%5V(SCܑ++yn&$[ۆ2b1ϭX((((((((((((((((((()ՏB-E?Bb购jɋBҔuO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭lY}#RP?h$,je!H>'n?_4S$M̪u#!0FQUY9/䋃9C`H }s5E 2W@us4A!w(2A,P~u.zK#)>Rnnz鍊(iq}cIew9Tdw,N29QOukͬ~M;xۃڷ( 'KGygGrasK#cfwC,Aw8!@RMZ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ("X}?!RS*Z+&/ ?J֬/-)K``|GTER]o~uO_5+_Q?' |y/9ku$>/9ku$/8W0+:B(((((((((((((((( +/k_S֭β7jѨL*(?՟B5-EF"[HsgV\:KaYHfR=I?M5`)ԁCo0^LY/m[cFDJof#$/e Sh*{HaUCFK"ƎPeX2;wx 2Ѭe>W|:$Cտ4&f #2Fc%a8tL|W3Jdr$(H4Koہ nrU+d[mJHxg'UՓXfRdvݵV#QsE دmod}@mPvYQs$hʹ2~]e8N,iC_d` }a0sx^m%[CgvJ2ۀUױp 4O6"@S+)1qz^-^N]9|F:\^éyr<8Ao383/y8kk6QYܹ&^pb*I-nqİ^< Ͱ$_$v}к2,p~}9 8s6WI"ʥBeܹc>oo-Y#Y~ H!Cr:qN4((((((((((((((((()ՏB-E?Bb购jɋBҔuO_5+_Q|GTER]o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭l =}h1U@(7'ƀ%OGOY?BzhZ*/!=d4y 'o h7'ƀ%OGOY?BzhZ*/!=d4y 'o h7'ƀ%OGOY?BzhZ*/!=d4y 'o h7'ƀ%OGOY?BzhZ*/!=d4y 'o h7'ƀ%OGOY?BzhZ*/!=d4y 'o h7'ƀ%OGOY?BzhZ*/!=d4y 'ou*Z`Epbáf'I@d!}GiZՓE)lL HjW˭־"F|xk2_7'Do?Pr-zٿDPr-zٿD1|6u4QEyHQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEe-oգY_ѭZ5iQ@Š(((((((((((((((((((((((((b购jɋBҔu?_5+_QGSER\o~/p7~lYQ"JYQ"J~H :(((((((((((((((((²7jѬ/k_S֭l(aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPY1_Q}?ZVd!}GiJ[S?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ǩvo%y?܇^Ǩvo%yyg$iw_?͝MQ^yQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEaY_FhukVG`AEfxEӧ/uk+iqNU0 _(4WSj_0iG&K9%9ڢO<2?`-?Ɠ RmXg 3h?0iG$<{tV(񇆉i54k$neYNA[4ERQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQA *[_ؠ ~o?b[_ؠ ~o?b[_ؠ ~o?b[_ؠ ~o?b#mIcf IY1_Q}?ZVd!}GiJ[S?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ǩvo%y?܇^Ǩvo%yyg$iw_?͝MQ^yQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEaY_FhukVG`FGq.Iwۉgoy 4yJs~& (YK gD@KYcI#,FP+k_x[\iI,,G$: IO0Iɮ5H~ozjZi-m>IIդFb,[% W(Y9Hлѝ<*XIRy^ymۯe[:7FZf|XOS𞥨B= .$d uΰYI YB'vK>i5Z֝뺅#;W6RcFlx `wJk]+Xf4;E+ 0PBzbeH <,aRs {+]5oI_U-?v6Š(((((((((((((((na.Bn/tOTԘG<[q3m$.x*:5+YmD\$s@C}oq*MhFy֬W3i7_K7 nᕗ9yci#c;RA\GfA?΍,4†O . }Ps+̈h_ct;Ccaԕحs7zf ?v|e}Z -Oq"c5CsB&/-+Zb财[S?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ǩvo%y?܇^軼(Ɇ@9<H/8W0_?͝M 5?fQ 5?fW̍+kOͿkOͿ9EbMiMiY26_I?6rI?6r0F 5?fQ 5?fQfڢ&L?&L,ÙTV/$֟ɛ9G$֟ɛ9Es#j3o(3o(dmQXZs&mZs&ma̍+kOͿkOͿ9EbMiMiY26_I?6rI?6r0F 5?fQ 5?fQfڢ&L?&L,ÙTV/$֟ɛ9G$֟ɛ9Es#j3o(3o(dmQXZs&mZs&măY_Fh54vI6d3#z-?E?: 3W i%y3)Vv,a"XK?,?Zz-?z-?W3Q?,?G_;ji4i4s>߀r_~#e ֯A OGA OG3*/,?G_;ji4i4s>߀r'J:=i$)R8wv.N)z-?z-?&VԵEU!ih!iiXz-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? \ fۏ?UGBBҰ\m*/OO_OO_rM/6X?=?Ə=?Ƌ6Xq=bgZ?Z,$q=bg1JDPCaS#i4i4X.Z/-*A OTmmJXd0E)l s ?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^Ȯ0k˾ dž?Z:3/`#_ʤ5?ZlJX^Zq|un8έCsz΍Ezl77F袀 ѹ:(sxtnoΊ(?77F袀 :77袀 :77袀 :77袀 ѹOEnoSѹOEno΍EtnoSEtnoΊ(?77F?POF?P:77Eno΍EsxtQ@?tQ@?tQ@?tQ@ާ77ާ77?P:77Eno΍EsxtQ@?P:77Eno΍EsxtQ@?P:77Eno΍EsxtQ@?P:77EnoSѹOEnoSѹ:(sxtnoΊ(?77F袀 ѹ:(sxtnoΊ(?%RcGopen-zwave-1.5/docs/images+css/Doxywizard5.JPG000066400000000000000000001432061264474202400212410ustar00rootroot00000000000000JFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222B" }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr $4%&'()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz ?׼_smFYIl"W$o9< `UXbQ+ OZ:fᥱKwWFqp^ӌyOd>rJj[w9Cm~0Qϝe^ٞ[B&Z3%f1F0#q+)U<]ҍgϥ QTtkҋ|УJ/Bv]8h\äe&3)KDg3,J!b]?r8S1 :4́y=j}{7MߡG_m~A&Ez,B9ی£^Om!MBG t-iE>vQߡSˣY2jA=^|0Am效.AGh6%ߞھQ@)g$z VJWWmۣ-{ҋ|УJ/B /yogˍ>GHj @]]ؑŒsMLq4%hwf47ֿWҋ|УJ/B K|xX81i:WM>.4,0 +~j}џ~dQϝiE>vTw5KZJ[u2b6*ll;ҵQvĬ6"#~>R= JI]ÏJ׳,iE>vQߡPGjSY뷶 X̰1LA;dDžvVTn$]AFjYa h半:ᔎ 5O%( ?;o*9oK.ߴܴŷ g` Qnu$]%*4y{/(Ôwg#JUw8jvv3;o(ҋ|Ы:{mF//|?fa]َ@H`3H^+>m'QgJ<,.xA*եR*Qz1N;o(ҋ|Ш&5+uӮҗ`$'#G=:=UzD&!mntJjv>^dQϝiE>vUhGKd$<RH,?J>hey)H-<@-,:qi7jߡG_m~Z|+Yh5; #GNҳL܉,SDM|)M^/0Gt?qϝi>vTQ蚬"!1 ݞuS+)fQ n[/J;/)=i>vQߡP6v/em rJ.&ٴp9۶8q}M>j}н;o(Ӌ|Шfѵ;xm68`FO@Ď#G6{okw[WH)fr_m~qϝnciWљdn{FG'=M|]*LIPw\p7N2gUٿܥFodqϝi>vVx6[ RIﯴmKQnݼF1\ӯMߋ;yM呜pSM,E??F9SkN/B8 m'QgJ<,.xA*yyeckv-voIT#*9z5~Қv>[Ӌ|УN/BאK5D3#2ԁ^ƭk麃Jb 821H✧N.ͫ&GߡG_m~?K;mh䴸hh8蠞$5ڔ/qjm@&ߎ }k9W(QKlAߡG_m~VK.EO[ϲ>n߽Ґ_+h")^>܏f_qϝi>vTRh71K^0g @ΘN%i5C2BtW\g/2_m~qϝ6MgRlgYl3M0ac%Ix^X㸆LK=XǷ!ܩw$瀪2x5F Iiob㇩&O_ЫߡG_m~I6k&uw]ZLdEl U[Sӣ_ivʹ42z$u ?1J7_m~qϝNo4ϧE-͒i>vQߡZv[Y\6K[EWQX5^SтNPyR&dg<}np׿ɛ}Ro>RiE>UeoM]DX] &pbo/1ZVҵhd?6T101s p9Z;fQϥiE>U[:eŷ΍pԼ9ugI=$ ِ1\ .4oq2i?QϥiE>U_wu &ABd _$ |}2 f(dxfT8)N*qjr(V?QϥiE>UWӯcK,KW;Rv1 {jU"[Qux$``ą'toJ3J/B( xVO,l!;ֆ8|[ +(^Si8$Z!RFQvoJ/B( ]SXMI< GֆѵD{o%^SR'<|}&ҋ}-УJ/Bͧ^u=VeG0 GԬ"ivhY>#;úfɿK_(ҋ}-Эywx@ t"E|p=j߇kصKP1Jܮ9#ޱ"54xjWhJ/B( F;@ @аvqКF%i5C2BtW'ҋ}-УJ/BeCNQy(]7ț{z>N R۲7sYKF2籤pӒ_ZߡG_k~]|1kMqt7e XٲsFk*KӶ}xy2ndsNZU>kLS8|HZߡG_k~fcڌ{Vܨϔ4B.cӬFHb=@vzڀk}㕽%8x@NҼuOd;^V[[ >k=  ")=7lc=֬ǣjrB;N]CVpGUo6\c 0Way$6$c$8(Q[RD_t)ѵFm*76 OecKw(HN:^>=jh22 kuj޺SNQrqkV9`I7*m3LCnmчcQշ՗܈.0-}u6R5vy\X=}̡|S?M?3Ս: he3ِa'oث[X`φ~wͥZ#əa)bkFo[dRTtS<J4j# 1pO^,LkEqm@2Oֱ7:թ:]JϚxʺOT&b⫯2STd]~F&.0##l`ޠյ'_b32;ojށDaU@N3L_Uxb%mZoorڹy]=іuoY^3I؛H] fXC!~U̳Wt٘K1 b6m& `=qVoQG&/*_ n_ľͭ.SSt>3F?7=60 (Yܧ#?Zv /Kּ+o5ot.T*UG&/*B<[@s1UI[-[LSnȿiq)@tn˓F̜|Xdi7t'ZLjzHP\.LeY##`F9_xb#ſ?JT^1Ʈ1?iv}dmLs;灜RxK_Ҭm#6vψ!ʟ+y+G&/*B<[@s1U2Ҷtqvqvz^I*kl..3@0Tb֢ y@I}\X' 3IG&/*ܫ-no:oI%My|Igi6-֛u{dV * n5e չӛ˳Hec\e8J#ſ?G!-9 ˙]~5:vk=QiB;NNJmI-o#g3jnʱĉ4 ),T^Nyx{vv+G$^5*rC"eF[nrMe L_U-^Y ۧ7{m/<gLg1 @sY$l|2lWo+xvnP&fF* 5km:h%PB h둃5xqƱB*QZVulRZRwgj\xL-Ą'L@!s9qL_,;[`Iv1d/(#^Cr3Pſ?G -1S˔e{1^#{7x =a_ 7'i]2]_Y$H- MT V9IoQ? &/*⬫.\cw2Mo F,h3^d8pb`ތVM])cHI {R L_UhR^|kmD#,ﬤӬ&kf}I]DQ|dw#]V >ݤ[<\M'ml,k3Ko$4a#j%/q;Y%Kdz, c핕ҽݾ] W/fN:VմK:]>{Yg!͹v*0=j͖moim.YH[՚#m,w*AE#듚/`weɺ#&I'3j? &/*A[@c1TWe_XOٽ#ZiBkH&9B0ƥrvEiq6-hvg=qG֪ L_UGˬV_Ͼٚor\M1/Ji 6 p(%Cvgk -jI=3,Rp(q=j -1?oS˭gY5%Ryz?/*Ŗ O7<k0a2p0y:͖~'?ltΑ HR6b.YFRx<3? &/*/0ȱp5#xK fc[F5jJ=rYէZ7Ӫ/եcZu+%*oO2NJ|OeY_:KuZZNҢƣ!)@"jƹ׌oGk!` 39o*]1qR_Uky|RJ˼_ڌL[-Z#[i5`cV+O7^3h-қK$Um@'+ &bH<[YlJ# #h0+Gn~^[Œ|RoG&caiv=դT3+.!UW:m#Z5+ɁO8T,54\*T\_U _S}kIm:{e[4ӕK:;pA%y⳼#i}J9UY!1(D$X H=7&bſɘzn37,]Խ׵妣xjus Yp"B1AVuOFou(upNh+fg 7$АSſɘ?of/*aGJs9A[@o&b⫵c֏xjiM&{kֶg+_2Da;Rx±i6qsrdU zC䑠ecm|#8<  %}5/j(sGMbKmq]T^5vlF b¶OE=:O gk[%)1 V d3TN[X7>$ʹ8殦#?{GϝNX}Zmc{.bcV 䐬 Y6z|/a/$To"Ɩ>O%Y)̋X#'d^([o(eU;u=Pmfc O^?!` 3)<\:ً?s0u!O_i/$Wfq k/:9+%|zTq{Y{h9s۟|$o l‡Q3Id-EK%>d hȨvj… [)Tt~k[֮#lt&He8 AAoU$Z}w52\A%tT8-lpdDM Kt[$i%2٭ /ʀFK30v:Mj~̻l|B)k|vUqW9yݪ:ZW]핶3}"cr:c2WqXݿxv$RI$Jb36Wܜ|+Vڟ_ڶ7{LS'V7'/^xeNmfCsX$`F&<"dl'%*H+Oޛ0dMgRwZ+*~eay?釠2ulgʰt۫:/Ѫ$qR/tG\1& :ULW@ n޸EQ</CՍǙ=q|X: R;DfX8çqSN}+JKMŦً1bbʹgbԆa^xI5Re7utU O;ǥxMl$/ װA+((^TVX`1\gN-7׮O7?h|7}χvm͌ ldm51f"4"%8eU"iciwڝ㽞 s9KYEsK8O4@OK(]Epu+M*)6[paH0T8GuCQHaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEP+#D SJu}k/ jHjW˯_Y?'7~lo7f,$?p/< zw٥k~ ǎJM:ﮡ@8cב~H؟fgS4SO}m APx=23v5ni?>/|V*8';yRXePWR2#@_O&K?):WecUE7d~bPK?)i?Tgl-i˗`FհTK6޹#pfgS5b6dliF73[>`Ҡrˑ FBui?>/|V( fgS5bfdm,p~y"=Y~<}_O&K?)ԂxT3"aV$)#`}*Ji?>/|V*jq\𺣂@dW\ʒ (fgS5bn] 7*!I@%[@_O&K?)Պ(٥h4?M2=J]J]>7wwI&( fw`պi?>/|V( fgS4ynX$DSg *H #)*ÎA٥h4?M-徣am}i'mspy֋{YaM]Ja`:|ǟO'٥h4?MX+_O&K?)Պ(٥h4?MX+t4T ,*{@ PfgS5kvqOD2~i*:uUi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5bi?>/|V( fgS5b"C"xSfm־"F|xk2_7'D6{?܇]׉v\IC,Okbr,|ݎ pPr-zy9O䍰_?͞t 伽ԌZէZ &P+F6#W(6%U76/u-vm.}EkyI,w 2"$ ߏS)^'$w̠l8f$w*I>j4&GR]Ű`\nQt🃢Na8dbh:[:X ռ2.)g{K.Z{UXɥ*\Qw3C@rIiS | ȼV6,!m/$1Ƒ:4M MYz 0En!#BQ@crI$$xI3{GRww[KZw#g9XOYkmZ=>y)hül8TcIc qQEؒas/5YȴϵtH"]/ވu | 4hSj2޶/HRFO44 2 l}rE\:,.F4 xeV.ݖhcRFţOZhĚIkgtTr s\Ҵ\孩1`N\שK/Oշ4* d#*r#Qp1Mk|3~V~ͻ|s{lԘIx,~l8c%d Ld^'K)Ss_q-{΋`#@ePQ %y}ǭ 'I{sD^82&?~^4Qp<-o5{;}2C=bWR]Eך OC3 r>HٰMBOOboK >y.V,2 sЄ+lj]EGDq"<;FU`.O¨Ϡo75GǓ1#g1 ,T}u;T;{sdBo1b/Kg CF&I1 nzP+ dž?Z!;z~H 6Exn.cϴ_pn?ꟁd<7iw}=:s\L?v[6嵼_a9o| ꖳ6UiַV]JX5pS#$bhx.΋#ų ._*Leյ%LԪem|Oʪv"LOs}\i0?ʒ¨]bUtҤfY.M1G4TrNwc^}3O֮.lmVLPQ3[Rk0IA?*P2Fϟssj#ϥͭ2yyDZ<[n3]YZ 52F ?iav-ٕ8bWe4l-7>i^fl% PYOs}\i0?ʒ¨]\YVC<)%ܦf;#HG ʌyXų 36^%4OWq#ٵŅ"xK$, #P2KՋF#ṯbB=H?>[cd9EYgO?/G-<\UyvZM+p<-8%\f.3}RuB%D?[l5lyadz$nko-H^I$U Il9Z&!kmgdGPXFn€⸽_E|=z-UT{Z3%ߑ / d ]ݖu5^,:7;gr#U<advlzn^+i-uC`FpAǸضrU$ִۛVw-dҡ{T[XeV˹yp[pv QC\`"K۴I-ʼn<ȉ_=yݞ|. t۫x-h%@쌮dC`9il/ K4>ȕdil/ڬp;{WiK{.yqjYOxmn&Y0Bf//3ʭ'u\&KѦԣ]6U$xk~#( #?l]GVuֵBkW^5 ;ї鑚)HDrSO=VIJHLw2qmݽ y 𮭩O^[Db$cW0R*I.vF-<\UضrU"EKMsZ;VbA9S CxLcrT1!VfMm#it˚].?l1p4tEw^ɹU Hݐ V}+4VrJP_8Jmr[/4>FyX.XXҷhXy<{Ù6 hJ/f$vGI-׆->u-$L쌀 ]kS._*=k6wr흭rXF+21pcsw>zYTLY[;9. Iqx(T*3.[?yGqj c8EQx ,g{8|WX_yZ{{;V~ͲS/AJy?6ᫍJN\[-Gqw7Iy;X9]7-ݜڴSZ$lȑ(=>F5pik\=)]nUbB7dU=J ^-hvŦj;QK&I%f]?gBIe-QgmFXln.2mЃ # V?*Y-<\UضrUE_?;MYc-bI1ΊxB_ۉ-n5m3ڦ_Gkk-q}¶j$10(?7<74]3hIjqr,l>_>fY8N 0s3hbWZVL-8o,hϐI*ı֥$}W$>m7'O]g>d?-( #ų gI`\bi3|œ&7q??#͗:u2]K7N76pTعnu-D}"[/76'xz}bK:;=+PHY!'3 +Yr+ wIovGAgO?/G-<\Uqk>iΣ-..#=!)G2KV B"'}s7/Mf+E{Xf[ەğ@P[]e;p.O[?y?l⫗Ҭ;]GO/Z7P 㺵 >3%mZ2+=[R\V` u޺ n޺ nO}MԶq|Mzq*NOof{;{kiVng,}3NIFW+aؑޟEч(WmMҿ+o o7IQ(9Eҿ+o o7G[S ⹷TT=Q>Vn=Qp\!H4(9T,Y,I'$0J|)WmM)''$m0=N==J=RѥΖ4-.]<"wUѰnj qV L$q9UE#qI*F; 1 H%ч(WmMҿ+o o7IEч(WmMҿ+o o7IEч(WmMҿ+o o7Q kYP̊цXi(9Eҿ+o o7G[SJII%DydjvlSc@Oj=R_+ti_ϕ7hÔ_+ti_ϕ7hÔ_+ti_ϕ7-[&ugX ̪@bRezri_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)%{Fi_ϕ7J|)E$D$<Ͳ5f`±Ǡ'IGa/[S?TpOͼwʡ6 dGޏhÔJ|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)WmM(0J|)@kng(FI 9*?SQI͵`1nSPg-,Z+xdDWCHAAOZz;rfGίBl-__=ZQo9_s#gWj?uz(е: WV{EWZzJMNS)8`Yw&1ҵԺG[~#ȃ}"ѩ_.?Z?:/}Kg Cx->m"!jZ}+8+m6H`p";q\o?܇^^NwS#lWg]asy}6R7NT)/NRPq* /!-RQiߤOZA>p !4q|K 'ŝֳM-e3BrF(O~WaϯҼ'6u{F >J$ NcP#$Fp~Onn k[gQ)l |ͣk? Wؿ6}s߷ۻoǙT\0ojPwViT ufvePᑂ lTQp-`ҳ]ıYF-+4RX4A\V*UF ;{x(bPTP0RQp9}SU,]B8}R F9 ?_ѮͮeΙl\˯gd?,;O\z\Q5[6Yp,"RDeaדpV_" cMŶ’F3]wm3L2`~xt!Nڋ;;}>-gĒrY嘒IbI$I&\ڭ5 X[+ Crg@wpr3#\ֵ[5+)L$lVq$w|r{(u%Ÿ`o$^W9a 7.B9eF,7EŭQj[e,JۈEίosy!'jg$(8:\h}D5sMm=Ʊ Yپ>ҁ$T2 ˦ f-n;g"y˅"0sHj +IY[[hD`CNO\m<[ ClAl쥄H! E"` 9heÒ:(}axhtřq%̶,] eʓ-dkQƧkM $vrݢlT`rz(osw4:xkհСYGxRK !X+<\?~]A!.aYi-KpckxS\o]KO`6cm1 "Lm~ h-5˨.lj/@dV[B$ 9\ (_y ++oR݂36آ,mxkVm{m%SANlTRCrp3EvQp< z_Ba#Ϲ ^ e4-ќ$2NtGT73s\E_XY#G q }߸Q3 8#zt_FhTxlDQydfw"l 笼Cvѵ_إG[]H,dxlrQHَpI(NsuwGR_Eώ{ۅUZ3ZL>heA|u"a^MXmR.dJ- |v~fb ˎΊ. 66Sr>o#@L:&]@_8>$%3kp֋q4Is mCXN%]Ow\ #7y9Sc Ab@yv7Y k["mNxmYȆDFsǸDjH7\5 }ɷHmIon+4YQFor|^.zΩ]:{v[(mn!;qg"d1*36\a2Ux#\ֵ[5+)L$lVq$w|r{(gXئu% J|Bd"}+QxBu=Jtp=Ԣ#,w3÷`Ͷ($>[f^> (߉#gaƳ%b_ީ$[VAZF7/3^Cvyw1Ŧkm*͟i_1V DpnW$#*A* Qp<"1VVgc.fmDY!2,ֳq@өϫicU4yf8#(yY6C>(nVK=DlFa"VRYc1>lEwm 58FU9c-$f',bQEo5{=3LDך|Q [iqǓ cnΐ9yq}̖+c!N`072NV6ERQEQEQEQEQEQEQEGTER]o~uO_5+_Y??'_%~ dž?Z A$ TRfxjCJ?u\_sT~HhXް[?g;uowyַzK u)o.nZFU{YB챠I_GA}m>y?]p:ֵn/*C:^G/?xd 6)$i'$)36q.6-N}-Ẳ߯YÈ^8RICs@9 /?)\_s4~DPP~UlGgwUP(ª"9A%OG7??rwPh-4ɼ0b R® y#,,&}z?R3_#ѿy#sb2k2G+#ϧ4fneqCGq~ьRyCwujd*C<+0@N')}f5l.ff$wt[oLTIroV2%9MAESQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEGTER]o~uO_5+_Y??'_%~ dž?ZIThTBŘ89!vO^Vs# $kl%jaq|}! F3px+A_躮tELi3v߼Ǧ5?Mf6K@r̨S]Y|:}ވPmhڻT cp\Zooiq1 HETP0pj,01Ւqmw傼N ?uI֢䎋w-ձ1}ͳ'pbzKyJɧRDUpw*vn}sEsRY}Ǘ|ڽ1zTťXcqlr[ɧ;F[y%J`6}y] X 7 /Rh^Hȁ7/ gg5E QE(g GT-r8UoIۢ0 /Gx]$MmK١ݘk_w4}K{4f'x]$Mk_w5Eى /Gx]$MmGAvb}K /[tRh.OI>ֿ%kn= k<._&IۢfZ k<._&]k_w4}K{4f'x]$Mk_w5Eى /Gx]$MmGAvb}K /[tQ]k_w4}K{4f'x]$Mk_w5Eى /Gx]$MmGAvb}K /[tQ]k_w4}K{4f'x]$Mk_w5Eى /Gx]$MmGAvb}K /[tQ]k_w4}K{4f'x]$Mk_w5Eى /Gx]$MmGAvb}K /[tQ]k_w4}K{4f'x]$Mk_w5Eى /Gx]$MmGAvb}K /[tQ]k_w4}K{4f'x]$Mk_w5Eى /Gx]$MmGAvb}K /[tQ]k_w4}K{4f'x]$Mk_w5Eى /N9˄] pBEl gRҦPI\9 HjW˭־"F|xk2_7'Do?Pr-zsCOxjCNoiݿSו§FO/͚sqydM$~x^+2/":VcmdW KW;^ڒk]C*Qbj3VSazݴgK{fK5skڼ]1,d r. ]o۸EXZ;!)l1V8wZvΟVSzSo1I:ŎKko5ż-= 2]䙁ݻ`#|'B>46X&2Emœp  l?0Nߙaj3-(տg?[VbW HĺNv=hP>EIoB؈Wumtױ770kxL1䪺{ήXN n ӷiaj3-)FbFsmP#׈5V\a?bAy \ym|^}kUeQE;x9f/Rm+~gOousTh9Z=۟Ƶ+ws{xfZ^5 X饹[ }V68TVGP,]S#Ğ%"EX>\4~յcK!򝄒%&H|Ej@;z+mYYjZ|yW2I]'|u+wM]օMZ9n-rU"p0;E^:J񞯩ڍkezaowo=u%D Lȟ;Vӥ~kt|;;dڶԦn<7= =ZC!]"J)nN3dewf&\@Y1POl?CoO&q]C7K'Fٿ_?I%ҥeiH(U"U gLp2FiWq#  +f )8v3ol/Mf$kuMP^#2EéPP g'\Msqȥ1us]oO&Կ5.~֗Ad{I7%*0;xF,8cw=ǭ`.ٿ_?iydo=U*{v֞#C9pƙ?O ՄԿ购O _?ZUOa#"F|xk/ HjW˭־%sN*/͞_<5!rק74)~ dž?Z]E=yY*|$klد=i9olt;ŒK1Y2s;J WQ^eJ~%v糧55ױrpzݦ%/RtDfeq"Pُ $Вj85M:KKCm$^K*G; W.>f5tV~WoCP_zs"#8'sLMSN<x6m]P& =_$yƱ yÚ՞-^4飒6LmR1UxU=j[-okn$z/J ,{G@q}:=_$yͭf2A@MaZT,Q* [$u}jK qA}N*oM.aFq_*8GO ڳ/guF/,Q\cmD;}dU] H'-4{y0ۢI&㹷09 ])[C3"o xroR[[n!{8E嶩\N:Ջ Hgt۳~e76}6;U(2zŵŮ=+TVIbB2b@5lٵֆm66&K^qf'=rs֬Q@47QIOIeq"@ĐBIt5^O`-BRH`cEW{9"KX;0DPx/AZ>*ktuؙھ@t-k-!P  eB ADZNc|o*taBDظ*xCL|C{D7^ocخf4R*]ߢ((((((((((((((((((((+$%5[Kɴol>qiqp<]5Ӱ8+M"ݬqfEBWap\6W=pq҉n9巖o ]%4 #6u&/|ĎIvQh_!{9Ƕ?D[͕f:5"|ؘ=FGR5{u?}{ DE 2FFpO>:(|{9=އ%jn0L挀 ;yYeNΝ%ݾclF.0 7z(A_:+#U[x^VhSAr$3d,rKF$8"xvK -RK4 GR,b~\zqһ(|{9jWzjxjϗ yvg3 jZB=~^;'J)-䐬`t5E|"CbH|5wkr`Ч@\ \t_K\҅wmois-5ۮ^9Tzg'Mv4SV[܆YU,C+`w*=7oT5rm4x ="IF- @^zΝ >L6"(ؖWpz9E.P=]5kVSlKqtMºheض@9Gִ裔.`UM ƶN(J?b9ݛv;;fݹaQs=+F9Bx@qQ,6$0F 9 `P3}Ė/mޯq$RU9!Ͱl9_v>kqvY5 |F/%# `8pU߲AؒFv'»Z(tt]94|j'n9d W;JtOjZWo{~"eY&7۲ W9?1QhKm:`&Q(C*0B,v.,&%"[[jX} HM*Ůn0\^h2ˀ tPF+?S|M<+(al~:xLsO2[ $*Oe'zWe')t]9_|Vj$nyT;ZB/4* MǴm]F cdxX1O%ǝeb6s ݕR̩䓰_6:F-6ܵ 2]䙁ݻ`"5iƞ\z|O!pU 2R1wt7X[}SO\:u ʡF@`FpO>8R:4 O`h+OM _/Qw˸#%S0Gcq6sw%ER[",ɡiZǥXͤB iFUpHE΍g6֐رjMhr[F"`>LmR1UxP ~ 5mB]5mMŝŻ y*.|Ǖ6<c9CK1]x_Uᱳ?i_fQE_x|U((()i(Z)(Z)(4f(3Fh њ((((((Z)(Z)((((((((((Z)(Z)($Υ]EnVgRҦ{#ȃ}"ѩ_.?Z?:/}Kg Cvo?Pr-zs]E=yY*|$kl֬ k:;ĎR,@<|Phh\+cwR> ]1z.(gAK/")w|U(X?.?Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/??Wb|b(ϟ_E^?R> ^1z.(gAK/")y|U(X?/?msk]\&t^(2ł@' KA4MhX4Υ购O ?J{?:/}#ȃ}"ѩ_.?ZlQ8k6{?܇^fO^c_<5!rק?ٿSו§FO/jG%{G a^"VKQE!Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@R? ^&-c@'iq=? ?JڬX1-+9R9 HjW˭־"F|xk_7'Do?Pr-zkvo_Pr-zkvog?0 Z a^"X״RQHaEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPT_״ KX%{IqObjŏCҶk? j?J[?:/}#ȃ}"ѩ_.?Z|Q8k6{?܇^a]E=y?܇^a]E=yY*|$klըX״sQhh\ c~(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@R? ^&-c@'iq=k? j?Jجx1-+9lR9 HjW˭־"F|xk_G'Do?Pr-zkvo_Pr-zla]E=yY*|$klԨX״4X״ܻEP0(((((((((((((((((((((((((((((((((((((((((Z/OڥM8'%c!GiZ5Eg-9 HjW˭־"F|xk_G'Do?Pr-zla]E=y?܇^'XfO^Vs# /?4?,??S?,??W](QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU-c@'jR? ^&w}dG!GiZ5Eg-G?DSJu_A>ԯ[}>K(5_=xjCM??觯2/9kd)οaS#\'f7G%{Gu7G%{G[.E (((((((((((((((((((((((((((((((((((((((((* KA5vki?N;:b购jȋBҳA>ԯ[}EDSJuO_%~ dž?Z?7z/6OF>_5|6hhhKIEp-(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@R? ^&-c@'iq=VD_OY1_Q}?ZVRأ?:/}#ȃ}"ѩ_.?ZQ8k6{?܇^'XfO^e_<5!rצٿSו§FO/M@)i4X״ܻEP0(((((((((((((((((((((((((((((((((((((((((Z/OڥM8'EkVL_O+DSJu_Aԯ[}FK(5_=xjCM??觯2/9kd)οaS#\'f& KA?,??W](QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU-c@'jR? ^&wZɋBҵ&/ ?J["F|xk/ HjW˭־%sN/͞_<5!rצٿSי| Cvog_0 FG%{GZM@+ln.E (((((((((((((((((((((((((((((((((((((((((* KA5vki?N;-d!}GiZՓEe-`|GTER]o~uO_5+_Q?' |y/9kd)̾ dž?Z?7zT~H ٣IE-& KA7{hQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEKX%{IT_״ b购jɋBҲu0>#ȃ}"ѩ_.?Z?:/}Kg Cvo_Pr-zla]E=yY*|$klѤ a^"G%{G[˴QE ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( M]Z/Oӎ{ Y1_Q}?ZVd!}GiYKbA>ԯ[}EDSJudoO_%~ dž?Z?7z/6OF>_5|6hhhKIEp-(Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@Q@R? ^&-c@'iq=/-+Zb贬]L HjW˭־"F|xk2_7'Do?Pr-zla]E=y?܇^'XfO^Vu# /?4i4X״ a^"rQ@Š(((((((((((((((((((((((((((((((((((((((((ki?Wj KA4㸞L_OY1_Q}?ZVRخuO_5+_Q|GTER]o~/p7~l6OxjCM??觯+:Op_?͚4?,??Rhh\ cwv(aEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPEPT_״ KX%{IqOak&/ ?J֬/-+)lWS?:/}#ȃ"ѩ_.7?ZQ8k6{?܇^'XfO^e_<5!rצٿSו§FO/M@)i4X״ܻEP0(((((((((((((((((((((((((((((((((((((((((Z/OڥM8'EkVL_O+DOJqAԯ}FK(5_=xjCM??觯2/9kd)οaS#\'f& KA?,??W](QEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEQEU-c@'jR? ^&wZɋBҵ&/ ?J["F|xk/ HjW˭־%sN/͞_<5!rצٿSי| Cvog_0 FZdjVAhW*7kʊ} ^zint4?cL_cL_o?b[_أ/ƙA?GƙA?Q}~"jG2 2_36Ə36ƢUE}>o?bddglglE}~",4?4V(UE}9Yli4li5ڭ->dbli4li4Q̅f'ƙA?GƙA?KE,?#gh?#gihglgl-s cL_cL_񥢎dbli4li4Q̂O36Ə36Ɩ9YFFG2 1?4?4Z(Af'ƙA?GƙA?KE,?#gh?#gihglgl-s cL_cL_񥢎dbli4li4Q̂O36Ə36Ɩ9YFFG2 1?4?4Z(Af'ƙA?GƙA?KE,?#gh?#gihglgl-s cL_cL_񥢎dbli4li4Q̂O36Ə36Ɩ9YFFG2 1?4?4Z(Af'ƙA?GƙA?KE,?#gh?#gihglgl-s cL_cL_񥢎dbli4li4Q̂O36Ə36Ɩ9YFFG2 1?4?4Z(Af'ƙA?GƙA?KE,?#gh?#gihglgl-s cL_񪚮Iޢ_ڳUfRIx(RK4²b购jɋBҳu0>#ȃ}"ѩ_.?Z?:/}Kg Cvo_Pr-zla]E=yY*|$klѪ& 8.HXiǝ g#UʺdخI&a ж86}~vn93$<֒U N0W̼uJ6eoz,mEpI 9>cpm|Bd(Nloʨr5X  *sv,g<MEgޤQDrpJpsk>^E-xц0np"6Z~u%qmcVYd6a I=z͕֕་O[# amm%v%;M1Е ɇEͤ$V74U}m;B~ص8?*QE((((((((((((((((((((((((((((((((((((+&/ ?J֬/-)K``|GTER]o~uO_5+_Q??' |y/9kd)̾ dž?ZcIHLg`5g_0 RJT)%ɜr{gA OGA O^um߳Qz~Qi4i4$q=bgm*!ih!ih\m*/OO_OO_rM/6X?=?Ə=?Ƌ6Xq=bgZ?Z,$)pF<ǸU" 5EUZ?Zv z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? z-?z-? &/ ?JBi#R'Y#gL:0 GQS-na|GTER]o~uO_5+_Q??' |y/9kY= yw?܇^^FwS#lWdgyGkTWu濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕gyRQ@濕9QPaTN9_ HjW˭־"F|xk2_7'D6{?܇^^1zNawv #6vx~u (SmiO+ Zi%)$ΦcxOK /^o1_ #}h[?,?_&?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy_Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>KގcOh? ?>Re_Xy?cOhϩ/}ꨮW?,?_&Xy?_ /_z:+? ?,?_&_>Kގ4FIj/S1 /Q? )_f+usG~/}KXA FVfO y{02/~[}oxUggc1B`uINk_MQK R./ugռ]_noSѹ:(M?P:77Eno΍EsxtQ@?POF?POF?POF?P:77袀 :77袀 ѹ:(sz΍:(sz΍EsxtQ@ާ77ާ77F袀 ѹ:(sxtnoΊ(ާszΊ(ާszΊ(ާszΊ(?tQ@?tQ@?77F袀 ѹ:(sxtnoΊ(?77F袀 ѹ:(sxtnoΊ(?77F袀 ѹ:(sxtnoΊ(?77F袀 :77袀 :77Eno΍EsxtQ@?P:77Eno΍E󤢊Lhopen-zwave-1.5/docs/images+css/OpenZWave.css000066400000000000000000000011111264474202400210220ustar00rootroot00000000000000 /* Font Definitions */ .Heading1 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 24pt; } .Heading2 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11pt; font-weight: bold; } .BodyText { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 11pt; } .FooterText { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 7pt; } .TableText { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9pt; padding: 5pt 5pt 5pt 5pt; } .TableBullet { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9pt; } open-zwave-1.5/docs/images+css/image003.gif000066400000000000000000000047021264474202400204370ustar00rootroot00000000000000GIF87a7w!Software: Microsoft Office,7ZRccֽcccccֵֽ{ZZZZkZZZkZZkZ)Z)Z)Z)ZZZZkk)Z)Z)){Z1Z{JcZΜZZZZJZZZJZZJZZZZZZZZJΜJZZRk1R挥{ޥΥﵵccBBֵBBsssֵ:k:1:):Ōc1:k::):c1ccc1kck)ck):J:::έ:J:έ::cJcέJέ{Ŕ{sR1Z{{{k{Z{kZ1Z1Z11kZ1){){)Z11)Z1{{{k111k1){){)11)RRZRJ{{J{Z{JZ1Z11JZ1{{Z11Z{{{J11Μ1J1{{11{1J1c!ֵR1)BBBBsssRJssRk{RJ{s{{{k)ckZJ1{{{kcJZ:kRkRH*\ȰÇ#JHŋ3&Ǐ+d'!-)lȗ013) @M(ǘ@&DFdId-ǍCZ 6JL Ie8 TSXdX@d<ݎ[qML=Ng݆K8$%SѼsɔw 撁eJ&ԤNHC3aMXؼlr%tmf =sAJmU*%9Luid5ܓSxTLhFf.]? 0 +L_a&hgTN apAIy^HsD"A<+F@2҈3޸Bą+"iE @P4LT@4=48#47$eJ@a߄)&8r=^)7@dW{(4cA4 Gh$( I85pi(G$p3B|) 8iA4}j!<2 <Ⱥ*8J,'BV84A%D2A#9DbmR:9G@ m3p40$B λ81&3=LcfYP88 @;@%+*.$Ͳ<.4fjzqϗ3*AhWy1.ٚGuAqM ʼnDc~7>v>AMx+ 8a)%ñisP7aX*:UI#IHЗ(MȭA8۳ (15D5B (:$T6Ij>O ”@!$8Ё臨)ML?]Aa:ӌG;hGI4LzZ3(az ?Dl`=Hαö)Ǜ -{8XJ!XRCG$`)t e b"A FLh>r &hQT3ewan ~ F^C'>EY( IcNPB#WeMv1,<5)gcpEDY cݺڎ0 "iʪ$mPfr v9 a;+܏-DWrК(mG4ABjXABA^՚#+];$5+|oUBt sJ;BLv ,k/'L [;open-zwave-1.5/dotnet/000077500000000000000000000000001264474202400147545ustar00rootroot00000000000000open-zwave-1.5/dotnet/build/000077500000000000000000000000001264474202400160535ustar00rootroot00000000000000open-zwave-1.5/dotnet/build/vs2008/000077500000000000000000000000001264474202400170155ustar00rootroot00000000000000open-zwave-1.5/dotnet/build/vs2008/OpenZWaveDotNet.sln000066400000000000000000000030071264474202400225270ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual C# Express 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWaveDotNet", "OpenZWaveDotNet.vcproj", "{0DD42424-B4AB-45C3-897C-774D1C5917C3}" ProjectSection(ProjectDependencies) = postProject {497F9828-DEC2-4C80-B9E0-AD066CCB587C} = {497F9828-DEC2-4C80-B9E0-AD066CCB587C} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "..\..\..\cpp\build\windows\vs2008\OpenZWave.vcproj", "{497F9828-DEC2-4C80-B9E0-AD066CCB587C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Win32.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Win32.Build.0 = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Win32.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.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}.Release|Win32.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal open-zwave-1.5/dotnet/build/vs2008/OpenZWaveDotNet.vcproj000066400000000000000000000116761264474202400232510ustar00rootroot00000000000000 open-zwave-1.5/dotnet/build/vs2010/000077500000000000000000000000001264474202400170065ustar00rootroot00000000000000open-zwave-1.5/dotnet/build/vs2010/OpenZWaveDotNet.sln000066400000000000000000000030051264474202400225160ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWaveDotNet", "OpenZWaveDotNet.vcxproj", "{0DD42424-B4AB-45C3-897C-774D1C5917C3}" ProjectSection(ProjectDependencies) = postProject {497F9828-DEC2-4C80-B9E0-AD066CCB587C} = {497F9828-DEC2-4C80-B9E0-AD066CCB587C} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "..\..\..\cpp\build\windows\vs2010\OpenZWave.vcxproj", "{497F9828-DEC2-4C80-B9E0-AD066CCB587C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Win32.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Win32.Build.0 = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Win32.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.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}.Release|Win32.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal open-zwave-1.5/dotnet/build/vs2010/OpenZWaveDotNet.vcxproj000066400000000000000000000154541264474202400234300ustar00rootroot00000000000000 Debug Win32 Release Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3} OpenZWaveDotNet ManagedCProj DynamicLibrary Unicode true true DynamicLibrary Unicode true <_ProjectFileVersion>10.0.30319.1 $(SolutionDir)$(Configuration)\ $(Configuration)\ true $(SolutionDir)$(Configuration)\ $(Configuration)\ false AllRules.ruleset AllRules.ruleset $(ProjectName)d Disabled ..\..\..\cpp\src;..\..\..\cpp\src\value_classes;..\..\..\cpp\src;..\..\..\cpp\src\value_classes;..\..\..\cpp\src\command_classes;..\..\..\cpp\src\platform;%(AdditionalIncludeDirectories) WIN32;_DEBUG;%(PreprocessorDefinitions) MultiThreadedDebugDLL Level3 ProgramDatabase $(OutDir)\OpenZWave.lib true true MachineX86 ..\..\..\cpp\src;..\..\..\cpp\src\value_classes;..\..\..\cpp\src;..\..\..\cpp\src\value_classes;..\..\..\cpp\src\command_classes;..\..\..\cpp\src\platform;%(AdditionalIncludeDirectories) WIN32;NDEBUG;%(PreprocessorDefinitions) MultiThreadedDLL Level3 ProgramDatabase $(OutDir)\OpenZWave.lib true MachineX86 true true true true true true open-zwave-1.5/dotnet/build/vs2010/OpenZWaveDotNet.vcxproj.filters000066400000000000000000000034101264474202400250640ustar00rootroot00000000000000 {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav Source Files Source Files Source Files Source Files Source Files Source Files Source Files Source Files Resource Files Resource Files open-zwave-1.5/dotnet/examples/000077500000000000000000000000001264474202400165725ustar00rootroot00000000000000open-zwave-1.5/dotnet/examples/OZWForm/000077500000000000000000000000001264474202400200755ustar00rootroot00000000000000open-zwave-1.5/dotnet/examples/OZWForm/CopyFilesVS2008.cmd000066400000000000000000000001021264474202400232330ustar00rootroot00000000000000set rootdir=%~dp0 copy %rootdir%\build\vs2008\*.* %rootdir%\src open-zwave-1.5/dotnet/examples/OZWForm/CopyFilesVS2010.cmd000066400000000000000000000001021264474202400232240ustar00rootroot00000000000000set rootdir=%~dp0 copy %rootdir%\build\vs2010\*.* %rootdir%\src open-zwave-1.5/dotnet/examples/OZWForm/README.TXT000066400000000000000000000022221264474202400214310ustar00rootroot00000000000000 Building OZWForm under VS2008 and VS2010 Unlike the base OpenZWave C++ project, Visual Studio appears to be much more "particular" about where the project files are stored. Originally, we had two copies of the OZWForm source files...one for VS2008 and a second for VS2010. But they've been difficult to keep fully in sync as changes are made. So the files in this directory provide a rough (but hopefully effective) solution: 1) a single source code directory with all of the common files, 2) two separate "build" directories with .sln and .csproj files (one for VS2010 and one for VS2008), and 3) some batch files for copying the appropriate .sln and .csproj files into the source code directory. Hopefully the batch files will work; if they don't you should be able to simply copy the .sln and .csproj files from the build subdirectory that matches your Visual Studio version into the .\src directory. If too many people have difficulty with this (or if there are other issues with VS2010 that disallow this approach), we may have to go back to two separate (but essentially identical) source code directories. Let's hope not!open-zwave-1.5/dotnet/examples/OZWForm/build/000077500000000000000000000000001264474202400211745ustar00rootroot00000000000000open-zwave-1.5/dotnet/examples/OZWForm/build/vs2008/000077500000000000000000000000001264474202400221365ustar00rootroot00000000000000open-zwave-1.5/dotnet/examples/OZWForm/build/vs2008/OZWForm.csproj000066400000000000000000000222251264474202400246660ustar00rootroot00000000000000 Debug AnyCPU 9.0.30729 2.0 {3A782BF0-5863-4500-A03F-51B2BD25EF2A} WinExe Properties OZWForm OZWForm v3.5 512 publish\ true Disk false Foreground 7 Days false false true 0 1.0.0.%2a false false true true full false bin\Debug\ DEBUG;TRACE prompt 4 x86 pdbonly true bin\Release\ TRACE prompt 4 x86 .\ .\ x86 3.5 Form ControllerCommandDlg.cs Form ConfigurationWakeUpDlg.cs UserControl UserControl UserControl Form MainForm.cs Form NodeForm.cs ControllerCommandDlg.cs ConfigurationWakeUpDlg.cs ValuePanelDecimal.cs ValuePanelList.cs ValuePanelString.cs MainForm.cs NodeForm.cs ResXFileCodeGenerator Resources.Designer.cs Designer ValuePanel.cs ValuePanelBool.cs ValuePanelButton.cs ValuePanelByte.cs True Resources.resx SettingsSingleFileGenerator Settings.Designer.cs True Settings.settings True UserControl ValuePanel.cs UserControl UserControl UserControl UserControl UserControl {0DD42424-B4AB-45C3-897C-774D1C5917C3} OpenZWaveDotNet False .NET Framework Client Profile false False .NET Framework 2.0 %28x86%29 false False .NET Framework 3.0 %28x86%29 true False .NET Framework 3.5 false False .NET Framework 3.5 SP1 false False Windows Installer 3.1 true open-zwave-1.5/dotnet/examples/OZWForm/build/vs2008/OZWForm.sln000066400000000000000000000104751264474202400241660ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 10.00 # Visual Studio 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "..\..\..\..\cpp\build\windows\vs2008\OpenZWave.vcproj", "{497F9828-DEC2-4C80-B9E0-AD066CCB587C}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWaveDotNet", "..\..\..\build\vs2008\OpenZWaveDotNet.vcproj", "{0DD42424-B4AB-45C3-897C-774D1C5917C3}" ProjectSection(ProjectDependencies) = postProject {497F9828-DEC2-4C80-B9E0-AD066CCB587C} = {497F9828-DEC2-4C80-B9E0-AD066CCB587C} EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OZWForm", "OZWForm.csproj", "{3A782BF0-5863-4500-A03F-51B2BD25EF2A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Any CPU.ActiveCfg = Debug|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Mixed Platforms.Build.0 = Debug|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}.Debug|x86.ActiveCfg = Debug|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Any CPU.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Mixed Platforms.Build.0 = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Win32.Build.0 = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|x86.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Any CPU.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Win32.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Win32.Build.0 = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|x86.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Any CPU.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Mixed Platforms.Build.0 = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Win32.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Win32.Build.0 = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|x86.ActiveCfg = Release|Win32 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Any CPU.Build.0 = Debug|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Mixed Platforms.Build.0 = Debug|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Win32.ActiveCfg = Debug|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|x86.ActiveCfg = Debug|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|x86.Build.0 = Debug|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Any CPU.Build.0 = Release|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Mixed Platforms.ActiveCfg = Release|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Mixed Platforms.Build.0 = Release|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Win32.ActiveCfg = Release|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|x86.ActiveCfg = Release|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal open-zwave-1.5/dotnet/examples/OZWForm/build/vs2010/000077500000000000000000000000001264474202400221275ustar00rootroot00000000000000open-zwave-1.5/dotnet/examples/OZWForm/build/vs2010/OZWForm.csproj000066400000000000000000000243121264474202400246560ustar00rootroot00000000000000 Debug AnyCPU 9.0.30729 2.0 {3A782BF0-5863-4500-A03F-51B2BD25EF2A} WinExe Properties OZWForm OZWForm v4.0 512 3.5 false publish\ true Disk false Foreground 7 Days false false true 0 1.0.0.%2a false true true full false bin\Debug\ DEBUG;TRACE prompt 4 AllRules.ruleset pdbonly true bin\Release\ TRACE prompt 4 AllRules.ruleset true bin\x86\Debug\ DEBUG;TRACE full x86 bin\Debug\OZWForm.exe.CodeAnalysisLog.xml true GlobalSuppressions.cs prompt AllRules.ruleset ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets false ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules false false bin\x86\Release\ TRACE true pdbonly x86 bin\Release\OZWForm.exe.CodeAnalysisLog.xml true GlobalSuppressions.cs prompt AllRules.ruleset ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\\Rule Sets false ;C:\Program Files (x86)\Microsoft Visual Studio 10.0\Team Tools\Static Analysis Tools\FxCop\\Rules false false Form ConfigurationWakeUpDlg.cs Form ControllerCommandDlg.cs Form MainForm.cs Form NodeForm.cs ConfigurationWakeUpDlg.cs ControllerCommandDlg.cs MainForm.cs NodeForm.cs ResXFileCodeGenerator Resources.Designer.cs Designer ValuePanel.cs ValuePanelBool.cs ValuePanelButton.cs ValuePanelByte.cs True Resources.resx True SettingsSingleFileGenerator Settings.Designer.cs True Settings.settings True UserControl ValuePanel.cs UserControl UserControl UserControl UserControl UserControl False .NET Framework 3.5 SP1 Client Profile false False .NET Framework 3.5 SP1 true False Windows Installer 3.1 true {0DD42424-B4AB-45C3-897C-774D1C5917C3} OpenZWaveDotNet open-zwave-1.5/dotnet/examples/OZWForm/build/vs2010/OZWForm.sln000066400000000000000000000075121264474202400241550ustar00rootroot00000000000000 Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OZWForm", "OZWForm.csproj", "{3A782BF0-5863-4500-A03F-51B2BD25EF2A}" ProjectSection(ProjectDependencies) = postProject {497F9828-DEC2-4C80-B9E0-AD066CCB587C} = {497F9828-DEC2-4C80-B9E0-AD066CCB587C} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWaveDotNet", "..\..\..\build\vs2010\OpenZWaveDotNet.vcxproj", "{0DD42424-B4AB-45C3-897C-774D1C5917C3}" ProjectSection(ProjectDependencies) = postProject {497F9828-DEC2-4C80-B9E0-AD066CCB587C} = {497F9828-DEC2-4C80-B9E0-AD066CCB587C} EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "OpenZWave", "..\..\..\..\cpp\build\windows\vs2010\OpenZWave.vcxproj", "{497F9828-DEC2-4C80-B9E0-AD066CCB587C}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Debug|Mixed Platforms = Debug|Mixed Platforms Debug|Win32 = Debug|Win32 Release|Any CPU = Release|Any CPU Release|Mixed Platforms = Release|Mixed Platforms Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Any CPU.Build.0 = Debug|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Mixed Platforms.ActiveCfg = Debug|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Mixed Platforms.Build.0 = Debug|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Debug|Win32.ActiveCfg = Debug|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Any CPU.Build.0 = Release|Any CPU {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Mixed Platforms.ActiveCfg = Release|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Mixed Platforms.Build.0 = Release|x86 {3A782BF0-5863-4500-A03F-51B2BD25EF2A}.Release|Win32.ActiveCfg = Release|Any CPU {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Any CPU.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Mixed Platforms.Build.0 = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Win32.ActiveCfg = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Debug|Win32.Build.0 = Debug|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Any CPU.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Mixed Platforms.Build.0 = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Win32.ActiveCfg = Release|Win32 {0DD42424-B4AB-45C3-897C-774D1C5917C3}.Release|Win32.Build.0 = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Any CPU.ActiveCfg = Debug|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Debug|Mixed Platforms.Build.0 = Debug|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}.Release|Any CPU.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Mixed Platforms.ActiveCfg = Release|Win32 {497F9828-DEC2-4C80-B9E0-AD066CCB587C}.Release|Mixed Platforms.Build.0 = 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 open-zwave-1.5/dotnet/examples/OZWForm/src/000077500000000000000000000000001264474202400206645ustar00rootroot00000000000000open-zwave-1.5/dotnet/examples/OZWForm/src/ConfigurationWakeUpDlg.Designer.cs000066400000000000000000000051411264474202400273260ustar00rootroot00000000000000namespace OZWForm { partial class ConfigurationWakeUpDlg { ///

/// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.ButtonCancel = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // ButtonCancel // this.ButtonCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.ButtonCancel.Location = new System.Drawing.Point(83, 109); this.ButtonCancel.Name = "ButtonCancel"; this.ButtonCancel.Size = new System.Drawing.Size(75, 23); this.ButtonCancel.TabIndex = 0; this.ButtonCancel.Text = "Cancel"; this.ButtonCancel.UseVisualStyleBackColor = true; // // label1 // this.label1.Location = new System.Drawing.Point(12, 9); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(217, 97); this.label1.TabIndex = 1; this.label1.Text = "Default Text"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // ConfigurationWakeUpDlg // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(241, 144); this.Controls.Add(this.label1); this.Controls.Add(this.ButtonCancel); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "ConfigurationWakeUpDlg"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Retrieving Configurable Parameters"; this.Shown += new System.EventHandler(this.ConfigurationWakeUpDlg_Shown); this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ConfigurationWakeUpDlg_FormClosing); this.ResumeLayout(false); } #endregion private System.Windows.Forms.Button ButtonCancel; private System.Windows.Forms.Label label1; } }open-zwave-1.5/dotnet/examples/OZWForm/src/ConfigurationWakeUpDlg.cs000066400000000000000000000113231264474202400255660ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ConfigurationWakeUpDlg.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using System.Windows.Forms; using OpenZWaveDotNet; namespace OZWForm { /// /// Requests all Configuration parameters and shows a dialog window while the request is running /// public partial class ConfigurationWakeUpDlg : Form { static private ZWManager m_manager; static private UInt32 m_homeId; private ZWNotification m_notification = null; static private Byte m_nodeId; /// /// Initializes a new instance of the class. /// /// The _manager. /// The home identifier. /// The node identifier. public ConfigurationWakeUpDlg( ZWManager _manager, UInt32 homeId, Byte nodeId) { m_manager = _manager; m_homeId = homeId; m_nodeId = nodeId; InitializeComponent(); // Set the text according to whether the device is listening if( m_manager.IsNodeListeningDevice( homeId, nodeId ) ) { label1.Text = "Waiting for configurable parameter info from device..."; } else { label1.Text = "Waiting for configurable parameter info from device.\r\nPlease ensure device is awake..."; } } /// /// The notification handler. /// /// The notification. public void NotificationHandler(ZWNotification notification) { // Handle the notification on a thread that can safely // modify the form controls without throwing an exception. m_notification = notification; Invoke(new MethodInvoker(NotificationHandler)); m_notification = null; } /// /// The notification handler. /// private void NotificationHandler() { // Check whether all the queries on this node have completed if( m_notification.GetType() == ZWNotification.Type.NodeQueriesComplete ) { if ((m_notification.GetHomeId() == m_homeId) && (m_notification.GetNodeId() == m_nodeId)) { // Done! m_manager.OnNotification -= new ManagedNotificationsHandler(NotificationHandler); DialogResult = DialogResult.OK; } } } /// /// Handles the FormClosing event of the ConfigurationWakeUpDlg control. /// /// The source of the event. /// The instance containing the event data. private void ConfigurationWakeUpDlg_FormClosing(object sender, FormClosingEventArgs e) { } /// /// Handles the Shown event of the ConfigurationWakeUpDlg control. /// /// The source of the event. /// The instance containing the event data. private void ConfigurationWakeUpDlg_Shown(object sender, EventArgs e) { // Add a handler so that we receive notification of when the node queries are complete. m_manager.OnNotification += new ManagedNotificationsHandler(NotificationHandler); // Request refreshed config param values. m_manager.RequestAllConfigParams(m_homeId, m_nodeId); } } }open-zwave-1.5/dotnet/examples/OZWForm/src/ConfigurationWakeUpDlg.resx000066400000000000000000000132661264474202400261520ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ControllerCommandDlg.Designer.cs000066400000000000000000000045461264474202400270340ustar00rootroot00000000000000namespace OZWForm { partial class ControllerCommandDlg { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.ButtonCancel = new System.Windows.Forms.Button(); this.label1 = new System.Windows.Forms.Label(); this.SuspendLayout(); // // ButtonCancel // this.ButtonCancel.Location = new System.Drawing.Point(83, 109); this.ButtonCancel.Name = "ButtonCancel"; this.ButtonCancel.Size = new System.Drawing.Size(75, 23); this.ButtonCancel.TabIndex = 0; this.ButtonCancel.Text = "Cancel"; this.ButtonCancel.UseVisualStyleBackColor = true; this.ButtonCancel.Click += new System.EventHandler(this.ButtonCancel_Click); // // label1 // this.label1.Location = new System.Drawing.Point(12, 9); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(217, 97); this.label1.TabIndex = 1; this.label1.Text = "Default Text"; this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; // // ZWaveOperationDialog // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(241, 144); this.Controls.Add(this.label1); this.Controls.Add(this.ButtonCancel); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "ZWaveOperationDialog"; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.ResumeLayout(false); } #endregion private System.Windows.Forms.Button ButtonCancel; private System.Windows.Forms.Label label1; } }open-zwave-1.5/dotnet/examples/OZWForm/src/ControllerCommandDlg.cs000066400000000000000000000355521264474202400252760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ControllerCommandDlg.cs // // Executes a controller command and show a dialog window while the // controller command is running. // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using System.Windows.Forms; using OpenZWaveDotNet; namespace OZWForm { /// /// Executes a controller command and show a dialog window while the controller command is running /// public partial class ControllerCommandDlg : Form { private static ZWManager m_manager; private static ControllerCommandDlg m_dlg; private static UInt32 m_homeId; private static ZWControllerCommand m_op; private static Byte m_nodeId; private static DialogResult result; private MainForm m_mainDlg; public MainForm MainDlg { get { return m_mainDlg; } } /// /// Initializes a new instance of the class. /// /// The main form. /// The manager. /// The home identifier. /// The Controller Command. /// The node identifier. public ControllerCommandDlg(MainForm _mainDlg, ZWManager _manager, UInt32 homeId, ZWControllerCommand _op, Byte nodeId) { m_mainDlg = _mainDlg; m_manager = _manager; m_homeId = homeId; m_op = _op; m_nodeId = nodeId; m_dlg = this; InitializeComponent(); m_manager.OnNotification += new ManagedNotificationsHandler(NotificationHandler); switch (m_op) { case ZWControllerCommand.RequestNodeNeighborUpdate: { this.Text = "Node Neighbor Update"; this.label1.Text = "Request that a node update its list of neighbors."; if (!m_manager.RequestNodeNeighborUpdate(m_homeId, m_nodeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.AddDevice: { this.Text = "Add Device"; this.label1.Text = "Press the program button on the Z-Wave device to add it to the network.\nFor security reasons, the PC Z-Wave Controller must be close to the device being added."; if (!m_manager.AddNode(m_homeId, m_mainDlg.SecurityEnabled)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.CreateNewPrimary: { this.Text = "Create New Primary Controller"; this.label1.Text = "Put the target controller into receive configuration mode.\nThe PC Z-Wave Controller must be within 2m of the controller that is being made the primary."; if (!m_manager.CreateNewPrimary(m_homeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.ReceiveConfiguration: { this.Text = "Receive Configuration"; this.label1.Text = "Transfering the network configuration\nfrom another controller.\n\nPlease bring the other controller within 2m of the PC controller and set it to send its network configuration."; if (!m_manager.ReceiveConfiguration(m_homeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.RemoveDevice: { this.Text = "Remove Device"; this.label1.Text = "Press the program button on the Z-Wave device to remove it from the network.\nFor security reasons, the PC Z-Wave Controller must be close to the device being removed."; if (!m_manager.RemoveNode(m_homeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.TransferPrimaryRole: { this.Text = "Transfer Primary Role"; this.label1.Text = "Transfering the primary role\nto another controller.\n\nPlease bring the new controller within 2m of the PC controller and set it to receive the network configuration."; if (!m_manager.TransferPrimaryRole(m_homeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.HasNodeFailed: { this.ButtonCancel.Enabled = false; this.Text = "Has Node Failed"; this.label1.Text = "Testing whether the node has failed.\nThis command cannot be cancelled."; if (!m_manager.HasNodeFailed(m_homeId, m_nodeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.RemoveFailedNode: { this.ButtonCancel.Enabled = false; this.Text = "Remove Failed Node"; this.label1.Text = "Removing the failed node from the controller's list.\nThis command cannot be cancelled."; if (!m_manager.RemoveFailedNode(m_homeId, m_nodeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.ReplaceFailedNode: { this.ButtonCancel.Enabled = false; this.Text = "Replacing Failed Node"; this.label1.Text = "Testing the failed node.\nThis command cannot be cancelled."; if (!m_manager.ReplaceFailedNode(m_homeId, m_nodeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } case ZWControllerCommand.RequestNetworkUpdate: { this.ButtonCancel.Enabled = false; this.Text = "Requesting Network Update"; this.label1.Text = "Requesting the Network Update."; if (!m_manager.RequestNetworkUpdate(m_homeId, m_nodeId)) { MyControllerStateChangedHandler(ZWControllerState.Failed); } break; } default: { m_manager.OnNotification -= NotificationHandler; break; } } } /// /// Handles Notifications. /// /// The notification. public static void NotificationHandler(ZWNotification notification) { switch (notification.GetType()) { case ZWNotification.Type.ControllerCommand: { MyControllerStateChangedHandler(((ZWControllerState) notification.GetEvent())); break; } } } /// /// Handles controller state changes. /// /// The state. public static void MyControllerStateChangedHandler(ZWControllerState state) { // Handle the controller state notifications here. bool complete = false; String dlgText = ""; bool buttonEnabled = true; switch (state) { case ZWControllerState.Waiting: { // Display a message to tell the user to press the include button on the controller if (m_op == ZWControllerCommand.ReplaceFailedNode) { dlgText = "Press the program button on the replacement Z-Wave device to add it to the network.\nFor security reasons, the PC Z-Wave Controller must be close to the device being added.\nThis command cannot be cancelled."; } break; } case ZWControllerState.InProgress: { // Tell the user that the controller has been found and the adding process is in progress. dlgText = "Please wait..."; buttonEnabled = false; break; } case ZWControllerState.Completed: { // Tell the user that the controller has been successfully added. // The command is now complete dlgText = "Command Completed OK."; complete = true; result = DialogResult.OK; break; } case ZWControllerState.Failed: { // Tell the user that the controller addition process has failed. // The command is now complete dlgText = "Command Failed."; complete = true; result = DialogResult.Abort; break; } case ZWControllerState.NodeOK: { dlgText = "Node has not failed."; complete = true; result = DialogResult.No; break; } case ZWControllerState.NodeFailed: { dlgText = "Node has failed."; complete = true; result = DialogResult.Yes; break; } case ZWControllerState.Cancel: { dlgText = "Command was cancelled."; complete = true; result = DialogResult.Cancel; break; } case ZWControllerState.Error: { dlgText = "An error occurred while processing the controller command."; complete = true; result = DialogResult.Cancel; break; } } if (dlgText != "") { m_dlg.SetDialogText(dlgText); } m_dlg.SetButtonEnabled(buttonEnabled); if (complete) { m_dlg.SetButtonText("OK"); // Remove the event handler m_manager.OnNotification -= NotificationHandler; } } /// /// Sets the dialog text. /// /// The text. private void SetDialogText(String text) { if (m_dlg.InvokeRequired) { Invoke(new MethodInvoker(delegate() { SetDialogText(text); })); } else { m_dlg.label1.Text = text; } } /// /// Sets the button text. /// /// The text. private void SetButtonText(String text) { if (m_dlg.InvokeRequired) { Invoke(new MethodInvoker(delegate() { SetButtonText(text); })); } else { m_dlg.ButtonCancel.Text = text; } } /// /// Sets the button enabled. /// /// if set to true [enabled]. private void SetButtonEnabled(bool enabled) { if (m_dlg.InvokeRequired) { Invoke(new MethodInvoker(delegate() { SetButtonEnabled(enabled); })); } else { m_dlg.ButtonCancel.Enabled = enabled; } } /// /// Handles the Click event of the ButtonCancel control. /// /// The source of the event. /// The instance containing the event data. private void ButtonCancel_Click(object sender, EventArgs e) { if (ButtonCancel.Text != "OK") { // Remove the event handler m_manager.OnNotification -= NotificationHandler; // Cancel the operation m_manager.CancelControllerCommand(m_homeId); } // Close the dialog Close(); m_dlg.DialogResult = result; } } }open-zwave-1.5/dotnet/examples/OZWForm/src/ControllerCommandDlg.resx000066400000000000000000000132661264474202400256500ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/MainForm.Designer.cs000066400000000000000000000613071264474202400244710ustar00rootroot00000000000000namespace OZWForm { partial class MainForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.components = new System.ComponentModel.Container(); this.NodeGridView = new System.Windows.Forms.DataGridView(); this.NodeContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components); this.PowerOnToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.PowerOffToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); this.requestNodeNeighborUpdateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.assignReturnRouteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.deleteReturnRouteToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator5 = new System.Windows.Forms.ToolStripSeparator(); this.hasNodeFailedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.markNodeAsFailedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.replaceFailedNodeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); this.propertiesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.MenuBar = new System.Windows.Forms.MenuStrip(); this.FileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.SaveToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.controllerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.createNewPrmaryControllerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.transferPrimaryRoleToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.addControllerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.addDeviceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); this.removeControllerToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.removeDeviceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); this.receiveConfigurationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); this.requestNetworkUpdateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripSeparator7 = new System.Windows.Forms.ToolStripSeparator(); this.resetControllersoftToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.softToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.eraseAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); this.addSecureDeviceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); ((System.ComponentModel.ISupportInitialize)(this.NodeGridView)).BeginInit(); this.NodeContextMenuStrip.SuspendLayout(); this.MenuBar.SuspendLayout(); this.statusStrip1.SuspendLayout(); this.SuspendLayout(); // // NodeGridView // this.NodeGridView.AllowUserToAddRows = false; this.NodeGridView.AllowUserToDeleteRows = false; this.NodeGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.NodeGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.NodeGridView.ContextMenuStrip = this.NodeContextMenuStrip; this.NodeGridView.Location = new System.Drawing.Point(13, 37); this.NodeGridView.MultiSelect = false; this.NodeGridView.Name = "NodeGridView"; this.NodeGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.CellSelect; this.NodeGridView.Size = new System.Drawing.Size(609, 381); this.NodeGridView.TabIndex = 0; this.NodeGridView.CellMouseDown += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.NodeGridView_CellMouseDown); this.NodeGridView.CellParsing += new System.Windows.Forms.DataGridViewCellParsingEventHandler(this.NodeGridView_CellParsing); // // NodeContextMenuStrip // this.NodeContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.PowerOnToolStripMenuItem, this.PowerOffToolStripMenuItem, this.toolStripSeparator4, this.requestNodeNeighborUpdateToolStripMenuItem, this.assignReturnRouteToolStripMenuItem, this.deleteReturnRouteToolStripMenuItem, this.toolStripSeparator5, this.hasNodeFailedToolStripMenuItem, this.markNodeAsFailedToolStripMenuItem, this.replaceFailedNodeToolStripMenuItem, this.toolStripSeparator6, this.propertiesToolStripMenuItem}); this.NodeContextMenuStrip.Name = "NodeContextMenuStrip"; this.NodeContextMenuStrip.Size = new System.Drawing.Size(243, 220); // // PowerOnToolStripMenuItem // this.PowerOnToolStripMenuItem.Name = "PowerOnToolStripMenuItem"; this.PowerOnToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.PowerOnToolStripMenuItem.Text = "Power On"; this.PowerOnToolStripMenuItem.Click += new System.EventHandler(this.PowerOnToolStripMenuItem_Click); // // PowerOffToolStripMenuItem // this.PowerOffToolStripMenuItem.Name = "PowerOffToolStripMenuItem"; this.PowerOffToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.PowerOffToolStripMenuItem.Text = "Power Off"; this.PowerOffToolStripMenuItem.Click += new System.EventHandler(this.PowerOffToolStripMenuItem_Click); // // toolStripSeparator4 // this.toolStripSeparator4.Name = "toolStripSeparator4"; this.toolStripSeparator4.Size = new System.Drawing.Size(239, 6); // // requestNodeNeighborUpdateToolStripMenuItem // this.requestNodeNeighborUpdateToolStripMenuItem.Name = "requestNodeNeighborUpdateToolStripMenuItem"; this.requestNodeNeighborUpdateToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.requestNodeNeighborUpdateToolStripMenuItem.Text = "Request Node Neighbor Update"; this.requestNodeNeighborUpdateToolStripMenuItem.Click += new System.EventHandler(this.requestNodeNeighborUpdateToolStripMenuItem_Click); // // assignReturnRouteToolStripMenuItem // this.assignReturnRouteToolStripMenuItem.Name = "assignReturnRouteToolStripMenuItem"; this.assignReturnRouteToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.assignReturnRouteToolStripMenuItem.Text = "Assign Return Route"; this.assignReturnRouteToolStripMenuItem.Click += new System.EventHandler(this.assignReturnRouteToolStripMenuItem_Click); // // deleteReturnRouteToolStripMenuItem // this.deleteReturnRouteToolStripMenuItem.Name = "deleteReturnRouteToolStripMenuItem"; this.deleteReturnRouteToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.deleteReturnRouteToolStripMenuItem.Text = "Delete All Return Routes"; this.deleteReturnRouteToolStripMenuItem.Click += new System.EventHandler(this.deleteReturnRouteToolStripMenuItem_Click); // // toolStripSeparator5 // this.toolStripSeparator5.Name = "toolStripSeparator5"; this.toolStripSeparator5.Size = new System.Drawing.Size(239, 6); // // hasNodeFailedToolStripMenuItem // this.hasNodeFailedToolStripMenuItem.Name = "hasNodeFailedToolStripMenuItem"; this.hasNodeFailedToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.hasNodeFailedToolStripMenuItem.Text = "Has Node Failed"; this.hasNodeFailedToolStripMenuItem.Click += new System.EventHandler(this.hasNodeFailedToolStripMenuItem_Click); // // markNodeAsFailedToolStripMenuItem // this.markNodeAsFailedToolStripMenuItem.Name = "markNodeAsFailedToolStripMenuItem"; this.markNodeAsFailedToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.markNodeAsFailedToolStripMenuItem.Text = "Remove Failed Node"; this.markNodeAsFailedToolStripMenuItem.Click += new System.EventHandler(this.markNodeAsFailedToolStripMenuItem_Click); // // replaceFailedNodeToolStripMenuItem // this.replaceFailedNodeToolStripMenuItem.Name = "replaceFailedNodeToolStripMenuItem"; this.replaceFailedNodeToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.replaceFailedNodeToolStripMenuItem.Text = "Replace Failed Node"; this.replaceFailedNodeToolStripMenuItem.Click += new System.EventHandler(this.replaceFailedNodeToolStripMenuItem_Click); // // toolStripSeparator6 // this.toolStripSeparator6.Name = "toolStripSeparator6"; this.toolStripSeparator6.Size = new System.Drawing.Size(239, 6); // // propertiesToolStripMenuItem // this.propertiesToolStripMenuItem.Name = "propertiesToolStripMenuItem"; this.propertiesToolStripMenuItem.Size = new System.Drawing.Size(242, 22); this.propertiesToolStripMenuItem.Text = "Properties"; this.propertiesToolStripMenuItem.Click += new System.EventHandler(this.propertiesToolStripMenuItem_Click); // // MenuBar // this.MenuBar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.FileToolStripMenuItem, this.controllerToolStripMenuItem}); this.MenuBar.Location = new System.Drawing.Point(0, 0); this.MenuBar.Name = "MenuBar"; this.MenuBar.Size = new System.Drawing.Size(634, 24); this.MenuBar.TabIndex = 1; this.MenuBar.Text = "menuStrip1"; // // FileToolStripMenuItem // this.FileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.SaveToolStripMenuItem}); this.FileToolStripMenuItem.Name = "FileToolStripMenuItem"; this.FileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); this.FileToolStripMenuItem.Text = "&File"; // // SaveToolStripMenuItem // this.SaveToolStripMenuItem.Name = "SaveToolStripMenuItem"; this.SaveToolStripMenuItem.Size = new System.Drawing.Size(98, 22); this.SaveToolStripMenuItem.Text = "&Save"; this.SaveToolStripMenuItem.Click += new System.EventHandler(this.SaveToolStripMenuItem_Click); // // controllerToolStripMenuItem // this.controllerToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.createNewPrmaryControllerToolStripMenuItem, this.transferPrimaryRoleToolStripMenuItem, this.addControllerToolStripMenuItem, this.addDeviceToolStripMenuItem, this.addSecureDeviceToolStripMenuItem, this.toolStripSeparator1, this.removeControllerToolStripMenuItem, this.removeDeviceToolStripMenuItem, this.toolStripSeparator2, this.receiveConfigurationToolStripMenuItem, this.toolStripSeparator3, this.requestNetworkUpdateToolStripMenuItem, this.toolStripSeparator7, this.resetControllersoftToolStripMenuItem}); this.controllerToolStripMenuItem.Name = "controllerToolStripMenuItem"; this.controllerToolStripMenuItem.Size = new System.Drawing.Size(72, 20); this.controllerToolStripMenuItem.Text = "Controller"; // // createNewPrmaryControllerToolStripMenuItem // this.createNewPrmaryControllerToolStripMenuItem.Name = "createNewPrmaryControllerToolStripMenuItem"; this.createNewPrmaryControllerToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.createNewPrmaryControllerToolStripMenuItem.Text = "Create New Prmary Controller"; this.createNewPrmaryControllerToolStripMenuItem.Click += new System.EventHandler(this.createNewPrmaryControllerToolStripMenuItem_Click); // // transferPrimaryRoleToolStripMenuItem // this.transferPrimaryRoleToolStripMenuItem.Name = "transferPrimaryRoleToolStripMenuItem"; this.transferPrimaryRoleToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.transferPrimaryRoleToolStripMenuItem.Text = "Transfer Primary Role"; this.transferPrimaryRoleToolStripMenuItem.Click += new System.EventHandler(this.transferPrimaryRoleToolStripMenuItem_Click); // // addControllerToolStripMenuItem // this.addControllerToolStripMenuItem.Name = "addControllerToolStripMenuItem"; this.addControllerToolStripMenuItem.Size = new System.Drawing.Size(232, 22); // // addDeviceToolStripMenuItem // this.addDeviceToolStripMenuItem.Name = "addDeviceToolStripMenuItem"; this.addDeviceToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.addDeviceToolStripMenuItem.Text = "Add Device"; this.addDeviceToolStripMenuItem.Click += new System.EventHandler(this.addDeviceToolStripMenuItem_Click); // // toolStripSeparator1 // this.toolStripSeparator1.Name = "toolStripSeparator1"; this.toolStripSeparator1.Size = new System.Drawing.Size(229, 6); // // removeControllerToolStripMenuItem // this.removeControllerToolStripMenuItem.Name = "removeControllerToolStripMenuItem"; this.removeControllerToolStripMenuItem.Size = new System.Drawing.Size(232, 22); // // removeDeviceToolStripMenuItem // this.removeDeviceToolStripMenuItem.Name = "removeDeviceToolStripMenuItem"; this.removeDeviceToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.removeDeviceToolStripMenuItem.Text = "Remove Device"; this.removeDeviceToolStripMenuItem.Click += new System.EventHandler(this.removeDeviceToolStripMenuItem_Click); // // toolStripSeparator2 // this.toolStripSeparator2.Name = "toolStripSeparator2"; this.toolStripSeparator2.Size = new System.Drawing.Size(229, 6); // // receiveConfigurationToolStripMenuItem // this.receiveConfigurationToolStripMenuItem.Name = "receiveConfigurationToolStripMenuItem"; this.receiveConfigurationToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.receiveConfigurationToolStripMenuItem.Text = "Receive Configuration"; this.receiveConfigurationToolStripMenuItem.Click += new System.EventHandler(this.receiveConfigurationToolStripMenuItem_Click); // // toolStripSeparator3 // this.toolStripSeparator3.Name = "toolStripSeparator3"; this.toolStripSeparator3.Size = new System.Drawing.Size(229, 6); // // requestNetworkUpdateToolStripMenuItem // this.requestNetworkUpdateToolStripMenuItem.Name = "requestNetworkUpdateToolStripMenuItem"; this.requestNetworkUpdateToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.requestNetworkUpdateToolStripMenuItem.Text = "Request Network Update"; this.requestNetworkUpdateToolStripMenuItem.Click += new System.EventHandler(this.requestNetworkUpdateToolStripMenuItem_Click); // // toolStripSeparator7 // this.toolStripSeparator7.Name = "toolStripSeparator7"; this.toolStripSeparator7.Size = new System.Drawing.Size(229, 6); // // resetControllersoftToolStripMenuItem // this.resetControllersoftToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.softToolStripMenuItem, this.eraseAllToolStripMenuItem}); this.resetControllersoftToolStripMenuItem.Name = "resetControllersoftToolStripMenuItem"; this.resetControllersoftToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.resetControllersoftToolStripMenuItem.Text = "Reset Controller"; // // softToolStripMenuItem // this.softToolStripMenuItem.Name = "softToolStripMenuItem"; this.softToolStripMenuItem.Size = new System.Drawing.Size(118, 22); this.softToolStripMenuItem.Text = "Soft"; this.softToolStripMenuItem.Click += new System.EventHandler(this.softToolStripMenuItem_Click); // // eraseAllToolStripMenuItem // this.eraseAllToolStripMenuItem.Name = "eraseAllToolStripMenuItem"; this.eraseAllToolStripMenuItem.Size = new System.Drawing.Size(118, 22); this.eraseAllToolStripMenuItem.Text = "Erase All"; this.eraseAllToolStripMenuItem.Click += new System.EventHandler(this.eraseAllToolStripMenuItem_Click); // // statusStrip1 // this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripStatusLabel1}); this.statusStrip1.Location = new System.Drawing.Point(0, 430); this.statusStrip1.Name = "statusStrip1"; this.statusStrip1.Size = new System.Drawing.Size(634, 22); this.statusStrip1.TabIndex = 2; this.statusStrip1.Text = "statusStrip1"; // // toolStripStatusLabel1 // this.toolStripStatusLabel1.Name = "toolStripStatusLabel1"; this.toolStripStatusLabel1.Size = new System.Drawing.Size(70, 17); this.toolStripStatusLabel1.Text = "Initializing..."; // // addSecureDeviceToolStripMenuItem // this.addSecureDeviceToolStripMenuItem.Name = "addSecureDeviceToolStripMenuItem"; this.addSecureDeviceToolStripMenuItem.Size = new System.Drawing.Size(232, 22); this.addSecureDeviceToolStripMenuItem.Text = "Add Secure Device"; this.addSecureDeviceToolStripMenuItem.Click += new System.EventHandler(this.addSecureDeviceToolStripMenuItem_Click); // // MainForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(634, 452); this.Controls.Add(this.statusStrip1); this.Controls.Add(this.NodeGridView); this.Controls.Add(this.MenuBar); this.MainMenuStrip = this.MenuBar; this.Name = "MainForm"; this.Text = "OpenZWave Test"; ((System.ComponentModel.ISupportInitialize)(this.NodeGridView)).EndInit(); this.NodeContextMenuStrip.ResumeLayout(false); this.MenuBar.ResumeLayout(false); this.MenuBar.PerformLayout(); this.statusStrip1.ResumeLayout(false); this.statusStrip1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.DataGridView NodeGridView; private System.Windows.Forms.MenuStrip MenuBar; private System.Windows.Forms.ToolStripMenuItem FileToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem SaveToolStripMenuItem; private System.Windows.Forms.ContextMenuStrip NodeContextMenuStrip; private System.Windows.Forms.ToolStripMenuItem requestNodeNeighborUpdateToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem controllerToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem createNewPrmaryControllerToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem addControllerToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem addDeviceToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem removeControllerToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem removeDeviceToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem transferPrimaryRoleToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem receiveConfigurationToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator1; private System.Windows.Forms.ToolStripSeparator toolStripSeparator2; private System.Windows.Forms.ToolStripSeparator toolStripSeparator3; private System.Windows.Forms.ToolStripMenuItem PowerOnToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem PowerOffToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator4; private System.Windows.Forms.ToolStripSeparator toolStripSeparator5; private System.Windows.Forms.ToolStripMenuItem hasNodeFailedToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem markNodeAsFailedToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem replaceFailedNodeToolStripMenuItem; private System.Windows.Forms.ToolStripSeparator toolStripSeparator6; private System.Windows.Forms.ToolStripMenuItem propertiesToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem requestNetworkUpdateToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem assignReturnRouteToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem deleteReturnRouteToolStripMenuItem; private System.Windows.Forms.StatusStrip statusStrip1; private System.Windows.Forms.ToolStripStatusLabel toolStripStatusLabel1; private System.Windows.Forms.ToolStripSeparator toolStripSeparator7; private System.Windows.Forms.ToolStripMenuItem resetControllersoftToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem softToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem eraseAllToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem addSecureDeviceToolStripMenuItem; } } open-zwave-1.5/dotnet/examples/OZWForm/src/MainForm.cs000066400000000000000000001017001264474202400227220ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // MainForm.cs // // The Main Form of the OZWForm application. // Handles most of the Open Zwave notifications and commands. // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using System.ComponentModel; using System.Windows.Forms; using OpenZWaveDotNet; namespace OZWForm { /// /// The Main Form of the OZWForm application. /// Handles most of the Open Zwave notifications and commands. /// public partial class MainForm : Form { private static ZWOptions m_options = null; public static ZWOptions Options { get { return m_options; } } private static ZWManager m_manager = null; public static ZWManager Manager { get { return m_manager; } } private bool m_securityEnabled = false; public bool SecurityEnabled { get { return m_securityEnabled; } } private UInt32 m_homeId = 0; private ZWNotification m_notification = null; private BindingList m_nodeList = new BindingList(); private Byte m_rightClickNode = 0xff; private string m_driverPort = string.Empty; /// /// Initializes a new instance of the class. /// public MainForm() { // Initialize the form InitializeComponent(); // Add the columns to the grid view // Data Grid NodeGridView.AutoGenerateColumns = false; NodeGridView.AllowUserToResizeColumns = true; NodeGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells; DataGridViewTextBoxColumn column; //DataGridViewCheckBoxColumn check; // Id column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "ID"; column.Name = "Node"; column.ReadOnly = true; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.ToolTipText = "The Z-Wave node ID of the device.\nThis value is not editable."; NodeGridView.Columns.Add(column); // Location column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Location"; column.Name = "Location"; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.ToolTipText = "The user-defined location of the Z-Wave device."; NodeGridView.Columns.Add(column); // Name column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Name"; column.Name = "Name"; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.ToolTipText = "The user-defined name for the Z-Wave device."; NodeGridView.Columns.Add(column); // Device Type column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Label"; column.Name = "Type"; column.ReadOnly = true; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.ToolTipText = "The Z-Wave device type.\nThis value is not editable."; NodeGridView.Columns.Add(column); // Manufacturer column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Manufacturer"; column.Name = "Manufacturer"; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.ToolTipText = "The manufacturer of the Z-Wave device."; NodeGridView.Columns.Add(column); // Product column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Product"; column.Name = "Product"; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill; column.ToolTipText = "The product name of the Z-Wave device."; NodeGridView.Columns.Add(column); /* // Poll Interval column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "PollInterval"; column.Name = "Poll Interval"; column.ReadOnly = false; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.ToolTipText = "Polling interval in seconds, or zero for no polling.\nNewer devices should not need to be polled for\nyour PC to know their current state.\nFor those that do requre polling, the interval should\nbe as long as possible to reduce network traffic."; NodeGridView.Columns.Add(column); */ /* // Schema column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Schema"; column.Name = "Schema"; column.ReadOnly = true; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.ToolTipText = "The xPL message schema family that will be used\nif the 'Use zwave.basic' option is not checked.\nThe schema is chosen automatically according to\nthe Z-Wave device type, and cannot be changed."; NodeGridView.Columns.Add(column); // ZWaveBasic //check = new DataGridViewCheckBoxColumn(); //check.DataPropertyName = "ZWaveBasic"; //check.Name = "Use zwave.basic"; //check.Frozen = false; //check.Resizable = DataGridViewTriState.True; //check.SortMode = DataGridViewColumnSortMode.NotSortable; //check.ToolTipText = "If the box is checked, the device will send and respond to\nnative zwave.basic messages rather than those of the\ngeneric schema family listed under the Schema column."; //NodeGridView.Columns.Add(check); */ // Level column = new DataGridViewTextBoxColumn(); column.DataPropertyName = "Level"; column.Name = "Level"; column.Frozen = false; column.Resizable = DataGridViewTriState.True; column.SortMode = DataGridViewColumnSortMode.NotSortable; column.ToolTipText = "Current level of the device"; NodeGridView.Columns.Add(column); // On-Off button DataGridViewButtonColumn buttonColumn = new DataGridViewButtonColumn(); buttonColumn.DataPropertyName = "ButtonText"; buttonColumn.Name = "Power"; buttonColumn.Frozen = false; buttonColumn.Resizable = DataGridViewTriState.True; buttonColumn.SortMode = DataGridViewColumnSortMode.NotSortable; buttonColumn.ToolTipText = "Click a button to turn a light on or off"; NodeGridView.Columns.Add(buttonColumn); BindingSource bs = new BindingSource(); bs.DataSource = m_nodeList; NodeGridView.DataSource = bs; // Create the Options m_options = new ZWOptions(); m_options.Create(@"..\..\..\..\..\..\..\config\", @"", @""); // Add any app specific options here... m_options.AddOptionInt("SaveLogLevel", (int) ZWLogLevel.Detail); // ordinarily, just write "Detail" level messages to the log m_options.AddOptionInt("QueueLogLevel", (int) ZWLogLevel.Debug); // save recent messages with "Debug" level messages to be dumped if an error occurs m_options.AddOptionInt("DumpTriggerLevel", (int) ZWLogLevel.Error); // only "dump" Debug to the log emessages when an error-level message is logged // Lock the options m_options.Lock(); // Create the OpenZWave Manager m_manager = new ZWManager(); m_manager.Create(); m_manager.OnNotification += new ManagedNotificationsHandler(NotificationHandler); // Add a driver m_driverPort = @"\\.\COM5"; m_manager.AddDriver(m_driverPort); // m_manager.AddDriver(@"HID Controller", ZWControllerInterface.Hid); } /// /// The notifications handler. /// /// The notification. public void NotificationHandler(ZWNotification notification) { // Handle the notification on a thread that can safely // modify the form controls without throwing an exception. m_notification = notification; Invoke(new MethodInvoker(NotificationHandler)); m_notification = null; } /// /// The notification handler. /// private void NotificationHandler() { switch (m_notification.GetType()) { case ZWNotification.Type.ValueAdded: { Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId()); if (node != null) { node.AddValue(m_notification.GetValueID()); } break; } case ZWNotification.Type.ValueRemoved: { Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId()); if (node != null) { node.RemoveValue(m_notification.GetValueID()); } break; } case ZWNotification.Type.ValueChanged: { /* Console.WriteLine("Value Changed"); ZWValueID v = m_notification.GetValueID(); Console.WriteLine(" Node : " + v.GetNodeId().ToString()); Console.WriteLine(" CC : " + v.GetCommandClassId().ToString()); Console.WriteLine(" Type : " + v.GetType().ToString()); Console.WriteLine(" Index: " + v.GetIndex().ToString()); Console.WriteLine(" Inst : " + v.GetInstance().ToString()); Console.WriteLine(" Value: " + GetValue(v).ToString()); Console.WriteLine(" Label: " + m_manager.GetValueLabel(v)); Console.WriteLine(" Help : " + m_manager.GetValueHelp(v)); Console.WriteLine(" Units: " + m_manager.GetValueUnits(v)); */ break; } case ZWNotification.Type.Group: { break; } case ZWNotification.Type.NodeAdded: { // if this node was in zwcfg*.xml, this is the first node notification // if not, the NodeNew notification should already have been received if (GetNode(m_notification.GetHomeId(), m_notification.GetNodeId()) == null) { Node node = new Node(); node.ID = m_notification.GetNodeId(); node.HomeID = m_notification.GetHomeId(); m_nodeList.Add(node); } break; } case ZWNotification.Type.NodeNew: { // Add the new node to our list (and flag as uninitialized) Node node = new Node(); node.ID = m_notification.GetNodeId(); node.HomeID = m_notification.GetHomeId(); m_nodeList.Add(node); break; } case ZWNotification.Type.NodeRemoved: { foreach (Node node in m_nodeList) { if (node.ID == m_notification.GetNodeId()) { m_nodeList.Remove(node); break; } } break; } case ZWNotification.Type.NodeProtocolInfo: { Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId()); if (node != null) { node.Label = m_manager.GetNodeType(m_homeId, node.ID); } break; } case ZWNotification.Type.NodeNaming: { Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId()); if (node != null) { node.Manufacturer = m_manager.GetNodeManufacturerName(m_homeId, node.ID); node.Product = m_manager.GetNodeProductName(m_homeId, node.ID); node.Location = m_manager.GetNodeLocation(m_homeId, node.ID); node.Name = m_manager.GetNodeName(m_homeId, node.ID); } break; } case ZWNotification.Type.NodeEvent: { break; } case ZWNotification.Type.PollingDisabled: { Console.WriteLine("Polling disabled notification"); break; } case ZWNotification.Type.PollingEnabled: { Console.WriteLine("Polling enabled notification"); break; } case ZWNotification.Type.DriverReady: { m_homeId = m_notification.GetHomeId(); toolStripStatusLabel1.Text = "Initializing...driver with Home ID 0x" + m_homeId.ToString("X8") + " is ready."; break; } case ZWNotification.Type.NodeQueriesComplete: { // as an example, enable query of BASIC info (CommandClass = 0x20) Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId()); //if (node != null) //{ // foreach (ZWValueID vid in node.Values) // { // if (vid.GetCommandClassId() == 0x84) // remove this "if" to poll all values // m_manager.EnablePoll(vid); // } //} toolStripStatusLabel1.Text = "Initializing...node " + node.ID + " query complete."; break; } case ZWNotification.Type.EssentialNodeQueriesComplete: { Node node = GetNode(m_notification.GetHomeId(), m_notification.GetNodeId()); toolStripStatusLabel1.Text = "Initializing...node " + node.ID + " essential queries complete."; break; } case ZWNotification.Type.AllNodesQueried: { toolStripStatusLabel1.Text = "Ready: All nodes queried."; m_manager.WriteConfig(m_notification.GetHomeId()); break; } case ZWNotification.Type.AllNodesQueriedSomeDead: { toolStripStatusLabel1.Text = "Ready: All nodes queried but some are dead."; m_manager.WriteConfig(m_notification.GetHomeId()); break; } case ZWNotification.Type.AwakeNodesQueried: { toolStripStatusLabel1.Text = "Ready: Awake nodes queried (but not some sleeping nodes)."; m_manager.WriteConfig(m_notification.GetHomeId()); break; } } //NodeGridView.Refresh(); NodeGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; NodeGridView.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.DisplayedCells; } /// /// Gets the node. /// /// The home identifier. /// The node identifier. /// private Node GetNode(UInt32 homeId, Byte nodeId) { foreach (Node node in m_nodeList) { if ((node.ID == nodeId) && (node.HomeID == homeId)) { return node; } } return null; } /// /// Handles the Click event of the SaveToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void SaveToolStripMenuItem_Click(object sender, EventArgs e) { m_manager.WriteConfig(m_homeId); } /// /// Handles the CellMouseDown event of the NodeGridView control. /// /// The source of the event. /// The instance containing the event data. private void NodeGridView_CellMouseDown(object sender, DataGridViewCellMouseEventArgs e) { if ((e.RowIndex >= 0) && (e.Button == System.Windows.Forms.MouseButtons.Right)) { // Highlight the clicked row NodeGridView.Rows[e.RowIndex].Selected = true; // Store the index of the selected node m_rightClickNode = Convert.ToByte(NodeGridView.Rows[e.RowIndex].Cells["Node"].Value); } } /// /// Handles the Click event of the PowerOnToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void PowerOnToolStripMenuItem_Click(object sender, EventArgs e) { m_manager.SetNodeOn(m_homeId, m_rightClickNode); } /// /// Handles the Click event of the PowerOffToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void PowerOffToolStripMenuItem_Click(object sender, EventArgs e) { m_manager.SetNodeOff(m_homeId, m_rightClickNode); } /// /// Handles the Click event of the hasNodeFailedToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void hasNodeFailedToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.HasNodeFailed); } /// /// Handles the Click event of the markNodeAsFailedToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void markNodeAsFailedToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.RemoveFailedNode); } /// /// Handles the Click event of the replaceFailedNodeToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void replaceFailedNodeToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.ReplaceFailedNode); } /// /// Handles the Click event of the createNewPrmaryControllerToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void createNewPrmaryControllerToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.CreateNewPrimary); } /// /// Handles the Click event of the addDeviceToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void addDeviceToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.AddDevice); } /// /// Handles the Click event of the removeDeviceToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void removeDeviceToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.RemoveDevice); } /// /// Handles the Click event of the transferPrimaryRoleToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void transferPrimaryRoleToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.TransferPrimaryRole); } /// /// Handles the Click event of the receiveConfigurationToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void receiveConfigurationToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.ReceiveConfiguration); } /// /// Handles the Click event of the requestNetworkUpdateToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void requestNetworkUpdateToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.RequestNetworkUpdate); } /// /// Handles the Click event of the requestNodeNeighborUpdateToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void requestNodeNeighborUpdateToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.RequestNodeNeighborUpdate); } /// /// Handles the Click event of the assignReturnRouteToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void assignReturnRouteToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.AssignReturnRoute); } /// /// Handles the Click event of the deleteReturnRouteToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void deleteReturnRouteToolStripMenuItem_Click(object sender, EventArgs e) { DoCommand(ZWControllerCommand.DeleteAllReturnRoutes); } /// /// Does the command. /// /// The command. private void DoCommand(ZWControllerCommand command) { ControllerCommandDlg dlg = new ControllerCommandDlg(this, m_manager, m_homeId, command, m_rightClickNode); DialogResult d = dlg.ShowDialog(this); dlg.Dispose(); } /// /// Handles the Click event of the propertiesToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void propertiesToolStripMenuItem_Click(object sender, EventArgs e) { Node node = GetNode(m_homeId, m_rightClickNode); if (node != null) { // Wait for refreshed config param values ConfigurationWakeUpDlg configDlg = new ConfigurationWakeUpDlg(m_manager, node.HomeID, node.ID); if (DialogResult.OK == configDlg.ShowDialog(this)) { // Show the form NodeForm dlg = new NodeForm(node); dlg.ShowDialog(this); dlg.Dispose(); } configDlg.Dispose(); } } /// /// Handles the CellParsing event of the NodeGridView control. /// /// The source of the event. /// The instance containing the event data. private void NodeGridView_CellParsing(object sender, DataGridViewCellParsingEventArgs e) { if ((e.RowIndex < 0) || (e.ColumnIndex < 0)) { // Invalid cell return; } if (e.ColumnIndex == 1) { // Location Byte nodeId = Convert.ToByte(NodeGridView.Rows[e.RowIndex].Cells["Node"].Value); Node node = GetNode(m_homeId, nodeId); if (node != null) { String newLocation = e.Value.ToString(); if (newLocation != node.Location) { m_manager.SetNodeLocation(m_homeId, node.ID, newLocation); } } } if (e.ColumnIndex == 2) { // Name Byte nodeId = Convert.ToByte(NodeGridView.Rows[e.RowIndex].Cells["Node"].Value); Node node = GetNode(m_homeId, nodeId); if (node != null) { String newName = e.Value.ToString(); if (newName != node.Name) { m_manager.SetNodeName(m_homeId, node.ID, newName); } } } } /// /// Gets the value. /// /// The v. /// private string GetValue(ZWValueID v) { switch (v.GetType()) { case ZWValueID.ValueType.Bool: bool r1; m_manager.GetValueAsBool(v, out r1); return r1.ToString(); case ZWValueID.ValueType.Byte: byte r2; m_manager.GetValueAsByte(v, out r2); return r2.ToString(); case ZWValueID.ValueType.Decimal: decimal r3; m_manager.GetValueAsDecimal(v, out r3); return r3.ToString(); case ZWValueID.ValueType.Int: Int32 r4; m_manager.GetValueAsInt(v, out r4); return r4.ToString(); case ZWValueID.ValueType.List: string[] r5; m_manager.GetValueListItems(v, out r5); string r6 = ""; foreach (string s in r5) { r6 += s; r6 += "/"; } return r6; case ZWValueID.ValueType.Schedule: return "Schedule"; case ZWValueID.ValueType.Short: short r7; m_manager.GetValueAsShort(v, out r7); return r7.ToString(); case ZWValueID.ValueType.String: string r8; m_manager.GetValueAsString(v, out r8); return r8; default: return ""; } } /// /// Handles the Click event of the softToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void softToolStripMenuItem_Click(object sender, EventArgs e) { m_manager.SoftReset(m_homeId); } /// /// Handles the Click event of the eraseAllToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void eraseAllToolStripMenuItem_Click(object sender, EventArgs e) { if (DialogResult.Yes == MessageBox.Show( "Are you sure you want to fully reset the controller? This will delete all network information and require re-including all nodes.", "Hard Reset", MessageBoxButtons.YesNo)) { m_manager.ResetController(m_homeId); m_manager.RemoveDriver(m_driverPort); m_manager.AddDriver(m_driverPort); } } /// /// Handles the Click event of the addSecureDeviceToolStripMenuItem control. /// /// The source of the event. /// The instance containing the event data. private void addSecureDeviceToolStripMenuItem_Click(object sender, EventArgs e) { m_securityEnabled = true; DoCommand(ZWControllerCommand.AddDevice); m_securityEnabled = false; } } }open-zwave-1.5/dotnet/examples/OZWForm/src/MainForm.resx000066400000000000000000000144231264474202400233030ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 118, 17 17, 17 284, 17 open-zwave-1.5/dotnet/examples/OZWForm/src/Node.cs000066400000000000000000000107431264474202400221050ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Node.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using System.Collections.Generic; using OpenZWaveDotNet; namespace OZWForm { /// /// Container for Nodes /// public class Node { private Byte m_id = 0; /// /// Gets or sets the identifier. /// /// /// The identifier. /// public Byte ID { get { return m_id; } set { m_id = value; } } private UInt32 m_homeId = 0; /// /// Gets or sets the home identifier. /// /// /// The home identifier. /// public UInt32 HomeID { get { return m_homeId; } set { m_homeId = value; } } private String m_name = ""; /// /// Gets or sets the name. /// /// /// The name. /// public String Name { get { return m_name; } set { m_name = value; } } private String m_location = ""; /// /// Gets or sets the location. /// /// /// The location. /// public String Location { get { return m_location; } set { m_location = value; } } private String m_label = ""; /// /// Gets or sets the label. /// /// /// The label. /// public String Label { get { return m_label; } set { m_label = value; } } private String m_manufacturer = ""; /// /// Gets or sets the manufacturer. /// /// /// The manufacturer. /// public String Manufacturer { get { return m_manufacturer; } set { m_manufacturer = value; } } private String m_product = ""; /// /// Gets or sets the product. /// /// /// The product. /// public String Product { get { return m_product; } set { m_product = value; } } private List m_values = new List(); /// /// Gets the values. /// /// /// The values. /// public List Values { get { return m_values; } } /// /// Initializes a new instance of the class. /// public Node() { } /// /// Adds the value. /// /// The value identifier. public void AddValue(ZWValueID valueID) { m_values.Add(valueID); } /// /// Removes the value. /// /// The value identifier. public void RemoveValue(ZWValueID valueID) { m_values.Remove(valueID); } } } open-zwave-1.5/dotnet/examples/OZWForm/src/NodeForm.Designer.cs000066400000000000000000000051001264474202400244570ustar00rootroot00000000000000namespace OZWForm { partial class NodeForm { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Windows Form Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.NodeLayoutPanel = new System.Windows.Forms.TableLayoutPanel(); this.SuspendLayout(); // // NodeLayoutPanel // this.NodeLayoutPanel.AutoScroll = true; this.NodeLayoutPanel.AutoSize = true; this.NodeLayoutPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.NodeLayoutPanel.ColumnCount = 1; this.NodeLayoutPanel.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); this.NodeLayoutPanel.Location = new System.Drawing.Point(12, 12); this.NodeLayoutPanel.Name = "NodeLayoutPanel"; this.NodeLayoutPanel.RowCount = 1; this.NodeLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle()); this.NodeLayoutPanel.Size = new System.Drawing.Size(0, 0); this.NodeLayoutPanel.TabIndex = 0; // // NodeForm // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoScroll = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.ClientSize = new System.Drawing.Size(526, 323); this.Controls.Add(this.NodeLayoutPanel); this.Name = "NodeForm"; this.ShowInTaskbar = false; this.Text = "NodeForm"; this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.TableLayoutPanel NodeLayoutPanel; } }open-zwave-1.5/dotnet/examples/OZWForm/src/NodeForm.cs000066400000000000000000000077351264474202400227400ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // NodeForm.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System.Windows.Forms; using OpenZWaveDotNet; namespace OZWForm { /// /// Shows a form containing all the details and configuration parameters of a node /// public partial class NodeForm : Form { private Node m_node; /// /// Initializes a new instance of the class. /// /// The node. public NodeForm( Node node ) { m_node = node; InitializeComponent(); // load all possible configuration parameters for (byte i = 0; i <= 10; i++) { MainForm.Manager.RequestConfigParam(node.HomeID, node.ID, i); } if (node.Manufacturer != "") { this.Text = "Node " + node.ID.ToString() + ": " + node.Manufacturer + " " + node.Product; } else { this.Text = "Node " + node.ID.ToString() + ": " + node.Label; } foreach (ZWValueID valueID in node.Values) { Control control = null; switch (valueID.GetType()) { case ZWValueID.ValueType.Bool: { control = new ValuePanelBool(valueID); break; } case ZWValueID.ValueType.Button: { control = new ValuePanelButton(valueID); break; } case ZWValueID.ValueType.Byte: { control = new ValuePanelByte(valueID); break; } case ZWValueID.ValueType.Decimal: { control = new ValuePanelDecimal(valueID); break; } case ZWValueID.ValueType.Int: { control = new ValuePanelInt(valueID); break; } case ZWValueID.ValueType.List: { control = new ValuePanelList(valueID); break; } case ZWValueID.ValueType.Short: { control = new ValuePanelShort(valueID); break; } case ZWValueID.ValueType.String: { control = new ValuePanelString(valueID); break; } } if (control != null) { NodeLayoutPanel.Controls.Add(control); } } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/NodeForm.resx000066400000000000000000000132661264474202400233100ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/Program.cs000066400000000000000000000031451264474202400226250ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // Program.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using System.Windows.Forms; namespace OZWForm { /// /// The class containing the entry point for the application /// static class Program { /// /// The main entry point for the application. /// [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new MainForm()); } } } open-zwave-1.5/dotnet/examples/OZWForm/src/Properties/000077500000000000000000000000001264474202400230205ustar00rootroot00000000000000open-zwave-1.5/dotnet/examples/OZWForm/src/Properties/AssemblyInfo.cs000066400000000000000000000026221264474202400257440ustar00rootroot00000000000000using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("OZWForm")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("OZWForm")] [assembly: AssemblyCopyright("Copyright © 2010")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("ebf0dfc0-d755-4760-ba8f-e05326741318")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] open-zwave-1.5/dotnet/examples/OZWForm/src/Properties/Resources.Designer.cs000066400000000000000000000054261264474202400270670ustar00rootroot00000000000000//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.1 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace OZWForm.Properties { using System; /// /// A strongly-typed resource class, for looking up localized strings, etc. /// // This class was auto-generated by the StronglyTypedResourceBuilder // class via a tool like ResGen or Visual Studio. // To add or remove a member, edit your .ResX file then rerun ResGen // with the /str option, or rebuild your VS project. [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class Resources { private static global::System.Resources.ResourceManager resourceMan; private static global::System.Globalization.CultureInfo resourceCulture; [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] internal Resources() { } /// /// Returns the cached ResourceManager instance used by this class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Resources.ResourceManager ResourceManager { get { if (object.ReferenceEquals(resourceMan, null)) { global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("OZWForm.Properties.Resources", typeof(Resources).Assembly); resourceMan = temp; } return resourceMan; } } /// /// Overrides the current thread's CurrentUICulture property for all /// resource lookups using this strongly typed resource class. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] internal static global::System.Globalization.CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/Properties/Resources.resx000066400000000000000000000127541264474202400257060ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/Properties/Settings.Designer.cs000066400000000000000000000020761264474202400267130ustar00rootroot00000000000000//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.1 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ namespace OZWForm.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "10.0.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); public static Settings Default { get { return defaultInstance; } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/Properties/Settings.settings000066400000000000000000000003711264474202400264030ustar00rootroot00000000000000 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanel.Designer.cs000066400000000000000000000027311264474202400250110ustar00rootroot00000000000000namespace OZWForm { partial class ValuePanel { /// /// Required designer variable. /// private System.ComponentModel.IContainer components = null; /// /// Clean up any resources being used. /// /// true if managed resources should be disposed; otherwise, false. protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// private void InitializeComponent() { this.SuspendLayout(); // // ValuePanel // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Name = "ValuePanel"; this.Size = new System.Drawing.Size(0, 0); this.ResumeLayout(false); } #endregion } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanel.cs000066400000000000000000000050101264474202400232430ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanel.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System.Windows.Forms; using OpenZWaveDotNet; namespace OZWForm { /// /// User control panel to show values /// public partial class ValuePanel : UserControl { private ZWValueID m_valueID; /// /// Gets the value identifier. /// /// /// The value identifier. /// public ZWValueID ValueID { get { return m_valueID; } } private bool m_sendChanges = false; /// /// Gets or sets a value indicating whether [send changes]. /// /// /// true if [send changes]; otherwise, false. /// public bool SendChanges { get { return m_sendChanges; } set { m_sendChanges = value; } } /// /// Prevents a default instance of the class from being created. /// private ValuePanel() { } /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanel( ZWValueID valueID ) { m_valueID = valueID; InitializeComponent(); } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanel.resx000066400000000000000000000132661264474202400236330ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelBool.cs000066400000000000000000000075201264474202400240670ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanelBool.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using OpenZWaveDotNet; namespace OZWForm { /// /// Valuepanel for containing boolean values /// public class ValuePanelBool: ValuePanel { private System.Windows.Forms.CheckBox ValueCheckBox; /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanelBool( ZWValueID valueID ): base( valueID ) { InitializeComponent(); if (MainForm.Manager.IsValueReadOnly(valueID)) { ValueCheckBox.Enabled = false; } ValueCheckBox.Text = MainForm.Manager.GetValueLabel(valueID); bool state; if (MainForm.Manager.GetValueAsBool(valueID, out state)) { ValueCheckBox.Checked = state; } SendChanges = true; } /// /// Initializes the component. /// private void InitializeComponent() { this.ValueCheckBox = new System.Windows.Forms.CheckBox(); this.SuspendLayout(); // // ValueCheckBox // this.ValueCheckBox.AutoSize = true; this.ValueCheckBox.Location = new System.Drawing.Point(4, 4); this.ValueCheckBox.Name = "ValueCheckBox"; this.ValueCheckBox.Size = new System.Drawing.Size(52, 17); this.ValueCheckBox.TabIndex = 0; this.ValueCheckBox.Text = "Label"; this.ValueCheckBox.UseVisualStyleBackColor = true; this.ValueCheckBox.CheckedChanged += new System.EventHandler(this.ValueCheckBox_CheckedChanged); // // ValuePanelBool // this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.ValueCheckBox); this.Name = "ValuePanelBool"; this.Size = new System.Drawing.Size(59, 24); this.ResumeLayout(false); this.PerformLayout(); } /// /// Handles the CheckedChanged event of the ValueCheckBox control. /// /// The source of the event. /// The instance containing the event data. private void ValueCheckBox_CheckedChanged(object sender, EventArgs e) { if (SendChanges) { MainForm.Manager.SetValue(ValueID, ValueCheckBox.Checked); } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelBool.resx000066400000000000000000000132661264474202400244470ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelButton.cs000066400000000000000000000105741264474202400244520ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanelButton.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using OpenZWaveDotNet; namespace OZWForm { /// /// Value panel for containing buttons /// public class ValuePanelButton: ValuePanel { private System.Windows.Forms.Button ValueButtonButton; /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanelButton( ZWValueID valueID ): base( valueID ) { InitializeComponent(); ValueButtonButton.Text = MainForm.Manager.GetValueLabel(valueID); if (MainForm.Manager.IsValueReadOnly(valueID)) { ValueButtonButton.Enabled = false; } SendChanges = true; } /// /// Initializes the component. /// private void InitializeComponent() { this.ValueButtonButton = new System.Windows.Forms.Button(); this.SuspendLayout(); // // ValueButtonButton // this.ValueButtonButton.AutoSize = true; this.ValueButtonButton.Location = new System.Drawing.Point(3, 6); this.ValueButtonButton.Name = "ValueButtonButton"; this.ValueButtonButton.Size = new System.Drawing.Size(59, 23); this.ValueButtonButton.TabIndex = 1; this.ValueButtonButton.Text = "Label"; this.ValueButtonButton.UseVisualStyleBackColor = true; this.ValueButtonButton.KeyUp += new System.Windows.Forms.KeyEventHandler(this.ValueButtonButton_KeyUp); this.ValueButtonButton.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ValueButtonButton_KeyDown); // // ValuePanelButton // this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.ValueButtonButton); this.Name = "ValuePanelButton"; this.Size = new System.Drawing.Size(65, 32); this.ResumeLayout(false); this.PerformLayout(); } /// /// Handles the KeyDown event of the ValueButtonButton control. /// /// The source of the event. /// The instance containing the event data. private void ValueButtonButton_KeyDown(object sender, System.Windows.Forms.KeyEventArgs e) { if (SendChanges) { MainForm.Manager.PressButton(ValueID); } } /// /// Handles the KeyUp event of the ValueButtonButton control. /// /// The source of the event. /// The instance containing the event data. private void ValueButtonButton_KeyUp(object sender, System.Windows.Forms.KeyEventArgs e) { if (SendChanges) { MainForm.Manager.ReleaseButton(ValueID); } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelButton.resx000066400000000000000000000132661264474202400250270ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelByte.cs000066400000000000000000000127001264474202400240730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanelByte.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using OpenZWaveDotNet; namespace OZWForm { /// /// Value panel for containing bytes /// public class ValuePanelByte: ValuePanel { private System.Windows.Forms.NumericUpDown ValueByteNumericUpDown; private System.Windows.Forms.Label ValueByteLabel; private System.Windows.Forms.Button ValueByteButtonSet; /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanelByte( ZWValueID valueID ): base( valueID ) { InitializeComponent(); ValueByteLabel.Text = MainForm.Manager.GetValueLabel(valueID); if (MainForm.Manager.IsValueReadOnly(valueID)) { ValueByteNumericUpDown.Enabled = false; ValueByteButtonSet.Visible = false; } Byte value; if (MainForm.Manager.GetValueAsByte(valueID, out value)) { ValueByteNumericUpDown.Value = Convert.ToDecimal(value); } SendChanges = true; } /// /// Initializes the component. /// private void InitializeComponent() { this.ValueByteNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.ValueByteButtonSet = new System.Windows.Forms.Button(); this.ValueByteLabel = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.ValueByteNumericUpDown)).BeginInit(); this.SuspendLayout(); // // ValueByteNumericUpDown // this.ValueByteNumericUpDown.Location = new System.Drawing.Point(3, 6); this.ValueByteNumericUpDown.Maximum = new decimal(new int[] { 255, 0, 0, 0}); this.ValueByteNumericUpDown.Name = "ValueByteNumericUpDown"; this.ValueByteNumericUpDown.Size = new System.Drawing.Size(59, 20); this.ValueByteNumericUpDown.TabIndex = 0; // // ValueByteButtonSet // this.ValueByteButtonSet.Location = new System.Drawing.Point(68, 6); this.ValueByteButtonSet.Name = "ValueByteButtonSet"; this.ValueByteButtonSet.Size = new System.Drawing.Size(59, 20); this.ValueByteButtonSet.TabIndex = 1; this.ValueByteButtonSet.Text = "Set"; this.ValueByteButtonSet.UseVisualStyleBackColor = true; this.ValueByteButtonSet.Click += new System.EventHandler(this.ValueByteButtonSet_Click); // // ValueByteLabel // this.ValueByteLabel.AutoSize = true; this.ValueByteLabel.Location = new System.Drawing.Point(133, 10); this.ValueByteLabel.Name = "ValueByteLabel"; this.ValueByteLabel.Size = new System.Drawing.Size(33, 13); this.ValueByteLabel.TabIndex = 2; this.ValueByteLabel.Text = "Label"; // // ValuePanelByte // this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.ValueByteLabel); this.Controls.Add(this.ValueByteButtonSet); this.Controls.Add(this.ValueByteNumericUpDown); this.Name = "ValuePanelByte"; this.Size = new System.Drawing.Size(169, 29); ((System.ComponentModel.ISupportInitialize)(this.ValueByteNumericUpDown)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } /// /// Handles the Click event of the ValueByteButtonSet control. /// /// The source of the event. /// The instance containing the event data. private void ValueByteButtonSet_Click(object sender, EventArgs e) { if (SendChanges) { Byte value = Convert.ToByte(ValueByteNumericUpDown.Value); MainForm.Manager.SetValue(ValueID, value); } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelByte.resx000066400000000000000000000132661264474202400244570ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelDecimal.cs000066400000000000000000000123231264474202400245270ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanelDecimal.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using OpenZWaveDotNet; namespace OZWForm { /// /// Value panel for containing decimal values /// public class ValuePanelDecimal: ValuePanel { private System.Windows.Forms.TextBox ValueDecimalTextBox; private System.Windows.Forms.Button ValueDecimalButtonSet; private System.Windows.Forms.Label ValueDecimalLabel; /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanelDecimal( ZWValueID valueID ): base( valueID ) { InitializeComponent(); ValueDecimalLabel.Text = MainForm.Manager.GetValueLabel(valueID); if (MainForm.Manager.IsValueReadOnly(valueID)) { ValueDecimalTextBox.Enabled = false; ValueDecimalButtonSet.Enabled = false; } Decimal value; if (MainForm.Manager.GetValueAsDecimal(valueID, out value)) { ValueDecimalTextBox.Text = value.ToString(); } SendChanges = true; } /// /// Initializes the component. /// private void InitializeComponent() { this.ValueDecimalLabel = new System.Windows.Forms.Label(); this.ValueDecimalTextBox = new System.Windows.Forms.TextBox(); this.ValueDecimalButtonSet = new System.Windows.Forms.Button(); this.SuspendLayout(); // // ValueDecimalLabel // this.ValueDecimalLabel.AutoSize = true; this.ValueDecimalLabel.Location = new System.Drawing.Point(152, 7); this.ValueDecimalLabel.Name = "ValueDecimalLabel"; this.ValueDecimalLabel.Size = new System.Drawing.Size(33, 13); this.ValueDecimalLabel.TabIndex = 2; this.ValueDecimalLabel.Text = "Label"; // // ValueDecimalTextBox // this.ValueDecimalTextBox.Location = new System.Drawing.Point(4, 4); this.ValueDecimalTextBox.MaxLength = 255; this.ValueDecimalTextBox.Name = "ValueDecimalTextBox"; this.ValueDecimalTextBox.Size = new System.Drawing.Size(77, 20); this.ValueDecimalTextBox.TabIndex = 3; // // ValueDecimalButtonSet // this.ValueDecimalButtonSet.Location = new System.Drawing.Point(87, 3); this.ValueDecimalButtonSet.Name = "ValueDecimalButtonSet"; this.ValueDecimalButtonSet.Size = new System.Drawing.Size(59, 20); this.ValueDecimalButtonSet.TabIndex = 4; this.ValueDecimalButtonSet.Text = "Set"; this.ValueDecimalButtonSet.UseVisualStyleBackColor = true; this.ValueDecimalButtonSet.Click += new System.EventHandler(this.ValueDecimalButtonSet_Click); // // ValuePanelDecimal // this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.ValueDecimalButtonSet); this.Controls.Add(this.ValueDecimalTextBox); this.Controls.Add(this.ValueDecimalLabel); this.Name = "ValuePanelDecimal"; this.Size = new System.Drawing.Size(188, 27); this.ResumeLayout(false); this.PerformLayout(); } /// /// Handles the Click event of the ValueDecimalButtonSet control. /// /// The source of the event. /// The instance containing the event data. private void ValueDecimalButtonSet_Click(object sender, EventArgs e) { if (SendChanges) { float value = Convert.ToSingle(ValueDecimalTextBox.Text); MainForm.Manager.SetValue(ValueID, value); } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelDecimal.resx000066400000000000000000000132661264474202400251120ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelInt.cs000066400000000000000000000131741264474202400237300ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanelInt.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using OpenZWaveDotNet; namespace OZWForm { /// /// Value panel containing int values /// public class ValuePanelInt: ValuePanel { private System.Windows.Forms.NumericUpDown ValueIntNumericUpDown; private System.Windows.Forms.Label ValueIntLabel; private System.Windows.Forms.Button ValueIntButtonSet; /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanelInt( ZWValueID valueID ): base( valueID ) { InitializeComponent(); ValueIntLabel.Text = MainForm.Manager.GetValueLabel(valueID); if (MainForm.Manager.IsValueReadOnly(valueID)) { ValueIntNumericUpDown.Enabled = false; ValueIntButtonSet.Visible = false; } Int32 value; if (MainForm.Manager.GetValueAsInt(valueID, out value)) { ValueIntNumericUpDown.Value = Convert.ToDecimal(value); } SendChanges = true; } /// /// Initializes the component. /// private void InitializeComponent() { this.ValueIntNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.ValueIntButtonSet = new System.Windows.Forms.Button(); this.ValueIntLabel = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.ValueIntNumericUpDown)).BeginInit(); this.SuspendLayout(); // // ValueIntNumericUpDown // this.ValueIntNumericUpDown.Location = new System.Drawing.Point(3, 6); this.ValueIntNumericUpDown.Maximum = new decimal(new int[] { 2147483647, 0, 0, 0}); this.ValueIntNumericUpDown.Minimum = new decimal(new int[] { -2147483648, 0, 0, -2147483648}); this.ValueIntNumericUpDown.Name = "ValueIntNumericUpDown"; this.ValueIntNumericUpDown.Size = new System.Drawing.Size(59, 20); this.ValueIntNumericUpDown.TabIndex = 0; this.ValueIntNumericUpDown.ThousandsSeparator = true; // // ValueIntButtonSet // this.ValueIntButtonSet.Location = new System.Drawing.Point(68, 6); this.ValueIntButtonSet.Name = "ValueIntButtonSet"; this.ValueIntButtonSet.Size = new System.Drawing.Size(59, 20); this.ValueIntButtonSet.TabIndex = 1; this.ValueIntButtonSet.Text = "Set"; this.ValueIntButtonSet.UseVisualStyleBackColor = true; this.ValueIntButtonSet.Click += new System.EventHandler(this.ValueIntButtonSet_Click); // // ValueIntLabel // this.ValueIntLabel.AutoSize = true; this.ValueIntLabel.Location = new System.Drawing.Point(133, 10); this.ValueIntLabel.Name = "ValueIntLabel"; this.ValueIntLabel.Size = new System.Drawing.Size(33, 13); this.ValueIntLabel.TabIndex = 2; this.ValueIntLabel.Text = "Label"; // // ValuePanelInt // this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.ValueIntLabel); this.Controls.Add(this.ValueIntButtonSet); this.Controls.Add(this.ValueIntNumericUpDown); this.Name = "ValuePanelInt"; this.Size = new System.Drawing.Size(169, 29); ((System.ComponentModel.ISupportInitialize)(this.ValueIntNumericUpDown)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } /// /// Handles the Click event of the ValueIntButtonSet control. /// /// The source of the event. /// The instance containing the event data. private void ValueIntButtonSet_Click(object sender, EventArgs e) { if (SendChanges) { Int32 value = Convert.ToInt32(ValueIntNumericUpDown.Value); MainForm.Manager.SetValue(ValueID, value); } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelInt.resx000066400000000000000000000132661264474202400243060ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelList.cs000066400000000000000000000116021264474202400241030ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanelList.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using OpenZWaveDotNet; namespace OZWForm { /// /// Value panel containing lists /// public class ValuePanelList: ValuePanel { private System.Windows.Forms.ComboBox ValueListComboBox; private System.Windows.Forms.Label ValueListLabel; /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanelList( ZWValueID valueID ): base( valueID ) { InitializeComponent(); ValueListLabel.Text = MainForm.Manager.GetValueLabel(valueID); if (MainForm.Manager.IsValueReadOnly(valueID)) { ValueListComboBox.Enabled = false; } String[] items; if (MainForm.Manager.GetValueListItems(valueID, out items)) { ValueListComboBox.Items.Clear(); foreach (String item in items) { ValueListComboBox.Items.Add(item); } } String value; if (MainForm.Manager.GetValueListSelection(valueID, out value)) { ValueListComboBox.Text = value; } SendChanges = true; } /// /// Initializes the component. /// private void InitializeComponent() { this.ValueListLabel = new System.Windows.Forms.Label(); this.ValueListComboBox = new System.Windows.Forms.ComboBox(); this.SuspendLayout(); // // ValueListLabel // this.ValueListLabel.AutoSize = true; this.ValueListLabel.Location = new System.Drawing.Point(133, 10); this.ValueListLabel.Name = "ValueListLabel"; this.ValueListLabel.Size = new System.Drawing.Size(33, 13); this.ValueListLabel.TabIndex = 2; this.ValueListLabel.Text = "Label"; // // ValueListComboBox // this.ValueListComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.ValueListComboBox.FormattingEnabled = true; this.ValueListComboBox.Location = new System.Drawing.Point(4, 4); this.ValueListComboBox.MaxDropDownItems = 100; this.ValueListComboBox.Name = "ValueListComboBox"; this.ValueListComboBox.Size = new System.Drawing.Size(121, 21); this.ValueListComboBox.TabIndex = 3; this.ValueListComboBox.SelectedIndexChanged += new System.EventHandler(this.ValueListComboBox_SelectedIndexChanged); // // ValuePanelList // this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.ValueListComboBox); this.Controls.Add(this.ValueListLabel); this.Name = "ValuePanelList"; this.Size = new System.Drawing.Size(169, 28); this.ResumeLayout(false); this.PerformLayout(); } /// /// Handles the SelectedIndexChanged event of the ValueListComboBox control. /// /// The source of the event. /// The instance containing the event data. private void ValueListComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (SendChanges) { MainForm.Manager.SetValueListSelection(ValueID, ValueListComboBox.Text); } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelList.resx000066400000000000000000000132661264474202400244670ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelShort.cs000066400000000000000000000132201264474202400242650ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanelShort.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using OpenZWaveDotNet; namespace OZWForm { /// /// Value panel to contain shorts /// public class ValuePanelShort: ValuePanel { private System.Windows.Forms.NumericUpDown ValueShortNumericUpDown; private System.Windows.Forms.Label ValueShortLabel; private System.Windows.Forms.Button ValueShortButtonSet; /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanelShort( ZWValueID valueID ): base( valueID ) { InitializeComponent(); ValueShortLabel.Text = MainForm.Manager.GetValueLabel(valueID); if (MainForm.Manager.IsValueReadOnly(valueID)) { ValueShortNumericUpDown.Enabled = false; ValueShortButtonSet.Visible = false; } Int16 value; if (MainForm.Manager.GetValueAsShort(valueID, out value)) { ValueShortNumericUpDown.Value = Convert.ToDecimal(value); } SendChanges = true; } /// /// Initializes the component. /// private void InitializeComponent() { this.ValueShortNumericUpDown = new System.Windows.Forms.NumericUpDown(); this.ValueShortButtonSet = new System.Windows.Forms.Button(); this.ValueShortLabel = new System.Windows.Forms.Label(); ((System.ComponentModel.ISupportInitialize)(this.ValueShortNumericUpDown)).BeginInit(); this.SuspendLayout(); // // ValueShortNumericUpDown // this.ValueShortNumericUpDown.Location = new System.Drawing.Point(3, 6); this.ValueShortNumericUpDown.Maximum = new decimal(new int[] { 32767, 0, 0, 0}); this.ValueShortNumericUpDown.Minimum = new decimal(new int[] { 32768, 0, 0, -2147483648}); this.ValueShortNumericUpDown.Name = "ValueShortNumericUpDown"; this.ValueShortNumericUpDown.Size = new System.Drawing.Size(59, 20); this.ValueShortNumericUpDown.TabIndex = 0; // // ValueShortButtonSet // this.ValueShortButtonSet.Location = new System.Drawing.Point(68, 6); this.ValueShortButtonSet.Name = "ValueShortButtonSet"; this.ValueShortButtonSet.Size = new System.Drawing.Size(59, 20); this.ValueShortButtonSet.TabIndex = 1; this.ValueShortButtonSet.Text = "Set"; this.ValueShortButtonSet.UseVisualStyleBackColor = true; this.ValueShortButtonSet.Click += new System.EventHandler(this.ValueShortButtonSet_Click); // // ValueShortLabel // this.ValueShortLabel.AutoSize = true; this.ValueShortLabel.Location = new System.Drawing.Point(133, 10); this.ValueShortLabel.Name = "ValueShortLabel"; this.ValueShortLabel.Size = new System.Drawing.Size(33, 13); this.ValueShortLabel.TabIndex = 2; this.ValueShortLabel.Text = "Label"; // // ValuePanelShort // this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.ValueShortLabel); this.Controls.Add(this.ValueShortButtonSet); this.Controls.Add(this.ValueShortNumericUpDown); this.Name = "ValuePanelShort"; this.Size = new System.Drawing.Size(169, 29); ((System.ComponentModel.ISupportInitialize)(this.ValueShortNumericUpDown)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); } /// /// Handles the Click event of the ValueShortButtonSet control. /// /// The source of the event. /// The instance containing the event data. private void ValueShortButtonSet_Click(object sender, EventArgs e) { if (SendChanges) { Int16 value = Convert.ToInt16(ValueShortNumericUpDown.Value); MainForm.Manager.SetValue(ValueID, value); } } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelShort.resx000066400000000000000000000132661264474202400246530ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelString.cs000066400000000000000000000074071264474202400244460ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ValuePanelString.cs // // // // Copyright (c) 2010 Mal Lansell // // SOFTWARE NOTICE AND LICENSE // // This file is part of OZWForm. // // OZWForm is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // OZWForm 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . // //----------------------------------------------------------------------------- using System; using OpenZWaveDotNet; namespace OZWForm { /// /// Value panel to contain strings /// public class ValuePanelString: ValuePanel { private System.Windows.Forms.TextBox ValueStringTextBox; private System.Windows.Forms.Label ValueStringLabel; /// /// Initializes a new instance of the class. /// /// The value identifier. public ValuePanelString( ZWValueID valueID ): base( valueID ) { InitializeComponent(); ValueStringLabel.Text = MainForm.Manager.GetValueLabel(valueID); if (MainForm.Manager.IsValueReadOnly(valueID)) { ValueStringTextBox.Enabled = false; } String value; if (MainForm.Manager.GetValueAsString(valueID, out value)) { ValueStringTextBox.Text = value; } SendChanges = true; } /// /// Initializes the component. /// private void InitializeComponent() { this.ValueStringLabel = new System.Windows.Forms.Label(); this.ValueStringTextBox = new System.Windows.Forms.TextBox(); this.SuspendLayout(); // // ValueStringLabel // this.ValueStringLabel.AutoSize = true; this.ValueStringLabel.Location = new System.Drawing.Point(133, 10); this.ValueStringLabel.Name = "ValueStringLabel"; this.ValueStringLabel.Size = new System.Drawing.Size(33, 13); this.ValueStringLabel.TabIndex = 2; this.ValueStringLabel.Text = "Label"; // // ValueStringTextBox // this.ValueStringTextBox.Location = new System.Drawing.Point(4, 4); this.ValueStringTextBox.MaxLength = 255; this.ValueStringTextBox.Name = "ValueStringTextBox"; this.ValueStringTextBox.Size = new System.Drawing.Size(123, 20); this.ValueStringTextBox.TabIndex = 3; // // ValuePanelString // this.AutoSize = true; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; this.Controls.Add(this.ValueStringTextBox); this.Controls.Add(this.ValueStringLabel); this.Name = "ValuePanelString"; this.Size = new System.Drawing.Size(169, 27); this.ResumeLayout(false); this.PerformLayout(); } } } open-zwave-1.5/dotnet/examples/OZWForm/src/ValuePanelString.resx000066400000000000000000000132661264474202400250220ustar00rootroot00000000000000 text/microsoft-resx 2.0 System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 open-zwave-1.5/dotnet/examples/OZWForm/src/app.config000066400000000000000000000002201264474202400226250ustar00rootroot00000000000000 open-zwave-1.5/dotnet/src/000077500000000000000000000000001264474202400155435ustar00rootroot00000000000000open-zwave-1.5/dotnet/src/AssemblyInfo.cpp000066400000000000000000000044751264474202400206540ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // AssemblyInfo.cpp // // // // Copyright (c) 2010 Amer Harb // // 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 . // //----------------------------------------------------------------------------- using namespace System; using namespace System::Reflection; using namespace System::Runtime::CompilerServices; using namespace System::Runtime::InteropServices; using namespace System::Security::Permissions; // // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. // [assembly:AssemblyTitleAttribute("cli")]; [assembly:AssemblyDescriptionAttribute("")]; [assembly:AssemblyConfigurationAttribute("")]; [assembly:AssemblyCompanyAttribute("Microsoft")]; [assembly:AssemblyProductAttribute("cli")]; [assembly:AssemblyCopyrightAttribute("Copyright (c) Microsoft 2010")]; [assembly:AssemblyTrademarkAttribute("")]; [assembly:AssemblyCultureAttribute("")]; // // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the value or you can default the Revision and Build Numbers // by using the '*' as shown below: [assembly:AssemblyVersionAttribute("1.0.*")]; [assembly:ComVisible(false)]; [assembly:CLSCompliantAttribute(true)]; [assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)]; open-zwave-1.5/dotnet/src/ZWManager.cpp000066400000000000000000000407031264474202400201060ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ZWManager.cpp // // Cli/C++ wrapper for the C++ OpenZWave Manager class // // Copyright (c) 2010 Amer Harb // // 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 "ZWManager.h" using namespace OpenZWaveDotNet; using namespace OpenZWave; using namespace Runtime::InteropServices; //----------------------------------------------------------------------------- // // Create the unmanaged Manager singleton object, and add a watcher //----------------------------------------------------------------------------- void ZWManager::Create ( ) { // Create the Manager singleton Manager::Create(); // Add a notification handler m_onNotification = gcnew OnNotificationFromUnmanagedDelegate( this, &ZWManager::OnNotificationFromUnmanaged ); m_gchNotification = GCHandle::Alloc( m_onNotification ); IntPtr ip = Marshal::GetFunctionPointerForDelegate( m_onNotification ); Manager::Get()->AddWatcher( (Manager::pfnOnNotification_t)ip.ToPointer(), NULL ); // Add a controller state changed handler m_onStateChanged = gcnew OnControllerStateChangedFromUnmanagedDelegate( this, &ZWManager::OnControllerStateChangedFromUnmanaged ); m_gchControllerState = GCHandle::Alloc( m_onStateChanged ); } //----------------------------------------------------------------------------- // // Trigger an event from the unmanaged notification callback //----------------------------------------------------------------------------- void ZWManager::OnNotificationFromUnmanaged ( Notification* _notification, void* _context ) { ZWNotification^ notification = gcnew ZWNotification( _notification ); ZWOnNotification(notification); } //----------------------------------------------------------------------------- // // Trigger an event from the unmanaged controller state callback //----------------------------------------------------------------------------- void ZWManager::OnControllerStateChangedFromUnmanaged ( Driver::ControllerState _state, void* _context ) { ZWOnControllerStateChanged( (ZWControllerState)_state ); } //----------------------------------------------------------------------------- // // Gets a value as a Bool //----------------------------------------------------------------------------- bool ZWManager::GetValueAsBool ( ZWValueID^ id, [Out] System::Boolean %o_value ) { bool value; if( Manager::Get()->GetValueAsBool(id->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Gets a value as a Byte //----------------------------------------------------------------------------- bool ZWManager::GetValueAsByte ( ZWValueID^ id, [Out] System::Byte %o_value ) { uint8 value; if( Manager::Get()->GetValueAsByte(id->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Gets a value as a Decimal //----------------------------------------------------------------------------- bool ZWManager::GetValueAsDecimal ( ZWValueID^ id, [Out] System::Decimal %o_value ) { string value; if( Manager::Get()->GetValueAsString(id->CreateUnmanagedValueID(), &value ) ) { String^ decimal = gcnew String(value.c_str()); o_value = Decimal::Parse( decimal ); return true; } return false; } //----------------------------------------------------------------------------- // // Gets a value as an Int32 //----------------------------------------------------------------------------- bool ZWManager::GetValueAsInt ( ZWValueID^ id, [Out] System::Int32 %o_value ) { int32 value; if( Manager::Get()->GetValueAsInt(id->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Gets a value as an Int16 //----------------------------------------------------------------------------- bool ZWManager::GetValueAsShort ( ZWValueID^ id, [Out] System::Int16 %o_value ) { int16 value; if( Manager::Get()->GetValueAsShort(id->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Gets a value as a String //----------------------------------------------------------------------------- bool ZWManager::GetValueAsString ( ZWValueID^ id, [Out] String^ %o_value ) { string value; if( Manager::Get()->GetValueAsString(id->CreateUnmanagedValueID(), &value ) ) { o_value = gcnew String(value.c_str()); return true; } return false; } //----------------------------------------------------------------------------- // // Gets the selected item from a list value (returning a string) //----------------------------------------------------------------------------- bool ZWManager::GetValueListSelection ( ZWValueID^ id, [Out] String^ %o_value ) { string value; if( Manager::Get()->GetValueListSelection(id->CreateUnmanagedValueID(), &value ) ) { o_value = gcnew String(value.c_str()); return true; } return false; } //----------------------------------------------------------------------------- // // Gets the selected item from a list value (returning the value) //----------------------------------------------------------------------------- bool ZWManager::GetValueListSelection ( ZWValueID^ id, [Out] System::Int32 %o_value ) { Int32 value; if( Manager::Get()->GetValueListSelection(id->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Gets the list of items from a list value //----------------------------------------------------------------------------- bool ZWManager::GetValueListItems ( ZWValueID^ id, [Out] cli::array^ %o_value ) { vector items; if( Manager::Get()->GetValueListItems(id->CreateUnmanagedValueID(), &items ) ) { o_value = gcnew cli::array(items.size()); for( uint32 i=0; i // Gets the list of values from a list value //----------------------------------------------------------------------------- bool ZWManager::GetValueListValues ( ZWValueID^ id, [Out] cli::array^ %o_value ) { vector items; if( Manager::Get()->GetValueListValues(id->CreateUnmanagedValueID(), &items ) ) { o_value = gcnew cli::array(items.size()); for( uint32 i=0; i // Gets the neighbors for a node //----------------------------------------------------------------------------- uint32 ZWManager::GetNodeNeighbors ( uint32 homeId, uint8 nodeId, [Out] cli::array^ %o_neighbors ) { uint8* neighbors; uint32 numNeighbors = Manager::Get()->GetNodeNeighbors( homeId, nodeId, &neighbors ); if( numNeighbors ) { o_neighbors = gcnew cli::array(numNeighbors); for( uint32 i=0; i // Get switchpoint data from the schedule //----------------------------------------------------------------------------- bool ZWManager::GetSwitchPoint ( ZWValueID^ id, uint8 idx, [Out] System::Byte %o_hours, [Out] System::Byte %o_minutes, [Out] System::SByte %o_setback ) { uint8 hours; uint8 minutes; int8 setback; if( Manager::Get()->GetSwitchPoint( id->CreateUnmanagedValueID(), idx, &hours, &minutes, &setback ) ) { o_hours = hours; o_minutes = minutes; o_setback = setback; return true; } return false; } //----------------------------------------------------------------------------- // // Gets the associations for a group //----------------------------------------------------------------------------- uint32 ZWManager::GetAssociations ( uint32 homeId, uint8 nodeId, uint8 groupIdx, [Out] cli::array^ %o_associations ) { uint8* associations; uint32 numAssociations = Manager::Get()->GetAssociations( homeId, nodeId, groupIdx, &associations ); if( numAssociations ) { o_associations = gcnew cli::array(numAssociations); for( uint32 i=0; i // Start a controller command process //----------------------------------------------------------------------------- [Obsolete("BeginControllerCommand is deprecated, please use the specialized methods instead.", true)] bool ZWManager::BeginControllerCommand ( uint32 homeId, ZWControllerCommand command, bool highPower, uint8 nodeId ) { IntPtr ip = Marshal::GetFunctionPointerForDelegate( m_onStateChanged ); return( Manager::Get()->BeginControllerCommand( homeId, (Driver::ControllerCommand)command, (Driver::pfnControllerCallback_t)ip.ToPointer(), NULL, highPower, nodeId ) ); } bool ZWManager::GetNodeClassInformation ( uint32 homeId, uint8 nodeId, uint8 commandClassId, [Out] String^ %o_name, [Out] System::Byte %o_version ) { string value; uint8 version; if (Manager::Get()->GetNodeClassInformation(homeId, nodeId, commandClassId, &value, &version)) { o_name = gcnew String(value.c_str()); o_version = version; return true; } return false; } //----------------------------------------------------------------------------- // // Gets a list of all the SceneIds //----------------------------------------------------------------------------- uint8 ZWManager::GetAllScenes ( [Out] cli::array^ %o_sceneIds ) { uint8* sceneIds; uint32 numScenes = Manager::Get()->GetAllScenes( &sceneIds ); if( numScenes ) { o_sceneIds = gcnew cli::array(numScenes); for( uint32 i=0; i // Retrieves the scene's list of values //----------------------------------------------------------------------------- int ZWManager::SceneGetValues ( uint8 sceneId, [Out] cli::array^ %o_values ) { vector values; uint32 numValues = Manager::Get()->SceneGetValues( sceneId, &values ); if( numValues ) { o_values = gcnew cli::array(numValues); for( uint32 i=0; i // Retrieves a scene's value as a bool //----------------------------------------------------------------------------- bool ZWManager::SceneGetValueAsBool ( uint8 sceneId, ZWValueID^ valueId, [Out] System::Boolean %o_value ) { bool value; if( Manager::Get()->SceneGetValueAsBool( sceneId, valueId->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Retrieves a scene's value as an 8-bit unsigned integer //----------------------------------------------------------------------------- bool ZWManager::SceneGetValueAsByte ( uint8 sceneId, ZWValueID^ valueId, [Out] System::Byte %o_value ) { uint8 value; if( Manager::Get()->SceneGetValueAsByte( sceneId, valueId->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Retrieves a scene's value as a decimal //----------------------------------------------------------------------------- bool ZWManager::SceneGetValueAsDecimal ( uint8 sceneId, ZWValueID^ valueId, [Out] System::Decimal %o_value ) { string value; if( Manager::Get()->SceneGetValueAsString( sceneId, valueId->CreateUnmanagedValueID(), &value ) ) { String^ decimal = gcnew String(value.c_str()); o_value = Decimal::Parse( decimal ); return true; } return false; } //----------------------------------------------------------------------------- // // Retrieves a scene's value as a 32-bit signed integer //----------------------------------------------------------------------------- bool ZWManager::SceneGetValueAsInt ( uint8 sceneId, ZWValueID^ valueId, [Out] System::Int32 %o_value ) { int32 value; if( Manager::Get()->SceneGetValueAsInt( sceneId, valueId->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Retrieves a scene's value as a 16-bit signed integer //----------------------------------------------------------------------------- bool ZWManager::SceneGetValueAsShort ( uint8 sceneId, ZWValueID^ valueId, [Out] System::Int16 %o_value ) { int16 value; if( Manager::Get()->SceneGetValueAsShort( sceneId, valueId->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Retrieves a scene's value as a string //----------------------------------------------------------------------------- bool ZWManager::SceneGetValueAsString ( uint8 sceneId, ZWValueID^ valueId, [Out] String^ %o_value ) { string value; if( Manager::Get()->SceneGetValueAsString( sceneId, valueId->CreateUnmanagedValueID(), &value ) ) { o_value = gcnew String(value.c_str()); return true; } return false; } //----------------------------------------------------------------------------- // // Retrieves a scene's value in a list (as a string) //----------------------------------------------------------------------------- bool ZWManager::SceneGetValueListSelection ( uint8 sceneId, ZWValueID^ valueId, [Out] String^ %o_value ) { string value; if( Manager::Get()->SceneGetValueListSelection( sceneId, valueId->CreateUnmanagedValueID(), &value ) ) { o_value = gcnew String(value.c_str()); return true; } return false; } //----------------------------------------------------------------------------- // // Retrieves a scene's value in a list (as a integer) //----------------------------------------------------------------------------- bool ZWManager::SceneGetValueListSelection ( uint8 sceneId, ZWValueID^ valueId, System::Int32 %o_value ) { int32 value; if( Manager::Get()->SceneGetValueListSelection( sceneId, valueId->CreateUnmanagedValueID(), &value ) ) { o_value = value; return true; } return false; } open-zwave-1.5/dotnet/src/ZWManager.h000066400000000000000000003553371264474202400175670ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ZWManager.h // // Cli/C++ wrapper for the C++ OpenZWave Manager class // // Copyright (c) 2010 Amer Harb // // 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 . // //----------------------------------------------------------------------------- #pragma once #include #include #include #include #include "ZWValueID.h" #include "ZWNotification.h" #include "Manager.h" #include "ValueID.h" #include "Notification.h" #include "Driver.h" #include "Log.h" using namespace System; using namespace System::Threading; using namespace System::Collections::Generic; using namespace Runtime::InteropServices; using namespace OpenZWave; namespace OpenZWaveDotNet { // Delegate for handling notification callbacks public delegate void ManagedNotificationsHandler(ZWNotification^ notification); [UnmanagedFunctionPointer(CallingConvention::Cdecl)] private delegate void OnNotificationFromUnmanagedDelegate(Notification* _notification, void* _context); // Logging levels public enum class ZWLogLevel { None = LogLevel_None, Always = LogLevel_Always, Fatal = LogLevel_Fatal, Error = LogLevel_Error, Warning = LogLevel_Warning, Alert = LogLevel_Alert, Info = LogLevel_Info, Detail = LogLevel_Detail, Debug = LogLevel_Debug, StreamDetail= LogLevel_StreamDetail, Internal = LogLevel_Internal }; // Delegate for handling controller command callbacks public enum class ZWControllerState { Normal = Driver::ControllerState_Normal, /**< No command in progress. */ Starting = Driver::ControllerState_Starting, /**< The command is starting. */ Cancel = Driver::ControllerState_Cancel, /**< The command was cancelled. */ Error = Driver::ControllerState_Error, /**< Command invocation had error(s) and was aborted */ Waiting = Driver::ControllerState_Waiting, /**< Controller is waiting for a user action. */ Sleeping = Driver::ControllerState_Sleeping, /**< Controller command is on a sleep queue wait for device. */ InProgress = Driver::ControllerState_InProgress, /**< The controller is communicating with the other device to carry out the command. */ Completed = Driver::ControllerState_Completed, /**< The command has completed successfully. */ Failed = Driver::ControllerState_Failed, /**< The command has failed. */ NodeOK = Driver::ControllerState_NodeOK, /**< Used with the HasNodeFailed, RemoveFailedNode and ReplaceFailedNode commands to indicate that the controller thinks the node is OK. */ NodeFailed = Driver::ControllerState_NodeFailed /**< Used only with HasNodeFailed to indicate that the controller thinks the node has failed. */ }; // Controller interface types public enum class ZWControllerInterface { Unknown = Driver::ControllerInterface_Unknown, Serial = Driver::ControllerInterface_Serial, Hid = Driver::ControllerInterface_Hid }; public enum class ZWControllerCommand { None = Driver::ControllerCommand_None, /**< No command. */ AddDevice = Driver::ControllerCommand_AddDevice, /**< Add a new device (but not a controller) to the Z-Wave network. */ CreateNewPrimary = Driver::ControllerCommand_CreateNewPrimary, /**< Add a new controller to the Z-Wave network. The new controller will be the primary, and the current primary will become a secondary controller. */ ReceiveConfiguration = Driver::ControllerCommand_ReceiveConfiguration, /**< Receive Z-Wave network configuration information from another controller. */ RemoveDevice = Driver::ControllerCommand_RemoveDevice, /**< Remove a new device (but not a controller) from the Z-Wave network. */ RemoveFailedNode = Driver::ControllerCommand_RemoveFailedNode, /**< Move a node to the controller's failed nodes list. This command will only work if the node cannot respond. */ HasNodeFailed = Driver::ControllerCommand_HasNodeFailed, /**< Check whether a node is in the controller's failed nodes list. */ ReplaceFailedNode = Driver::ControllerCommand_ReplaceFailedNode, /**< Replace a non-responding device with another. */ TransferPrimaryRole = Driver::ControllerCommand_TransferPrimaryRole, /**< Make a different controller the primary. */ RequestNetworkUpdate = Driver::ControllerCommand_RequestNetworkUpdate, /**< Request network information from the SUC/SIS. */ RequestNodeNeighborUpdate = Driver::ControllerCommand_RequestNodeNeighborUpdate, /**< Get a node to rebuild its neighbour list. This method also does ControllerCommand_RequestNodeNeighbors */ AssignReturnRoute = Driver::ControllerCommand_AssignReturnRoute, /**< Assign a network return route to a device. */ DeleteAllReturnRoutes = Driver::ControllerCommand_DeleteAllReturnRoutes, /**< Delete all network return routes from a device. */ SendNodeInformation = Driver::ControllerCommand_SendNodeInformation, /**< Send a node information frame */ ReplicationSend = Driver::ControllerCommand_ReplicationSend, /**< Send information from primary to secondary */ CreateButton = Driver::ControllerCommand_CreateButton, /**< Create an id that tracks handheld button presses */ DeleteButton = Driver::ControllerCommand_DeleteButton /**< Delete id that tracks handheld button presses */ }; public delegate void ManagedControllerStateChangedHandler( ZWControllerState _state); [UnmanagedFunctionPointer(CallingConvention::Cdecl)] private delegate void OnControllerStateChangedFromUnmanagedDelegate(Driver::ControllerState _state, void* _context); public ref class ZWManager { //----------------------------------------------------------------------------- // Events //----------------------------------------------------------------------------- private: ManagedNotificationsHandler^ m_notificationEvent; event ManagedNotificationsHandler^ ZWOnNotification { void add( ManagedNotificationsHandler ^ d ) { m_notificationEvent += d; } void remove(ManagedNotificationsHandler ^ d) { m_notificationEvent -= d; } void raise(ZWNotification^ notification) { ManagedNotificationsHandler^ tmp = m_notificationEvent; if (tmp) { tmp->Invoke( notification ); } } } public: property ManagedNotificationsHandler^ OnNotification { ManagedNotificationsHandler^ get() { return m_notificationEvent; } void set( ManagedNotificationsHandler^ value ) { m_notificationEvent = value; } } private: ManagedControllerStateChangedHandler^ m_controllerStateChangedEvent; event ManagedControllerStateChangedHandler^ ZWOnControllerStateChanged { void add( ManagedControllerStateChangedHandler ^ d ) { m_controllerStateChangedEvent += d; } void remove(ManagedControllerStateChangedHandler ^ d) { m_controllerStateChangedEvent -= d; } void raise(ZWControllerState state) { ManagedControllerStateChangedHandler^ tmp = m_controllerStateChangedEvent; if (tmp) { tmp->Invoke( state ); } } } ManagedControllerStateChangedHandler^ m_onControllerStateChanged; public: property ManagedControllerStateChangedHandler^ OnControllerStateChanged { ManagedControllerStateChangedHandler^ get() { return m_controllerStateChangedEvent; } void set( ManagedControllerStateChangedHandler^ value ) { m_controllerStateChangedEvent = value; } } //----------------------------------------------------------------------------- // 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. 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 _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. * \return a pointer to the newly created Manager object. * \see Destroy, AddWatcher, AddDriver */ void Create(); /** * \brief Deletes the Manager and cleans up any associated objects. * * \see Create, Get */ void Destroy(){ Manager::Get()->Destroy(); } /** * \brief Get the Version Number of OZW as a string * \return a String representing the version number as MAJOR.MINOR.REVISION */ String^ GetVersionAsString() { return gcnew String(Manager::Get()->getVersionAsString().c_str()); } /** * \brief Get the Version Number as the Version Struct (Only Major/Minor returned) * \return the version struct representing the version */ //ozwversion GetVersion(); /** * \brief Sets the library logging state. * \param bState True to enable logging; false to disable logging. * \see GetLoggingState */ void SetLoggingState(bool bState){ Log::SetLoggingState(bState); } /** * \brief Gets the current library logging state. * \return True if logging is enabled; false otherwise * \see SetLoggingState */ bool GetLoggingState() { return Log::GetLoggingState(); } /** * \brief Sets the current library log file name to a new name */ void SetLogFileName( String^ _filename ) { Log::SetLogFileName((const char*)(Marshal::StringToHGlobalAnsi(_filename)).ToPointer()); } /** * \brief Sends current driver statistics to the log file */ void LogDriverStatistics(uint32 homeId ) { Manager::Get()->LogDriverStatistics(homeId); } /*@}*/ //----------------------------------------------------------------------------- // 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 the configuration 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 'zwcfg_'. * This convention allows OpenZWave to find the correct configuration file for a controller, even if it is * attached to a different serial port. * \param homeId The Home ID of the Z-Wave controller to save. */ void WriteConfig(uint32 homeId){ Manager::Get()->WriteConfig(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 serialPortName The string used to open the serial port, for example "\\.\COM3". 8 \param interfaceType Specifies whether this is a serial or HID interface (default is serial). * \return True if a new driver was created, false if a driver for the controller already exists. * \see Create, Get, RemoveDriver */ bool AddDriver( String^ serialPortName ){ return Manager::Get()->AddDriver((const char*)(Marshal::StringToHGlobalAnsi(serialPortName)).ToPointer()); } bool AddDriver( String^ serialPortName, ZWControllerInterface interfaceType ){ return Manager::Get()->AddDriver((const char*)(Marshal::StringToHGlobalAnsi(serialPortName)).ToPointer(), (Driver::ControllerInterface) interfaceType); } /** * \brief Removes the driver for a Z-Wave controller, and closes the serial port. * * Drivers do not need to be explicitly removed before calling Destroy - this is handled automatically. * @paaram serialPortName 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^ serialPortName ){ return Manager::Get()->RemoveDriver((const char*)(Marshal::StringToHGlobalAnsi(serialPortName)).ToPointer()); } /** * \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 homeId ){ return Manager::Get()->GetControllerNodeId(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 homeId ) { return Manager::Get()->GetSUCNodeId(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 promary 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 homeId ){ return Manager::Get()->IsPrimaryController(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 homeId ){ return Manager::Get()->IsStaticUpdateController(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 ){ return Manager::Get()->IsBridgeController(homeId); } /** * \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 ){ return gcnew String(Manager::Get()->GetLibraryVersion(homeId).c_str()); } /** * \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 ){ return gcnew String(Manager::Get()->GetLibraryTypeName(homeId).c_str()); } /** * \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 ){ return Manager::Get()->GetSendQueueCount( homeId ); } /** * \brief Obtain controller interface type * \param homeId The Home ID of the Z-Wave controller. */ ZWControllerInterface GetControllerInterfaceType( uint32 homeId ) { return (ZWControllerInterface)Manager::Get()->GetControllerInterfaceType(homeId); } /** * \brief Obtain controller interface path * \param homeId The Home ID of the Z-Wave controller. */ String^ GetControllerPath( uint32 homeId ) { return gcnew String(Manager::Get()->GetControllerPath(homeId).c_str()); } /*@}*/ //----------------------------------------------------------------------------- // 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() { return Manager::Get()->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). * * Note that the polling interval cannot be set on a per-node basis. Every node that is polled is * polled at the specified interval. * \param milliseconds The length of the polling interval in milliseconds. */ void SetPollInterval( int32 milliseconds, bool bIntervalBetweenPolls ){ Manager::Get()->SetPollInterval(milliseconds, bIntervalBetweenPolls); } /** * \brief Enable the polling of a device's state. * * \param valueId The ID of the value to start polling. * \return True if polling was enabled. */ bool EnablePoll( ZWValueID^ valueId ){ return Manager::Get()->EnablePoll(valueId->CreateUnmanagedValueID()); } /** * \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( ZWValueID^ valueId, uint8 intensity ){ return Manager::Get()->EnablePoll(valueId->CreateUnmanagedValueID(), intensity); } /** * \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( ZWValueID^ valueId ){ return Manager::Get()->DisablePoll(valueId->CreateUnmanagedValueID()); } /** * \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( ZWValueID^ valueId ) { return Manager::Get()->isPolled(valueId->CreateUnmanagedValueID()); } /** * \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 * \param intensity The intensity to set */ void SetPollIntensity( ZWValueID^ valueId, uint8 intensity ) { Manager::Get()->SetPollIntensity(valueId->CreateUnmanagedValueID(), 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( ZWValueID^ valueId ) { return Manager::Get()->GetPollIntensity( valueId->CreateUnmanagedValueID()); } /*@}*/ //----------------------------------------------------------------------------- // Node information //----------------------------------------------------------------------------- /** \name Node information * Methods for accessing information on indivdual nodes. */ /*@{*/ public: /** * \brief Trigger the fetching of fixed data about a node. * * Causes the node's data to be obtained from the Z-Wave network in the same way as if it had just been added. * This method would normally be called automatically by OpenZWave, but if you know that a node has been * changed, calling this method will force a refresh of the data held by the library. This can be especially * useful for devices that were asleep when the application was first run. * \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 homeId, uint8 nodeId ){ return Manager::Get()->RefreshNodeInfo(homeId,nodeId); } /** * \brief Trigger the fetching of session and dynamic value data for a node. * * Causes the node's values to be requested from the Z-Wave network. * \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. */ void RequestNodeState( uint32 homeId, uint8 nodeId ){ Manager::Get()->RequestNodeState(homeId,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 ){ return Manager::Get()->RequestNodeDynamic(homeId, 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 ){ return Manager::Get()->IsNodeListeningDevice(homeId,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 ){ return Manager::Get()->IsNodeFrequentListeningDevice(homeId, 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 frequent listening node. */ bool IsNodeBeamingDevice( uint32 const homeId, uint8 const nodeId ){ return Manager::Get()->IsNodeBeamingDevice(homeId, 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 ){ return Manager::Get()->IsNodeRoutingDevice(homeId,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 ){ return Manager::Get()->IsNodeSecurityDevice(homeId, 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 ){ return Manager::Get()->GetNodeMaxBaudRate(homeId, 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 ){ return Manager::Get()->GetNodeVersion(homeId, nodeId); } /** * \brief Get the security byte for a node. Bit meanings are still to be determined. * \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 ){ return Manager::Get()->GetNodeSecurity(homeId, nodeId); } /** * \brief Get a node's "basic" type. * \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 basic type. */ uint8 GetNodeBasic( uint32 homeId, uint8 nodeId ){ return Manager::Get()->GetNodeBasic(homeId, nodeId); } /** * \brief Get a node's "generic" type. * \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 generic type. */ uint8 GetNodeGeneric( uint32 homeId, uint8 nodeId ){ return Manager::Get()->GetNodeGeneric(homeId,nodeId); } /** * \brief Get a node's "specific" type. * \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 specific type. */ uint8 GetNodeSpecific( uint32 homeId, uint8 nodeId ){ return Manager::Get()->GetNodeSpecific(homeId,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 homeId, uint8 nodeId ){ return gcnew String(Manager::Get()->GetNodeType(homeId,nodeId).c_str()); } /** * \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 o_associations An array of 29 uint8s to hold the neighbor bitmap */ uint32 GetNodeNeighbors( uint32 const homeId, uint8 const nodeId, [Out] cli::array^ %o_associations ); /** * \brief Get the manufacturer name of a device. * * The manufacturer name would normally be handled by the Manufacturer Specific commmand 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 homeId, uint8 nodeId ){ return gcnew String(Manager::Get()->GetNodeManufacturerName(homeId,nodeId).c_str()); } /** * \brief Get the product name of a device. * * The product name would normally be handled by the Manufacturer Specific commmand 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 homeId, uint8 nodeId ){ return gcnew String(Manager::Get()->GetNodeProductName(homeId,nodeId).c_str()); } /** * \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 commmand 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 homeId, uint8 nodeId ){ return gcnew String(Manager::Get()->GetNodeName(homeId,nodeId).c_str()); } /** * \brief Get the location of a node. * * The node location is a user-editable string that would normally be handled by the Node Naming * commmand 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 homeId, uint8 nodeId ){ return gcnew String(Manager::Get()->GetNodeLocation(homeId,nodeId).c_str()); } /** * \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 commmand 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 manufactuer * specific command class is not supported by the device. * \see GetNodeProductType, GetNodeProductId, GetNodeManufacturerName, GetNodeProductName */ String^ GetNodeManufacturerId( uint32 homeId, uint8 nodeId ){ return gcnew String(Manager::Get()->GetNodeManufacturerId(homeId,nodeId).c_str()); } /** * \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 * commmand 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 manufactuer * specific command class is not supported by the device. * \see GetNodeManufacturerId, GetNodeProductId, GetNodeManufacturerName, GetNodeProductName */ String^ GetNodeProductType( uint32 homeId, uint8 nodeId ){ return gcnew String(Manager::Get()->GetNodeProductType(homeId,nodeId).c_str()); } /** * \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 * commmand 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 manufactuer * specific command class is not supported by the device. * \see GetNodeManufacturerId, GetNodeProductType, GetNodeManufacturerName, GetNodeProductName */ String^ GetNodeProductId( uint32 homeId, uint8 nodeId ){ return gcnew String(Manager::Get()->GetNodeProductId( homeId, nodeId ).c_str()); } /** * \brief Set the manufacturer name of a device. * * The manufacturer name would normally be handled by the Manufacturer Specific commmand 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 homeId, uint8 nodeId, String^ manufacturerName ){ Manager::Get()->SetNodeManufacturerName( homeId, nodeId, (const char*)(Marshal::StringToHGlobalAnsi(manufacturerName)).ToPointer()); } /** * \brief Set the product name of a device. * * The product name would normally be handled by the Manufacturer Specific commmand 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 homeId, uint8 nodeId, String^ productName ){ Manager::Get()->SetNodeProductName( homeId, nodeId, (const char*)(Marshal::StringToHGlobalAnsi(productName)).ToPointer()); } /** * \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 commmand 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 homeId, uint8 nodeId, String^ nodeName ){ Manager::Get()->SetNodeName( homeId, nodeId, (const char*)(Marshal::StringToHGlobalAnsi(nodeName)).ToPointer()); } /** * \brief Set the location of a node. * * The node location is a user-editable string that would normally be handled by the Node Naming * commmand 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 homeId, uint8 nodeId, String^ location ){ Manager::Get()->SetNodeLocation( homeId, nodeId, (const char*)(Marshal::StringToHGlobalAnsi(location)).ToPointer()); } /** * \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. * \see SetNodeOff, SetNodeLevel */ void SetNodeOn( uint32 homeId, uint8 nodeId ){ Manager::Get()->SetNodeOn( homeId, 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. * \see SetNodeOn, SetNodeLevel */ void SetNodeOff( uint32 homeId, uint8 nodeId ){ Manager::Get()->SetNodeOff( homeId, 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). * \see SetNodeOn, SetNodeOff */ void SetNodeLevel( uint32 homeId, uint8 nodeId, uint8 level ){ Manager::Get()->SetNodeLevel( homeId, nodeId, 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 homeId, uint8 nodeId ) { return Manager::Get()->IsNodeInfoReceived( homeId, 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 homeId, uint8 nodeId, uint8 commandClassId, [Out] String^ %className, [Out] System::Byte %classVersion); /** * \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 homeId, uint8 nodeId ) { return Manager::Get()->IsNodeAwake( homeId, 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 homeId, uint8 nodeId ) { return Manager::Get()->IsNodeFailed( homeId, 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 homeId, uint8 nodeId ) { return gcnew String(Manager::Get()->GetNodeQueryStage( homeId, nodeId).c_str()); } /*@}*/ //----------------------------------------------------------------------------- // 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. * \return The value label. * \see ValueID */ String^ GetValueLabel( ZWValueID^ id ){ return gcnew String(Manager::Get()->GetValueLabel(id->CreateUnmanagedValueID()).c_str()); } /** * \brief Sets the user-friendly label for the value. * \param id The unique identifier of the value. * \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( ZWValueID^ id, String^ value ) { Manager::Get()->SetValueLabel( id->CreateUnmanagedValueID(), (const char*)(Marshal::StringToHGlobalAnsi(value)).ToPointer()); } /** * \brief Gets the units that the value is measured in. * * \param id The unique identifier of the value. * \return The value units. * \see ValueID */ String^ GetValueUnits( ZWValueID^ id ){ return gcnew String(Manager::Get()->GetValueUnits(id->CreateUnmanagedValueID()).c_str()); } /** * \brief Gets a help string describing the value's purpose and usage. * * \param id The unique identifier of the value. * \return The value help text. * \see ValueID */ String^ GetValueHelp( ZWValueID^ id ){ return gcnew String(Manager::Get()->GetValueHelp(id->CreateUnmanagedValueID()).c_str()); } /** * \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. * \see ValueID */ bool IsValueReadOnly( ZWValueID^ id ){ return Manager::Get()->IsValueReadOnly(id->CreateUnmanagedValueID()); } /** * \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. * \see ValueID */ bool IsValueSet( ZWValueID^ id ){ return Manager::Get()->IsValueSet(id->CreateUnmanagedValueID()); } /** * \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, false otherwise. * \see ValueID */ bool IsValuePolled( ZWValueID^ id ){ return Manager::Get()->IsValuePolled(id->CreateUnmanagedValueID()); } /** * \brief Gets a value as a bool. * * \param _id The unique identifier of the value. * \param o_value a Boolean that will be filled with the value. * \return true if the value was obtained. Returns false if the value is not a ZWValueID::ValueType_Bool. The type can be tested with a call to ZWValueID::GetType. * \see ValueID::GetType, GetValueAsByte, GetValueAsDecimal, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems */ bool GetValueAsBool( ZWValueID^ id, [Out] System::Boolean %o_value ); /** * \brief Gets a value as an 8-bit unsigned integer. * * \param _id The unique identifier of the value. * \param o_value a Byte that will be filled with the value. * \return true if the value was obtained. Returns false if the value is not a ZWValueID::ValueType_Byte. The type can be tested with a call to ZWValueID::GetType * \see ValueID::GetType, GetValueAsBool, GetValueAsDecimal, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems */ bool GetValueAsByte( ZWValueID^ id, [Out] System::Byte %o_value ); /** * \brief Gets a value as a decimal. * * \param _id The unique identifier of the value. * \param o_value a Decimal that will be filled with the value. * \return true if the value was obtained. Returns false if the value is not a ZWValueID::ValueType_Decimal. The type can be tested with a call to ZWValueID::GetType * \see ValueID::GetType, GetValueAsBool, GetValueAsByte, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems */ bool GetValueAsDecimal( ZWValueID^ id, [Out] System::Decimal %o_value ); /** * \brief Gets a value as a 32-bit signed integer. * * \param _id The unique identifier of the value. * \param o_value an Int32 that will be filled with the value. * \return true if the value was obtained. Returns false if the value is not a ZWValueID::ValueType_Int. The type can be tested with a call to ZWValueID::GetType * \see ValueID::GetType, GetValueAsBool, GetValueAsByte, GetValueAsDecimal, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueListItems */ bool GetValueAsInt( ZWValueID^ id, [Out] System::Int32 %o_value ); /** * \brief Gets a value as a 16-bit signed integer. * * \param _id The unique identifier of the value. * \param o_value an Int16 that will be filled with the value. * \return true if the value was obtained. Returns false if the value is not a ZWValueID::ValueType_Short. The type can be tested with a call to ZWValueID::GetType * \see ValueID::GetType, GetValueAsBool, GetValueAsByte, GetValueAsDecimal, GetValueAsInt, GetValueAsString, GetValueListSelection, GetValueListItems */ bool GetValueAsShort( ZWValueID^ id, [Out] System::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 a String that will be filled with the value. * \return true if the value was obtained. * \see ValueID::GetType, GetValueAsBool, GetValueAsByte, GetValueAsDecimal, GetValueAsInt, GetValueAsShort, GetValueListSelection, GetValueListItems */ bool GetValueAsString( ZWValueID^ id, [Out] String^ %o_value ); /** * \brief Gets the selected item from a list value (as a string). * * \param _id The unique identifier of the value. * \param o_value 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 ZWValueID::ValueType_List. The type can be tested with a call to ZWValueID::GetType * \see ValueID::GetType, GetValueAsBool, GetValueAsByte, GetValueAsDecimal, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListItems */ bool GetValueListSelection( ZWValueID^ id, [Out] String^ %o_value ); /** * \brief Gets the selected item from a list value (as an integer). * * \param _id The unique identifier of the value. * \param o_value 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 ZWValueID::ValueType_List. The type can be tested with a call to ZWValueID::GetType * \see ValueID::GetType, GetValueAsBool, GetValueAsByte, GetValueAsDecimal, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListItems */ bool GetValueListSelection( ZWValueID^ id, [Out] System::Int32 %o_value ); /** * \brief Gets the list of items from a list value. * * \param id The unique identifier of the value. * \param o_value List that will be filled with list items. * \return true if the list items were obtained. Returns false if the value is not a ZWValueID::ValueType_List. The type can be tested with a call to ZWValueID::GetType * \see ValueID::GetType, GetValueAsBool, GetValueAsByte, GetValueAsDecimal, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection */ bool GetValueListItems( ZWValueID^ id, [Out] cli::array^ %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. * \see ValueID::GetType, GetValueAsBool, GetValueAsByte, GetValueAsFloat, GetValueAsInt, GetValueAsShort, GetValueAsString, GetValueListSelection, GetValueAsRaw */ bool GetValueListValues( ZWValueID^ id, [Out] cli::array^ %o_value ); /** * \brief Sets the state of a bool. * * Due to the possibility of a device being asleep, the command is assumed to suceeed, 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 ZWValueID::ValueType_Bool. The type can be tested with a call to ZWValueID::GetType */ bool SetValue( ZWValueID^ id, bool value ){ return Manager::Get()->SetValue(id->CreateUnmanagedValueID(), value); } /** * \brief Sets the value of a byte. * * Due to the possibility of a device being asleep, the command is assumed to suceeed, 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 ZWValueID::ValueType_Byte. The type can be tested with a call to ZWValueID::GetType */ bool SetValue( ZWValueID^ id, uint8 value ){ return Manager::Get()->SetValue(id->CreateUnmanagedValueID(), 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 suceeed, 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 ZWValueID::ValueType_Decimal. The type can be tested with a call to ZWValueID::GetType */ bool SetValue( ZWValueID^ id, float value ){ return Manager::Get()->SetValue(id->CreateUnmanagedValueID(), 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 suceeed, 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 ZWValueID::ValueType_Int. The type can be tested with a call to ZWValueID::GetType */ bool SetValue( ZWValueID^ id, int32 value ){ return Manager::Get()->SetValue(id->CreateUnmanagedValueID(), 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 suceeed, 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 ZWValueID::ValueType_Short. The type can be tested with a call to ZWValueID::GetType */ bool SetValue( ZWValueID^ id, int16 value ){ return Manager::Get()->SetValue(id->CreateUnmanagedValueID(), value); } /** * \brief Sets the value from a string, regardless of type. * * Due to the possibility of a device being asleep, the command is assumed to suceeed, 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. */ bool SetValue( ZWValueID^ id, String^ value ){ return Manager::Get()->SetValue(id->CreateUnmanagedValueID(), string((const char*)((Marshal::StringToHGlobalAnsi(value)).ToPointer())) ); } /** * \brief Sets the selected item in a list. * * Due to the possibility of a device being asleep, the command is assumed to suceeed, 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 value 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 ZWValueID::ValueType_List. * The type can be tested with a call to ZWValueID::GetType */ bool SetValueListSelection( ZWValueID^ id, String^ selectedItem ){ return Manager::Get()->SetValueListSelection(id->CreateUnmanagedValueID(), (const char*)(Marshal::StringToHGlobalAnsi(selectedItem)).ToPointer()); } /** * \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 */ bool RefreshValue( ZWValueID^ id ){ return Manager::Get()->RefreshValue(id->CreateUnmanagedValueID()); } /** * \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. */ void SetChangeVerified( ZWValueID^ id, bool verify ){ Manager::Get()->SetChangeVerified(id->CreateUnmanagedValueID(), verify); } /** * \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 ZWValueID::ValueType_Button. The type can be tested with a call to ZWValueID::GetType */ bool PressButton( ZWValueID^ id ){ return Manager::Get()->PressButton(id->CreateUnmanagedValueID()); } /** * \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 ZWValueID::ValueType_Button. The type can be tested with a call to ZWValueID::GetType */ bool ReleaseButton( ZWValueID^ id ){ return Manager::Get()->ReleaseButton(id->CreateUnmanagedValueID()); } /*@}*/ //----------------------------------------------------------------------------- // 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. */ uint8 GetNumSwitchPoints( ZWValueID^ id ){ return Manager::Get()->GetNumSwitchPoints( id->CreateUnmanagedValueID() ); } /** * \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. * \see GetNumSwitchPoints, RemoveSwitchPoint, ClearSwitchPoints */ bool SetSwitchPoint( ZWValueID^ id, uint8 hours, uint8 minutes, int8 setback ){ return Manager::Get()->SetSwitchPoint( id->CreateUnmanagedValueID(), hours, minutes, 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. * \see GetNumSwitchPoints, SetSwitchPoint, ClearSwitchPoints */ bool RemoveSwitchPoint( ZWValueID^ id, uint8 hours, uint8 minutes ){ return Manager::Get()->RemoveSwitchPoint( id->CreateUnmanagedValueID(), hours, minutes ); } /** * \brief Clears all switch points from the schedule. * \param id The unique identifier of the schedule value. * \see GetNumSwitchPoints, SetSwitchPoint, RemoveSwitchPoint */ void ClearSwitchPoints( ZWValueID^ id ){ Manager::Get()->ClearSwitchPoints( id->CreateUnmanagedValueID() ); } /** * \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. * \see GetNumSwitchPoints */ bool GetSwitchPoint( ZWValueID^ id, uint8 idx, [Out] System::Byte %o_value, [Out] System::Byte %o_minutes, [Out] System::SByte %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. */ void SwitchAllOn( uint32 homeId ){ Manager::Get()->SwitchAllOn( homeId ); } /** * \brief Switch all devices off. * All devices that support the SwitchAll command class will be turned off. */ void SwitchAllOff( uint32 homeId ){ Manager::Get()->SwitchAllOff( 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 behaviour. * 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. * \return true if the a message setting the value was sent to the device. * \see RequestConfigParam */ bool SetConfigParam( uint32 homeId, uint8 nodeId, uint8 param, int32 value ){ return Manager::Get()->SetConfigParam( homeId, nodeId, param, value ); } /** * \brief Request the value of a configurable parameter from a device. * * Some devices have various parameters that can be configured to control the device behaviour. * 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 homeId, uint8 nodeId, uint8 param ){ Manager::Get()->RequestConfigParam( homeId, nodeId, 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, RequestConfigParam, ValueID, Notification */ void RequestAllConfigParams( uint32 homeId, uint8 nodeId ){ Manager::Get()->RequestAllConfigParams( homeId, 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, AddAssociation, RemoveAssociation */ uint8 GetNumGroups( uint32 homeId, uint8 nodeId ){ return Manager::Get()->GetNumGroups( homeId, 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 */ uint32 GetAssociations( uint32 const homeId, uint8 const nodeId, uint8 const groupIdx, [Out] cli::array^ %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 */ uint8 GetMaxAssociations( uint32 const homeId, uint8 const nodeId, uint8 const groupIdx ){ return Manager::Get()->GetMaxAssociations( homeId, nodeId, groupIdx ); } /** * \brief Adds a node to an association group. * * Due to the possibility of a device being asleep, the command is assumed to suceeed, 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. * \see GetNumGroups, GetAssociations, RemoveAssociation */ void AddAssociation( uint32 homeId, uint8 nodeId, uint8 groupIdx, uint8 targetNodeId ){ return Manager::Get()->AddAssociation( homeId, nodeId, groupIdx, targetNodeId ); } /** * \brief Removes a node from an association group. * * Due to the possibility of a device being asleep, the command is assumed to suceeed, 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. * \see GetNumGroups, GetAssociations, AddAssociation */ void RemoveAssociation( uint32 homeId, uint8 nodeId, uint8 groupIdx, uint8 targetNodeId ){ return Manager::Get()->RemoveAssociation( homeId, nodeId, groupIdx, targetNodeId ); } /*@}*/ //----------------------------------------------------------------------------- // 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 homeId ){ Manager::Get()->ResetController( 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 homeId ){ Manager::Get()->SoftReset( homeId ); } /** * \brief Start a controller command process. * * \param homeId The Home ID of the Z-Wave controller. * \param command The command to be sent to the controller. * \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 used only with the ReplaceFailedNode command, to specify the node that is going to be replaced. * \return true if the command was accepted and has started. * \see CancelControllerCommand, HasNodeFailed, RemoveFailedNode, Driver::ControllerCommand, Driver::pfnControllerCallback_t, * to notify the user of progress or to request actions on the user's part. Defaults to NULL. *

Commands * - ZWControllerCommand.AddController - Add a new secondary controller to the Z-Wave network. * - ZWControllerCommand.AddDevice - Add a new device (but not a controller) to the Z-Wave network. * - ZWControllerCommand.CreateNewPrimary (Not yet implemented) * - ZWControllerCommand.ReceiveConfiguration - * - ZWControllerCommand.RemoveController - remove a controller from the Z-Wave network. * - ZWControllerCommand.RemoveDevice - remove a device (but not a controller) from the Z-Wave network. * - ZWControllerCommand.RemoveFailedNode - move a node to the controller's list of failed nodes. The node must actually * have failed or have been disabled since the command will fail if it responds. A node must be in the controller's failed nodes list * for ControllerCommand_ReplaceFailedNode to work. * - ZWControllerCommand.HasNodeFailed - Check whether a node is in the controller's failed nodes list. * - ZWControllerCommand.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. * - ZWControllerCommand.TransferPrimaryRole (Not yet implemented) - Add a new controller to the network and * make it the primary. The existing primary will become a secondary controller. * - ZWControllerCommand.RequestNetworkUpdate - Update the controller with network information from the SUC/SIS. * - ZWControllerCommand.RequestNodeNeighborUpdate - Get a node to rebuild its neighbour list. This method also does ControllerCommand_RequestNodeNeighbors afterwards. * - ZWControllerCommand.AssignReturnRoute - Assign network routes to a device. * - ZWControllerCommand.DeleteReturnRoute - Delete network routes from a device. *

These processes are asynchronous, and at various stages OpenZWave will trigger a callback * to notify the user of progress or to request actions on the user's part. *

Controller States * - ZWControllerState.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. * - ZWControllerState.InProgress - the controller is in the process of adding or removing the chosen node. * - ZWControllerState.Complete - the controller has finished adding or removing the node, and the command is complete. * - ZWControllerState.Failed - will be sent if the command fails for any reason. *

To register for these notifications, create an event handler with the same signature as * the ManagedControllerStateChangedHandler delegate. Just before calling the BeginControllerCommand * method, subscribe to the OnControllerStateChanged event. Once the command has completed, remember * to unsubscribe from the event. * /code * private UInt32 m_homeId; * private ZWManager m_manager; * private ManagedControllerStateChangedHandler m_myEventHandler = new ManagedControllerStateChangedHandler( MyControllerStateChangedHandler ); * * public void MyAddControllerMethod() * { * m_manager.OnControllerStateChanged += m_myEventHandler; * m_manager.BeginControllerCommand( m_homeId, ZWControllerCommand::AddController, false ); * } * * public void MyControllerStateChangedHandler( ZWControllerState state ) * { * // Handle the controller state notifications here. * bool complete = false; * switch( state ) * { * case ZWControllerState::Waiting: * { * // Display a message to tell the user to press the include button on the controller * break; * } * case ZWControllerState::InProgress: * { * // Tell the user that the controller has been found and the adding process is in progress. * break; * } * case ZWControllerState::Completed: * { * // Tell the user that the controller has been successfully added. * // The command is now complete * complete = true; * break; * } * case ZWControllerState::Failed: * { * // Tell the user that the controller addition process has failed. * // The command is now complete * complete = true; * break; * } * case ZWControllerState::NodeOK: * { * // Tell the user that the node referenced by one of the Failed commands is actually working. * // The command is now complete * complete = true; * break; * } * case ZWControllerState::Failed: * { * // Tell the user that the node referenced in the HasNodeFailed command has failed. * // The command is now complete * complete = true; * break; * } * } * * if( complete ) * { * // Remove the event handler * m_manager.OnControllerStateChanged -= m_myEventHandler; * } * } * /endcode */ bool BeginControllerCommand( uint32 homeId, ZWControllerCommand command, bool highPower, uint8 nodeId ); /** * \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 homeId){ return Manager::Get()->CancelControllerCommand(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 ){ Manager::Get()->TestNetworkNode(homeId, nodeId, 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 ){ Manager::Get()->TestNetwork(homeId, 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 ){ Manager::Get()->HealNetworkNode(homeId, nodeId, 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 ){ Manager::Get()->HealNetwork(homeId, 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 succcesfully to the Controller */ bool AddNode(uint32 const homeId, bool doSecurity){ return Manager::Get()->AddNode(homeId, doSecurity); } /** * \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 AddNode 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 succesfully to the Controller */ bool RemoveNode(uint32 const homeId){return Manager::Get()->RemoveNode(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 AddNode 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 succesfully to the Controller */ bool RemoveFailedNode(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->RemoveFailedNode(homeId, 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 AddNode 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 succesfully to the Controller */ bool HasNodeFailed(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->HasNodeFailed(homeId, 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 AddNode 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 succesfully to the Controller */ bool AssignReturnRoute(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->AssignReturnRoute(homeId, nodeId); } /** * \brief Ask a Node to update its Neighbor Tables * This command will ask a Node to update its Neighbor Tables. * * Results of the AddNode 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 succesfully to the Controller */ bool RequestNodeNeighborUpdate(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->RequestNodeNeighborUpdate(homeId, 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 AddNode 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 succesfully to the Controller */ bool DeleteAllReturnRoutes(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->DeleteAllReturnRoutes(homeId, nodeId); } /** * \brief Send a NIF frame from the Controller to a Node. * This command send a NIF frame from the Controller to a Node * * Results of the AddNode 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 NodeID of the Node to recieve the NIF * \return if the sendNIF Command was send succesfully to the Controller */ bool SendNodeInformation(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->SendNodeInformation(homeId, 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 succesfully to the Controller * \sa CancelControllerCommand */ bool CreateNewPrimary(uint32 const homeId){ return Manager::Get()->CreateNewPrimary(homeId); } /** * \brief Receive network configuration information from primary controller. Requires secondary. * This command prepares the controller to recieve 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 succesfully to the Controller * \sa CancelControllerCommand */ bool ReceiveConfiguration(uint32 const homeId){ return Manager::Get()->ReceiveConfiguration(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 succesfully to the Controller * \sa HasNodeFailed * \sa CancelControllerCommand */ bool ReplaceFailedNode(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->ReplaceFailedNode(homeId, 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 succesfully to the Controller * \sa CancelControllerCommand */ bool TransferPrimaryRole(uint32 const homeId){ return Manager::Get()->TransferPrimaryRole(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 asc * 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 succesfully to the Controller * \sa CancelControllerCommand */ bool RequestNetworkUpdate(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->RequestNetworkUpdate(homeId, 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 succesfully to the Controller * \sa CancelControllerCommand */ bool ReplicationSend(uint32 const homeId, uint8 const nodeId){ return Manager::Get()->ReplicationSend(homeId, 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 succesfully to the Controller * \sa CancelControllerCommand */ bool CreateButton(uint32 const homeId, uint8 const nodeId, uint8 const buttonid) { return Manager::Get()->CreateButton(homeId, nodeId, 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 succesfully to the Controller * \sa CancelControllerCommand */ bool DeleteButton(uint32 const homeId, uint8 const nodeId, uint8 const buttonid){ return Manager::Get()->DeleteButton(homeId, nodeId, buttonid); } //----------------------------------------------------------------------------- // Scene commands //----------------------------------------------------------------------------- /** \name Scene Commands * Commands for Z-Wave scene interface. */ /*@{*/ public: /** * \brief Gets the number of scenes that have been defined. * \return The number of scenes. * \see GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ uint8 GetNumScenes(){ return Manager::Get()->GetNumScenes(); } /** * \brief Gets a list of all the SceneIds. * \param sceneIds returns an array of bytes containing the ids if the existing scenes. * \return The number of scenes. * \see GetNumScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ uint8 GetAllScenes( [Out] cli::array^ %sceneIds ); /** * \brief Create a new Scene passing in Scene ID * \return uint8 Scene ID used to reference the scene. 0 is failure result. * \see GetNumScenes, GetAllScenes, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ uint8 CreateScene(){ return Manager::Get()->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. * \see GetNumScenes, GetAllScenes, CreateScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool RemoveScene( uint8 sceneId ){ return Manager::Get()->RemoveScene( 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool AddSceneValue( uint8 sceneId, ZWValueID^ valueId, bool value ){ return Manager::Get()->AddSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool AddSceneValue( uint8 sceneId, ZWValueID^ valueId, uint8 value ){ return Manager::Get()->AddSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool AddSceneValue( uint8 sceneId, ZWValueID^ valueId, float const value ){ return Manager::Get()->AddSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool AddSceneValue( uint8 sceneId, ZWValueID^ valueId, int32 const value ){ return Manager::Get()->AddSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool AddSceneValue( uint8 sceneId, ZWValueID^ valueId, int16 const value ){ return Manager::Get()->AddSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool AddSceneValue( uint8 sceneId, ZWValueID^ valueId, String^ value ){ return Manager::Get()->AddSceneValue( sceneId, valueId->CreateUnmanagedValueID(), string((const char*)((Marshal::StringToHGlobalAnsi(value)).ToPointer())) ); } /** * \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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool AddSceneValueListSelection( uint8 sceneId, ZWValueID^ valueId, String^ value ){ return Manager::Get()->AddSceneValueListSelection( sceneId, valueId->CreateUnmanagedValueID(), string((const char*)((Marshal::StringToHGlobalAnsi(value)).ToPointer())) ); } /** * \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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool AddSceneValueListSelection( uint8 sceneId, ZWValueID^ valueId, int32 value ){ return Manager::Get()->AddSceneValueListSelection( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool RemoveSceneValue( uint8 sceneId, ZWValueID^ valueId ){ return Manager::Get()->RemoveSceneValue( sceneId, valueId->CreateUnmanagedValueID() ); } /** * \brief Retrieves the scene's list of values. * \param sceneId The Scene ID of the scene to retrieve the value from. * \param o_value an array of ValueIDs. * \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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ int SceneGetValues( uint8 sceneId, [Out] cli::array^ %o_values ); /** * \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 boolean that will be filled with the returned value. * \return true if the value was obtained. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SceneGetValueAsBool( uint8 sceneId, ZWValueID^ valueId, [Out] System::Boolean %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 Byte that will be filled with the returned value. * \return true if the value was obtained. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SceneGetValueAsByte( uint8 sceneId, ZWValueID^ valueId, [Out] System::Byte %o_value ); /** * \brief Retrieves a scene's value as a decimal. * \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 decimal that will be filled with the returned value. * \return true if the value was obtained. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SceneGetValueAsDecimal( uint8 sceneId, ZWValueID^ valueId, [Out] System::Decimal %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 Int32 that will be filled with the returned value. * \return true if the value was obtained. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SceneGetValueAsInt( uint8 sceneId, ZWValueID^ valueId, [Out] System::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 Int16 that will be filled with the returned value. * \return true if the value was obtained. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SceneGetValueAsShort( uint8 sceneId, ZWValueID^ valueId, [Out] System::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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SceneGetValueAsString( uint8 sceneId, ZWValueID^ valueId, [Out] 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SceneGetValueListSelection( uint8 sceneId, ZWValueID^ valueId, [Out] 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SceneGetValueListSelection( uint8 sceneId, ZWValueID^ valueId, System::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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SetSceneValue( uint8 sceneId, ZWValueID^ valueId, bool value ){ return Manager::Get()->SetSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SetSceneValue( uint8 sceneId, ZWValueID^ valueId, uint8 value ){ return Manager::Get()->SetSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SetSceneValue( uint8 sceneId, ZWValueID^ valueId, float value ){ return Manager::Get()->SetSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SetSceneValue( uint8 sceneId, ZWValueID^ valueId, int32 value ){ return Manager::Get()->SetSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SetSceneValue( uint8 sceneId, ZWValueID^ valueId, int16 value ){ return Manager::Get()->SetSceneValue( sceneId, valueId->CreateUnmanagedValueID(), 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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SetSceneValue( uint8 sceneId, ZWValueID^ valueId, String^ value ){ return Manager::Get()->SetSceneValue( sceneId, valueId->CreateUnmanagedValueID(), string((const char*)((Marshal::StringToHGlobalAnsi(value)).ToPointer())) ); } /** * \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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SetSceneValueListSelection( uint8 sceneId, ZWValueID^ valueId, String^ value ){ return Manager::Get()->SetSceneValueListSelection( sceneId, valueId->CreateUnmanagedValueID(), string((const char*)((Marshal::StringToHGlobalAnsi(value)).ToPointer())) ); } /** * \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. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists, ActivateScene */ bool SetSceneValueListSelection( uint8 sceneId, ZWValueID^ valueId, int32 value ){ return Manager::Get()->SetSceneValueListSelection( sceneId, valueId->CreateUnmanagedValueID(), value ); } /** * \brief Returns a label for the particular scene. * \param sceneId The Scene ID * \return The label string. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, SetSceneLabel, SceneExists, ActivateScene */ String^ GetSceneLabel( uint8 sceneId ){ return gcnew String(Manager::Get()->GetSceneLabel( sceneId ).c_str()); } /** * \brief Sets a label for the particular scene. * \param sceneId The Scene ID * \param value The new value of the label. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SceneExists, ActivateScene */ void SetSceneLabel( uint8 sceneId, String^ value ){ return Manager::Get()->SetSceneLabel( sceneId, (const char*)(Marshal::StringToHGlobalAnsi(value)).ToPointer() ); } /** * \brief Check if a Scene ID is defined. * \param sceneId The Scene ID. * \return true if Scene ID exists. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, ActivateScene */ bool SceneExists( uint8 sceneId ){ return Manager::Get()->SceneExists( sceneId ); } /** * \brief Activate given scene to perform all its actions. * \param sceneId The Scene ID. * \return true if it is successful. * \see GetNumScenes, GetAllScenes, CreateScene, RemoveScene, AddSceneValue, RemoveSceneValue, SceneGetValues, SceneGetValueAsBool, SceneGetValueAsByte, SceneGetValueAsFloat, SceneGetValueAsInt, SceneGetValueAsShort, SceneGetValueAsString, SetSceneValue, GetSceneLabel, SetSceneLabel, SceneExists */ bool ActivateScene( uint8 sceneId ){ return Manager::Get()->ActivateScene( sceneId ); } /*@}*/ public: ZWManager(){} private: void OnNotificationFromUnmanaged(Notification* _notification,void* _context); // Forward notification to managed delegates hooked via Event addhandler void OnControllerStateChangedFromUnmanaged(Driver::ControllerState _state,void* _context); // Forward controller state change to managed delegates hooked via Event addhandler GCHandle m_gchNotification; OnNotificationFromUnmanagedDelegate^ m_onNotification; GCHandle m_gchControllerState; OnControllerStateChangedFromUnmanagedDelegate^ m_onStateChanged; }; } open-zwave-1.5/dotnet/src/ZWNotification.h000066400000000000000000000112151264474202400206230ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ZWNotification.h // // Cli/C++ wrapper for the C++ OpenZWave Manager class // // Copyright (c) 2010 Amer Harb // // 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 . // //----------------------------------------------------------------------------- #pragma once #include "Windows.h" #include "Manager.h" #include "Value.h" #include "ValueStore.h" #include "ValueID.h" #include "ValueBool.h" #include "ValueInt.h" #include "ValueByte.h" #include "ValueString.h" #include "ValueShort.h" #include "ValueDecimal.h" #include "Notification.h" #include "stdio.h" #include #include using namespace System; using namespace System::Threading; using namespace System::Collections::Generic; using namespace OpenZWave; using namespace Runtime::InteropServices; namespace OpenZWaveDotNet { public ref class ZWNotification { public: enum class Type { ValueAdded = Notification::Type_ValueAdded, ValueRemoved = Notification::Type_ValueRemoved, ValueChanged = Notification::Type_ValueChanged, ValueRefreshed = Notification::Type_ValueRefreshed, Group = Notification::Type_Group, NodeNew = Notification::Type_NodeNew, NodeAdded = Notification::Type_NodeAdded, NodeRemoved = Notification::Type_NodeRemoved, NodeReset = Notification::Type_NodeReset, NodeProtocolInfo = Notification::Type_NodeProtocolInfo, NodeNaming = Notification::Type_NodeNaming, NodeEvent = Notification::Type_NodeEvent, PollingDisabled = Notification::Type_PollingDisabled, PollingEnabled = Notification::Type_PollingEnabled, SceneEvent = Notification::Type_SceneEvent, CreateButton = Notification::Type_CreateButton, DeleteButton = Notification::Type_DeleteButton, ButtonOn = Notification::Type_ButtonOn, ButtonOff = Notification::Type_ButtonOff, DriverReady = Notification::Type_DriverReady, DriverFailed = Notification::Type_DriverFailed, DriverReset = Notification::Type_DriverReset, EssentialNodeQueriesComplete = Notification::Type_EssentialNodeQueriesComplete, NodeQueriesComplete = Notification::Type_NodeQueriesComplete, AwakeNodesQueried = Notification::Type_AwakeNodesQueried, AllNodesQueriedSomeDead = Notification::Type_AllNodesQueriedSomeDead, AllNodesQueried = Notification::Type_AllNodesQueried, Notification = Notification::Type_Notification, DriverRemoved = Notification::Type_DriverRemoved, ControllerCommand = Notification::Type_ControllerCommand }; public: enum class Code { MsgComplete = Notification::Code_MsgComplete, Timeout = Notification::Code_Timeout, NoOperation = Notification::Code_NoOperation, Awake = Notification::Code_Awake, Sleep = Notification::Code_Sleep, Dead = Notification::Code_Dead, Alive = Notification::Code_Alive }; ZWNotification( Notification* notification ) { m_type = (Type)Enum::ToObject( Type::typeid, notification->GetType() ); m_byte = notification->GetByte(); //Check if notification is either NodeEvent or ControllerCommand, otherwise GetEvent() will fail if ((m_type == Type::NodeEvent) || (m_type == Type::ControllerCommand)) { m_event = notification->GetEvent(); } m_valueId = gcnew ZWValueID( notification->GetValueID() ); } Type GetType(){ return m_type; } Code GetCode() { return (Code)Enum::ToObject( Code::typeid, m_byte); } uint32 GetHomeId(){ return m_valueId->GetHomeId(); } uint8 GetNodeId(){ return m_valueId->GetNodeId(); } ZWValueID^ GetValueID(){ return m_valueId; } uint8 GetGroupIdx(){ assert(Type::Group==m_type); return m_byte; } uint8 GetEvent(){ return m_event; } uint8 GetByte(){ return m_byte; } internal: Type m_type; ZWValueID^ m_valueId; uint8 m_byte; uint8 m_event; }; } open-zwave-1.5/dotnet/src/ZWOptions.cpp000066400000000000000000000126571264474202400201760ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ZWOptions.cpp // // Cli/C++ wrapper for the C++ OpenZWave Options class // // 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 . // //----------------------------------------------------------------------------- #include "ZWOptions.h" using namespace OpenZWaveDotNet; using namespace OpenZWave; using namespace Runtime::InteropServices; //----------------------------------------------------------------------------- // // Create the unmanaged Options singleton object //----------------------------------------------------------------------------- void ZWOptions::Create ( String^ _configPath, String^ _userPath, String^ _commandLine ) { // Create the Manager singleton const char* config = (const char*)(Marshal::StringToHGlobalAnsi(_configPath)).ToPointer(); const char* user = (const char*)(Marshal::StringToHGlobalAnsi(_userPath)).ToPointer(); const char* command = (const char*)(Marshal::StringToHGlobalAnsi(_commandLine)).ToPointer(); Options::Create( config, user, command ); } //----------------------------------------------------------------------------- // // Add a boolean option to the program //----------------------------------------------------------------------------- bool ZWOptions::AddOptionBool ( String^ _name, bool _default ) { const char* name = (const char*)(Marshal::StringToHGlobalAnsi(_name)).ToPointer(); return Options::Get()->AddOptionBool( name, _default ); } //----------------------------------------------------------------------------- // // Add an integer option to the program //----------------------------------------------------------------------------- bool ZWOptions::AddOptionInt ( String^ _name, int32 _default ) { const char* name = (const char*)(Marshal::StringToHGlobalAnsi(_name)).ToPointer(); return Options::Get()->AddOptionInt( name, _default ); } //----------------------------------------------------------------------------- // // Add a string option to the program //----------------------------------------------------------------------------- bool ZWOptions::AddOptionString ( String^ _name, String^ _default, bool _append ) { const char* name = (const char*)(Marshal::StringToHGlobalAnsi(_name)).ToPointer(); const char* defaultStr = (const char*)(Marshal::StringToHGlobalAnsi(_default)).ToPointer(); return Options::Get()->AddOptionString( name, defaultStr, _append ); } //----------------------------------------------------------------------------- // // Gets the value of a boolean option //----------------------------------------------------------------------------- bool ZWOptions::GetOptionAsBool ( String^ _name, [Out] System::Boolean %o_value ) { bool value; if( Options::Get()->GetOptionAsBool( (const char*)(Marshal::StringToHGlobalAnsi(_name)).ToPointer(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Gets the value of an integer option //----------------------------------------------------------------------------- bool ZWOptions::GetOptionAsInt ( String^ _name, [Out] System::Int32 %o_value ) { int32 value; if( Options::Get()->GetOptionAsInt( (const char*)(Marshal::StringToHGlobalAnsi(_name)).ToPointer(), &value ) ) { o_value = value; return true; } return false; } //----------------------------------------------------------------------------- // // Gets the value of a string option //----------------------------------------------------------------------------- bool ZWOptions::GetOptionAsString ( String^ _name, [Out] String^ %o_value ) { string value; if( Options::Get()->GetOptionAsString( (const char*)(Marshal::StringToHGlobalAnsi(_name)).ToPointer(), &value ) ) { o_value = gcnew String(value.c_str()); return true; } return false; } //----------------------------------------------------------------------------- // // Gets the type of the value stored by the option //----------------------------------------------------------------------------- ZWOptionType ZWOptions::GetOptionType ( String^ _name ) { const char* name = (const char*)(Marshal::StringToHGlobalAnsi(_name)).ToPointer(); return (ZWOptionType)Enum::ToObject( ZWOptionType::typeid, Options::Get()->GetOptionType( name ) ); } open-zwave-1.5/dotnet/src/ZWOptions.h000066400000000000000000000227151264474202400176370ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ZWOptions.h // // Cli/C++ wrapper for the C++ OpenZWave Options class // // 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 . // //----------------------------------------------------------------------------- #pragma once #include #include #include #include #include "Options.h" using namespace System; using namespace System::Threading; using namespace System::Collections::Generic; using namespace Runtime::InteropServices; using namespace OpenZWave; namespace OpenZWaveDotNet { public enum class ZWOptionType { Invalid = Options::OptionType_Invalid, Bool = Options::OptionType_Bool, Int = Options::OptionType_Int, String = Options::OptionType_String }; /** * \nosubgrouping * A class that manages program options read from XML files or the command line. * The OpenZWave Manager class requires a complete and locked Options * object when created. The Options are therefore one of the first things that * any OpenZWave application must deal with. * Options are first read from an XML file called options.xml located in the * User data folder (the path to which is supplied to the Options::Create method). * This is the same folder that will be used by the Manager to save the state of * each controller in the Z-Wave network, to avoid querying them for their entire * state every time the application starts up. * The second source of program options is a string, which will normally be the * command line used to launch the application. * In this way, common options can be specified in the XML, but over-ridden if * necessary by the command line. * The Options process is as follows: * 1) Create an Options object, providing paths to the OpenZWave config folder, * the User data folder and any command line string containing program options. * 2) Call Options::AddOptionBool, Options::AddOptionInt or Options::AddOptionString * to add any application-specific configurable options * The OpenZWave options will already have been added during construction of the * Options object. * 3) Call Options::Lock. This will cause the option values to be read from * the options.xml file and the command line string, and will lock the options * so that no more calls aside from GetOptionAs may be made. * 4) Create the OpenZWave Manager object. */ public ref class ZWOptions { public: /** * 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. * \see Get, Destroy, AddOption, GetOptionAs, Lock */ void Create( String^ _configPath, String^ _userPath, String^ _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 */ bool Destroy(){ return Options::Destroy(); } /** * 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(){ return Options::Get()->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^ _name, bool _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^ _name, int32 _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^ _name, String^ _default, bool _append ); /** * Get the value of a boolean option. * \param _name the name of the option. Option names are case insensitive. * \param o_value 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^ _name, [Out] System::Boolean %o_value ); /** * Get the value of an integer option. * \param _name the name of the option. Option names are case insensitive. * \param o_value 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^ _name, [Out] System::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 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^ _name, [Out] 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 */ ZWOptionType GetOptionType( String^ _name ); /** * Test whether the options have been locked. * \return true if the options have been locked. * \see Lock */ bool AreLocked(){ return Options::Get()->AreLocked(); } }; } // namespace OpenZWaveDotNet open-zwave-1.5/dotnet/src/ZWValueID.h000066400000000000000000000106351264474202400174730ustar00rootroot00000000000000//----------------------------------------------------------------------------- // // ZWValueID.h // // Cli/C++ wrapper for the C++ OpenZWave Manager class // // Copyright (c) 2010 Amer Harb // // 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 . // //----------------------------------------------------------------------------- #pragma once #include "Windows.h" #include "ValueID.h" #include "stdio.h" #include #include using namespace System; using namespace System::Threading; using namespace System::Collections::Generic; using namespace OpenZWave; using namespace Runtime::InteropServices; namespace OpenZWaveDotNet { public ref class ZWValueID { public: enum class ValueGenre { Basic = ValueID::ValueGenre_Basic, User = ValueID::ValueGenre_User, Config = ValueID::ValueGenre_Config, System = ValueID::ValueGenre_System }; enum class ValueType { Bool = ValueID::ValueType_Bool, Byte = ValueID::ValueType_Byte, Decimal = ValueID::ValueType_Decimal, Int = ValueID::ValueType_Int, List = ValueID::ValueType_List, Schedule = ValueID::ValueType_Schedule, Short = ValueID::ValueType_Short, String = ValueID::ValueType_String, Button = ValueID::ValueType_Button, Raw = ValueID::ValueType_Raw }; /** * Create a ZWValue ID from its component parts. * This method is provided 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 */ ZWValueID ( uint32 homeId, uint8 nodeId, ZWValueID::ValueGenre genre, uint8 commandClassId, uint8 instance, uint8 valueIndex, ZWValueID::ValueType type, uint8 pollIntensity ) { m_valueId = new ValueID( homeId, nodeId, (ValueID::ValueGenre)genre, commandClassId, instance, valueIndex, (ValueID::ValueType)type ); } ZWValueID( ValueID const& valueId ) { m_valueId = new ValueID( valueId ); } ~ZWValueID() { delete m_valueId; } ValueID CreateUnmanagedValueID(){ return ValueID( *m_valueId ); } uint32 GetHomeId() { return m_valueId->GetHomeId(); } uint8 GetNodeId() { return m_valueId->GetNodeId(); } ValueGenre GetGenre() { return (ValueGenre)Enum::ToObject( ValueGenre::typeid, m_valueId->GetGenre() ); } uint8 GetCommandClassId() { return m_valueId->GetCommandClassId(); } uint8 GetInstance() { return m_valueId->GetInstance(); } uint8 GetIndex() { return m_valueId->GetIndex(); } ValueType GetType() { return (ValueType)Enum::ToObject( ValueType::typeid, m_valueId->GetType() ); } uint64 GetId() { return m_valueId->GetId(); } // Comparison Operators bool operator == ( ZWValueID^ _other ){ return( (*m_valueId) == (*_other->m_valueId) ); } bool operator != ( ZWValueID^ _other ){ return( (*m_valueId) != (*_other->m_valueId) ); } bool operator < ( ZWValueID^ _other ){ return( (*m_valueId) < (*_other->m_valueId) ); } bool operator > ( ZWValueID^ _other ){ return( (*m_valueId) > (*_other->m_valueId) ); } internal: ValueID* m_valueId; }; } open-zwave-1.5/dotnet/src/app.ico000066400000000000000000000020661264474202400170230ustar00rootroot00000000000000 &(( @wwwwwwwwwwwwwwpDDDDDDDDDDDDDDppppppppppppppppppppDDDDDDDDDDDDDDpLLLLLLLLLNItpDDDDDDDDDDDDD@( wwwwwwwDDDDDDDGOGOGOGOGOGOGOGOGHGLGDDDDDDopen-zwave-1.5/dotnet/src/app.rc000066400000000000000000000024221264474202400166510ustar00rootroot00000000000000// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon placed first or with lowest ID value becomes application icon LANGUAGE 9, 1 #pragma code_page(1252) 1 ICON "app.ico" #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE BEGIN "resource.h\0" "\0" END 2 TEXTINCLUDE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE BEGIN "\0" END #endif // APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED open-zwave-1.5/dotnet/src/resource.h000066400000000000000000000001301264474202400175350ustar00rootroot00000000000000//{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. // Used by app.rc open-zwave-1.5/license/000077500000000000000000000000001264474202400151015ustar00rootroot00000000000000open-zwave-1.5/license/Apache-License-2.0.txt000066400000000000000000000262331264474202400207060ustar00rootroot00000000000000This license applies to the cpp/build/sh2ju.sh file only. Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. open-zwave-1.5/license/gpl.txt000066400000000000000000001047331264474202400164340ustar00rootroot00000000000000The source files in the cpp/examples are distributed under the GPL V3 License. The rest of the OpenZWave Library is under the LGPL V3 license GNU 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. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . open-zwave-1.5/license/lgpl.txt000066400000000000000000000173341264474202400166100ustar00rootroot00000000000000The OpenZWave Library is distributed under the LGPL Version 3 license as per below. The Example Programs and some support files are distributed under different licenses, you should consult the other license files in this directory to identify those other files 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. open-zwave-1.5/license/license.txt000066400000000000000000000013221264474202400172620ustar00rootroot00000000000000 OpenZWave Copyright (c) 2010 Mal Lansell SOFTWARE NOTICE AND LICENSE 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 . open-zwave-1.5/makedist000077500000000000000000000011021264474202400152000ustar00rootroot00000000000000#!/usr/bin/perl use strict; use XML::Simple; use Data::Dumper; my $input = ".distfiles"; my $output = "distfiles.mk"; open( my $fh => $input) || die "Cannot open $input: $!"; open( my $oh, ">", $output) || die "Cannot open $output: $!"; print $oh "# This File is automatically generated by make dist-update\n"; print $oh "# Any Edits on this file will be lost next time dist-update is run\n"; print $oh "\n"; print $oh "DISTFILES =\t"; while(my $line = <$fh>) { chomp($line); print $oh $line." \\\n\t"; } print $oh "cpp/src/vers.cpp\n"; close($oh); close($fh); open-zwave-1.5/openzwave.dsc000066400000000000000000000016751264474202400162010ustar00rootroot00000000000000Format: 3.0 (quilt) Source: openzwave Binary: libopenzwave1.0, libopenzwave1.0-dev, openzwave Architecture: any Version: 1.4.0-1 Maintainer: Harald Klein Standards-Version: 3.9.3 Build-Depends: debhelper (>= 9), dh-exec (>= 0.3), g++ (>= 4.4), quilt, libudev-dev Package-List: libopenzwave1.0 deb libs optional libopenzwave1.0-dev deb libdevel optional openzwave deb misc optional Checksums-Sha1: 1fed10d9550220a6943a0376fd28febc9b670072 755515 openzwave_1.0.742.orig.tar.gz 6e1a47811cbb39121f865c199f8f38bf0c4101ca 3252 openzwave_1.0.742-1.debian.tar.gz Checksums-Sha256: 623da0f0ba0af3e7898f7ded381e3a748b05e2c6618bf0997c1a894358c513b6 755515 openzwave_1.0.742.orig.tar.gz 70ec260b3edf1e417f887001fce35b44a33b6f2d626f47a1c6717ba067951c0a 3252 openzwave_1.0.742-1.debian.tar.gz Files: 07294fb33951ee0e9adee232ed7ed72c 755515 openzwave_1.0.742.orig.tar.gz 0775eadbf1a4feaa6af914eb0df3f74d 3252 openzwave_1.0.742-1.debian.tar.gz open-zwave-1.5/openzwave.spec000066400000000000000000000116751264474202400163630ustar00rootroot00000000000000Name: libopenzwave %if 0%{?fedora} > 0 Group: Development/Libraries %else Group: Productivity/Networking/Other %endif Summary: Library to access Z-Wave interfaces URL:http://code.google.com/p/open-zwave/ %if 0%{?suse_version} > 0 License: LGPL-2.0+ %else License: LGPLv2+ %endif Version: 1.4.0 Release: 1 BuildRequires: gcc-c++ make libudev-devel doxygen graphviz %if 0%{?fedora} >= 18 BuildRequires: systemd-devel pkgconfig %else %if 0%{?suse_version} >= 1220 BuildRequires: systemd-devel pkg-config %else BuildRequires: libudev-devel pkgconfig %endif %endif Source0: libopenzwave-%{version}.tar.gz #Source0: openzwave-%{version}.tar.gz BuildRoot: %{_tmppath}/libopenzwave-root %description OpenZWave is an open-source, cross-platform library designed to enable anyone to add support for Z-Wave home-automation devices to their applications, without requiring any in depth knowledge of the Z-Wave protocol. Z-Wave employs a proprietary protocol which the owners, Sigma Designs, have chosen not to release into the public domain. There is also no official free or low-cost SDK that can be used to develop applications (The ControlThink SDK is now tied exclusively to their own Z-Wave PC interface). The only way to obtain the protocol documentation and sample code is to purchase an expensive development kit, and sign a non-disclosure agreement (NDA) preventing the release of that knowledge. OpenZWave was created to fill that gap. We do not have the official documentation, have signed no NDA, and are free to develop the library as we see fit. Our knowledge comes from existing bodies of open-source code (principally the Z-Wave parts of LinuxMCE), and through examining the messages sent by Z-Wave devices. 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. It is NOT our aim to publish alternative documentation of the Z-Wave protocol, or to attempt to "punish" Sigma Designs for their decision to keep the protocol closed. %package -n libopenzwave-devel Summary: Open-ZWave header files %if 0%{?fedora} > 0 Group: Development/Libraries %else Group: Development/Libraries/C and C++ %endif Requires: %{name} = %{version}-%{release} #BuildRequires: %{name} %description -n libopenzwave-devel header files needed when you want to compile your own applications using openzwave %package -n openzwave Summary: Open-ZWave Sample Executables %if 0%{?fedora} > 0 Group: Development/Libraries %else Group: Development/Libraries/C and C++ %endif Requires: %{name} = %{version}-%{release} #BuildRequires: %{name} %description -n openzwave Sample Executables for OpenZWave %prep %setup -q %build major_ver=$(echo %{version} | awk -F \. {'print $1'}) minor_ver=$(echo %{version} | awk -F \. {'print $2'}) revision=$(echo %{version} | awk -F \. {'print $3'}) 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 %install rm -rf %{buildroot}/* major_ver=$(echo %{version} | awk -F \. {'print $1'}) minor_ver=$(echo %{version} | awk -F \. {'print $2'}) revision=$(echo %{version} | awk -F \. {'print $3'}) mkdir -p %{buildroot}/%{_bindir} mkdir -p %{buildroot}/%{_libdir} mkdir -p %{buildroot}/%{_defaultdocdir}/openzwave-%{version}/ mkdir -p %{buildroot}/%{_sysconfdir}/ mkdir -p %{buildroot}/%{_includedir}/openzwave/ DESTDIR=%{buildroot} 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 cp -p INSTALL %{buildroot}/%{_defaultdocdir}/openzwave-%{version}/ cp -pr license %{buildroot}/%{_defaultdocdir}/openzwave-%{version}/ rm %{buildroot}%{_defaultdocdir}/openzwave-%{version}/Doxyfile.in rm -rf %{buildroot}%{_defaultdocdir}/openzwave-%{version}/html/ %files %defattr(-,root,root,-) %{_libdir}/libopenzwave.so.* %dir %{_defaultdocdir}/openzwave-%{version} %doc %{_defaultdocdir}/openzwave-%{version}/default.htm %doc %{_defaultdocdir}/openzwave-%{version}/general/ %doc %{_defaultdocdir}/openzwave-%{version}/images+css/ %doc %{_defaultdocdir}/openzwave-%{version}/license/ %doc %{_defaultdocdir}/openzwave-%{version}/INSTALL %config(noreplace) %{_sysconfdir}/openzwave/ %files -n libopenzwave-devel %defattr(-,root,root,-) %{_includedir}/openzwave/ %{_libdir}/libopenzwave.so %{_libdir}/pkgconfig/libopenzwave.pc %dir %{_defaultdocdir}/openzwave-%{version} %doc %{_defaultdocdir}/openzwave-%{version}/api/ %files -n openzwave %defattr(-,root,root,-) %{_bindir}/MinOZW %post /sbin/ldconfig %post -n libopenzwave-devel /sbin/ldconfig %postun /sbin/ldconfig %changelog * Tue Feb 04 2014 Justin Hammond+justin@dynam.ac - 1.0.730-1 - Initial Release