ansible4ozw 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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