summaryrefslogtreecommitdiff
path: root/peripheral/libupm/src/ozw/ozw.h
blob: e4f4152e8919d33fc3055e1ea14580868f73f695 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
/*
 * Author: Jon Trulson <jtrulson@ics.com>
 * Copyright (c) 2015 Intel Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#pragma once

#include <string>
#include <map>

#include "Manager.h"
#include "Notification.h"
#include "Options.h"
#include "Driver.h"
#include "Node.h"
#include "Group.h"
#include "platform/Log.h"

namespace upm {
  
  /**
   * @brief OZW OpenZWave library
   * @defgroup ozw libupm-ozw
   * @ingroup uart wifi
   */

  /**
   * @library ozw
   * @sensor ozw
   * @comname UPM wrapper for the OpenZWave library
   * @type wifi
   * @man other
   * @con uart
   * @web http://www.openzwave.com/
   *
   * @brief UPM API for the OpenZWave library
   *
   * This module implements a wrapper around the OpenZWave library.
   * OpenZWave must be compiled and installed on your machine in order
   * to use this library.
   *
   * This module was developed with OpenZWave 1.3, and an Aeon Z-Stick
   * Gen5 configured as a Primary Controller.  It provides the ability
   * to query and set various values that can be used to control ZWave
   * devices.  It does not concern itself with configuration of
   * devices.  It is assumed that you have already setup your ZWave
   * network using a tool like the OpenZWave control panel, and have
   * already configured your devices as appropriate.
   *
   * To avoid exposing some of the internals of OpenZWave, devices
   * (nodes) and their values, are accessed via a nodeId and a value
   * index number.  The example will run dumpNodes() which will list
   * the currently connected devices and the values that are available
   * to them, along with an index number for that value.  It is
   * through these values (nodeId and index) that you can query and
   * set device values.
   *
   * In addition to querying values from a device (such as state
   * (on/off), or temperature, etc), methods are provided to allow you
   * to control these devices to the extent they allow, for example,
   * using a ZWave connected switch to turn on a lamp.
   *
   * Since it's likely no two ZWave networks are going to be the same,
   * the example will just initialize OpenZWave and run the
   * dumpNodes() method to allow you to see what devices are present,
   * the values they support and their current content, along with the
   * per-node index number you can use to address them.  There will be
   * commented out code examples showing you how to query or set a
   * specific value for a device.
   * 
   * See the ozw example code comments for an example of the ouput of
   * running dumpNodes().
   *
   * In most of the methods below, You will need the NodeId (Node
   * number), and the Index number to access or otherwise affect these
   * values.
   *
   * @snippet openzwave.cxx Interesting
   */

  // forward declaration of private zwNode data
  class zwNode;

  class OZW {
  public:

    typedef std::map<uint8_t, zwNode *> zwNodeMap_t;

    /**
     * OZW constructor
     */
    OZW();

    /**
     * OZW Destructor
     */
    ~OZW();

    /**
     * Start configuration with basic options.  This must be called
     * prior to init(), after the OZW() contructor is called.
     *
     * @param configPath Set the location of the OpenZWave config
     * directory, default is /etc/openzwave
     * @param userConfigDir Set the path to the user configuration
     * directory.  This is the location of the zwcfg*.xml and
     * option.xml files for the user (probably created by the
     * OpenZWave Control Panel example application).  The default is
     * the current directory ("").
     * @param cmdLine Specify command line formatted options to
     * OpenZWave.  The default is "".
     */
    void optionsCreate(std::string configPath="/etc/openzwave", 
                       std::string userConfigDir="",
                       std::string cmdLine="");
    
    /**
     * Add an integer Option.  See the OpenZWave documentation for
     * valid values.
     *
     * @param name The name of the configuration option
     * @param val The value to set it to
     */
    void optionAddInt(std::string name, int val);

    /**
     * Add a boolean Option.  See the OpenZWave documentation for
     * valid values.
     *
     * @param name The name of the configuration option
     * @param val The value to set it to
     */
    void optionAddBool(std::string name, bool val);

    /**
     * Add a string Option.  See the OpenZWave documentation for valid
     * values.
     *
     * @param name The name of the configuration option
     * @param val The value to set it to
     * @append true to append to the option, false to override
     */
    void optionAddString(std::string name, std::string val, bool append);

    /**
     * Lock the Options.  This must be called after all options have
     * been set, and before init() is called.  If init() is called
     * without locking the Options, init() will lock them itself.
     * After the options have been locked, no further options can be
     * specified.
     */
    void optionsLock();

    /**
     * Initialize the ZWave network.  This method will start a probe
     * of all defined devices on the ZWave network and query essential
     * information about them.  This function will not return until
     * either initialization has failed, or has succeeded far enough
     * along for the following methods to work.  Depending on the size
     * an complexity of the ZWave network, this may take anywhere from
     * seconds to several minutes to complete.
     *
     * All Options (via option*()) must have been specified before
     * this function is called.  If the Options have not been locked
     * via optionsLock() prior to calling init(), this method will
     * lock them for you before proceeding.
     *
     * @param devicePath The device path for the ZWave controller,
     * typically something like /dev/ttyACM0, or similiar
     * @param isHID true if this is a HID device, false otherwise (ie:
     * a serial port like /dev/ttyACM0, /dev/ttyUSB0, etc).  Default
     * is false.
     * @return true if init succeeded, false otherwise
     */
    bool init(std::string devicePath, bool isHID=false);

    /**
     * Dump information about all configured nodes and their values to
     * stdout.  This is useful to determine what nodes are available,
     * and the index (used for querying and seting values for them).
     * In addition, it includes information about each value (type,
     * current value, etc).
     *
     * @param all set to true to dump information about all values
     * available for each node.  If false, only information about
     * 'user' values (ignoring 'system' and 'configuration') are
     * output.  The default is false ('user' values only).
     */
    void dumpNodes(bool all=false);

    /**
     * Return a string (which may be empty) indicating the Units of
     * measure for a given value.  For example, querying a temperature
     * value may return "F" to indicate Fahrenheit.
     *
     * @param nodeId The node ID to query
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return A string containing the Unit of measure for the value
     */
    std::string getValueUnits(int nodeId, int index);

    /**
     * Set the text for the Units of measure for a value.
     *
     * @param nodeId The node ID to query
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param text The text to set
     */
    void setValueUnits(int nodeId, int index, std::string text);

    /**
     * Return a string (which may be empty) containing the
     * user-freindly Label for a value.
     *
     * @param nodeId The node ID to query
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return A string containing the Value's label
     */
    std::string getValueLabel(int nodeId, int index);

    /**
     * Set the text for a Value's label.
     *
     * @param nodeId The node ID to query
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param text The text to set
     */
    void setValueLabel(int nodeId, int index, std::string text);

    /**
     * Return a string (which may be empty) indicating the Help text
     * of a value, if available.
     *
     * @param nodeId The node ID to query
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return A string containing the Help text, if available
     */
    std::string getValueHelp(int nodeId, int index);

    /**
     * Set the text for a Value's help text.
     *
     * @param nodeId The node ID to query
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param text The text to set
     */
    void setValueHelp(int nodeId, int index, std::string text);

    /**
     * Set the contents of a Value to a string.  This should always
     * succeed if the supplied content makes sense for a given value,
     * regardless of the value's actual type.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param val the content to assign to the value referenced by
     * nodeId, and index.
     */
    void setValueAsString(int nodeId, int index, std::string val);

    /**
     * Set the contents of a Value, to a bool.  This will fail, and an
     * error message printed if the value type is not a boolean value.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param val the boolean content to assign to the value referenced
     * by nodeId, and index.
     */
    void setValueAsBool(int nodeId, int index, bool val);

    /**
     * Set the contents of a Value, to a byte.  This will fail, and an
     * error message printed if the value type is not a byte value.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param val the byte content to assign to the value referenced
     * by nodeId, and index.
     */
    void setValueAsByte(int nodeId, int index, uint8_t val);

    /**
     * Set the contents of a Value, to a float.  This will fail, and an
     * error message printed if the value type is not a float value.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param val the float content to assign to the value referenced
     * by nodeId, and index.
     */
    void setValueAsFloat(int nodeId, int index, float val);

    /**
     * Set the contents of a Value, to a 32 bit integer (int32).  This
     * will fail, and an error message printed if the value type is
     * not an int32.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param val the int32 content to assign to the value referenced
     * by nodeId, and index.
     */
    void setValueAsInt32(int nodeId, int index, int32_t val);

    /**
     * Set the contents of a Value, to a 16 bit integer (int16).  This
     * will fail, and an error message printed if the value type is
     * not an int16.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param val the int16 content to assign to the value referenced
     * by nodeId, and index.
     */
    void setValueAsInt16(int nodeId, int index, int16_t val);

    /**
     * Set the contents of a Value, to an array of bytes.  This will
     * fail, and an error message printed if the value type is not
     * settable as an array of bytes.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param val the byte array content to assign to the value referenced
     * by nodeId, and index.
     * @param len The length of the byte array
     */
    void setValueAsBytes(int nodeId, int index, uint8_t *val, uint8_t len);

    /**
     * Get the minimum allowed value for a node's Value.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return The minumum allowed value
     */
    int getValueMin(int nodeId, int index);

    /**
     * Get the maximum allowed value for a node's Value.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return The maximum allowed value
     */
    int getValueMax(int nodeId, int index);

    /**
     * Test whether a value is read-only.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return true if the value is read-only, false otherwise
     */
    bool isValueReadOnly(int nodeId, int index);

    /**
     * Test whether a value is write only.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return true if the value is write-only, false otherwise
     */
    bool isValueWriteOnly(int nodeId, int index);

    /**
     * Test whether a value is really set on a node, and not a default
     * value chosen by the OpenZWave library.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return true if the value is really set, false if a default value is
     * being reported
     */
    bool isValueSet(int nodeId, int index);

    /**
     * Test whether a value is being manually polled by the OpenZWave
     * library.  Most modern devices are never polled, rather they are
     * configured to report changing values to the controller on their
     * own at device specific intervals or when appropriate events
     * (depending the device) have occured.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return true if the value is being maually polled, false otherwise
     * being reported
     */
    bool isValuePolled(int nodeId, int index);

    /**
     * Return the content of a value as a string.  This should always
     * succeed, regardless of the actual value type.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return A string representing the current contents of a value.
     */
    std::string getValueAsString(int nodeId, int index);

    /**
     * Return the content of a value as a booleang.  This will fail,
     * and an error message printed if the value type is not boolean.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return A boolean representing the current contents of a value.
     */
    bool getValueAsBool(int nodeId, int index);

    /**
     * Return the content of a value as a byte.  This will fail, and
     * an error message printed if the value type is not a byte.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return A byte representing the current contents of a value.
     */
    uint8_t getValueAsByte(int nodeId, int index);

    /**
     * Return the content of a value as a float.  This will fail, and
     * an error message printed if the value type is not a floating
     * point value.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return A float representing the current contents of a value.
     */
    float getValueAsFloat(int nodeId, int index);

    /**
     * Return the content of a value as an int32.  This will fail, and
     * an error message printed if the value type is not an int32.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return An int32 representing the current contents of a value.
     */
    int getValueAsInt32(int nodeId, int index);

    /**
     * Return the content of a value as an int16.  This will fail, and
     * an error message printed if the value type is not an int16.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @return An int16 representing the current contents of a value.
     */
    int getValueAsInt16(int nodeId, int index);

    /**
     * Issue a refresh request for a value on a node.  OpenZWave will
     * query the value and update it's internal state when the device
     * responds.  Note, this happens asynchronously - it may take some
     * time before the current value is reported to OpenZWave by the
     * node.  If the node is asleep, you may not get a current value
     * for some time (or at all, depending on the device).  This
     * method will return immediately after the request has been
     * queued.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     */
    void refreshValue(int nodeId, int index);

    /**
     * Enable or disable some debugging output.  Note, this will not
     * affect OpenZWave's own debugging, which is usually set in the
     * option.xml file.
     *
     * @param enable true to enable debugging, false otherwise
     */
    void setDebug(bool enable);

    /**
     * Determine if a node is a listening device -- in other words, the
     * node never sleeps.
     *
     * @param nodeId The node ID
     * @return true if the node never sleeps, false otherwise
     */
    bool isNodeListeningDevice(int nodeId);

    /**
     * Determine if a node is a frequent listening device -- in other
     * words, if the node is asleep, can it be woken by a beam.
     *
     * @param nodeId The node ID
     * @return true if the node is a frequent listening device, false
     * otherwise
     */
    bool isNodeFrequentListeningDevice(int nodeId);

    /**
     * Determine if a node is awake.
     *
     * @param nodeId The node ID
     * @return true if the node is awake, false otherwise
     */
    bool isNodeAwake(int nodeId);

  protected:
    /**
     * Based on a nodeId and a value index, lookup the corresponding
     * OpenZWave ValueID.
     *
     * @param nodeId The node ID
     * @param index The value index (see dumpNodes()) of the value to query.
     * @param A pointer to a ValueID that will be returned if successful
     * @return true of the nodeId and index was found, false otherwise
     */
    bool getValueID(int nodeId, int index, OpenZWave::ValueID *vid);

    /**
     * Lock the m_zwNodeMap mutex to protect against changes made to
     * the the the map by the OpenZWave notification handler.  Always
     * lock this mutex when acessing anything in the zwNodeMap map.
     */

    void lockNodes() { pthread_mutex_lock(&m_nodeLock); };
    /**
     * Unlock the m_zwNodeMap mutex after lockNodes() has been called.
     */
    void unlockNodes() { pthread_mutex_unlock(&m_nodeLock); };

  private:
    uint32_t m_homeId;
    bool m_mgrCreated;
    bool m_driverFailed;
    bool m_debugging;

    bool m_driverIsHID;
    std::string m_devicePath;

    // our notification handler, called by OpenZWave for events on the
    // network.
    static void notificationHandler(OpenZWave::Notification 
                                    const* notification, 
                                    void *ctx);

    // a map of added nodes
    zwNodeMap_t m_zwNodeMap;

    // for coordinating access to the node list
    pthread_mutex_t m_nodeLock;

    // We use these to determine init failure or success (if OpenZWave
    // has successfully queried essential data about the network).
    pthread_mutex_t m_initLock;
    pthread_cond_t m_initCond;
  };
}