ruby-sml 0.2

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.
@@ -0,0 +1,51 @@
1
+ require 'ruby-sml/nilclass-mixin'
2
+
3
+ module SML
4
+ module PublicClose
5
+
6
+ class Request
7
+ attr_accessor :global_signature
8
+
9
+ def initialize(global_signature)
10
+ @global_signature = global_signature
11
+ end
12
+
13
+ def self.construct(array_rep)
14
+ return nil if array_rep.nil?
15
+ return SML::PublicClose::Request.new(array_rep.shift)
16
+ end
17
+
18
+ def self.pconstruct(o={})
19
+ return SML::PublicClose::Request.new(o[:global_signature])
20
+ end
21
+
22
+ def to_a
23
+ return [] << global_signature
24
+ end
25
+
26
+ end
27
+
28
+ class Response
29
+ attr_accessor :global_signature
30
+
31
+ def initialize(global_signature)
32
+ @global_signature = global_signature
33
+ end
34
+
35
+ def self.construct(array_rep)
36
+ return nil if array_rep.nil?
37
+ return SML::PublicClose::Response.new(array_rep.shift)
38
+ end
39
+
40
+ def self.pconstruct(o={})
41
+ return SML::PublicClose::Response.new(o[:global_signature])
42
+ end
43
+
44
+ def to_a
45
+ return [] << global_signature
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,84 @@
1
+ require 'ruby-sml/nilclass-mixin'
2
+ require 'ruby-sml/sml-time'
3
+
4
+ module SML
5
+ module PublicOpen
6
+
7
+ class Request
8
+ attr_accessor :codepage, :client_id, :request_file_id, :server_id, :username, :password, :sml_version
9
+
10
+ def initialize(codepage, client_id, request_file_id, server_id, username, password, sml_version)
11
+ @codepage = codepage
12
+ @client_id = client_id
13
+ @request_file_id = request_file_id
14
+ @server_id = server_id
15
+ @username = username
16
+ @password = password
17
+ @sml_version = sml_version
18
+ end
19
+
20
+ def self.construct(array_rep)
21
+ return nil if array_rep.nil?
22
+ codepage = array_rep.shift
23
+ client_id = array_rep.shift
24
+ request_file_id = array_rep.shift
25
+ server_id = array_rep.shift
26
+ username = array_rep.shift
27
+ password = array_rep.shift
28
+ sml_version = array_rep.shift
29
+ array_rep.shift unless sml_version.nil?
30
+
31
+ return SML::PublicOpen::Request.new(codepage, client_id, request_file_id, server_id, username, password, sml_version)
32
+ end
33
+
34
+ def self.pconstruct(o={})
35
+ return SML::PublicOpen::Request.new(o[:codepage], o[:client_id], o[:request_file_id], o[:server_id], o[:username], o[:password], o[:sml_version])
36
+ end
37
+
38
+ def to_a
39
+ result = [] << codepage << client_id << request_file_id << server_id << username << password << sml_version
40
+ result << :uint8 unless sml_version.nil?
41
+ return result
42
+ end
43
+
44
+ end
45
+
46
+ class Response
47
+ attr_accessor :codepage, :client_id, :request_file_id, :server_id, :reference_time, :sml_version
48
+
49
+ def initialize(codepage, client_id, request_file_id, server_id, reference_time, sml_version)
50
+ @codepage = codepage
51
+ @client_id = client_id
52
+ @request_file_id = request_file_id
53
+ @server_id = server_id
54
+ @reference_time = reference_time
55
+ @sml_version = sml_version
56
+ end
57
+
58
+ def self.construct(array_rep)
59
+ return nil if array_rep.nil?
60
+ codepage = array_rep.shift
61
+ client_id = array_rep.shift
62
+ request_file_id = array_rep.shift
63
+ server_id = array_rep.shift
64
+ reference_time = SML::Time.construct(array_rep.shift)
65
+ sml_version = array_rep.shift
66
+ array_rep.shift unless sml_version.nil?
67
+
68
+ return SML::PublicOpen::Response.new(codepage, client_id, request_file_id, server_id, reference_time, sml_version)
69
+ end
70
+
71
+ def self.pconstruct(o={})
72
+ return SML::PublicOpen::Response.new(o[:codepage], o[:client_id], o[:request_file_id], o[:server_id], o[:reference_time], o[:sml_version])
73
+ end
74
+
75
+ def to_a
76
+ result = [] << codepage << client_id << request_file_id << server_id << reference_time.to_a << sml_version
77
+ result << :uint8 unless sml_version.nil?
78
+ return result
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+ end
@@ -0,0 +1,37 @@
1
+ require 'ruby-sml/nilclass-mixin'
2
+ require 'ruby-sml/sml-treepath'
3
+ require 'ruby-sml/sml-tree'
4
+
5
+ module SML
6
+ module SetProcParameter
7
+
8
+ class Request
9
+ attr_accessor :server_id, :username, :password, :parameter_treepath, :parameter_tree
10
+
11
+ def initialize(server_id, username, password, parameter_treepath, parameter_tree)
12
+ @server_id = server_id
13
+ @username = username
14
+ @password = password
15
+ @parameter_treepath = parameter_treepath
16
+ @parameter_tree = parameter_tree
17
+ end
18
+
19
+ def self.construct(array_rep)
20
+ return nil if array_rep.nil?
21
+ server_id = array_rep.shift
22
+ username = array_rep.shift
23
+ password = array_rep.shift
24
+ parameter_treepath = SML::Treepath.construct(array_rep.shift)
25
+ parameter_tree = SML::Tree.construct(array_rep.shift)
26
+
27
+ return nil if (parameter_treepath.nil? or parameter_tree.nil?)
28
+ return SML::SetProcParameter::Request.new(server_id, username, password, parameter_treepath, parameter_tree)
29
+ end
30
+ def to_a
31
+ return [] << server_id << username << password << parameter_treepath.to_a << parameter_tree.to_a
32
+ end
33
+
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,46 @@
1
+ require 'ruby-sml/nilclass-mixin'
2
+
3
+ module SML
4
+
5
+ class Time
6
+ attr_accessor :type, :value
7
+
8
+ def initialize(type, value)
9
+ @type = type
10
+ @value = value
11
+ end
12
+
13
+ def self.construct(array_rep)
14
+ return nil if array_rep.nil?
15
+ choice = array_rep.shift
16
+ array_rep.shift unless choice.nil?
17
+ type = case choice
18
+ when 0x01
19
+ :seconds_index
20
+ when 0x02
21
+ :timestamp
22
+ end
23
+ value = array_rep.shift
24
+ array_rep.shift unless value.nil?
25
+
26
+ return SML::Time.new(type, value)
27
+ end
28
+
29
+ def self.pconstruct(o={})
30
+ return SML::Time.new(o[:type], o[:value])
31
+ end
32
+
33
+ def to_a
34
+ choice = case type
35
+ when :seconds_index
36
+ 0x01
37
+ when :timestamp
38
+ 0x02
39
+ end
40
+
41
+ return [] << choice << :uint8 << value << :uint32
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,42 @@
1
+ require 'ruby-sml/nilclass-mixin'
2
+ require 'ruby-sml/sml-procparametervalue'
3
+
4
+ module SML
5
+
6
+ class Tree
7
+ attr_accessor :parameter_name, :parameter_value, :child_list
8
+
9
+ def initialize(parameter_name, parameter_value, child_list)
10
+ @parameter_name = parameter_name
11
+ @parameter_value = parameter_value
12
+ @child_list = child_list
13
+ end
14
+
15
+ def self.construct(array_rep)
16
+ return nil if array_rep.nil?
17
+ parameter_name = array_rep.shift
18
+ parameter_value = SML::ProcParameterValue.construct(array_rep.shift)
19
+ child_list = []
20
+ child_list_array_rep = array_rep.shift
21
+ unless child_list_array_rep.nil?
22
+ child_list_array_rep.each do |entry_array_rep|
23
+ entry = SML::Tree.construct(entry_array_rep)
24
+ return nil if entry.nil?
25
+ child_list << entry
26
+ end
27
+ end
28
+
29
+ return SML::Tree.new(parameter_name, parameter_value, child_list)
30
+ end
31
+ def to_a
32
+ child_list_array = []
33
+ child_list.each do |entry|
34
+ child_list_array << entry.to_a
35
+ end
36
+
37
+ return [] << parameter_name << SML::ProcParameterValue.to_a(parameter_value) << child_list_array
38
+ end
39
+
40
+ end
41
+
42
+ end
@@ -0,0 +1,24 @@
1
+ require 'ruby-sml/nilclass-mixin'
2
+
3
+ module SML
4
+
5
+ class Treepath
6
+ attr_accessor :path_entry
7
+
8
+ def initialize(path_entry)
9
+ @path_entry = path_entry
10
+ end
11
+
12
+ def self.construct(array_rep)
13
+ return nil if array_rep.nil?
14
+ path_entry = array_rep.shift
15
+
16
+ return SML::Treepath.new(path_entry)
17
+ end
18
+ def to_a
19
+ return [] << path_entry
20
+ end
21
+
22
+ end
23
+
24
+ end
@@ -0,0 +1,105 @@
1
+ require 'ruby-sml/nilclass-mixin'
2
+ require 'ruby-sml/sml-time'
3
+
4
+ module SML
5
+
6
+ class TupelEntry
7
+ attr_accessor :server_id, :seconds_index, :status, :unit_pa, :scaler_pa, :value_pa, :unit_r1, :scaler_r1, :value_r1, :unit_r4, :scaler_r4, :value_r4, :signature_pa_r1_r4, :unit_ma, :scaler_ma, :value_ma, :unit_r2, :scaler_r2, :value_r2, :unit_r3, :scaler_r3, :value_r3, :signature_ma_r2_r3
8
+
9
+ def initialize(server_id, seconds_index, status, unit_pa, scaler_pa, value_pa, unit_r1, scaler_r1, value_r1, unit_r4, scaler_r4, value_r4, signature_pa_r1_r4, unit_ma, scaler_ma, value_ma, unit_r2, scaler_r2, value_r2, unit_r3, scaler_r3, value_r3, signature_ma_r2_r3)
10
+ @server_id = server_id
11
+ @seconds_index = seconds_index
12
+ @status = status
13
+
14
+ @unit_pa = unit_pa
15
+ @scaler_pa = scaler_pa
16
+ @value_pa = value_pa
17
+
18
+ @unit_r1 = unit_r1
19
+ @scaler_r1 = scaler_r1
20
+ @value_r1 = value_r1
21
+
22
+ @unit_r4 = unit_r4
23
+ @scaler_r4 = scaler_r4
24
+ @value_r4 = value_r4
25
+
26
+ @signature_pa_r1_r4 = signature_pa_r1_r4
27
+
28
+ @unit_ma = unit_ma
29
+ @scaler_ma = scaler_ma
30
+ @value_ma = value_ma
31
+
32
+ @unit_r2 = unit_r2
33
+ @scaler_r2 = scaler_r2
34
+ @value_r2 = value_r2
35
+
36
+ @unit_r3 = unit_r3
37
+ @scaler_r3 = scaler_r3
38
+ @value_r3 = value_r3
39
+
40
+ @signature_ma_r2_r3 = signature_ma_r2_r3
41
+ end
42
+
43
+ def self.construct(array_rep)
44
+ return nil if array_rep.nil?
45
+ server_id = array_rep.shift
46
+ seconds_index = SML::Time.construct(array_rep.shift)
47
+ status = array_rep.shift
48
+ array_rep.shift
49
+
50
+ unit_pa = array_rep.shift
51
+ array_rep.shift
52
+ scaler_pa = array_rep.shift
53
+ array_rep.shift
54
+ value_pa = array_rep.shift
55
+ array_rep.shift
56
+
57
+ unit_r1 = array_rep.shift
58
+ array_rep.shift
59
+ scaler_r1 = array_rep.shift
60
+ array_rep.shift
61
+ value_r1 = array_rep.shift
62
+ array_rep.shift
63
+
64
+ unit_r4 = array_rep.shift
65
+ array_rep.shift
66
+ scaler_r4 = array_rep.shift
67
+ array_rep.shift
68
+ value_r4 = array_rep.shift
69
+ array_rep.shift
70
+
71
+ signature_pa_r1_r4 = array_rep.shift
72
+
73
+ unit_ma = array_rep.shift
74
+ array_rep.shift
75
+ scaler_ma = array_rep.shift
76
+ array_rep.shift
77
+ value_ma = array_rep.shift
78
+ array_rep.shift
79
+
80
+ unit_r2 = array_rep.shift
81
+ array_rep.shift
82
+ scaler_r2 = array_rep.shift
83
+ array_rep.shift
84
+ value_r2 = array_rep.shift
85
+ array_rep.shift
86
+
87
+ unit_r3 = array_rep.shift
88
+ array_rep.shift
89
+ scaler_r3 = array_rep.shift
90
+ array_rep.shift
91
+ value_r3 = array_rep.shift
92
+ array_rep.shift
93
+
94
+ signature_ma_r2_r3 = array_rep.shift
95
+
96
+ return nil if seconds_index.nil?
97
+ return SML::TupelEntry.new(server_id, seconds_index, status, unit_pa, scaler_pa, value_pa, unit_r1, scaler_r1, value_r1, unit_r4, scaler_r4, value_r4, signature_pa_r1_r4, unit_ma, scaler_ma, value_ma, unit_r2, scaler_r2, value_r2, unit_r3, scaler_r3, value_r3, signature_ma_r2_r3)
98
+ end
99
+ def to_a
100
+ return [] << server_id << seconds_index.to_a << status << :uint64 << unit_pa << :uint8 << scaler_pa << :int8 << value_pa << :int64 << unit_r1 << :uint8 << scaler_r1 << :int8 << value_r1 << :int64 << unit_r4 << :uint8 << scaler_r4 << :int8 << value_r4 << :int64 << signature_pa_r1_r4 << unit_ma << :uint8 << scaler_ma << :int8 << value_ma << :int64 << unit_r2 << :uint8 << scaler_r2 << :int8 << value_r2 << :int64 << unit_r3 << :uint8 << scaler_r3 << :int8 << value_r3 << :int64 << signature_ma_r2_r3
101
+ end
102
+
103
+ end
104
+
105
+ end
@@ -0,0 +1,29 @@
1
+ require 'ruby-sml/nilclass-mixin'
2
+
3
+ module SML
4
+
5
+ class ValueEntry
6
+ attr_accessor :value, :value_type, :signature
7
+
8
+ def initialize(value, value_type, signature)
9
+ @value = value
10
+ @value_type = value_type
11
+ @signature = signature
12
+ end
13
+
14
+ def self.construct(array_rep)
15
+ return nil if array_rep.nil?
16
+ value = array_rep.shift
17
+ value_type = array_rep.shift
18
+ signature = array_rep.shift
19
+
20
+ return nil if value.nil?
21
+ return SML::ValueEntry.new(value, value_type, signature)
22
+ end
23
+ def to_a
24
+ return [] << value << value_type << signature
25
+ end
26
+
27
+ end
28
+
29
+ end
@@ -0,0 +1,158 @@
1
+ require 'ruby-sml/crc16'
2
+
3
+ require 'stringio'
4
+
5
+ module SML
6
+
7
+ class BinaryTransport
8
+
9
+ def self.readfile(io)
10
+ file = String.new
11
+ received_checksum_bytes = String.new
12
+ raw = String.new
13
+
14
+ while not io.eof?
15
+ bytes_raw = io.read(4)
16
+ raw << bytes_raw
17
+ bytes = bytes_raw.unpack('N')[0]
18
+ if bytes == 0x1b1b1b1b
19
+ escape = []
20
+ 4.times do
21
+ byte = io.read(1)
22
+ raw << byte
23
+ escape.push(byte.unpack('C')[0])
24
+ end
25
+ escape_return, padding_length = handle_escape(escape)
26
+ case escape_return
27
+ when 1
28
+ 4.times do
29
+ file << [0x1b].pack('C')
30
+ end
31
+ when String
32
+ received_checksum_bytes = escape_return
33
+ break
34
+ end
35
+ else
36
+ file << [bytes].pack('N')
37
+ end
38
+ end
39
+
40
+ # calculate CRC16 over all received bytes (except last 2 - they contain the checksum itself)
41
+ raw.chop!.chop!
42
+ calculated_checksum = CRC16.crc16(raw)
43
+ calculated_checksum = (calculated_checksum ^ 0xffff)
44
+ calculated_checksum = ((calculated_checksum & 0xff00) >> 8) | ((calculated_checksum & 0x00ff) << 8)
45
+ # unpack the checksum we received
46
+ received_checksum = received_checksum_bytes.unpack('n')[0]
47
+
48
+ return nil unless calculated_checksum == received_checksum
49
+ return file[0..-(padding_length+1)]
50
+ end
51
+ def self.readstring(data)
52
+ io = StringIO.new(data)
53
+ end_of_transmission_found = false
54
+ file = String.new
55
+ received_checksum_bytes = String.new
56
+ raw = String.new
57
+
58
+ while not io.eof?
59
+ bytes_raw = io.read(4)
60
+ raw << bytes_raw
61
+ bytes = bytes_raw.unpack('N')[0]
62
+ if bytes == 0x1b1b1b1b
63
+ escape = []
64
+ 4.times do
65
+ byte = io.read(1)
66
+ raw << byte
67
+ escape.push(byte.unpack('C')[0])
68
+ end
69
+ escape_return, padding_length = handle_escape(escape)
70
+ case escape_return
71
+ when 1
72
+ 4.times do
73
+ file << [0x1b].pack('C')
74
+ end
75
+ when String
76
+ received_checksum_bytes = escape_return
77
+ end_of_transmission_found = true
78
+ break
79
+ end
80
+ else
81
+ file << [bytes].pack('N')
82
+ end
83
+ end
84
+
85
+ return [nil, nil, data] unless end_of_transmission_found
86
+
87
+ # calculate CRC16 over all received bytes (except last 2 - they contain the checksum itself)
88
+ raw.chop!.chop!
89
+ calculated_checksum = CRC16.crc16(raw)
90
+ calculated_checksum = (calculated_checksum ^ 0xffff)
91
+ calculated_checksum = ((calculated_checksum & 0xff00) >> 8) | ((calculated_checksum & 0x00ff) << 8)
92
+ # unpack the checksum we received
93
+ received_checksum = received_checksum_bytes.unpack('n')[0]
94
+
95
+ return [nil, false, data[io.pos..-1]] unless calculated_checksum == received_checksum
96
+ return [file[0..-(padding_length+1)], true, data[io.pos..-1]]
97
+ end
98
+ def self.writefile(io, file)
99
+ source = String.new(file)
100
+ result = String.new
101
+
102
+ # add transport begin header
103
+ result << [0x1b1b1b1b, 0x01010101].pack('NN')
104
+
105
+ while not source.empty?
106
+ value = source.unpack('N')[0]
107
+ if value == 0x1b1b1b1b
108
+ result << [0x1b1b1b1b].pack('N')
109
+ result << source.slice!(0,4)
110
+ else
111
+ result << source.slice!(0,1)
112
+ end
113
+ end
114
+
115
+ # calculate padding length
116
+ padding_length = (4-(file.length % 4)) % 4
117
+
118
+ # add padding
119
+ padding_length.times do
120
+ result << 0x00
121
+ end
122
+ # add transmission end header
123
+ result << [0x1b1b1b1b, 0x1a, padding_length].pack('NCC')
124
+
125
+ # calculate checksum
126
+ checksum = CRC16.crc16(result)
127
+ checksum = (checksum ^ 0xffff)
128
+ result << [(checksum & 0x00ff), ((checksum >> 8) & 0x00ff)].pack('CC')
129
+
130
+ io << result
131
+ end
132
+
133
+ def self.handle_escape(bytes)
134
+ # print "escape sequence: "
135
+ if bytes[0] == 0x01 and bytes[1] == 0x01 and bytes[2] == 0x01 and bytes[3] == 0x01
136
+ # puts "data transmission v1"
137
+ elsif bytes[0] == 0x1a
138
+ # puts "end of data transmission (padding: #{bytes[1]}, checksum: 0x#{bytes[2].to_s(16)}#{bytes[3].to_s(16)})"
139
+ return "" << bytes[2] << bytes[3], bytes[1]
140
+ elsif bytes[0] == 0x02
141
+ # puts "data transmission v2"
142
+ elsif bytes[0] == 0x03
143
+ # puts "v2 set timeout"
144
+ elsif bytes[0] == 0x04
145
+ # puts "v2 set block size"
146
+ elsif bytes[0] == 0x1b and bytes[1] == 0x1b and bytes[2] == 0x1b and bytes[3] == 0x1b
147
+ # puts "literal escape :("
148
+ return 1, 0
149
+ else
150
+ # print "unknown ["
151
+ # print "0x%08x" % escape
152
+ # puts "]"
153
+ end
154
+ return 0, 0
155
+ end
156
+ end
157
+
158
+ end