rzwaveway 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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