ansible4ozw 0.0.1
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/lib/ansible.rb +47 -0
- data/lib/ansible/ansible_callback.rb +142 -0
- data/lib/ansible/ansible_device.rb +68 -0
- data/lib/ansible/ansible_value.rb +179 -0
- data/lib/ansible/config.rb +92 -0
- data/lib/ansible/devices/ansible_dimmer.rb +80 -0
- data/lib/ansible/devices/ansible_switch.rb +66 -0
- data/lib/ansible/knx/EIBConnection.rb +2371 -0
- data/lib/ansible/knx/dpt/canonical_1bit.rb +54 -0
- data/lib/ansible/knx/dpt/dpt1.rb +224 -0
- data/lib/ansible/knx/dpt/dpt10.rb +85 -0
- data/lib/ansible/knx/dpt/dpt11.rb +72 -0
- data/lib/ansible/knx/dpt/dpt12.rb +61 -0
- data/lib/ansible/knx/dpt/dpt13.rb +100 -0
- data/lib/ansible/knx/dpt/dpt14.rb +87 -0
- data/lib/ansible/knx/dpt/dpt15.rb +72 -0
- data/lib/ansible/knx/dpt/dpt16.rb +67 -0
- data/lib/ansible/knx/dpt/dpt17.rb +65 -0
- data/lib/ansible/knx/dpt/dpt18.rb +66 -0
- data/lib/ansible/knx/dpt/dpt19.rb +100 -0
- data/lib/ansible/knx/dpt/dpt2.rb +156 -0
- data/lib/ansible/knx/dpt/dpt3.rb +104 -0
- data/lib/ansible/knx/dpt/dpt4.rb +75 -0
- data/lib/ansible/knx/dpt/dpt5.rb +124 -0
- data/lib/ansible/knx/dpt/dpt6.rb +73 -0
- data/lib/ansible/knx/dpt/dpt7.rb +146 -0
- data/lib/ansible/knx/dpt/dpt8.rb +118 -0
- data/lib/ansible/knx/dpt/dpt9.rb +204 -0
- data/lib/ansible/knx/dpt/tests/test_dpt10.rb +45 -0
- data/lib/ansible/knx/dpt/tests/test_dpt9.rb +60 -0
- data/lib/ansible/knx/hexdump.rb +113 -0
- data/lib/ansible/knx/knx_dpt.rb +58 -0
- data/lib/ansible/knx/knx_dpt_scalar.rb +62 -0
- data/lib/ansible/knx/knx_eistypes.rb +76 -0
- data/lib/ansible/knx/knx_protocol.rb +99 -0
- data/lib/ansible/knx/knx_scene.rb +48 -0
- data/lib/ansible/knx/knx_tools.rb +76 -0
- data/lib/ansible/knx/knx_transceiver.rb +237 -0
- data/lib/ansible/knx/knx_value.rb +327 -0
- data/lib/ansible/openzwave/ozw_constants.rb +11 -0
- data/lib/ansible/openzwave/ozw_headers.rb +80 -0
- data/lib/ansible/openzwave/ozw_remote_manager.rb +7615 -0
- data/lib/ansible/openzwave/ozw_types.rb +406 -0
- data/lib/ansible/orbiter_proxy.rb +12 -0
- data/lib/ansible/transceiver.rb +63 -0
- data/lib/ansible/zwave/types/valuetype_bool.rb +74 -0
- data/lib/ansible/zwave/types/valuetype_button.rb +63 -0
- data/lib/ansible/zwave/types/valuetype_byte.rb +78 -0
- data/lib/ansible/zwave/types/valuetype_decimal.rb +64 -0
- data/lib/ansible/zwave/types/valuetype_int.rb +63 -0
- data/lib/ansible/zwave/types/valuetype_list.rb +64 -0
- data/lib/ansible/zwave/types/valuetype_short.rb +63 -0
- data/lib/ansible/zwave/types/valuetype_string.rb +61 -0
- data/lib/ansible/zwave/zwave_command_classes.rb +113 -0
- data/lib/ansible/zwave/zwave_node.rb +5 -0
- data/lib/ansible/zwave/zwave_protocol.rb +52 -0
- data/lib/ansible/zwave/zwave_transceiver.rb +435 -0
- data/lib/ansible/zwave/zwave_value.rb +193 -0
- metadata +108 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
class DPT10 < BinData::Record
|
4
|
+
bit3 :dayofweek, {
|
5
|
+
:display_name => "Day of week",
|
6
|
+
:range => 0..7, :data_desc => {
|
7
|
+
0 => "(no day set)",
|
8
|
+
1 => "Monday",
|
9
|
+
2 => "Tuesday",
|
10
|
+
3 => "Wednesday",
|
11
|
+
4 => "Thursday",
|
12
|
+
5 => "Friday",
|
13
|
+
6 => "Saturday",
|
14
|
+
7 => "Sunday"
|
15
|
+
}
|
16
|
+
}
|
17
|
+
bit5 :hour, {
|
18
|
+
:display_name => "Hour", :range => 0..23
|
19
|
+
}
|
20
|
+
#
|
21
|
+
bit2 :unused1
|
22
|
+
bit6 :minutes, {
|
23
|
+
:display_name => "Minutes", :range => 0..59
|
24
|
+
}
|
25
|
+
#
|
26
|
+
bit2 :unused2
|
27
|
+
bit6 :seconds, {
|
28
|
+
:display_name => "Seconds", :range => 0..59
|
29
|
+
}
|
30
|
+
end
|
31
|
+
[
|
32
|
+
[0x8e, 0x21, 0x00]
|
33
|
+
].each {|arr|
|
34
|
+
f = DPT10.read(arr.pack('C*'))
|
35
|
+
puts arr.inspect + " ==> " + f.inspect
|
36
|
+
# f.data = -10
|
37
|
+
# puts "after set() ==> " + f.inspect + " serialized as " + f.to_binary_s.unpack("H*").join('0x')
|
38
|
+
#f.dayofweek.get_parameter(:range)
|
39
|
+
}
|
40
|
+
=begin
|
41
|
+
[
|
42
|
+
# DPT11.001 date
|
43
|
+
[0x17, 0x01, 0x0C] # 23/Jan/2012
|
44
|
+
].each {|arr|
|
45
|
+
=end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'bindata'
|
2
|
+
|
3
|
+
class DPT9_Float < BinData::Primitive
|
4
|
+
endian :big
|
5
|
+
#
|
6
|
+
bit1 :sign, :display_name => "Sign"
|
7
|
+
bit4 :exp, :display_name => "Exponent"
|
8
|
+
bit11 :mant, :display_name => "Mantissa"
|
9
|
+
#
|
10
|
+
def get
|
11
|
+
puts "get, sign=#{sign} exp=#{exp} mant=#{mant}"
|
12
|
+
mantissa = (self.sign==1) ? ~(self.mant^2047) : self.mant
|
13
|
+
return Math.ldexp((0.01*mantissa), self.exp)
|
14
|
+
end
|
15
|
+
#
|
16
|
+
def set(v)
|
17
|
+
mantissa, exponent = Math.frexp(v)
|
18
|
+
puts "#{self}.set(#{v}) with initial mantissa=#{mantissa}, exponent=#{exponent}"
|
19
|
+
# find the minimum exponent that will upsize the normalized mantissa (0,5 to 1 range)
|
20
|
+
# in order to fit in 11 bits (-2048..2047)
|
21
|
+
max_mantissa = 0
|
22
|
+
minimum_exp = exponent.downto(-15).find{ | e |
|
23
|
+
max_mantissa = Math.ldexp(100*mantissa, e).to_i
|
24
|
+
max_mantissa.between?(-2048, 2047)
|
25
|
+
}
|
26
|
+
self.sign = (mantissa < 0) ? 1 : 0
|
27
|
+
self.mant = (mantissa < 0) ? ~(max_mantissa^2047) : max_mantissa
|
28
|
+
self.exp = exponent - minimum_exp
|
29
|
+
puts "... set(#{v}) finished: sign=#{sign}, mantissa=#{mant}, exponent=#{exp}"
|
30
|
+
end # set
|
31
|
+
end
|
32
|
+
|
33
|
+
class DPT9 < BinData::Record
|
34
|
+
dpt9_float :data
|
35
|
+
end
|
36
|
+
|
37
|
+
{
|
38
|
+
#forward test (raw data to float)
|
39
|
+
DPT9.read([0x00, 0x02].pack('C*')).data => 0.02,
|
40
|
+
DPT9.read([0x87, 0xfe].pack('C*')).data => -0.02,
|
41
|
+
DPT9.read([0x5c, 0xc4].pack('C*')).data => 24980..25000,
|
42
|
+
DPT9.read([0xdb, 0x3c].pack('C*')).data => -25000..-24980,
|
43
|
+
DPT9.read([0x7f, 0xfe].pack('C*')).data => 670400..670760,
|
44
|
+
DPT9.read([0xf8, 0x02].pack('C*')).data => -670760..-670400,
|
45
|
+
#backward test (float to raw data)
|
46
|
+
"----" => "----",
|
47
|
+
DPT9_Float.new(0.02).to_binary_s.unpack("C*") => [0x00, 0x02],
|
48
|
+
DPT9_Float.new(-0.02).to_binary_s.unpack("C*") => [0x87, 0xfe],
|
49
|
+
DPT9_Float.new(25000).to_binary_s.unpack("C*") => [0x5c, 0xc4],
|
50
|
+
DPT9_Float.new(-25000).to_binary_s.unpack("C*") => [0xdb, 0x3c],
|
51
|
+
DPT9_Float.new(670760).to_binary_s.unpack("C*") => [0x7f, 0xfe],
|
52
|
+
DPT9_Float.new(-670760).to_binary_s.unpack("C*") => [0xf8, 0x02],
|
53
|
+
}.each {|arr, test|
|
54
|
+
#f = DPT9.read(arr.pack('C*'))
|
55
|
+
puts arr.inspect + " ==> " + test.inspect + " \t TEST: " + (test === arr ? 'ok':"\t---FAIL---")
|
56
|
+
# f.data = -30
|
57
|
+
# puts "after set() ==> " + f.inspect + " serialized as " + f.to_binary_s.unpack('B*').join(' ') + " (0x" + f.to_binary_s.unpack("H*").join('') + ")"
|
58
|
+
}
|
59
|
+
|
60
|
+
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# ==============================================================================
|
2
|
+
# EXTENDING CLASS STRING
|
3
|
+
# ==============================================================================
|
4
|
+
#
|
5
|
+
# (C) Copyright 2004 by Tilo Sloboda <tools@unixgods.org>
|
6
|
+
#
|
7
|
+
# License:
|
8
|
+
# Freely available under the terms of the OpenSource "Artistic License"
|
9
|
+
# in combination with the Addendum A (below)
|
10
|
+
#
|
11
|
+
# In case you did not get a copy of the license along with the software,
|
12
|
+
# it is also available at: http://www.unixgods.org/~tilo/artistic-license.html
|
13
|
+
#
|
14
|
+
# Addendum A:
|
15
|
+
# THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU!
|
16
|
+
# SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
17
|
+
# REPAIR OR CORRECTION.
|
18
|
+
#
|
19
|
+
# IN NO EVENT WILL THE COPYRIGHT HOLDERS BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
|
20
|
+
# SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY
|
21
|
+
# TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
22
|
+
# INACCURATE OR USELESS OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
|
23
|
+
# TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF THE COPYRIGHT HOLDERS OR OTHER PARTY HAS BEEN
|
24
|
+
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
25
|
+
|
26
|
+
|
27
|
+
class String
|
28
|
+
#
|
29
|
+
# prints out a good'ol hexdump of the data contained in the string
|
30
|
+
#
|
31
|
+
# parameters: sparse: true / false do we want to print multiple lines with zero values?
|
32
|
+
|
33
|
+
def hexdump(sparse = false)
|
34
|
+
selfsize = self.size
|
35
|
+
first = true
|
36
|
+
|
37
|
+
print "\n index 0 1 2 3 4 5 6 7 8 9 A B C D E F\n\n"
|
38
|
+
|
39
|
+
lines,rest = selfsize.divmod(16)
|
40
|
+
address = 0; i = 0 # we count them independently for future extension.
|
41
|
+
|
42
|
+
while lines > 0
|
43
|
+
str = self[i..i+15]
|
44
|
+
|
45
|
+
# we don't print lines with all zeroes, unless it's the last line
|
46
|
+
|
47
|
+
if str == "\0"*16 # if the 16 bytes are all zero
|
48
|
+
|
49
|
+
if (!sparse) || (sparse && lines == 1 && rest == 0)
|
50
|
+
str.tr!("\000-\037\177-\377",'.')
|
51
|
+
printf( "%08x %8s %8s %8s %8s %s\n",
|
52
|
+
address, self[i..i+3].unpack('H8'), self[i+4..i+7].unpack('H8'),
|
53
|
+
self[i+8..i+11].unpack('H8'), self[i+12..i+15].unpack('H8'), str)
|
54
|
+
else
|
55
|
+
print " .... 00 .. 00 00 .. 00 00 .. 00 00 .. 00 ................\n" if first
|
56
|
+
first = false
|
57
|
+
end
|
58
|
+
|
59
|
+
else # print string which is not all zeros
|
60
|
+
|
61
|
+
str.tr!("\000-\037\177-\377",'.')
|
62
|
+
printf( "%08x %8s %8s %8s %8s %s\n",
|
63
|
+
address, self[i..i+3].unpack('H8'), self[i+4..i+7].unpack('H8'),
|
64
|
+
self[i+8..i+11].unpack('H8'), self[i+12..i+15].unpack('H8'), str)
|
65
|
+
first = true
|
66
|
+
end
|
67
|
+
i += 16; address += 16; lines -= 1
|
68
|
+
end
|
69
|
+
|
70
|
+
# now do the remaining bytes, which don't fit a full line..
|
71
|
+
# yikes - this is truly ugly! REWRITE THIS!!
|
72
|
+
|
73
|
+
if rest > 0
|
74
|
+
chunks2,rest2 = rest.divmod(4)
|
75
|
+
j = i; k = 0
|
76
|
+
if (i < selfsize)
|
77
|
+
printf( "%08x ", address)
|
78
|
+
while (i < selfsize)
|
79
|
+
printf "%02x", self[i]
|
80
|
+
i += 1; k += 1
|
81
|
+
print " " if ((i % 4) == 0)
|
82
|
+
end
|
83
|
+
for i in (k..15)
|
84
|
+
print " "
|
85
|
+
end
|
86
|
+
str = self[j..selfsize]
|
87
|
+
str.tr!("\000-\037\177-\377",'.')
|
88
|
+
print " " * (4 - chunks2+1)
|
89
|
+
printf(" %s\n", str)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
__END__
|
99
|
+
|
100
|
+
require 'hexdump'
|
101
|
+
|
102
|
+
s = "some random long string"
|
103
|
+
|
104
|
+
t = s << "\0"*40 << s << "\0"*32 << s << "bla bla bla!"
|
105
|
+
t.hexdump(true)
|
106
|
+
t.hexdump(false)
|
107
|
+
|
108
|
+
4.times {t.chop!}
|
109
|
+
|
110
|
+
t.hexdump(true)
|
111
|
+
t.hexdump(false)
|
112
|
+
|
113
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
=begin
|
2
|
+
Project Ansible - An extensible home automation scripting framework
|
3
|
+
----------------------------------------------------
|
4
|
+
Copyright (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
|
5
|
+
|
6
|
+
SOFTWARE NOTICE AND LICENSE
|
7
|
+
|
8
|
+
Project Ansible is free software: you can redistribute it and/or modify
|
9
|
+
it under the terms of the GNU Lesser General Public License as published
|
10
|
+
by the Free Software Foundation, either version 3 of the License,
|
11
|
+
or (at your option) any later version.
|
12
|
+
|
13
|
+
Project Ansible is distributed in the hope that it will be useful,
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
GNU Lesser General Public License for more details.
|
17
|
+
|
18
|
+
You should have received a copy of the GNU Lesser General Public License
|
19
|
+
along with Project Ansible. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
|
21
|
+
for more information on the LGPL, see:
|
22
|
+
http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
|
23
|
+
=end
|
24
|
+
|
25
|
+
require 'bindata'
|
26
|
+
|
27
|
+
module Ansible
|
28
|
+
|
29
|
+
module KNX
|
30
|
+
|
31
|
+
# a base class for DPT data structures.
|
32
|
+
# derives from BinData::Record,
|
33
|
+
# implements some common stuff
|
34
|
+
class DPTFrame < BinData::Record
|
35
|
+
# endianness in KNX is big
|
36
|
+
endian :big
|
37
|
+
|
38
|
+
# make sure all frame fields are valid (within min,max range)
|
39
|
+
def validate_ranges()
|
40
|
+
# range checking is global: applies to all subtypes
|
41
|
+
field_names.each { |fieldname|
|
42
|
+
# skip padding fields
|
43
|
+
next if /pad/.match(fieldname)
|
44
|
+
field = self.send(fieldname)
|
45
|
+
if range = field.get_parameter(:range) then
|
46
|
+
raise "#{self}: field #{fieldname} value (#{field.value}) out of range #{range}" unless range === field.value
|
47
|
+
end
|
48
|
+
}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
#
|
53
|
+
# load all known DPT modules
|
54
|
+
Dir["knx/dpt/*.rb"].each { |f| load f }
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
=begin
|
2
|
+
Project Ansible - An extensible home automation scripting framework
|
3
|
+
----------------------------------------------------
|
4
|
+
Copyright (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
|
5
|
+
|
6
|
+
SOFTWARE NOTICE AND LICENSE
|
7
|
+
|
8
|
+
Project Ansible is free software: you can redistribute it and/or modify
|
9
|
+
it under the terms of the GNU Lesser General Public License as published
|
10
|
+
by the Free Software Foundation, either version 3 of the License,
|
11
|
+
or (at your option) any later version.
|
12
|
+
|
13
|
+
Project Ansible is distributed in the hope that it will be useful,
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
GNU Lesser General Public License for more details.
|
17
|
+
|
18
|
+
You should have received a copy of the GNU Lesser General Public License
|
19
|
+
along with Project Ansible. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
|
21
|
+
for more information on the LGPL, see:
|
22
|
+
http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
|
23
|
+
=end
|
24
|
+
|
25
|
+
module Ansible
|
26
|
+
|
27
|
+
module KNX
|
28
|
+
|
29
|
+
# KNX specification declares some special DPTs (5.001 and 5.003) that need
|
30
|
+
# scalar adjustment functions to get the true value contained in a DPT frame.
|
31
|
+
module ScalarValue
|
32
|
+
|
33
|
+
# convert value to its scalar representation
|
34
|
+
# e.g. in DPT5.001, 0x7F => 50(%), 0xFF => 100(%)
|
35
|
+
def to_scalar(val, data_range, scalar_range)
|
36
|
+
if data_range.is_a?(Range) and scalar_range.is_a?(Range) then
|
37
|
+
a = (scalar_range.max - scalar_range.min).to_f / (data_range.max - data_range.min)
|
38
|
+
b = (scalar_range.min - data_range.min)
|
39
|
+
return (a*val + b).round
|
40
|
+
else
|
41
|
+
return val
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# convert value from its scalar representation
|
46
|
+
# e.g. in DPT5.001, 50(%) => 0x7F , 100(%) => 0xFF
|
47
|
+
def from_scalar(val, data_range, scalar_range)
|
48
|
+
if data_range.is_a?(Range) and scalar_range.is_a?(Range) then
|
49
|
+
a = (scalar_range.max - scalar_range.min).to_f / (data_range.max - data_range.min)
|
50
|
+
b = (scalar_range.min - data_range.min)
|
51
|
+
#puts "a=#{a} b=#{b}"
|
52
|
+
return ((val - b) / a).round
|
53
|
+
else
|
54
|
+
return val
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
=begin
|
2
|
+
Project Ansible - An extensible home automation scripting framework
|
3
|
+
----------------------------------------------------
|
4
|
+
Copyright (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
|
5
|
+
|
6
|
+
SOFTWARE NOTICE AND LICENSE
|
7
|
+
|
8
|
+
Project Ansible is free software: you can redistribute it and/or modify
|
9
|
+
it under the terms of the GNU Lesser General Public License as published
|
10
|
+
by the Free Software Foundation, either version 3 of the License,
|
11
|
+
or (at your option) any later version.
|
12
|
+
|
13
|
+
Project Ansible is distributed in the hope that it will be useful,
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
GNU Lesser General Public License for more details.
|
17
|
+
|
18
|
+
You should have received a copy of the GNU Lesser General Public License
|
19
|
+
along with Project Ansible. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
|
21
|
+
for more information on the LGPL, see:
|
22
|
+
http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
|
23
|
+
=end
|
24
|
+
|
25
|
+
module Ansible
|
26
|
+
|
27
|
+
module KNX
|
28
|
+
|
29
|
+
# the skeleton class for the datatypes in use by the KNX standard
|
30
|
+
class EISType
|
31
|
+
|
32
|
+
# singleton hash holding all known EISType instances
|
33
|
+
# key => primary_type (integer 1 to 255)
|
34
|
+
# value => hash of secondary types (secondary_type => instance)
|
35
|
+
# -- NOTE: the contained secondary types hash can be set
|
36
|
+
# to report a default instance that holds a generic EISType.
|
37
|
+
# Thus we define datatypes with great granularity.
|
38
|
+
@@alltypes = {}
|
39
|
+
|
40
|
+
# method for getting all known EIS types as a flat array
|
41
|
+
def EISType.all
|
42
|
+
return @@alltypes.values.collect{ |st| st.values + st.default}.flatten.compact
|
43
|
+
end
|
44
|
+
|
45
|
+
# initializes a new datatype
|
46
|
+
def initialize(primary_type, secondary_type)
|
47
|
+
puts "Initializing new EISType pri=#{primary_type} sec=#{secondary_type}"
|
48
|
+
@primary_type , @secondary_type = primary_type , secondary_type
|
49
|
+
@@alltypes[primary_type] = {} unless @@alltypes[primary_type].is_a? Hash
|
50
|
+
# store ourselves in the big hash of types
|
51
|
+
if secondary_type.nil? then
|
52
|
+
puts "==> Redeclaring default EISType for primary=#{primary_type}" if @@alltypes[primary_type]
|
53
|
+
@@alltypes[primary_type].default = self
|
54
|
+
else
|
55
|
+
@@alltypes[primary_type][secondary_type] = self
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# return a human-readable description for this EISType
|
60
|
+
def to_s
|
61
|
+
return 'EIS' + @primary_type.to_s + (@secondary_type.nil? ? "" : ".#{@secondary_type}")
|
62
|
+
end
|
63
|
+
|
64
|
+
# takes a KNX value and abstracts its data
|
65
|
+
# usage: eis1.abstractor {|value| value.to_s }
|
66
|
+
|
67
|
+
def abstractor=(&block)
|
68
|
+
# in its most basic form, abstract_value just returns the value
|
69
|
+
return(value.get()
|
70
|
+
end
|
71
|
+
|
72
|
+
end # class
|
73
|
+
|
74
|
+
end #module KNX
|
75
|
+
|
76
|
+
end #module Ansible
|
@@ -0,0 +1,99 @@
|
|
1
|
+
=begin
|
2
|
+
Project Ansible - An extensible home automation scripting framework
|
3
|
+
----------------------------------------------------
|
4
|
+
Copyright (c) 2011 Elias Karakoulakis <elias.karakoulakis@gmail.com>
|
5
|
+
|
6
|
+
SOFTWARE NOTICE AND LICENSE
|
7
|
+
|
8
|
+
Project Ansible is free software: you can redistribute it and/or modify
|
9
|
+
it under the terms of the GNU Lesser General Public License as published
|
10
|
+
by the Free Software Foundation, either version 3 of the License,
|
11
|
+
or (at your option) any later version.
|
12
|
+
|
13
|
+
Project Ansible is distributed in the hope that it will be useful,
|
14
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
GNU Lesser General Public License for more details.
|
17
|
+
|
18
|
+
You should have received a copy of the GNU Lesser General Public License
|
19
|
+
along with Project Ansible. If not, see <http://www.gnu.org/licenses/>.
|
20
|
+
|
21
|
+
for more information on the LGPL, see:
|
22
|
+
http://en.wikipedia.org/wiki/GNU_Lesser_General_Public_License
|
23
|
+
=end
|
24
|
+
|
25
|
+
require 'bindata'
|
26
|
+
|
27
|
+
module Ansible
|
28
|
+
|
29
|
+
module KNX
|
30
|
+
|
31
|
+
# the basic Control field structure for KNX/TP (Twisted Pair) telegrams
|
32
|
+
# contains only low-level transmission medium data
|
33
|
+
class TP_ControlField < BinData::Record
|
34
|
+
bit2 :lpdu_code, { :display_name => "LPDU (2bit) 2=L_DATA.req 3=L_Poll_data.req" }
|
35
|
+
bit1 :rep_flag, { :display_name => "Repeat flag"}
|
36
|
+
bit1 :ack_not, { :display_name => "0 = Acknowledge frame, 1 = standard frame"}
|
37
|
+
bit2 :prio_class,{ :display_name => "Priority class (0=highest .. 3=lowest)"}
|
38
|
+
bit2 :unused1, { :display_name => "two unused bits (should be 00)"}
|
39
|
+
end
|
40
|
+
|
41
|
+
# same as TP_ControlField, plus network- and application-layer data
|
42
|
+
# also known as APDU (Application Datagram Unit)
|
43
|
+
class L_DATA_Frame < BinData::Record
|
44
|
+
endian :big
|
45
|
+
# octet 0: TP1 control field
|
46
|
+
bit2 :lpdu_code, { :display_name => "LPDU (2bit) 2=L_DATA.req 3=L_Poll_data.req"}
|
47
|
+
bit1 :rep_flag, { :display_name => "Repeat flag"}
|
48
|
+
bit1 :ack_not, { :display_name => "0 = Acknowledge frame, 1 = standard frame"}
|
49
|
+
bit2 :prio_class,{ :display_name => "Priority class (0=highest .. 3=lowest)"}
|
50
|
+
bit2 :unused1, { :display_name => "two unused bits (should be 00)"}
|
51
|
+
# octet 1+2: source
|
52
|
+
uint16 :src_addr, { :display_name => "Source Address"}
|
53
|
+
# octet 3+4: destination
|
54
|
+
uint16 :dst_addr, { :display_name => "Destination Address"}
|
55
|
+
# octet 5: control fields
|
56
|
+
bit1 :daf, { :display_name => "Dest.Address flag 0=physical 1=group"}
|
57
|
+
bit3 :ctrlfield, { :display_name => "Network control field"}
|
58
|
+
bit4 :datalength,{ :display_name => "Data length (bytes after octet #6)"}
|
59
|
+
# octet 6 + octet 7: TPCI+APCI+6-bit data
|
60
|
+
bit2 :tpci, { :display_name => "TPCI control bits 8+7"}
|
61
|
+
bit4 :seq, { :display_name => "Packet sequence"}
|
62
|
+
bit4 :apci, { :display_name => "APCI control bits"}
|
63
|
+
bit6 :apci_data, { :display_name => "APCI/Data combined"}
|
64
|
+
# octet 8 .. end
|
65
|
+
string :data, {
|
66
|
+
:read_length => lambda { datalength - 1 },
|
67
|
+
:display_nane => "rest of frame"
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
#########################################################
|
72
|
+
|
73
|
+
# APCI codes array
|
74
|
+
APCICODES = "A_GroupValue_Read A_GroupValue_Response A_GroupValue_Write \
|
75
|
+
A_PhysicalAddress_Write A_PhysicalAddress_Read A_PhysicalAddress_Response \
|
76
|
+
A_ADC_Read A_ADC_Response A_Memory_Read A_Memory_Response A_Memory_Write \
|
77
|
+
A_UserMemory A_DeviceDescriptor_Read A_DeviceDescriptor_Response A_Restart \
|
78
|
+
A_OTHER".split()
|
79
|
+
|
80
|
+
# TPDU codes array
|
81
|
+
TPDUCODES = "T_DATA_XXX_REQ T_DATA_CONNECTED_REQ T_DISCONNECT_REQ T_ACK".split()
|
82
|
+
|
83
|
+
# Priority classes
|
84
|
+
PRIOCLASSES = "system alarm high low".split()
|
85
|
+
|
86
|
+
#########################################################
|
87
|
+
|
88
|
+
end #module KNX
|
89
|
+
|
90
|
+
end #module
|
91
|
+
|
92
|
+
#~ data = [188, 17, 200, 18, 1, 242, 0, 128, 80, 171] .pack("c*")
|
93
|
+
#~ knxpacket = KNX_L_DATA_Frame.new(data)
|
94
|
+
#~ knxpacket.fields.each { |a|
|
95
|
+
#~ puts "#{a.name} == #{a.inspect_in_object(knxpacket, :default)}"
|
96
|
+
#~ }
|
97
|
+
#puts knxpacket.inspect_detailed
|
98
|
+
#~ require 'knx_tools'
|
99
|
+
#puts addr2str(knxpacket.src_addr)
|