rzwaveway 0.0.11 → 0.0.13
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.
- 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
|