rzwaveway 0.0.11 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +4 -4
- data/lib/rzwaveway.rb +3 -1
- data/lib/rzwaveway/command_class.rb +21 -10
- data/lib/rzwaveway/command_classes.rb +25 -11
- data/lib/rzwaveway/command_classes/alarm.rb +43 -0
- data/lib/rzwaveway/command_classes/alarm_sensor.rb +17 -0
- data/lib/rzwaveway/command_classes/battery.rb +8 -12
- data/lib/rzwaveway/command_classes/sensor_binary.rb +8 -16
- data/lib/rzwaveway/command_classes/switch_binary.rb +10 -19
- data/lib/rzwaveway/command_classes/switch_multi_level.rb +10 -19
- data/lib/rzwaveway/command_classes/wake_up.rb +23 -26
- data/lib/rzwaveway/events.rb +15 -63
- data/lib/rzwaveway/extensions/ssa_siren_strobe_alarm.rb +1 -6
- data/lib/rzwaveway/properties_cache.rb +38 -0
- data/lib/rzwaveway/property.rb +47 -0
- data/lib/rzwaveway/version.rb +1 -1
- data/lib/rzwaveway/zwave_device.rb +77 -82
- data/lib/rzwaveway/zway.rb +54 -48
- data/rzwaveway.gemspec +2 -1
- data/spec/command_classes/alarm_spec.rb +37 -0
- data/spec/command_classes/battery_spec.rb +16 -14
- data/spec/command_classes/sensor_binary_spec.rb +15 -13
- data/spec/command_classes/switch_binary_spec.rb +15 -13
- data/spec/command_classes/switch_multi_level_spec.rb +15 -13
- data/spec/command_classes/wake_up_spec.rb +59 -20
- data/spec/data/alarm.json +69 -0
- data/spec/data/alarm_v1.json +69 -0
- data/spec/events_spec.rb +27 -0
- data/spec/property_spec.rb +83 -0
- data/spec/spec_helper.rb +13 -2
- data/spec/zwave_device_spec.rb +12 -149
- metadata +25 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6f5e0b677ce1728466c714be10191c2fea92bc97
|
4
|
+
data.tar.gz: b07f33865fb9ac752453ef12efcccfa3f206d120
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e0043ffd5ae35ceaaea940771f828e1662256d9a145ae9440dcd7d53a03f4ce604ec5a7ebdfc7ec09855062bdbb24729865638f95f7c56d665a56341aec8dba5
|
7
|
+
data.tar.gz: b9d79401b008fe87b9ba484602fe4c7c7f3027d7dcc7ae210c328cb7fa6ebca8e29f632b27ec0dce053cc909283116652920c231230436e8ae8d0b23f34427c5
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ A Ruby library for communicating with the ZWave protocol stack from ZWay, runnin
|
|
10
10
|
require 'rzwaveway'
|
11
11
|
|
12
12
|
z_way = RZWaveWay::ZWay.instance
|
13
|
-
z_way.setup('192.168.1.123')
|
13
|
+
z_way.setup(hostname: '192.168.1.123', port: 8083)
|
14
14
|
z_way.start
|
15
15
|
```
|
16
16
|
|
@@ -27,7 +27,7 @@ z_way.on_event(RZWaveWay::AliveEvent) {|event| puts "A device woke up" }
|
|
27
27
|
z_way.on_event(RZWaveWay::LevelEvent) {|event| puts "A device got triggered" }
|
28
28
|
while true do
|
29
29
|
sleep 5
|
30
|
-
z_way.
|
30
|
+
z_way.process
|
31
31
|
end
|
32
32
|
```
|
33
33
|
|
@@ -40,6 +40,6 @@ or
|
|
40
40
|
|
41
41
|
```
|
42
42
|
switch = z_way.devices[4]
|
43
|
-
switch.SwitchBinary.
|
44
|
-
switch.SwitchBinary.
|
43
|
+
switch.SwitchBinary.level = 1
|
44
|
+
switch.SwitchBinary.level = 0
|
45
45
|
```
|
data/lib/rzwaveway.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
require_relative 'rzwaveway/logger'
|
2
|
+
require_relative 'rzwaveway/property'
|
3
|
+
require_relative 'rzwaveway/properties_cache'
|
1
4
|
require_relative 'rzwaveway/command_classes'
|
2
5
|
require_relative 'rzwaveway/events'
|
3
|
-
require_relative 'rzwaveway/logger'
|
4
6
|
require_relative 'rzwaveway/zwave_device'
|
5
7
|
require_relative 'rzwaveway/zway'
|
6
8
|
require_relative 'rzwaveway/extensions'
|
@@ -1,29 +1,40 @@
|
|
1
1
|
module RZWaveWay
|
2
|
-
|
2
|
+
class CommandClass
|
3
|
+
include Logger
|
4
|
+
include PropertiesCache
|
5
|
+
|
3
6
|
BASIC = 32
|
4
7
|
SWITCH_BINARY = 37
|
5
8
|
SWITCH_MULTI_LEVEL = 38
|
6
9
|
SENSOR_BINARY = 48
|
7
10
|
SENSOR_MULTI_LEVEL = 49
|
11
|
+
METER = 50
|
8
12
|
CONFIGURATION = 112
|
9
13
|
ALARM = 113
|
14
|
+
NOTIFICATION = ALARM
|
10
15
|
MANUFACTURER_SPECIFIC = 114
|
11
16
|
BATTERY = 128
|
12
17
|
WAKEUP = 132
|
13
18
|
ASSOCIATION = 133
|
14
19
|
VERSION = 134
|
20
|
+
SECURITY = 152
|
15
21
|
ALARM_SENSOR = 156
|
16
22
|
|
17
|
-
|
23
|
+
attr_reader :device
|
24
|
+
|
25
|
+
def initialize(device)
|
26
|
+
@device = device
|
27
|
+
end
|
28
|
+
|
29
|
+
def build_from(data)
|
30
|
+
end
|
18
31
|
|
19
|
-
def
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
end
|
26
|
-
result
|
32
|
+
def name
|
33
|
+
self.class.name.split('::').last
|
34
|
+
end
|
35
|
+
|
36
|
+
def to_s
|
37
|
+
name
|
27
38
|
end
|
28
39
|
end
|
29
40
|
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'singleton'
|
2
2
|
|
3
3
|
require_relative 'command_class'
|
4
|
+
require_relative 'command_classes/alarm'
|
5
|
+
require_relative 'command_classes/alarm_sensor'
|
4
6
|
require_relative 'command_classes/battery'
|
5
7
|
require_relative 'command_classes/switch_binary'
|
6
8
|
require_relative 'command_classes/switch_multi_level'
|
@@ -9,36 +11,48 @@ require_relative 'command_classes/wake_up'
|
|
9
11
|
|
10
12
|
module RZWaveWay
|
11
13
|
module CommandClasses
|
12
|
-
class
|
14
|
+
class Unsupported
|
13
15
|
include Singleton
|
14
16
|
|
15
|
-
def
|
17
|
+
def build_from(data)
|
16
18
|
end
|
17
19
|
|
18
20
|
def process(updates)
|
19
21
|
end
|
22
|
+
|
23
|
+
def save_properties
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_hash
|
27
|
+
{}
|
28
|
+
end
|
29
|
+
|
30
|
+
def to_s
|
31
|
+
'Unsupported'
|
32
|
+
end
|
20
33
|
end
|
21
34
|
|
22
35
|
class Factory
|
23
36
|
include Singleton
|
24
|
-
include CommandClass
|
25
37
|
|
26
|
-
def instantiate(id,
|
38
|
+
def instantiate(id, device)
|
27
39
|
if CLASSES.has_key? id
|
28
|
-
|
40
|
+
CLASSES[id].new(device)
|
29
41
|
else
|
30
|
-
|
42
|
+
CommandClasses::Unsupported.instance
|
31
43
|
end
|
32
44
|
end
|
33
45
|
|
34
46
|
private
|
35
47
|
|
36
48
|
CLASSES = {
|
37
|
-
SWITCH_BINARY => CommandClasses::SwitchBinary,
|
38
|
-
SWITCH_MULTI_LEVEL => CommandClasses::SwitchMultiLevel,
|
39
|
-
SENSOR_BINARY => CommandClasses::SensorBinary,
|
40
|
-
WAKEUP => CommandClasses::WakeUp,
|
41
|
-
|
49
|
+
CommandClass::SWITCH_BINARY => CommandClasses::SwitchBinary,
|
50
|
+
CommandClass::SWITCH_MULTI_LEVEL => CommandClasses::SwitchMultiLevel,
|
51
|
+
CommandClass::SENSOR_BINARY => CommandClasses::SensorBinary,
|
52
|
+
CommandClass::WAKEUP => CommandClasses::WakeUp,
|
53
|
+
CommandClass::ALARM => CommandClasses::Alarm,
|
54
|
+
CommandClass::ALARM_SENSOR => CommandClasses::AlarmSensor,
|
55
|
+
CommandClass::BATTERY => CommandClasses::Battery
|
42
56
|
}
|
43
57
|
end
|
44
58
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module RZWaveWay
|
2
|
+
module CommandClasses
|
3
|
+
class Alarm < CommandClass
|
4
|
+
|
5
|
+
def process(updates)
|
6
|
+
updates.each do |key, value|
|
7
|
+
if key == 'data.V1event'
|
8
|
+
alarm_type = value['alarmType']['value']
|
9
|
+
yield AlarmEvent.new(device_id: device.id,
|
10
|
+
time: value['updateTime'],
|
11
|
+
alarm_type: ALARM_TYPES[alarm_type],
|
12
|
+
level: value['level']['value'])
|
13
|
+
else
|
14
|
+
match_data = key.match(/^data.(\d+)/)
|
15
|
+
if match_data
|
16
|
+
alarm_type = match_data[1].to_i
|
17
|
+
yield AlarmEvent.new(device_id: device.id,
|
18
|
+
time: value['updateTime'],
|
19
|
+
alarm_type: ALARM_TYPES[alarm_type],
|
20
|
+
level: value['event']['value'])
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
ALARM_TYPES = {
|
29
|
+
0x01 => :smoke,
|
30
|
+
0x02 => :co,
|
31
|
+
0x03 => :co2,
|
32
|
+
0x04 => :heat,
|
33
|
+
0x05 => :water,
|
34
|
+
0x06 => :access_control,
|
35
|
+
0x07 => :burglar,
|
36
|
+
0x08 => :power_management,
|
37
|
+
0x09 => :system,
|
38
|
+
0x0a => :emergency,
|
39
|
+
0x0b => :clock
|
40
|
+
}
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RZWaveWay
|
2
|
+
module CommandClasses
|
3
|
+
class AlarmSensor < CommandClass
|
4
|
+
GENERAL_PURPOSE = 0x00
|
5
|
+
SMOKE = 0x01
|
6
|
+
CO = 0x02
|
7
|
+
CO2 = 0x03
|
8
|
+
HEAT = 0x04
|
9
|
+
WATER_LEAK = 0x05
|
10
|
+
|
11
|
+
def process(updates)
|
12
|
+
log.info updates
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,28 +1,24 @@
|
|
1
1
|
module RZWaveWay
|
2
2
|
module CommandClasses
|
3
|
-
class Battery
|
4
|
-
include CommandClass
|
3
|
+
class Battery < CommandClass
|
5
4
|
|
6
|
-
def
|
7
|
-
|
8
|
-
@device.add_property(name: :battery_level,
|
9
|
-
value: find('data.last.value', data),
|
10
|
-
update_time: find('data.last.updateTime', data))
|
5
|
+
def build_from(data)
|
6
|
+
define_property(:battery_level, 'data.last', true, data)
|
11
7
|
end
|
12
8
|
|
13
9
|
def process(updates)
|
14
10
|
if updates.keys.include?('data.last')
|
15
11
|
data = updates['data.last']
|
16
12
|
value = data['value']
|
17
|
-
|
18
|
-
if @
|
19
|
-
|
13
|
+
update_time = data['updateTime']
|
14
|
+
if @properties[:battery_level].update(value, update_time)
|
15
|
+
yield BatteryValueEvent.new(device_id: device.id, time: update_time, value: value)
|
20
16
|
end
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
24
|
-
def
|
25
|
-
RZWaveWay::ZWay.instance.execute(
|
20
|
+
def refresh
|
21
|
+
RZWaveWay::ZWay.instance.execute(device.id, BATTERY, :Get)
|
26
22
|
end
|
27
23
|
end
|
28
24
|
end
|
@@ -1,32 +1,24 @@
|
|
1
1
|
module RZWaveWay
|
2
2
|
module CommandClasses
|
3
|
-
class SensorBinary
|
4
|
-
include CommandClass
|
3
|
+
class SensorBinary < CommandClass
|
5
4
|
|
6
|
-
def
|
7
|
-
|
8
|
-
@device.add_property(name: :level,
|
9
|
-
value: find('data.1.level.value', data),
|
10
|
-
update_time: find('data.1.level.updateTime', data))
|
5
|
+
def build_from(data)
|
6
|
+
define_property(:level, 'data.1.level', true, data)
|
11
7
|
end
|
12
8
|
|
13
9
|
def process(updates)
|
14
10
|
if updates.keys.include?('data.1')
|
15
11
|
data = updates['data.1']['level']
|
16
12
|
value = data['value']
|
17
|
-
|
18
|
-
if @
|
19
|
-
|
13
|
+
update_time = data['updateTime']
|
14
|
+
if @properties[:level].update(value, update_time)
|
15
|
+
yield LevelEvent.new(device_id: device.id, time: update_time, level: value)
|
20
16
|
end
|
21
17
|
end
|
22
18
|
end
|
23
19
|
|
24
|
-
def
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def get
|
29
|
-
RZWaveWay::ZWay.instance.execute(@device.id, SENSOR_BINARY, :Get)
|
20
|
+
def refresh
|
21
|
+
RZWaveWay::ZWay.instance.execute(device.id, SENSOR_BINARY, :Get)
|
30
22
|
end
|
31
23
|
end
|
32
24
|
end
|
@@ -1,37 +1,28 @@
|
|
1
1
|
module RZWaveWay
|
2
2
|
module CommandClasses
|
3
|
-
class SwitchBinary
|
4
|
-
include CommandClass
|
3
|
+
class SwitchBinary < CommandClass
|
5
4
|
|
6
|
-
def
|
7
|
-
|
8
|
-
@device.add_property(name: :level,
|
9
|
-
value: find('data.level.value', data),
|
10
|
-
update_time: find('data.level.updateTime', data),
|
11
|
-
read_only: false)
|
5
|
+
def build_from(data)
|
6
|
+
define_property(:level, 'data.level', false, data)
|
12
7
|
end
|
13
8
|
|
14
9
|
def process(updates)
|
15
10
|
if updates.keys.include?('data.level')
|
16
11
|
data = updates['data.level']
|
17
12
|
value = data['value']
|
18
|
-
|
19
|
-
if @
|
20
|
-
|
13
|
+
update_time = data['updateTime']
|
14
|
+
if @properties[:level].update(value, update_time)
|
15
|
+
yield LevelEvent.new(device_id: device.id, time: update_time, level: value)
|
21
16
|
end
|
22
17
|
end
|
23
18
|
end
|
24
19
|
|
25
|
-
def level
|
26
|
-
|
20
|
+
def level=(value)
|
21
|
+
RZWaveWay::ZWay.instance.execute(device.id, SWITCH_BINARY, :Set, value)
|
27
22
|
end
|
28
23
|
|
29
|
-
def
|
30
|
-
RZWaveWay::ZWay.instance.execute(
|
31
|
-
end
|
32
|
-
|
33
|
-
def set(value)
|
34
|
-
RZWaveWay::ZWay.instance.execute(@device.id, SWITCH_BINARY, :Set, value)
|
24
|
+
def refresh
|
25
|
+
RZWaveWay::ZWay.instance.execute(device.id, SWITCH_BINARY, :Get)
|
35
26
|
end
|
36
27
|
end
|
37
28
|
end
|
@@ -1,37 +1,28 @@
|
|
1
1
|
module RZWaveWay
|
2
2
|
module CommandClasses
|
3
|
-
class SwitchMultiLevel
|
4
|
-
include CommandClass
|
3
|
+
class SwitchMultiLevel < CommandClass
|
5
4
|
|
6
|
-
def
|
7
|
-
|
8
|
-
@device.add_property(name: :level,
|
9
|
-
value: find('data.level.value', data),
|
10
|
-
update_time: find('data.level.updateTime', data),
|
11
|
-
read_only: false)
|
5
|
+
def build_from(data)
|
6
|
+
define_property(:level, 'data.level', false, data)
|
12
7
|
end
|
13
8
|
|
14
9
|
def process(updates)
|
15
10
|
if updates.keys.include?('data.level')
|
16
11
|
data = updates['data.level']
|
17
12
|
value = data['value']
|
18
|
-
|
19
|
-
if @
|
20
|
-
|
13
|
+
update_time = data['updateTime']
|
14
|
+
if @properties[:level].update(value, update_time)
|
15
|
+
yield MultiLevelEvent.new(device_id: device.id, time: update_time, level: value)
|
21
16
|
end
|
22
17
|
end
|
23
18
|
end
|
24
19
|
|
25
|
-
def level
|
26
|
-
|
20
|
+
def level=(value)
|
21
|
+
RZWaveWay::ZWay.instance.execute(device.id, SWITCH_MULTI_LEVEL, :Set, value)
|
27
22
|
end
|
28
23
|
|
29
|
-
def
|
30
|
-
RZWaveWay::ZWay.instance.execute(
|
31
|
-
end
|
32
|
-
|
33
|
-
def set(value)
|
34
|
-
RZWaveWay::ZWay.instance.execute(@device.id, SWITCH_MULTI_LEVEL, :Set, value)
|
24
|
+
def refresh
|
25
|
+
RZWaveWay::ZWay.instance.execute(device.id, SWITCH_MULTI_LEVEL, :Get)
|
35
26
|
end
|
36
27
|
end
|
37
28
|
end
|
@@ -1,44 +1,41 @@
|
|
1
1
|
module RZWaveWay
|
2
2
|
module CommandClasses
|
3
|
-
class WakeUp
|
4
|
-
include CommandClass
|
3
|
+
class WakeUp < CommandClass
|
5
4
|
|
6
|
-
def
|
7
|
-
|
8
|
-
|
9
|
-
last_wakeup_time
|
10
|
-
last_sleep_time = find('data.lastSleep.value', data)
|
5
|
+
def build_from(data)
|
6
|
+
define_property(:contact_frequency, 'data.interval', true, data)
|
7
|
+
define_property(:last_sleep_time, 'data.lastSleep', true, data)
|
8
|
+
define_property(:last_wakeup_time, 'data.lastWakeup', true, data)
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
update_time: find('data.lastSleep.updateTime', data),
|
19
|
-
internal: true)
|
20
|
-
@device.add_property(name: :wakeup_last_wakeup_time,
|
21
|
-
value: last_wakeup_time,
|
22
|
-
update_time: find('data.lastWakeup.updateTime', data),
|
23
|
-
internal: true)
|
10
|
+
device.notify_contacted(find('data.lastWakeup.value', data))
|
11
|
+
end
|
12
|
+
|
13
|
+
def missed_contact_count(time = Time.now)
|
14
|
+
(elapsed_seconds_since_last_contact(time) / contact_frequency).to_i
|
15
|
+
end
|
24
16
|
|
25
|
-
|
26
|
-
|
17
|
+
def on_time?(time = Time.now)
|
18
|
+
elapsed_seconds_since_last_contact(time) < (contact_frequency * 1.2)
|
27
19
|
end
|
28
20
|
|
29
21
|
def process(updates)
|
30
22
|
if updates.keys.include?('data.lastWakeup')
|
31
23
|
data = updates['data.lastWakeup']
|
32
24
|
value = data['value']
|
33
|
-
|
34
|
-
if @
|
35
|
-
|
36
|
-
return AliveEvent.new(@device.id, value)
|
25
|
+
update_time = data['updateTime']
|
26
|
+
if @properties[:last_wakeup_time].update(value, update_time)
|
27
|
+
device.notify_contacted(value)
|
37
28
|
end
|
38
29
|
end
|
39
|
-
|
30
|
+
nil
|
40
31
|
# TODO handle change of wake up interval value?
|
41
32
|
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def elapsed_seconds_since_last_contact(time)
|
37
|
+
time.to_i - device.last_contact_time
|
38
|
+
end
|
42
39
|
end
|
43
40
|
end
|
44
41
|
end
|