ruby-sml 0.2

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