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.
- data/lib/ansible.rb +47 -0
- data/lib/ansible/ansible_callback.rb +142 -0
- data/lib/ansible/ansible_device.rb +68 -0
- data/lib/ansible/ansible_value.rb +179 -0
- data/lib/ansible/config.rb +92 -0
- data/lib/ansible/devices/ansible_dimmer.rb +80 -0
- data/lib/ansible/devices/ansible_switch.rb +66 -0
- data/lib/ansible/knx/EIBConnection.rb +2371 -0
- data/lib/ansible/knx/dpt/canonical_1bit.rb +54 -0
- data/lib/ansible/knx/dpt/dpt1.rb +224 -0
- data/lib/ansible/knx/dpt/dpt10.rb +85 -0
- data/lib/ansible/knx/dpt/dpt11.rb +72 -0
- data/lib/ansible/knx/dpt/dpt12.rb +61 -0
- data/lib/ansible/knx/dpt/dpt13.rb +100 -0
- data/lib/ansible/knx/dpt/dpt14.rb +87 -0
- data/lib/ansible/knx/dpt/dpt15.rb +72 -0
- data/lib/ansible/knx/dpt/dpt16.rb +67 -0
- data/lib/ansible/knx/dpt/dpt17.rb +65 -0
- data/lib/ansible/knx/dpt/dpt18.rb +66 -0
- data/lib/ansible/knx/dpt/dpt19.rb +100 -0
- data/lib/ansible/knx/dpt/dpt2.rb +156 -0
- data/lib/ansible/knx/dpt/dpt3.rb +104 -0
- data/lib/ansible/knx/dpt/dpt4.rb +75 -0
- data/lib/ansible/knx/dpt/dpt5.rb +124 -0
- data/lib/ansible/knx/dpt/dpt6.rb +73 -0
- data/lib/ansible/knx/dpt/dpt7.rb +146 -0
- data/lib/ansible/knx/dpt/dpt8.rb +118 -0
- data/lib/ansible/knx/dpt/dpt9.rb +204 -0
- data/lib/ansible/knx/dpt/tests/test_dpt10.rb +45 -0
- data/lib/ansible/knx/dpt/tests/test_dpt9.rb +60 -0
- data/lib/ansible/knx/hexdump.rb +113 -0
- data/lib/ansible/knx/knx_dpt.rb +58 -0
- data/lib/ansible/knx/knx_dpt_scalar.rb +62 -0
- data/lib/ansible/knx/knx_eistypes.rb +76 -0
- data/lib/ansible/knx/knx_protocol.rb +99 -0
- data/lib/ansible/knx/knx_scene.rb +48 -0
- data/lib/ansible/knx/knx_tools.rb +76 -0
- data/lib/ansible/knx/knx_transceiver.rb +237 -0
- data/lib/ansible/knx/knx_value.rb +327 -0
- data/lib/ansible/openzwave/ozw_constants.rb +11 -0
- data/lib/ansible/openzwave/ozw_headers.rb +80 -0
- data/lib/ansible/openzwave/ozw_remote_manager.rb +7615 -0
- data/lib/ansible/openzwave/ozw_types.rb +406 -0
- data/lib/ansible/orbiter_proxy.rb +12 -0
- data/lib/ansible/transceiver.rb +63 -0
- data/lib/ansible/zwave/types/valuetype_bool.rb +74 -0
- data/lib/ansible/zwave/types/valuetype_button.rb +63 -0
- data/lib/ansible/zwave/types/valuetype_byte.rb +78 -0
- data/lib/ansible/zwave/types/valuetype_decimal.rb +64 -0
- data/lib/ansible/zwave/types/valuetype_int.rb +63 -0
- data/lib/ansible/zwave/types/valuetype_list.rb +64 -0
- data/lib/ansible/zwave/types/valuetype_short.rb +63 -0
- data/lib/ansible/zwave/types/valuetype_string.rb +61 -0
- data/lib/ansible/zwave/zwave_command_classes.rb +113 -0
- data/lib/ansible/zwave/zwave_node.rb +5 -0
- data/lib/ansible/zwave/zwave_protocol.rb +52 -0
- data/lib/ansible/zwave/zwave_transceiver.rb +435 -0
- data/lib/ansible/zwave/zwave_value.rb +193 -0
- 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,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
|