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 CHANGED
@@ -1 +1,3 @@
1
1
  *.gem
2
+ Gemfile.lock
3
+ *.log
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ platforms :ruby do
4
+ gemspec name: 'rzwaveway'
5
+ end
data/README.md CHANGED
@@ -3,20 +3,43 @@ rzwaveway
3
3
 
4
4
  A Ruby library for communicating with the ZWave protocol stack from ZWay, running on the Raspberry Pi "razberry" add-on card (see http://razberry.z-wave.me/).
5
5
 
6
- ## Example
6
+ ## Usage examples
7
+
8
+ ### Initialize the framework
7
9
  ```
8
10
  require 'rzwaveway'
9
11
 
10
- z_way = RZWaveWay::ZWay.new('192.168.1.123)
11
- devices = z_way.get_devices
12
- devices.values.each do | device |
12
+ z_way = RZWaveWay::ZWay.instance
13
+ z_way.setup('192.168.1.123')
14
+ z_way.start
15
+ ```
16
+
17
+ ### List the devices
18
+ ```
19
+ z_way.devices.each do |device_id,device|
13
20
  puts device.build_json
14
21
  end
22
+ ```
15
23
 
24
+ ### Listen to events
25
+ ```
16
26
  z_way.on_event(RZWaveWay::AliveEvent) {|event| puts "A device woke up" }
17
27
  z_way.on_event(RZWaveWay::LevelEvent) {|event| puts "A device got triggered" }
18
28
  while true do
19
29
  sleep 5
20
30
  z_way.process_events
21
31
  end
32
+ ```
33
+
34
+ ### Switch on/off a device
35
+ ```
36
+ z_way.execute(4, RZWaveWay::CommandClass::SWITCH_BINARY, :Set, 1)
37
+ z_way.execute(4, RZWaveWay::CommandClass::SWITCH_BINARY, :Set, 0)
38
+ ```
39
+ or
40
+
41
+ ```
42
+ switch = z_way.devices[4]
43
+ switch.SwitchBinary.set(1)
44
+ switch.SwitchBinary.set(0)
22
45
  ```
@@ -0,0 +1,29 @@
1
+ module RZWaveWay
2
+ module CommandClass
3
+ BASIC = 32
4
+ SWITCH_BINARY = 37
5
+ SWITCH_MULTI_LEVEL = 38
6
+ SENSOR_BINARY = 48
7
+ SENSOR_MULTI_LEVEL = 49
8
+ CONFIGURATION = 112
9
+ ALARM = 113
10
+ MANUFACTURER_SPECIFIC = 114
11
+ BATTERY = 128
12
+ WAKEUP = 132
13
+ ASSOCIATION = 133
14
+ VERSION = 134
15
+ ALARM_SENSOR = 156
16
+
17
+ private
18
+
19
+ def find(name, data)
20
+ parts = name.split '.'
21
+ result = data
22
+ parts.each do | part |
23
+ raise "Could not find part '#{part}' in '#{name}'" unless result.has_key? part
24
+ result = result[part]
25
+ end
26
+ result
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,33 @@
1
+ module RZWaveWay
2
+ module CommandClasses
3
+ class Battery
4
+ include CommandClass
5
+
6
+ def initialize(data, device)
7
+ @device = device
8
+ @device.add_property(:battery_level,
9
+ find('data.last.value', data),
10
+ find('data.last.updateTime', data))
11
+ end
12
+
13
+ def process(updates)
14
+ if updates.keys.include?('data.last')
15
+ data = updates['data.last']
16
+ value = data['value']
17
+ updateTime = data['updateTime']
18
+ if @device.update_property(:battery_level, value, updateTime)
19
+ return BatteryValueEvent.new(@device.id, updateTime, value)
20
+ end
21
+ end
22
+ end
23
+
24
+ def battery_value
25
+ @device.get_property(:battery_level)[0]
26
+ end
27
+
28
+ def get
29
+ RZWaveWay::ZWay.instance.execute(@device.id, BATTERY, :Get)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ module RZWaveWay
2
+ module CommandClasses
3
+ class SensorBinary
4
+ include CommandClass
5
+
6
+ def initialize(data, device)
7
+ @device = device
8
+ @device.add_property(:level,
9
+ find('data.1.level.value', data),
10
+ find('data.1.level.updateTime', data))
11
+ end
12
+
13
+ def process(updates)
14
+ if updates.keys.include?('data.1')
15
+ data = updates['data.1']['level']
16
+ value = data['value']
17
+ updateTime = data['updateTime']
18
+ if @device.update_property(:level, value, updateTime)
19
+ return LevelEvent.new(@device.id, updateTime, value)
20
+ end
21
+ end
22
+ end
23
+
24
+ def level
25
+ @device.get_property(:level)[0]
26
+ end
27
+
28
+ def get
29
+ RZWaveWay::ZWay.instance.execute(@device.id, SENSOR_BINARY, :Get)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,37 @@
1
+ module RZWaveWay
2
+ module CommandClasses
3
+ class SwitchBinary
4
+ include CommandClass
5
+
6
+ def initialize(data, device)
7
+ @device = device
8
+ @device.add_property(:level,
9
+ find('data.level.value', data),
10
+ find('data.level.updateTime', data))
11
+ end
12
+
13
+ def process(updates)
14
+ if updates.keys.include?('data.level')
15
+ data = updates['data.level']
16
+ value = data['value']
17
+ updateTime = data['updateTime']
18
+ if @device.update_property(:level, value, updateTime)
19
+ return LevelEvent.new(@device.id, updateTime, value)
20
+ end
21
+ end
22
+ end
23
+
24
+ def level
25
+ @device.get_property(:level)[0]
26
+ end
27
+
28
+ def get
29
+ RZWaveWay::ZWay.instance.execute(@device.id, SWITCH_BINARY, :Get)
30
+ end
31
+
32
+ def set(value)
33
+ RZWaveWay::ZWay.instance.execute(@device.id, SWITCH_BINARY, :Set, value)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,37 @@
1
+ module RZWaveWay
2
+ module CommandClasses
3
+ class SwitchMultiLevel
4
+ include CommandClass
5
+
6
+ def initialize(data, device)
7
+ @device = device
8
+ @device.add_property(:level,
9
+ find('data.level.value', data),
10
+ find('data.level.updateTime', data))
11
+ end
12
+
13
+ def process(updates)
14
+ if updates.keys.include?('data.level')
15
+ data = updates['data.level']
16
+ value = data['value']
17
+ updateTime = data['updateTime']
18
+ if @device.update_property(:level, value, updateTime)
19
+ return MultiLevelEvent.new(@device.id, updateTime, value)
20
+ end
21
+ end
22
+ end
23
+
24
+ def level
25
+ @device.get_property(:level)[0]
26
+ end
27
+
28
+ def get
29
+ RZWaveWay::ZWay.instance.execute(@device.id, SWITCH_MULTI_LEVEL, :Get)
30
+ end
31
+
32
+ def set(value)
33
+ RZWaveWay::ZWay.instance.execute(@device.id, SWITCH_MULTI_LEVEL, :Set, value)
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,41 @@
1
+ module RZWaveWay
2
+ module CommandClasses
3
+ class WakeUp
4
+ include CommandClass
5
+
6
+ def initialize(data, device)
7
+ @device = device
8
+ wakeup_interval = find('data.interval.value', data)
9
+ last_wakeup_time = find('data.lastWakeup.value', data)
10
+ last_sleep_time = find('data.lastSleep.value', data)
11
+
12
+ @device.add_property(:wakeup_interval,
13
+ wakeup_interval,
14
+ find('data.interval.updateTime', data))
15
+ @device.add_property(:wakeup_last_sleep_time,
16
+ last_sleep_time,
17
+ find('data.lastSleep.updateTime', data))
18
+ @device.add_property(:wakeup_last_wakeup_time,
19
+ last_wakeup_time,
20
+ find('data.lastSleep.updateTime', data))
21
+
22
+ @device.contact_frequency = wakeup_interval
23
+ @device.notify_contacted(last_wakeup_time)
24
+ end
25
+
26
+ def process(updates)
27
+ if updates.keys.include?('data.lastWakeup')
28
+ data = updates['data.lastWakeup']
29
+ value = data['value']
30
+ updateTime = data['updateTime']
31
+ if @device.update_property(:wakeup_last_wakeup_time, value, updateTime)
32
+ @device.notify_contacted(value)
33
+ return AliveEvent.new(@device.id, value)
34
+ end
35
+ end
36
+
37
+ # TODO handle change of wake up interval value?
38
+ end
39
+ end
40
+ end
41
+ end
@@ -1,82 +1,45 @@
1
- module RZWaveWay
2
- module CommandClasses
3
- BASIC = 32
4
- SENSOR_BINARY = 48
5
- MULTI_LEVEL_SENSOR = 49
6
- CONFIGURATION = 112
7
- BATTERY = 128
8
- WAKEUP = 132
9
- ALARM_SENSOR = 156
1
+ require 'singleton'
10
2
 
11
- DATA = {
12
- SENSOR_BINARY => {
13
- 'level' => 'data.1.level.value',
14
- 'lastLevelChangeTime' => 'data.1.level.updateTime'
15
- },
16
- WAKEUP => {
17
- 'wakeUpInterval' => 'data.interval.value',
18
- 'lastSleepTime' => 'data.lastSleep.value',
19
- 'lastWakeUpTime' => 'data.lastWakeup.value'
20
- },
21
- BATTERY => {
22
- 'batteryLevel' => 'data.last.value'
23
- }
24
- }
25
- end
3
+ require_relative 'command_class'
4
+ require_relative 'command_classes/battery'
5
+ require_relative 'command_classes/switch_binary'
6
+ require_relative 'command_classes/switch_multi_level'
7
+ require_relative 'command_classes/sensor_binary'
8
+ require_relative 'command_classes/wake_up'
26
9
 
27
- class CommandClass
28
- include CommandClasses
29
- attr_reader :id
30
- attr_reader :properties
10
+ module RZWaveWay
11
+ module CommandClasses
12
+ class Dummy
13
+ include Singleton
31
14
 
32
- def initialize(id, data)
33
- @id = id
34
- @properties = {}
35
- if DATA.has_key? id
36
- DATA[id].each do |key, name|
37
- @properties[key] = get_data(name, data)
38
- end
15
+ def initialize
39
16
  end
40
- end
41
17
 
42
- def get_data name, data
43
- parts = name.split '.'
44
- result = data
45
- parts.each do | part |
46
- raise "Could not find part '#{part}' in '#{name}'" unless result.has_key? part
47
- result = result[part]
18
+ def process(updates)
48
19
  end
49
- result
50
20
  end
51
21
 
52
- def process updates, device_id
53
- event = nil
54
- names = updates.keys
55
- case id
56
- when WAKEUP
57
- if names.include?("data.lastWakeup") &&
58
- names.include?("data.lastSleep")
59
- @properties['lastSleepTime'] = updates["data.lastSleep"]["value"]
60
- event = AliveEvent.new(device_id, @properties['lastSleepTime'])
61
- end
62
- when SENSOR_BINARY
63
- if names.include?("data.1")
64
- @properties['lastLevelChangeTime'] = updates['data.1']["level"]["updateTime"]
65
- @properties['level'] = updates['data.1']["level"]["value"]
66
- event = LevelEvent.new(device_id, @properties['lastLevelChangeTime'], @properties['level'])
22
+ class Factory
23
+ include Singleton
24
+ include CommandClass
25
+
26
+ def instantiate(id, data, device)
27
+ if CLASSES.has_key? id
28
+ return CLASSES[id].new(data, device)
29
+ else
30
+ return CommandClasses::Dummy.instance
67
31
  end
68
32
  end
69
- event
70
- end
71
33
 
72
- def process_alive_check device_id
73
- wakeup_interval = @properties['wakeUpInterval']
74
- last_sleep_time = @properties['lastSleepTime']
75
- current_time = Time.now.to_i
76
- estimated_wakeup_time = (last_sleep_time + wakeup_interval * 1.1).to_i
77
- if(current_time > estimated_wakeup_time)
78
- return NotAliveEvent.new(device_id, current_time - estimated_wakeup_time)
79
- end
34
+ private
35
+
36
+ CLASSES = {
37
+ SWITCH_BINARY => CommandClasses::SwitchBinary,
38
+ SWITCH_MULTI_LEVEL => CommandClasses::SwitchMultiLevel,
39
+ SENSOR_BINARY => CommandClasses::SensorBinary,
40
+ WAKEUP => CommandClasses::WakeUp,
41
+ BATTERY => CommandClasses::Battery
42
+ }
80
43
  end
81
44
  end
82
- end
45
+ end
@@ -12,10 +12,20 @@ module RZWaveWay
12
12
  class NotAliveEvent
13
13
  attr_reader :device_id
14
14
  attr_reader :time_delay
15
+ attr_reader :missed_count
15
16
 
16
- def initialize device_id, time_delay
17
+ def initialize(device_id, time_delay, missed_count)
17
18
  @device_id = device_id
18
19
  @time_delay = time_delay
20
+ @missed_count = missed_count
21
+ end
22
+ end
23
+
24
+ class DeadEvent
25
+ attr_reader :device_id
26
+
27
+ def initialize(device_id)
28
+ @device_id = device_id
19
29
  end
20
30
  end
21
31
 
@@ -24,13 +34,28 @@ module RZWaveWay
24
34
  attr_reader :time
25
35
  attr_reader :level
26
36
 
27
- def initialize device_id, time, level
37
+ def initialize(device_id, time, level)
28
38
  @device_id = device_id
29
39
  @time = time
30
40
  @level = level
31
41
  end
32
42
  end
33
43
 
44
+ class MultiLevelEvent < LevelEvent
45
+ end
46
+
47
+ class BatteryValueEvent
48
+ attr_reader :device_id
49
+ attr_reader :time
50
+ attr_reader :value
51
+
52
+ def initialize(device_id, time, value)
53
+ @device_id = device_id
54
+ @time = time
55
+ @value = value
56
+ end
57
+ end
58
+
34
59
  class SmokeEvent
35
60
  attr_reader :device_id
36
61
  attr_reader :time
@@ -45,4 +70,4 @@ module RZWaveWay
45
70
  attr_reader :device_id
46
71
  attr_reader :time
47
72
  end
48
- end
73
+ end
@@ -0,0 +1,11 @@
1
+ module RZWaveWay
2
+ module Extensions
3
+ class FibaroSmokeSensor
4
+ def initialize device
5
+ @device = device
6
+ end
7
+
8
+ # TODO add some usefull methods here for this kind of device
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,53 @@
1
+ module RZWaveWay
2
+ module Extensions
3
+ class SSASirenStrobeAlarm
4
+ def initialize device
5
+ @device = device
6
+ end
7
+
8
+ def disable
9
+ set DISABLED
10
+ end
11
+
12
+ def enable
13
+ set(STROBE + SIREN)
14
+ end
15
+
16
+ def enable_siren
17
+ set SIREN
18
+ end
19
+
20
+ def enable_strobe
21
+ set STROBE
22
+ end
23
+
24
+ def level
25
+ case @device.SwitchMultiLevel.level
26
+ when DISABLED
27
+ :disabled
28
+ when STROBE
29
+ :strobe
30
+ when SIREN
31
+ :siren
32
+ else
33
+ :strobe_and_siren
34
+ end
35
+ end
36
+
37
+ def level!
38
+ @device.SwitchMultiLevel.get
39
+ nil
40
+ end
41
+
42
+ private
43
+
44
+ DISABLED = 0
45
+ STROBE = 33
46
+ SIREN = 66
47
+
48
+ def set level
49
+ @device.SwitchMultiLevel.set level
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,2 @@
1
+ require_relative 'extensions/fibaro_smoke_sensor'
2
+ require_relative 'extensions/ssa_siren_strobe_alarm'
@@ -0,0 +1,3 @@
1
+ module RZWaveWay
2
+ VERSION = '0.0.6'
3
+ end