rzwaveway 0.0.4 → 0.0.6
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/.gitignore +2 -0
- data/Gemfile +5 -0
- data/README.md +27 -4
- data/lib/rzwaveway/command_class.rb +29 -0
- data/lib/rzwaveway/command_classes/battery.rb +33 -0
- data/lib/rzwaveway/command_classes/sensor_binary.rb +33 -0
- data/lib/rzwaveway/command_classes/switch_binary.rb +37 -0
- data/lib/rzwaveway/command_classes/switch_multi_level.rb +37 -0
- data/lib/rzwaveway/command_classes/wake_up.rb +41 -0
- data/lib/rzwaveway/command_classes.rb +32 -69
- data/lib/rzwaveway/events.rb +28 -3
- data/lib/rzwaveway/extensions/fibaro_smoke_sensor.rb +11 -0
- data/lib/rzwaveway/extensions/ssa_siren_strobe_alarm.rb +53 -0
- data/lib/rzwaveway/extensions.rb +2 -0
- data/lib/rzwaveway/version.rb +3 -0
- data/lib/rzwaveway/zwave_device.rb +118 -22
- data/lib/rzwaveway/zway.rb +159 -47
- data/lib/rzwaveway.rb +2 -1
- data/rzwaveway.gemspec +12 -6
- data/spec/command_classes/battery_spec.rb +44 -0
- data/spec/command_classes/sensor_binary_spec.rb +42 -0
- data/spec/command_classes/switch_binary_spec.rb +42 -0
- data/spec/command_classes/switch_multi_level_spec.rb +42 -0
- data/spec/command_classes/wake_up_spec.rb +45 -0
- data/spec/data/battery_get.txt +73 -0
- data/spec/data/sensor_level.txt +24 -0
- data/spec/data/switch_multi_level_get.txt +24 -0
- data/spec/data/wake_up.txt +45 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/zwave_device_spec.rb +217 -0
- data/spec/zway_spec.rb +31 -0
- metadata +77 -7
@@ -2,59 +2,142 @@ require 'json'
|
|
2
2
|
|
3
3
|
module RZWaveWay
|
4
4
|
class ZWaveDevice
|
5
|
+
include CommandClass
|
5
6
|
include CommandClasses
|
6
7
|
|
8
|
+
attr_reader :name
|
7
9
|
attr_reader :id
|
10
|
+
attr_reader :last_contact_time
|
11
|
+
attr_accessor :contact_frequency
|
8
12
|
|
9
13
|
def initialize(id, data)
|
10
14
|
@id = id
|
11
|
-
|
12
|
-
$log.info "Created ZWaveDevice with id='#{id}'"
|
15
|
+
initialize_from data
|
16
|
+
$log.info "Created ZWaveDevice with name='#{name}' (id='#{id}')"
|
13
17
|
end
|
14
18
|
|
15
|
-
def
|
16
|
-
|
17
|
-
data['instances']['0']['commandClasses'].each do |cc_id, sub_tree|
|
18
|
-
cc_classes[cc_id.to_i] = CommandClass.new(cc_id.to_i, sub_tree)
|
19
|
-
end
|
20
|
-
cc_classes
|
19
|
+
def contacts_controller_periodically?
|
20
|
+
support_commandclass? CommandClass::WAKEUP
|
21
21
|
end
|
22
22
|
|
23
|
-
def
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
23
|
+
def next_contact_time
|
24
|
+
@last_contact_time + (@contact_frequency * (1 + @missed_contact_count) * 1.1)
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_json
|
28
|
+
attributes = {
|
29
|
+
'name' => @name,
|
30
|
+
'deviceId' => @id,
|
31
|
+
# TODO remove these obsolete attributes (kept for backward compatibility)
|
32
|
+
'lastSleepTime' => @last_contact_time,
|
33
|
+
'lastWakeUpTime' => @last_contact_time,
|
34
|
+
'wakeUpInterval' => @contact_frequency
|
35
|
+
# ---
|
36
|
+
# 'lastContactTime' => @last_contact_time,
|
37
|
+
# 'contactFrequency' => @contact_frequency,
|
38
|
+
# 'properties' => @properties.to_json
|
39
|
+
}
|
40
|
+
attributes.to_json
|
29
41
|
end
|
30
42
|
|
31
|
-
def support_commandclass?
|
32
|
-
@command_classes.has_key?
|
43
|
+
def support_commandclass?(command_class_id)
|
44
|
+
@command_classes.has_key? command_class_id
|
33
45
|
end
|
34
46
|
|
35
47
|
def process updates
|
36
48
|
events = []
|
37
|
-
updates_per_commandclass =
|
49
|
+
updates_per_commandclass = group_per_commandclass updates
|
38
50
|
updates_per_commandclass.each do |cc, values|
|
39
51
|
if @command_classes.has_key? cc
|
40
|
-
event = @command_classes[cc].process(values
|
52
|
+
event = @command_classes[cc].process(values)
|
41
53
|
events << event if event
|
42
54
|
else
|
43
55
|
$log.warn "Could not find command class: '#{cc}'"
|
44
56
|
end
|
45
57
|
end
|
58
|
+
process_device_data(updates, events)
|
46
59
|
events
|
47
60
|
end
|
48
61
|
|
49
62
|
def process_alive_check
|
50
|
-
if
|
51
|
-
|
63
|
+
return if @dead
|
64
|
+
if @contact_frequency > 0
|
65
|
+
current_time = Time.now.to_i
|
66
|
+
delta = current_time - next_contact_time
|
67
|
+
if delta > 0
|
68
|
+
count = ((current_time - @last_contact_time) / @contact_frequency).to_i
|
69
|
+
if count > MAXIMUM_MISSED_CONTACT
|
70
|
+
@dead = true
|
71
|
+
DeadEvent.new(@id)
|
72
|
+
elsif count > @missed_contact_count
|
73
|
+
@missed_contact_count = count
|
74
|
+
NotAliveEvent.new(@id, delta, count)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def notify_contacted(time)
|
81
|
+
if time.to_i > @last_contact_time
|
82
|
+
@dead = false
|
83
|
+
@last_contact_time = time.to_i
|
84
|
+
@missed_contact_count = 0
|
85
|
+
true
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def add_property(name, value, updateTime)
|
90
|
+
@properties[name] = [value, updateTime]
|
91
|
+
end
|
92
|
+
|
93
|
+
def get_property(name)
|
94
|
+
@properties[name].dup
|
95
|
+
end
|
96
|
+
|
97
|
+
def update_property(name, value, updateTime)
|
98
|
+
if @properties.has_key?(name)
|
99
|
+
property = @properties[name]
|
100
|
+
if property[0] != value || property[1] < updateTime
|
101
|
+
property[0] = value
|
102
|
+
property[1] = updateTime
|
103
|
+
true
|
104
|
+
end
|
52
105
|
end
|
53
106
|
end
|
54
107
|
|
55
108
|
private
|
56
109
|
|
110
|
+
MAXIMUM_MISSED_CONTACT = 10
|
111
|
+
|
112
|
+
def create_commandclasses_from data
|
113
|
+
cc_classes = {}
|
114
|
+
data['instances']['0']['commandClasses'].each do |id, sub_tree|
|
115
|
+
cc_id = id.to_i
|
116
|
+
cc_class = CommandClasses::Factory.instance.instantiate(cc_id, sub_tree, self)
|
117
|
+
cc_classes[cc_id] = cc_class
|
118
|
+
cc_class_name = cc_class.class.name.split('::').last
|
119
|
+
(class << self; self end).send(:define_method, cc_class_name) { cc_class } unless cc_class_name == 'Dummy'
|
120
|
+
end
|
121
|
+
cc_classes
|
122
|
+
end
|
123
|
+
|
124
|
+
def initialize_from data
|
125
|
+
@name = find('data.givenName.value', data)
|
126
|
+
last_contact_times = [
|
127
|
+
find('data.lastReceived.updateTime', data),
|
128
|
+
find('data.lastSend.updateTime', data)
|
129
|
+
]
|
130
|
+
@last_contact_time = last_contact_times.max
|
131
|
+
|
132
|
+
@dead = false
|
133
|
+
@missed_contact_count = 0
|
134
|
+
@contact_frequency = 0
|
135
|
+
@properties = {}
|
136
|
+
@command_classes = create_commandclasses_from data
|
137
|
+
end
|
138
|
+
|
57
139
|
def group_per_commandclass updates
|
140
|
+
other_updates = {}
|
58
141
|
updates_per_commandclass = {}
|
59
142
|
updates.each do | key, value |
|
60
143
|
match_data = key.match(/\Ainstances.0.commandClasses.(\d+)./)
|
@@ -63,10 +146,23 @@ module RZWaveWay
|
|
63
146
|
updates_per_commandclass[command_class] = {} unless updates_per_commandclass.has_key?(command_class)
|
64
147
|
updates_per_commandclass[command_class][match_data.post_match] = value
|
65
148
|
else
|
66
|
-
|
149
|
+
other_updates[key] = value
|
67
150
|
end
|
68
151
|
end
|
152
|
+
updates.clear
|
153
|
+
updates.merge!(other_updates)
|
69
154
|
updates_per_commandclass
|
70
155
|
end
|
156
|
+
|
157
|
+
def process_device_data(updates, events)
|
158
|
+
times = []
|
159
|
+
updates.each do | key, value |
|
160
|
+
if key == 'data.lastReceived' || key == 'data.lastSend'
|
161
|
+
times << value['updateTime']
|
162
|
+
end
|
163
|
+
end
|
164
|
+
time = times.max
|
165
|
+
events << AliveEvent.new(@id, time) if notify_contacted(time)
|
166
|
+
end
|
71
167
|
end
|
72
|
-
end
|
168
|
+
end
|
data/lib/rzwaveway/zway.rb
CHANGED
@@ -1,38 +1,121 @@
|
|
1
|
-
require '
|
1
|
+
require 'singleton'
|
2
|
+
|
3
|
+
require 'faraday'
|
2
4
|
require 'log4r'
|
3
5
|
require 'json'
|
4
6
|
|
5
7
|
module RZWaveWay
|
6
|
-
|
7
|
-
|
8
|
+
class ZWay
|
9
|
+
include Singleton
|
8
10
|
include Log4r
|
9
11
|
|
10
|
-
|
12
|
+
attr_reader :devices
|
11
13
|
|
12
|
-
def
|
14
|
+
def initialize
|
13
15
|
$log = Logger.new 'RZWaveWay'
|
16
|
+
formatter = PatternFormatter.new(:pattern => "[%l] %d - %m")
|
14
17
|
outputter = Outputter.stdout
|
15
|
-
outputter.formatter =
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
outputter.formatter = formatter
|
19
|
+
outputter.level = Log4r::INFO
|
20
|
+
file_outputter = RollingFileOutputter.new('file', filename: 'rzwaveway.log', maxsize: 1048576, trunc: 86400)
|
21
|
+
file_outputter.formatter = formatter
|
22
|
+
file_outputter.level = Log4r::DEBUG
|
23
|
+
$log.outputters = [Outputter.stdout, file_outputter]
|
24
|
+
end
|
25
|
+
|
26
|
+
def execute(device_id, command_class, command_class_function, argument = nil)
|
27
|
+
raise "No device with id '#{device_id}'" unless @devices.has_key?(device_id)
|
28
|
+
raise "Device with id '#{device_id}' does not support command class '#{command_class}'" unless @devices[device_id].support_commandclass?(command_class)
|
29
|
+
function_name = command_class_function.to_s
|
30
|
+
run_zway_function(device_id, command_class, function_name, argument)
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_extension(name, device_id)
|
34
|
+
device = @devices[device_id.to_i]
|
35
|
+
raise ArgumentError, "No device with id '#{device_id}'" unless device
|
36
|
+
clazz = qualified_const_get "RZWaveWay::Extensions::#{name}"
|
37
|
+
clazz.new(device)
|
38
|
+
end
|
39
|
+
|
40
|
+
def setup(hostname, *adapter_params)
|
41
|
+
adapter_params = :httpclient if adapter_params.compact.empty?
|
21
42
|
@base_uri="http://#{hostname}:8083"
|
43
|
+
@connection = Faraday.new {|faraday| faraday.adapter *adapter_params}
|
22
44
|
end
|
23
45
|
|
24
|
-
def
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
46
|
+
def start
|
47
|
+
@devices = {}
|
48
|
+
@event_handlers = {}
|
49
|
+
@update_time = '0'
|
50
|
+
loop do
|
51
|
+
results = get_zway_data_tree_updates
|
52
|
+
if results.has_key?('devices')
|
53
|
+
results['devices'].each {|device_id,device_data_tree| create_device(device_id.to_i, device_data_tree)}
|
54
|
+
break
|
55
|
+
else
|
56
|
+
sleep 1.0
|
57
|
+
$log.warn 'No devices found at start-up, retrying'
|
58
|
+
end
|
29
59
|
end
|
30
|
-
|
60
|
+
end
|
61
|
+
|
62
|
+
def on_event(event, &listener)
|
63
|
+
@event_handlers[event] = listener
|
31
64
|
end
|
32
65
|
|
33
66
|
def process_events
|
67
|
+
check_devices
|
68
|
+
updates = get_zway_data_tree_updates
|
69
|
+
events = devices_process updates
|
70
|
+
check_not_alive_devices(events)
|
71
|
+
deliver_to_handlers(events)
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
DATA_TREE_BASE_PATH='/ZWaveAPI/Data/'
|
77
|
+
RUN_BASE_PATH='/ZWaveAPI/Run/'
|
78
|
+
|
79
|
+
def check_devices
|
80
|
+
@devices.values.each do |device|
|
81
|
+
unless device.contacts_controller_periodically?
|
82
|
+
current_time = Time.now.to_i
|
83
|
+
# TODO ensure last_contact_time is set in the device initializer
|
84
|
+
if (current_time % 10 == 0) && (current_time > device.next_contact_time - 60)
|
85
|
+
run_zway_no_operation device.id
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def check_not_alive_devices(events)
|
92
|
+
@devices.values.each do |device|
|
93
|
+
event = device.process_alive_check
|
94
|
+
events << event if event
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def create_device(device_id, device_data_tree)
|
99
|
+
if device_id > 1
|
100
|
+
device = ZWaveDevice.new(device_id, device_data_tree)
|
101
|
+
device.contact_frequency = 300 unless device.contacts_controller_periodically?
|
102
|
+
@devices[device_id] = device
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def deliver_to_handlers events
|
107
|
+
events.each do |event|
|
108
|
+
handler = @event_handlers[event.class]
|
109
|
+
if handler
|
110
|
+
handler.call(event)
|
111
|
+
else
|
112
|
+
$log.warn "No event handler for #{event.class}"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def devices_process updates
|
34
118
|
events = []
|
35
|
-
updates = http_post_request
|
36
119
|
updates_per_device = group_per_device updates
|
37
120
|
updates_per_device.each do | id, updates |
|
38
121
|
if @devices[id]
|
@@ -42,16 +125,6 @@ module RZWaveWay
|
|
42
125
|
$log.warn "Could not find device with id '#{id}'"
|
43
126
|
end
|
44
127
|
end
|
45
|
-
alive_events = check_not_alive_devices
|
46
|
-
events += alive_events unless alive_events.empty?
|
47
|
-
events.each do |event|
|
48
|
-
handler = @event_handlers[event.class]
|
49
|
-
if handler
|
50
|
-
handler.call(event)
|
51
|
-
else
|
52
|
-
$log.warn "no handler for #{event.class}"
|
53
|
-
end
|
54
|
-
end
|
55
128
|
events
|
56
129
|
end
|
57
130
|
|
@@ -64,36 +137,75 @@ module RZWaveWay
|
|
64
137
|
updates_per_device[device_id] = {} unless(updates_per_device.has_key?(device_id))
|
65
138
|
updates_per_device[device_id][match_data.post_match] = value
|
66
139
|
else
|
67
|
-
$log.
|
140
|
+
$log.debug "No device group match for key='#{key}'"
|
68
141
|
end
|
69
142
|
end
|
70
143
|
updates_per_device
|
71
144
|
end
|
72
145
|
|
73
|
-
def
|
74
|
-
|
75
|
-
@
|
76
|
-
|
77
|
-
|
146
|
+
def get_zway_data_tree_updates
|
147
|
+
results = {}
|
148
|
+
url = @base_uri + DATA_TREE_BASE_PATH + "#{@update_time}"
|
149
|
+
begin
|
150
|
+
response = @connection.get(url)
|
151
|
+
if response.success?
|
152
|
+
results = JSON.parse response.body
|
153
|
+
@update_time = results.delete('updateTime')
|
154
|
+
else
|
155
|
+
$log.error(response.reason)
|
156
|
+
end
|
157
|
+
rescue StandardError => e
|
158
|
+
$log.error("Failed to communicate with ZWay HTTP server: #{e}")
|
78
159
|
end
|
79
|
-
|
160
|
+
results
|
80
161
|
end
|
81
162
|
|
82
|
-
def
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
@update_time = results.delete("updateTime")
|
163
|
+
def qualified_const_get(str)
|
164
|
+
path = str.to_s.split('::')
|
165
|
+
from_root = path[0].empty?
|
166
|
+
if from_root
|
167
|
+
from_root = []
|
168
|
+
path = path[1..-1]
|
89
169
|
else
|
90
|
-
|
170
|
+
start_ns = ((Class === self)||(Module === self)) ? self : self.class
|
171
|
+
from_root = start_ns.to_s.split('::')
|
91
172
|
end
|
92
|
-
|
173
|
+
until from_root.empty?
|
174
|
+
begin
|
175
|
+
return (from_root+path).inject(Object) { |ns,name| ns.const_get(name) }
|
176
|
+
rescue NameError
|
177
|
+
from_root.delete_at(-1)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
path.inject(Object) { |ns,name| ns.const_get(name) }
|
93
181
|
end
|
94
182
|
|
95
|
-
def
|
96
|
-
|
183
|
+
def run_zway_function(device_id, command_class, function_name, argument)
|
184
|
+
command_path = "devices[#{device_id}].instances[0].commandClasses[#{command_class}]."
|
185
|
+
if argument
|
186
|
+
command_path += "#{function_name}(#{argument})"
|
187
|
+
else
|
188
|
+
command_path += "#{function_name}()"
|
189
|
+
end
|
190
|
+
run_zway command_path
|
191
|
+
end
|
192
|
+
|
193
|
+
def run_zway_no_operation device_id
|
194
|
+
run_zway "devices[#{device_id}].SendNoOperation()"
|
195
|
+
end
|
196
|
+
|
197
|
+
def run_zway command_path
|
198
|
+
begin
|
199
|
+
uri = URI.encode(@base_uri + RUN_BASE_PATH + command_path, '[]')
|
200
|
+
response = @connection.get(uri)
|
201
|
+
unless response.success?
|
202
|
+
$log.error(response.status)
|
203
|
+
$log.error(response.body)
|
204
|
+
end
|
205
|
+
rescue StandardError => e
|
206
|
+
$log.error("Failed to communicate with ZWay HTTP server: #{e}")
|
207
|
+
$log.error(e.backtrace)
|
208
|
+
end
|
97
209
|
end
|
98
210
|
end
|
99
|
-
end
|
211
|
+
end
|
data/lib/rzwaveway.rb
CHANGED
data/rzwaveway.gemspec
CHANGED
@@ -1,18 +1,24 @@
|
|
1
|
+
$LOAD_PATH.unshift 'lib'
|
2
|
+
require 'rzwaveway/version'
|
3
|
+
|
1
4
|
Gem::Specification.new do |s|
|
2
|
-
s.name =
|
3
|
-
s.version =
|
4
|
-
s.authors = [
|
5
|
+
s.name = 'rzwaveway'
|
6
|
+
s.version = RZWaveWay::VERSION
|
7
|
+
s.authors = ['Vincent Touchard']
|
5
8
|
s.date = %q{2014-02-18}
|
6
9
|
s.summary = 'ZWave API for ZWay'
|
7
10
|
s.description = 'A Ruby API to use the Razberry ZWave ZWay interface'
|
8
|
-
s.email = '
|
11
|
+
s.email = 'touchardv@yahoo.com'
|
9
12
|
s.homepage = 'https://github.com/touchardv/rzwaveway'
|
10
13
|
s.files = `git ls-files`.split("\n")
|
11
14
|
s.has_rdoc = false
|
12
15
|
|
13
16
|
dependencies = [
|
14
|
-
[:runtime,
|
15
|
-
[:runtime,
|
17
|
+
[:runtime, 'log4r', '~> 1.1.10'],
|
18
|
+
[:runtime, 'faraday'],
|
19
|
+
[:runtime, 'httpclient'],
|
20
|
+
[:development, 'bundler', '~> 1.0'],
|
21
|
+
[:development, 'rspec', '~> 3.0.0']
|
16
22
|
]
|
17
23
|
|
18
24
|
dependencies.each do |type, name, version|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RZWaveWay
|
4
|
+
module CommandClasses
|
5
|
+
describe Battery do
|
6
|
+
let(:device) { ZWaveDevice.new(create_id, create_device_data) }
|
7
|
+
let(:command_class) do
|
8
|
+
Battery.new(
|
9
|
+
{'data' => { 'last' => {
|
10
|
+
'value' => 60,
|
11
|
+
'type' => 'int',
|
12
|
+
'updateTime' => 1409681662
|
13
|
+
}}}, device)
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#new' do
|
17
|
+
it 'stores interesting properties' do
|
18
|
+
command_class
|
19
|
+
expect(device.get_property(:battery_level)).to eq [60, 1409681662]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#process' do
|
24
|
+
it 'does nothing when it processes no updates' do
|
25
|
+
expect(command_class.process({})).to be_nil
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns a battery event' do
|
29
|
+
updates = {
|
30
|
+
'data.last' => {
|
31
|
+
'value' => 50,
|
32
|
+
'type' => 'int',
|
33
|
+
'updateTime' => 1409681762
|
34
|
+
}}
|
35
|
+
event = command_class.process(updates)
|
36
|
+
expect(event.class).to be RZWaveWay::BatteryValueEvent
|
37
|
+
expect(event.value).to eq 50
|
38
|
+
expect(event.device_id).to eq device.id
|
39
|
+
expect(event.time).to eq 1409681762
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RZWaveWay
|
4
|
+
module CommandClasses
|
5
|
+
describe SensorBinary do
|
6
|
+
let(:device) { ZWaveDevice.new(create_id, create_device_data) }
|
7
|
+
let(:command_class) do
|
8
|
+
SensorBinary.new(
|
9
|
+
{'data' => { '1' => { 'level' => {
|
10
|
+
'value' => false,
|
11
|
+
'updateTime' => 1405102560
|
12
|
+
}}}}, device)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#new' do
|
16
|
+
it 'stores interesting properties' do
|
17
|
+
command_class
|
18
|
+
expect(device.get_property(:level)).to eq [false, 1405102560]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#process' do
|
23
|
+
it 'does nothing when it processes no updates' do
|
24
|
+
expect(command_class.process({})).to be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns a level event' do
|
28
|
+
updates = {
|
29
|
+
'data.1' => { 'level' => {
|
30
|
+
'value' => true,
|
31
|
+
'updateTime' => 1405102860
|
32
|
+
}}}
|
33
|
+
event = command_class.process(updates)
|
34
|
+
expect(event.class).to be RZWaveWay::LevelEvent
|
35
|
+
expect(event.level).to eq true
|
36
|
+
expect(event.device_id).to eq device.id
|
37
|
+
expect(event.time).to eq 1405102860
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RZWaveWay
|
4
|
+
module CommandClasses
|
5
|
+
describe SwitchBinary do
|
6
|
+
let(:device) { ZWaveDevice.new(create_id, create_device_data) }
|
7
|
+
let(:command_class) do
|
8
|
+
SwitchBinary.new(
|
9
|
+
{'data' => { 'level' => {
|
10
|
+
'value' => false,
|
11
|
+
'updateTime' => 1405102560
|
12
|
+
}}}, device)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#it caches the level' do
|
16
|
+
it 'stores interesting properties' do
|
17
|
+
command_class
|
18
|
+
expect(device.get_property(:level)).to eq [false, 1405102560]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#process' do
|
23
|
+
it 'does nothing when it processes no updates' do
|
24
|
+
expect(command_class.process({})).to be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns a multi level event' do
|
28
|
+
updates = {
|
29
|
+
'data.level' => {
|
30
|
+
'value' => true,
|
31
|
+
'updateTime' => 1405102860
|
32
|
+
}}
|
33
|
+
event = command_class.process(updates)
|
34
|
+
expect(event.class).to be RZWaveWay::LevelEvent
|
35
|
+
expect(event.level).to eq true
|
36
|
+
expect(event.device_id).to eq device.id
|
37
|
+
expect(event.time).to eq 1405102860
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RZWaveWay
|
4
|
+
module CommandClasses
|
5
|
+
describe SwitchMultiLevel do
|
6
|
+
let(:device) { ZWaveDevice.new(create_id, create_device_data) }
|
7
|
+
let(:command_class) do
|
8
|
+
SwitchMultiLevel.new(
|
9
|
+
{'data' => { 'level' => {
|
10
|
+
'value' => 33,
|
11
|
+
'updateTime' => 1405102560
|
12
|
+
}}}, device)
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '#new' do
|
16
|
+
it 'stores interesting properties' do
|
17
|
+
command_class
|
18
|
+
expect(device.get_property(:level)).to eq [33, 1405102560]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe '#process' do
|
23
|
+
it 'does nothing when it processes no updates' do
|
24
|
+
expect(command_class.process({})).to be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'returns a multi level event' do
|
28
|
+
updates = {
|
29
|
+
'data.level' => {
|
30
|
+
'value' => 66,
|
31
|
+
'updateTime' => 1405102860
|
32
|
+
}}
|
33
|
+
event = command_class.process(updates)
|
34
|
+
expect(event.class).to be RZWaveWay::MultiLevelEvent
|
35
|
+
expect(event.level).to eq 66
|
36
|
+
expect(event.device_id).to eq device.id
|
37
|
+
expect(event.time).to eq 1405102860
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|