ansible4ozw 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/lib/ansible.rb +47 -0
  2. data/lib/ansible/ansible_callback.rb +142 -0
  3. data/lib/ansible/ansible_device.rb +68 -0
  4. data/lib/ansible/ansible_value.rb +179 -0
  5. data/lib/ansible/config.rb +92 -0
  6. data/lib/ansible/devices/ansible_dimmer.rb +80 -0
  7. data/lib/ansible/devices/ansible_switch.rb +66 -0
  8. data/lib/ansible/knx/EIBConnection.rb +2371 -0
  9. data/lib/ansible/knx/dpt/canonical_1bit.rb +54 -0
  10. data/lib/ansible/knx/dpt/dpt1.rb +224 -0
  11. data/lib/ansible/knx/dpt/dpt10.rb +85 -0
  12. data/lib/ansible/knx/dpt/dpt11.rb +72 -0
  13. data/lib/ansible/knx/dpt/dpt12.rb +61 -0
  14. data/lib/ansible/knx/dpt/dpt13.rb +100 -0
  15. data/lib/ansible/knx/dpt/dpt14.rb +87 -0
  16. data/lib/ansible/knx/dpt/dpt15.rb +72 -0
  17. data/lib/ansible/knx/dpt/dpt16.rb +67 -0
  18. data/lib/ansible/knx/dpt/dpt17.rb +65 -0
  19. data/lib/ansible/knx/dpt/dpt18.rb +66 -0
  20. data/lib/ansible/knx/dpt/dpt19.rb +100 -0
  21. data/lib/ansible/knx/dpt/dpt2.rb +156 -0
  22. data/lib/ansible/knx/dpt/dpt3.rb +104 -0
  23. data/lib/ansible/knx/dpt/dpt4.rb +75 -0
  24. data/lib/ansible/knx/dpt/dpt5.rb +124 -0
  25. data/lib/ansible/knx/dpt/dpt6.rb +73 -0
  26. data/lib/ansible/knx/dpt/dpt7.rb +146 -0
  27. data/lib/ansible/knx/dpt/dpt8.rb +118 -0
  28. data/lib/ansible/knx/dpt/dpt9.rb +204 -0
  29. data/lib/ansible/knx/dpt/tests/test_dpt10.rb +45 -0
  30. data/lib/ansible/knx/dpt/tests/test_dpt9.rb +60 -0
  31. data/lib/ansible/knx/hexdump.rb +113 -0
  32. data/lib/ansible/knx/knx_dpt.rb +58 -0
  33. data/lib/ansible/knx/knx_dpt_scalar.rb +62 -0
  34. data/lib/ansible/knx/knx_eistypes.rb +76 -0
  35. data/lib/ansible/knx/knx_protocol.rb +99 -0
  36. data/lib/ansible/knx/knx_scene.rb +48 -0
  37. data/lib/ansible/knx/knx_tools.rb +76 -0
  38. data/lib/ansible/knx/knx_transceiver.rb +237 -0
  39. data/lib/ansible/knx/knx_value.rb +327 -0
  40. data/lib/ansible/openzwave/ozw_constants.rb +11 -0
  41. data/lib/ansible/openzwave/ozw_headers.rb +80 -0
  42. data/lib/ansible/openzwave/ozw_remote_manager.rb +7615 -0
  43. data/lib/ansible/openzwave/ozw_types.rb +406 -0
  44. data/lib/ansible/orbiter_proxy.rb +12 -0
  45. data/lib/ansible/transceiver.rb +63 -0
  46. data/lib/ansible/zwave/types/valuetype_bool.rb +74 -0
  47. data/lib/ansible/zwave/types/valuetype_button.rb +63 -0
  48. data/lib/ansible/zwave/types/valuetype_byte.rb +78 -0
  49. data/lib/ansible/zwave/types/valuetype_decimal.rb +64 -0
  50. data/lib/ansible/zwave/types/valuetype_int.rb +63 -0
  51. data/lib/ansible/zwave/types/valuetype_list.rb +64 -0
  52. data/lib/ansible/zwave/types/valuetype_short.rb +63 -0
  53. data/lib/ansible/zwave/types/valuetype_string.rb +61 -0
  54. data/lib/ansible/zwave/zwave_command_classes.rb +113 -0
  55. data/lib/ansible/zwave/zwave_node.rb +5 -0
  56. data/lib/ansible/zwave/zwave_protocol.rb +52 -0
  57. data/lib/ansible/zwave/zwave_transceiver.rb +435 -0
  58. data/lib/ansible/zwave/zwave_value.rb +193 -0
  59. metadata +108 -0
@@ -0,0 +1,61 @@
1
+ =begin
2
+ Project Ansible - An extensible home automation scripting framework
3
+ ----------------------------------------------------
4
+ Copyright (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
5
+
6
+ SOFTWARE NOTICE AND LICENSE
7
+
8
+ Project Ansible is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU Lesser General Public License as published
10
+ by the Free Software Foundation, either version 3 of the License,
11
+ or (at your option) any later version.
12
+
13
+ Project Ansible is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with Project Ansible. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ for more information on the LGPL, see:
22
+ http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
23
+ =end
24
+
25
+ module Ansible
26
+
27
+ module ZWave
28
+
29
+ # string value type for OpenZWave
30
+ module ValueType_String
31
+
32
+ # define type-specific OZW::Manager API calls
33
+ def read_operation
34
+ return :GetValueAsString
35
+ end
36
+
37
+ def write_operation
38
+ return :SetValue_String
39
+ end
40
+
41
+ #
42
+ def as_canonical_value()
43
+ puts 'TODO:: zwave_string: as_canonical'
44
+ return (current_value)
45
+ end
46
+
47
+ #
48
+ def to_protocol_value(new_val)
49
+ puts 'TODO:: zwave_string: to_protocol'
50
+ result = nil
51
+ result = new_val.to_s if [TrueClass, FalseClass].include?(new_val.class)
52
+ end
53
+
54
+ # return a human-readable representation of a ZWave frame
55
+ def explain
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,113 @@
1
+ =begin
2
+ Project Ansible - An extensible home automation scripting framework
3
+ ----------------------------------------------------
4
+ Copyright (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
5
+
6
+ SOFTWARE NOTICE AND LICENSE
7
+
8
+ Project Ansible is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU Lesser General Public License as published
10
+ by the Free Software Foundation, either version 3 of the License,
11
+ or (at your option) any later version.
12
+
13
+ Project Ansible is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with Project Ansible. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ for more information on the LGPL, see:
22
+ http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
23
+ =end
24
+
25
+ module OpenZWave
26
+
27
+ # hashmap of ZWave's command class symbol id to byte value
28
+ CommandClassesByName = {
29
+ :COMMAND_CLASS_VERSION => 0x86,
30
+ :COMMAND_CLASS_BATTERY => 0x80,
31
+ :COMMAND_CLASS_WAKE_UP => 0x84,
32
+ :COMMAND_CLASS_CONTROLLER_REPLICATION => 0x21,
33
+ :COMMAND_CLASS_BASIC => 0x20,
34
+ :COMMAND_CLASS_SWITCH_MULTILEVEL => 0x26,
35
+ :COMMAND_CLASS_SWITCH_ALL => 0x27,
36
+ :COMMAND_CLASS_SENSOR_BINARY => 0x30,
37
+ :COMMAND_CLASS_SENSOR_MULTILEVEL => 0x31,
38
+ :COMMAND_CLASS_ALARM => 0x71,
39
+ :COMMAND_CLASS_MULTI_CMD => 0x8F,
40
+ :COMMAND_CLASS_CLIMATE_CONTROL_SCHEDULE => 0x46,
41
+ :COMMAND_CLASS_CLOCK => 0x81,
42
+ :COMMAND_CLASS_ASSOCIATION => 0x85,
43
+ :COMMAND_CLASS_CONFIGURATION => 0x70,
44
+ :COMMAND_CLASS_MANUFACTURER_SPECIFIC => 0x72,
45
+ :COMMAND_CLASS_APPLICATION_STATUS => 0x22,
46
+ :COMMAND_CLASS_ASSOCIATION_COMMAND_CONFIGURATION => 0x9B,
47
+ :COMMAND_CLASS_AV_CONTENT_DIRECTORY_MD => 0x95,
48
+ :COMMAND_CLASS_AV_CONTENT_SEARCH_MD => 0x97,
49
+ :COMMAND_CLASS_AV_RENDERER_STATUS => 0x96,
50
+ :COMMAND_CLASS_AV_TAGGING_MD => 0x99,
51
+ :COMMAND_CLASS_BASIC_WINDOW_COVERING => 0x50,
52
+ :COMMAND_CLASS_CHIMNEY_FAN => 0x2A,
53
+ :COMMAND_CLASS_COMPOSITE => 0x8D,
54
+ :COMMAND_CLASS_DOOR_LOCK => 0x62,
55
+ :COMMAND_CLASS_ENERGY_PRODUCTION => 0x90,
56
+ :COMMAND_CLASS_FIRMWARE_UPDATE_MD => 0x7a,
57
+ :COMMAND_CLASS_GEOGRAPHIC_LOCATION => 0x8C,
58
+ :COMMAND_CLASS_GROUPING_NAME => 0x7B,
59
+ :COMMAND_CLASS_HAIL => 0x82,
60
+ :COMMAND_CLASS_INDICATOR => 0x87,
61
+ :COMMAND_CLASS_IP_CONFIGURATION => 0x9A,
62
+ :COMMAND_CLASS_LANGUAGE => 0x89,
63
+ :COMMAND_CLASS_LOCK => 0x76,
64
+ :COMMAND_CLASS_MANUFACTURER_PROPRIETARY => 0x91,
65
+ :COMMAND_CLASS_METER_PULSE => 0x35,
66
+ :COMMAND_CLASS_METER => 0x32,
67
+ :COMMAND_CLASS_MTP_WINDOW_COVERING => 0x51,
68
+ :COMMAND_CLASS_MULTI_INSTANCE_ASSOCIATION => 0x8E,
69
+ :COMMAND_CLASS_MULTI_INSTANCE => 0x60,
70
+ :COMMAND_CLASS_NO_OPERATION => 0x00,
71
+ :COMMAND_CLASS_NODE_NAMING => 0x77,
72
+ :COMMAND_CLASS_NON_INTEROPERABLE => 0xf0,
73
+ :COMMAND_CLASS_POWERLEVEL => 0x73,
74
+ :COMMAND_CLASS_PROPRIETARY => 0x88,
75
+ :COMMAND_CLASS_PROTECTION => 0x75,
76
+ :COMMAND_CLASS_REMOTE_ASSOCIATION_ACTIVATE => 0x7c,
77
+ :COMMAND_CLASS_REMOTE_ASSOCIATION => 0x7d,
78
+ :COMMAND_CLASS_SCENE_ACTIVATION => 0x2b,
79
+ :COMMAND_CLASS_SCENE_ACTUATOR_CONF => 0x2C,
80
+ :COMMAND_CLASS_SCENE_CONTROLLER_CONF => 0x2D,
81
+ :COMMAND_CLASS_SCREEN_ATTRIBUTES => 0x93,
82
+ :COMMAND_CLASS_SCREEN_MD => 0x92,
83
+ :COMMAND_CLASS_SECURITY => 0x98,
84
+ :COMMAND_CLASS_SENSOR_ALARM => 0x9C,
85
+ :COMMAND_CLASS_SENSOR_CONFIGURATION => 0x9E,
86
+ :COMMAND_CLASS_SILENCE_ALARM => 0x9d,
87
+ :COMMAND_CLASS_SIMPLE_AV_CONTROL => 0x94,
88
+ :COMMAND_CLASS_SWITCH_BINARY => 0x25,
89
+ :COMMAND_CLASS_SWITCH_TOGGLE_BINARY => 0x28,
90
+ :COMMAND_CLASS_SWITCH_TOGGLE_MULTILEVEL => 0x29,
91
+ :COMMAND_CLASS_THERMOSTAT_FAN_MODE => 0x44,
92
+ :COMMAND_CLASS_THERMOSTAT_FAN_STATE => 0x45,
93
+ :COMMAND_CLASS_THERMOSTAT_HEATING => 0x38,
94
+ :COMMAND_CLASS_THERMOSTAT_MODE => 0x40,
95
+ :COMMAND_CLASS_THERMOSTAT_OPERATING_STATE => 0x42,
96
+ :COMMAND_CLASS_THERMOSTAT_SETBACK => 0x47,
97
+ :COMMAND_CLASS_THERMOSTAT_SETPOINT => 0x43,
98
+ :COMMAND_CLASS_TIME_PARAMETERS => 0x8B,
99
+ :COMMAND_CLASS_TIME => 0x8a,
100
+ :COMMAND_CLASS_USER_CODE => 0x63,
101
+ :COMMAND_CLASS_ZIP_ADV_CLIENT => 0x34,
102
+ :COMMAND_CLASS_ZIP_ADV_SERVER => 0x33,
103
+ :COMMAND_CLASS_ZIP_ADV_SERVICES => 0x2F,
104
+ :COMMAND_CLASS_ZIP_CLIENT => 0x2e,
105
+ :COMMAND_CLASS_ZIP_SERVER => 0x24,
106
+ :COMMAND_CLASS_ZIP_SERVICES => 0x23
107
+ }
108
+
109
+ # hashmap of ZWave's command class byte to symbol
110
+ CommandClassesByID = {}
111
+ CommandClassesByName.each {|key, value| CommandClassesByID[value] = key }
112
+
113
+ end #module
@@ -0,0 +1,5 @@
1
+ #~ Project Ansible
2
+ #~ (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
3
+
4
+ require 'zwave_protocol'
5
+ require 'zwave_command_classes'
@@ -0,0 +1,52 @@
1
+ =begin
2
+ Project Ansible - An extensible home automation scripting framework
3
+ ----------------------------------------------------
4
+ Copyright (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
5
+
6
+ SOFTWARE NOTICE AND LICENSE
7
+
8
+ Project Ansible is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU Lesser General Public License as published
10
+ by the Free Software Foundation, either version 3 of the License,
11
+ or (at your option) any later version.
12
+
13
+ Project Ansible is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with Project Ansible. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ for more information on the LGPL, see:
22
+ http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
23
+ =end
24
+
25
+ require 'bindata'
26
+
27
+ #~ // ID Packing:
28
+ #~ // Bits
29
+ #~ // 24-31: 8 bits. Node ID of device
30
+ #~ // 22-23: 2 bits. genre of value (see ValueGenre enum).
31
+ #~ // 14-21: 8 bits. ID of command class that created and manages this value.
32
+ #~ // 12-13: 2 bits. Unused.
33
+ #~ // 04-11: 8 bits. Index of value within all the value created by the command class
34
+ #~ // instance (in configuration parameters, this is also the parameter ID).
35
+ #~ // 00-03: 4 bits. Type of value (bool, byte, string etc).
36
+ class OZW_ValueID_id < BinData::Record
37
+ bit8 :node_id, { :display_name => "Node ID of device" }
38
+ bit2 :value_genre, { :display_name => "Value Genre"}
39
+ bit8 :cmd_class, { :display_name => "command class"}
40
+ bit2 :pad1
41
+ bit8 :value_idx, { :display_name => "value index"}
42
+ bit4 :value_type, { :display_name => "value type( bool, byte, string etc)"}
43
+ end
44
+
45
+ #~ // ID1 Packing:
46
+ #~ // Bits
47
+ #~ // 24-31 8 bits. Instance Index of the command class.
48
+ class OZW_ValueID_id1 < BinData::Record
49
+ bit8 :cmd_class_instance, { :display_name => "cmd class instance" }
50
+ bit24 :unused2, { :display_name => "(unused)" }
51
+ end
52
+
@@ -0,0 +1,435 @@
1
+ =begin
2
+ Project Ansible - An extensible home automation scripting framework
3
+ ----------------------------------------------------
4
+ Copyright (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
5
+
6
+ SOFTWARE NOTICE AND LICENSE
7
+
8
+ Project Ansible is free software: you can redistribute it and/or modify
9
+ it under the terms of the GNU Lesser General Public License as published
10
+ by the Free Software Foundation, either version 3 of the License,
11
+ or (at your option) any later version.
12
+
13
+ Project Ansible is distributed in the hope that it will be useful,
14
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
+ GNU Lesser General Public License for more details.
17
+
18
+ You should have received a copy of the GNU Lesser General Public License
19
+ along with Project Ansible. If not, see <http://www.gnu.org/licenses/>.
20
+
21
+ for more information on the LGPL, see:
22
+ http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
23
+ =end
24
+
25
+ require 'rubygems'
26
+ require 'onstomp'
27
+ require 'thrift'
28
+
29
+ require 'config'
30
+ require 'zwave_protocol'
31
+ require 'zwave_value'
32
+ require 'transceiver'
33
+
34
+ module Ansible
35
+
36
+ module ZWave
37
+
38
+ # the ZWave transceiver is responsible for communication with the ZWave network
39
+ # uses ozwd, a Thrift wrapper around the OpenZWave library
40
+ class ZWave_Transceiver < Transceiver
41
+
42
+ # we also use callbacks
43
+ include AnsibleCallback
44
+
45
+ attr_reader :stompURL, :thriftURL
46
+
47
+ def initialize(stompURL, thriftURL)
48
+ raise "Already initialized!" unless Ansible::ZWave::ValueID::transceiver.nil?
49
+ puts "#{self}: initializing" if $DEBUG
50
+ @stompURL, @thriftURL = stompURL, thriftURL
51
+ #@stompMutex = Mutex.new
52
+ @thriftMutex = Mutex.new
53
+ @stomp_ok, @thrift_ok = false, false
54
+ @alive = true
55
+ super()
56
+ # store reference to ourselves to the classes that use us
57
+ Ansible::ZWave::ValueID.transceiver = self
58
+
59
+ @ValueMonitors = {}
60
+ @ValueMonitorMutex = Mutex.new
61
+ end
62
+
63
+ # initialize connection to STOMP server
64
+ def init_stomp
65
+ unless @stomp_ok
66
+ begin
67
+ #puts "init_stomp\n-------------\n\t" + caller.join("\n\t") + "\n"
68
+ @stompserver = OnStomp::Client.new(@stompURL)
69
+ @stompserver.on_connection_died { |client, con|
70
+ @stomp_ok = false
71
+ puts "STOMP connection died!! sleeping for 3 seconds and then retrying..."
72
+ puts "stack trace: \n\t"<< caller.join("\t\n")
73
+ sleep(3)
74
+ @stompserver.connect
75
+ }
76
+ #
77
+ @stompserver.on_connection_closed { |client, con|
78
+ @stomp_ok = false
79
+ puts "STOMP connection closed!! sleeping for 10 seconds and then retrying..."
80
+ puts "stack trace: \n\t"<< caller.join("\t\n")
81
+ sleep(10)
82
+ @stompserver.connect
83
+ }
84
+ #
85
+ @stompserver.on_connection_established { |client, con|
86
+ puts "STOMP: Connected to broker using protocol version #{con.version}"
87
+ @stomp_ok = true
88
+ }
89
+ @stompserver.connect
90
+ rescue Errno::ECONNREFUSED => e
91
+ @stomp_ok = false
92
+ puts "#{e}"
93
+ end
94
+ end
95
+ return @stompserver
96
+ end
97
+
98
+ # get handle to stomp server, connect unless already connected
99
+ # caller must unlock @stompMutex when done with stomp
100
+ def stomp
101
+ @stomp_ok ? @stompserver : init_stomp()
102
+ end
103
+
104
+ # Thrift URL Regexp
105
+ ThriftURL_RE = /thrift:\/\/([^:]*)(?::(.*))*/
106
+
107
+ # initialize connection to THRIFT server
108
+ def init_thrift()
109
+ unless @thrift_ok
110
+ # connect to Thrift server for OpenZWave
111
+ begin
112
+ if md = ThriftURL_RE.match(@thriftURL) then
113
+ host = md[1]
114
+ port = md[2].nil?? 9090: md[2].to_i
115
+ #puts "THRIFT host, port = #{host}:#{port}"
116
+ @thrift_transport = Thrift::BufferedTransport.new(Thrift::Socket.new(host, port))
117
+ @thrift_protocol = Thrift::BinaryProtocol.new(@thrift_transport)
118
+ @thrift_transport.open()
119
+ @manager = ::OpenZWave::RemoteManager::Client.new(@thrift_protocol)
120
+ # fetch all known ValueID's from the server
121
+ @manager.SendAllValues
122
+ @thrift_ok = true
123
+ @thrift_heartbeat = Thread.new{
124
+ puts "Thrift: New heartbeat thread, #{Thread.current}"
125
+ # aargh, ugly heartbeat
126
+ while (@thrift_ok) do
127
+ sleep(1)
128
+ #puts 'ping...'
129
+ manager_send(:GetControllerNodeId, HomeID)
130
+ end
131
+ puts "Thrift: heartbeat thread exiting, #{Thread.current}"
132
+ }
133
+ else
134
+ raise "Thrift URL invalid"
135
+ end
136
+ #rescue Thrift::TransportException => e
137
+ rescue Exception => e
138
+ @thrift_ok = false
139
+ puts "#{e}"
140
+ end
141
+ end
142
+ return @manager
143
+ end
144
+
145
+ # get handle to OpenZWave::RemoteManager
146
+ def manager
147
+ # TODO: add caller watch here, (check for unsynchronized access)
148
+ @thrift_ok ? @manager : init_thrift()
149
+ end
150
+
151
+ # the preferred method to access OpenZWave::Manager methods
152
+ # is via this generic call function, which takes care of all the nitty-gritty
153
+ # details such as connection monitoring and thread synchronization
154
+ def manager_send(meth, *args)
155
+ result = nil
156
+ @thriftMutex.synchronize {
157
+ begin
158
+ result = manager.method(meth).call(*args)
159
+ rescue Thrift::TransportException => e
160
+ @thrift_ok = false
161
+ puts "Thrift transport exception, in method #{meth.inspect}"
162
+ puts "--------------------------, callers=\n\t\t" + caller[0..2].join("\n\t\t")
163
+ sleep(1)
164
+ retry
165
+ rescue Exception => e
166
+ @thrift_ok = false
167
+ puts "OpenZWave exception: #{e}, in method #{meth.inspect}"
168
+ puts "--------------------, callers=\n\t\t" + caller[0..2].join("\n\t\t")
169
+ end
170
+ }
171
+ return(result)
172
+ end
173
+
174
+ #
175
+ # transceiver main loop, runs in its own Ruby thread
176
+ #
177
+ def run
178
+ # 1) subscribe to zwave's notification channel
179
+ stomp.subscribe '/queue/zwave/monitor' do |msg|
180
+ # Invoked every time the broker delivers a MESSAGE frame for the
181
+ # SUBSCRIBE frame generated by this method call.
182
+ puts "\n------ ZWAVE MESSAGE (#{Time.now}) ------" if $DEBUG
183
+ begin
184
+ value = nil
185
+ # lookup or create ValueID related to Notification
186
+ if msg.headers["HomeID"] and msg.headers["ValueID"] then
187
+ homeID = msg.headers["HomeID"]
188
+ valueID = msg.headers["ValueID"]
189
+ # sync current HomeID
190
+ h = homeID.to_i(16)
191
+ unless Ansible::ZWave.const_defined?(:HomeID) then
192
+ if h > 0 then
193
+ puts "------ SETTING HOME ID: #{homeID}"
194
+ Ansible::ZWave.const_set("HomeID", h)
195
+ end
196
+ end
197
+ # get or create ValueID object
198
+ value = Ansible::ZWave::ValueID.get_or_create(homeID, valueID)
199
+ end
200
+ # bind other notification parameters
201
+ if msg.headers["NotificationType"] then
202
+ node = msg.headers["NotificationNodeId"].to_i(16)
203
+ byte = msg.headers["NotificationByte"].to_i(16)
204
+ notif_type = msg.headers["NotificationType"].to_i(16)
205
+ name, desc = OpenZWave::NotificationTypes[notif_type]
206
+ # dynamic notification handler dispatch mechanism
207
+ if md = /Type_(.*)/.match(name) then
208
+ handler = "notification_" + md[1]
209
+ puts "#{handler} (n:#{node}) (b:#{byte}) (#{value})"
210
+ __send__(handler, node, byte, value) if respond_to?(handler)
211
+ # fire all notification-related callbacks for the value, if any
212
+ # e.g. onValueChanged, onValueRefreshed etc.
213
+ if value.is_a?AnsibleValue then
214
+ value.fire_callback("on#{md[1]}".to_sym)
215
+ end
216
+ end
217
+ end
218
+ # controller state change notification mechanism
219
+ if ctrl_state = msg.headers["ControllerState"] then
220
+ controller_state(ctrl_state.to_i(16))
221
+ end
222
+ rescue Exception => e
223
+ puts "ZWaveTransceiver::decode_monitor() exception: #{e}"
224
+ puts "\t"+e.backtrace[0..3].join("\n\t")
225
+ end
226
+ end # do subscribe
227
+ # 2) Sleep forever (how pretty)
228
+ while true #@alive #FIXME
229
+ sleep(1)
230
+ end
231
+ end
232
+
233
+
234
+ #
235
+ #
236
+ # NOTIFICATIONS
237
+ #
238
+
239
+ # a value has been added to the Z-Wave network
240
+ def notification_ValueAdded(nodeId, byte, value)
241
+ #@@Values[homeID].push(value)
242
+ end
243
+
244
+ # a value has been removed from the Z-Wave network
245
+ def notification_ValueRemoved(nodeId, byte, value)
246
+ # A node value has been removed from OpenZWave's list. This only occurs when a node is removed.
247
+ #@@Values[homeID].delete(value)
248
+ end
249
+
250
+ # A node value has been updated from the Z-Wave network.
251
+ def notification_ValueChanged(nodeId, byte, value)
252
+ # OpenZWave peculiarity: we got a ValueChanged event, but the value
253
+ # reported by OpenZWave is unchanged. Thus we need to poll the
254
+ # device using :RequestNodeDynamic, wait for NodeQueriesComplete
255
+ # then re-get the value
256
+ #trigger_value_monitor(value)
257
+ #
258
+ # as of r471 ValueChanged behaves correctly
259
+ AnsibleValue[:_nodeId => nodeId, :_gerne => 1].each { |v|
260
+ v.get
261
+ }
262
+ end
263
+
264
+ # A node value has been refreshed from the Z-Wave network.
265
+ def notification_ValueRefreshed(nodeId, byte, value)
266
+ #value.get unless value.nil?
267
+ end
268
+
269
+ # The associations for the node have changed. The application
270
+ # should rebuild any group information it holds about the node.
271
+ def notification_Group(nodeId, byte, value)
272
+ puts 'TODO'
273
+ end
274
+
275
+ # A new node has been found (not already stored in zwcfg*.xml file)
276
+ def notification_NodeNew(nodeId, byte, value)
277
+ puts 'TODO'
278
+ end
279
+
280
+ # A new node has been added to OpenZWave's list. This may be due
281
+ # to a device being added to the Z-Wave network, or because the
282
+ # application is initializing itself.
283
+ def notification_NodeAdded(nodeId, byte, value)
284
+ puts 'TODO'
285
+ end
286
+
287
+ # A node has been removed from OpenZWave's list. This may be due
288
+ # to a device being removed from the Z-Wave network, or because
289
+ # the application is closing.
290
+ def notification_NodeRemoved(nodeId, byte, value)
291
+ puts 'TODO'
292
+ end
293
+
294
+ # Basic node information has been receievd, such as whether
295
+ # the node is a listening device, a routing device and its
296
+ # baud rate and basic, generic and specific types. It is
297
+ # after this notification that you can call Manager::GetNodeType
298
+ # to obtain a label containing the device description. */
299
+ def notification_NodeProtocolInfo(nodeId, byte, value)
300
+ puts 'TODO'
301
+ end
302
+
303
+ # One of the node names has changed (name, manufacturer, product).
304
+ def notification_NodeNaming(nodeId, byte, value)
305
+ puts 'TODO'
306
+ end
307
+
308
+ # A node has triggered an event. This is commonly caused when a node
309
+ # sends a Basic_Set command to the controller. The event value is
310
+ # stored in the notification.
311
+ def notification_NodeEvent(nodeId, byte, value)
312
+ puts 'TODO'
313
+ end
314
+
315
+ # Polling of a node has been successfully turned off by a call
316
+ # to Manager::DisablePoll
317
+ def notification_PollingDisabled(nodeId, byte, value)
318
+ puts 'TODO'
319
+ end
320
+
321
+ # Polling of a node has been successfully turned on by a call
322
+ # to Manager::EnablePoll
323
+ def notification_PollingEnabled(nodeId, byte, value)
324
+ puts 'TODO'
325
+ end
326
+
327
+ # A driver for a PC Z-Wave controller has been added and is ready
328
+ # to use. The notification will contain the controller's Home ID,
329
+ # which is needed to call most of the Manager methods.
330
+ def notification_DriverReady(nodeId, byte, value)
331
+ puts 'TODO'
332
+ end
333
+
334
+ # Driver failed to load */
335
+ def notification_DriverFailed(nodeId, byte, value)
336
+ puts 'TODO'
337
+ end
338
+
339
+ # All nodes and values for this driver have been removed.
340
+ # This is sent instead of potentially hundreds of individual node
341
+ # and value notifications.
342
+ def notification_DriverReset(nodeId, byte, value)
343
+ puts 'TODO'
344
+ end
345
+
346
+ # The last message that was sent is now complete.
347
+ def notification_MsgComplete(nodeId, byte, value)
348
+ puts 'TODO'
349
+ end
350
+
351
+ # The queries on a node that are essential to its operation have
352
+ # been completed. The node can now handle incoming messages.
353
+ def notification_EssentialNodeQueriesComplete(nodeId, byte, value)
354
+ #OpenZWave::RefreshedNodes[nodeId] = true
355
+ end
356
+
357
+ # All the initialisation queries on a node have been completed.
358
+ def notification_NodeQueriesComplete(nodeId, byte, value)
359
+ # node monitor phase 2:
360
+ =begin
361
+ @ValueMonitorMutex.synchronize do
362
+ sleep(2)
363
+ AnsibleValue[:_nodeId => nodeId].each { |val|
364
+ val.get()
365
+ }
366
+ # all values now should be fresh
367
+ @ValueMonitors[nodeId] = false
368
+ fire_callback(:onMonitorStop)
369
+ puts "==> trigger change monitor ENDED<=="
370
+ end
371
+ =end
372
+ end
373
+
374
+ # All awake nodes have been queried, so client application can
375
+ # expected complete data for these nodes.
376
+ def notification_AwakeNodesQueried(nodeId, byte, value)
377
+ puts 'TODO'
378
+ end
379
+
380
+ # All nodes have been queried, so client application can
381
+ # expect complete data.
382
+ def notification_AllNodesQueried(nodeId, byte, value) #
383
+ puts 'TODO'
384
+ end
385
+
386
+ # ------------------------------
387
+ # CONTROLLER STATE NOTIFICATIONS
388
+ # ------------------------------
389
+
390
+ # handle controller state notifications
391
+ def controller_state(idx)
392
+ puts OpenZWave::ControllerStates[idx].join(': ')
393
+ end
394
+ =begin
395
+ ControllerCommand_RemoveFailedNode (id=7)
396
+ irb(main):024:0> ZWT.manager.BeginControllerCommand(HomeID, 7, false, 3, 0)
397
+ => true
398
+ irb(main):025:0>
399
+ ------ ZWAVE MESSAGE (2012-02-05 22:43:28 +0200) ------
400
+ ControllerState_InProgress: The controller is communicating with the other device to carry out the command.
401
+
402
+ ------ ZWAVE MESSAGE (2012-02-05 22:43:28 +0200) ------
403
+ ControllerState_Completed: The command has completed successfully.
404
+ =end
405
+ # TODO: remove all AnsibleValues upon completion of
406
+
407
+
408
+ =begin
409
+ DEPRECATED since OZW rev.477
410
+ # Zwave value notification system only informs us about a _manual_
411
+ # operation of a ZWave node using a ValueChanged notification.
412
+ # We need to monitor that node in order to get the actual device status.
413
+ def trigger_value_monitor(nodeId)
414
+ @ValueMonitorMutex.synchronize do
415
+ # define a node monitor proc then spawn a new thread to run it
416
+ unless @ValueMonitors[nodeId] then
417
+ puts "==> spawning trigger change monitor thread for #{nodeId}<=="
418
+ fire_callback(:onMonitorStart)
419
+ AnsibleValue[:_nodeId => nodeId].each { |val|
420
+ manager_send(:RefreshValue, val)
421
+ }
422
+ # node monitor phase 1: request all dynamic node values from OZW
423
+ #manager_send(:RequestNodeDynamic, Ansible::ZWave::HomeID, nodeId)
424
+ # then declare the handler to run upon NodeQueriesComplete notification
425
+ @ValueMonitors[nodeId] = true
426
+ # node monitor phase 2: see notification_NodeQueriesComplete
427
+ end # unless
428
+ end # do
429
+ end
430
+ =end
431
+ end #class
432
+
433
+ end
434
+
435
+ end # module Ansible