rzwaveway 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rzwaveway/command_classes.rb +41 -7
- data/lib/rzwaveway/events.rb +10 -0
- data/lib/rzwaveway/zwave_device.rb +14 -20
- data/lib/rzwaveway/zway.rb +39 -43
- data/rzwaveway.gemspec +5 -4
- metadata +20 -3
@@ -1,26 +1,47 @@
|
|
1
1
|
module RZWaveWay
|
2
2
|
module CommandClasses
|
3
|
+
BASIC = 32
|
3
4
|
SENSOR_BINARY = 48
|
4
5
|
MULTI_LEVEL_SENSOR = 49
|
5
6
|
CONFIGURATION = 112
|
6
7
|
BATTERY = 128
|
7
8
|
WAKEUP = 132
|
8
9
|
ALARM_SENSOR = 156
|
10
|
+
|
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
|
+
}
|
9
25
|
end
|
10
26
|
|
11
27
|
class CommandClass
|
12
28
|
include CommandClasses
|
13
29
|
attr_reader :id
|
14
|
-
|
30
|
+
attr_reader :properties
|
15
31
|
|
16
32
|
def initialize(id, data)
|
17
33
|
@id = id
|
18
|
-
@
|
34
|
+
@properties = {}
|
35
|
+
if DATA.has_key? id
|
36
|
+
DATA[id].each do |key, name|
|
37
|
+
@properties[key] = get_data(name, data)
|
38
|
+
end
|
39
|
+
end
|
19
40
|
end
|
20
41
|
|
21
|
-
def get_data name
|
42
|
+
def get_data name, data
|
22
43
|
parts = name.split '.'
|
23
|
-
result =
|
44
|
+
result = data
|
24
45
|
parts.each do | part |
|
25
46
|
raise "Could not find part '#{part}' in '#{name}'" unless result.has_key? part
|
26
47
|
result = result[part]
|
@@ -30,19 +51,32 @@ module RZWaveWay
|
|
30
51
|
|
31
52
|
def process updates, device_id
|
32
53
|
event = nil
|
33
|
-
names = updates.
|
54
|
+
names = updates.keys
|
34
55
|
case id
|
35
56
|
when WAKEUP
|
36
57
|
if names.include?("data.lastWakeup") &&
|
37
58
|
names.include?("data.lastSleep")
|
38
|
-
|
59
|
+
@properties['lastSleepTime'] = updates["data.lastSleep"]["value"]
|
60
|
+
event = AliveEvent.new(device_id, @properties['lastSleepTime'])
|
39
61
|
end
|
40
62
|
when SENSOR_BINARY
|
41
63
|
if names.include?("data.1")
|
42
|
-
|
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'])
|
43
67
|
end
|
44
68
|
end
|
45
69
|
event
|
46
70
|
end
|
71
|
+
|
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
|
80
|
+
end
|
47
81
|
end
|
48
82
|
end
|
data/lib/rzwaveway/events.rb
CHANGED
@@ -9,6 +9,16 @@ module RZWaveWay
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
class NotAliveEvent
|
13
|
+
attr_reader :device_id
|
14
|
+
attr_reader :time_delay
|
15
|
+
|
16
|
+
def initialize device_id, time_delay
|
17
|
+
@device_id = device_id
|
18
|
+
@time_delay = time_delay
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
12
22
|
class LevelEvent
|
13
23
|
attr_reader :device_id
|
14
24
|
attr_reader :time
|
@@ -22,23 +22,8 @@ module RZWaveWay
|
|
22
22
|
|
23
23
|
def build_json
|
24
24
|
properties = {'deviceId' => @id}
|
25
|
-
|
26
|
-
properties.merge!(
|
27
|
-
'level' => @command_classes[SENSOR_BINARY].get_data('data.1.level.value'),
|
28
|
-
'lastLevelChangeTime' => @command_classes[SENSOR_BINARY].get_data('data.1.level.updateTime')
|
29
|
-
})
|
30
|
-
end
|
31
|
-
if(support_commandclass? WAKEUP)
|
32
|
-
properties.merge!( {
|
33
|
-
'wakeUpInterval' => @command_classes[WAKEUP].get_data('data.interval.value'),
|
34
|
-
'lastSleepTime' => @command_classes[WAKEUP].get_data('data.lastSleep.value'),
|
35
|
-
'lastWakeUpTime' => @command_classes[WAKEUP].get_data('data.lastWakeup.value')
|
36
|
-
})
|
37
|
-
end
|
38
|
-
if(support_commandclass? BATTERY)
|
39
|
-
properties.merge!( {
|
40
|
-
'batteryLevel' => @command_classes[BATTERY].get_data('data.last.value')
|
41
|
-
})
|
25
|
+
@command_classes.each do |cc_id, cc|
|
26
|
+
properties.merge!(cc.properties)
|
42
27
|
end
|
43
28
|
properties.to_json
|
44
29
|
end
|
@@ -52,7 +37,8 @@ module RZWaveWay
|
|
52
37
|
updates_per_commandclass = group_per_commandclass updates
|
53
38
|
updates_per_commandclass.each do |cc, values|
|
54
39
|
if @command_classes.has_key? cc
|
55
|
-
|
40
|
+
event = @command_classes[cc].process(values, @id)
|
41
|
+
events << event if event
|
56
42
|
else
|
57
43
|
$log.warn "Could not find command class: '#{cc}'"
|
58
44
|
end
|
@@ -60,14 +46,22 @@ module RZWaveWay
|
|
60
46
|
events
|
61
47
|
end
|
62
48
|
|
49
|
+
def process_alive_check
|
50
|
+
if(support_commandclass? WAKEUP)
|
51
|
+
return @command_classes[WAKEUP].process_alive_check(@id)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
63
57
|
def group_per_commandclass updates
|
64
|
-
updates_per_commandclass = Hash.new
|
58
|
+
updates_per_commandclass = Hash.new({})
|
65
59
|
updates.each do | key, value |
|
66
60
|
match_data = key.match(/\Ainstances.0.commandClasses.(\d+)./)
|
67
61
|
if match_data
|
68
62
|
command_class = match_data[1].to_i
|
69
63
|
cc_updates = updates_per_commandclass[command_class]
|
70
|
-
cc_updates
|
64
|
+
cc_updates[match_data.post_match] = value
|
71
65
|
updates_per_commandclass[command_class] = cc_updates
|
72
66
|
else
|
73
67
|
$log.warn "? #{key}" unless key.match(/\Adata./)
|
data/lib/rzwaveway/zway.rb
CHANGED
@@ -1,54 +1,49 @@
|
|
1
|
-
require '
|
1
|
+
require 'httpclient'
|
2
2
|
require 'log4r'
|
3
|
-
require 'net/http'
|
4
3
|
require 'json'
|
5
4
|
|
6
5
|
module RZWaveWay
|
7
|
-
|
6
|
+
module ZWay
|
7
|
+
extend self
|
8
8
|
include Log4r
|
9
9
|
|
10
|
-
|
10
|
+
BASE_PATH='/ZWaveAPI/Data/'
|
11
|
+
|
12
|
+
def self.init hostname
|
11
13
|
$log = Logger.new 'RZWaveWay'
|
12
14
|
outputter = Outputter.stdout
|
13
15
|
outputter.formatter = PatternFormatter.new(:pattern => "[%l] %d - %m")
|
14
16
|
$log.outputters = Outputter.stdout
|
15
|
-
end
|
16
|
-
|
17
|
-
def initialize hostname
|
18
17
|
@devices = {}
|
19
18
|
@update_time = "0"
|
20
|
-
@uri = URI::HTTP.build({:host => hostname, :port => 8083})
|
21
19
|
@event_handlers = {}
|
20
|
+
@http_client = HTTPClient.new
|
21
|
+
@base_uri="http://#{hostname}:8083"
|
22
22
|
end
|
23
23
|
|
24
24
|
def get_devices
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@update_time = results["updateTime"]
|
30
|
-
results["devices"].each do |device |
|
31
|
-
device_id = device[0].to_i
|
32
|
-
@devices[device_id] = ZWaveDevice.new(device_id, device[1]) if device_id > 1
|
33
|
-
end
|
34
|
-
@devices
|
35
|
-
else
|
36
|
-
pp response.code
|
37
|
-
return {}
|
25
|
+
results = http_post_request
|
26
|
+
results["devices"].each do |device_id,device_data_tree|
|
27
|
+
device_id = device_id.to_i
|
28
|
+
@devices[device_id] = ZWaveDevice.new(device_id, device_data_tree) if device_id > 1
|
38
29
|
end
|
30
|
+
@devices
|
39
31
|
end
|
40
32
|
|
41
33
|
def process_events
|
42
34
|
events = []
|
43
|
-
updates =
|
35
|
+
updates = http_post_request
|
44
36
|
updates_per_device = group_per_device updates
|
45
37
|
updates_per_device.each do | id, updates |
|
46
38
|
if @devices[id]
|
47
|
-
|
39
|
+
device_events = @devices[id].process updates
|
40
|
+
events += device_events unless device_events.empty?
|
48
41
|
else
|
49
42
|
$log.warn "Could not find device with id '#{id}'"
|
50
43
|
end
|
51
44
|
end
|
45
|
+
alive_events = check_not_alive_devices
|
46
|
+
events += alive_events unless alive_events.empty?
|
52
47
|
events.each do |event|
|
53
48
|
handler = @event_handlers[event.class]
|
54
49
|
if handler
|
@@ -60,27 +55,14 @@ module RZWaveWay
|
|
60
55
|
events
|
61
56
|
end
|
62
57
|
|
63
|
-
def get_updates
|
64
|
-
@uri.path = "/ZWaveAPI/Data/#{@update_time}"
|
65
|
-
response = http_post_request
|
66
|
-
if response.is_a?(Net::HTTPSuccess)
|
67
|
-
results = JSON.parse response.body
|
68
|
-
@update_time = results.delete("updateTime")
|
69
|
-
return results
|
70
|
-
else
|
71
|
-
pp response.code
|
72
|
-
return {}
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
58
|
def group_per_device updates
|
77
|
-
updates_per_device = Hash.new
|
59
|
+
updates_per_device = Hash.new({})
|
78
60
|
updates.each do | key, value |
|
79
61
|
match_data = key.match(/\Adevices\.(\d+)\./)
|
80
62
|
if match_data
|
81
63
|
device_id = match_data[1].to_i
|
82
64
|
device_updates = updates_per_device[device_id]
|
83
|
-
device_updates
|
65
|
+
device_updates[match_data.post_match] = value
|
84
66
|
updates_per_device[device_id] = device_updates
|
85
67
|
else
|
86
68
|
$log.warn "? #{key}"
|
@@ -89,12 +71,26 @@ module RZWaveWay
|
|
89
71
|
updates_per_device
|
90
72
|
end
|
91
73
|
|
92
|
-
def
|
93
|
-
|
94
|
-
|
74
|
+
def check_not_alive_devices
|
75
|
+
events = []
|
76
|
+
@devices.values.each do |device|
|
77
|
+
event = device.process_alive_check
|
78
|
+
events << event if event
|
79
|
+
end
|
80
|
+
events
|
81
|
+
end
|
95
82
|
|
96
|
-
|
97
|
-
|
83
|
+
def http_post_request
|
84
|
+
results = {}
|
85
|
+
url = @base_uri + BASE_PATH + "#{@update_time}"
|
86
|
+
response = @http_client.post(url)
|
87
|
+
if response.ok?
|
88
|
+
results = JSON.parse response.body
|
89
|
+
@update_time = results.delete("updateTime")
|
90
|
+
else
|
91
|
+
$log.error(response.reason)
|
92
|
+
end
|
93
|
+
results
|
98
94
|
end
|
99
95
|
|
100
96
|
def on_event (event, &listener)
|
data/rzwaveway.gemspec
CHANGED
@@ -1,17 +1,18 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "rzwaveway"
|
3
|
-
s.version = "0.0.
|
3
|
+
s.version = "0.0.3"
|
4
4
|
s.authors = ["Vincent Touchard"]
|
5
5
|
s.date = %q{2014-02-08}
|
6
6
|
s.summary = 'ZWave API for ZWay'
|
7
7
|
s.description = 'A Ruby API to use the Razberry ZWave ZWay interface'
|
8
|
-
s.email = 'vincentoo@yahoo.com'
|
9
|
-
s.homepage = 'https://github.com/rzwaveway'
|
8
|
+
s.email = 'vincentoo.ignore@yahoo.com'
|
9
|
+
s.homepage = 'https://github.com/touchardv/rzwaveway'
|
10
10
|
s.files = `git ls-files`.split("\n")
|
11
11
|
s.has_rdoc = false
|
12
12
|
|
13
13
|
dependencies = [
|
14
|
-
[:runtime,
|
14
|
+
[:runtime, "log4r", "~> 1.1.10"],
|
15
|
+
[:runtime, "httpclient", "~> 2.3.4.1"]
|
15
16
|
]
|
16
17
|
|
17
18
|
dependencies.each do |type, name, version|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rzwaveway
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -27,8 +27,24 @@ dependencies:
|
|
27
27
|
- - ~>
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: 1.1.10
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: httpclient
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.3.4.1
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.3.4.1
|
30
46
|
description: A Ruby API to use the Razberry ZWave ZWay interface
|
31
|
-
email: vincentoo@yahoo.com
|
47
|
+
email: vincentoo.ignore@yahoo.com
|
32
48
|
executables: []
|
33
49
|
extensions: []
|
34
50
|
extra_rdoc_files: []
|
@@ -42,7 +58,7 @@ files:
|
|
42
58
|
- lib/rzwaveway/zwave_device.rb
|
43
59
|
- lib/rzwaveway/zway.rb
|
44
60
|
- rzwaveway.gemspec
|
45
|
-
homepage: https://github.com/rzwaveway
|
61
|
+
homepage: https://github.com/touchardv/rzwaveway
|
46
62
|
licenses: []
|
47
63
|
post_install_message:
|
48
64
|
rdoc_options: []
|
@@ -67,3 +83,4 @@ signing_key:
|
|
67
83
|
specification_version: 3
|
68
84
|
summary: ZWave API for ZWay
|
69
85
|
test_files: []
|
86
|
+
has_rdoc: false
|