elia 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/lib/bit_fields.rb +19 -29
- data/lib/ccsds.rb +167 -0
- data/lib/ccsds/cuc.rb +29 -0
- data/lib/file_with_read_buffer.rb +29 -0
- data/lib/indifferent_reader.rb +36 -0
- data/lib/io_string.rb +29 -0
- data/lib/sass_support.rb +3 -0
- data/lib/sass_support/_border_radius.sass +61 -0
- data/lib/sass_support/_glider.sass +19 -0
- data/lib/slapp.rb +61 -0
- data/lib/space_wire.rb +142 -0
- data/spec/lib/bit_fields_spec.rb +2 -0
- data/spec/lib/ccsds_spec.rb +9 -0
- data/spec/lib/indifferent_reader_spec.rb +24 -0
- data/spec/lib/space_wire/data.bin +0 -0
- data/spec/lib/space_wire/index.bin +0 -0
- data/spec/lib/space_wire_spec.rb +53 -0
- metadata +20 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.2.0
|
data/lib/bit_fields.rb
CHANGED
@@ -82,7 +82,6 @@ module BitFields
|
|
82
82
|
#
|
83
83
|
def field name, unpack_recipe = 'C', &bit_fields_definitions_block
|
84
84
|
include InstanceMethods # when used we include instance methods
|
85
|
-
logger.debug { self.ancestors.inspect }
|
86
85
|
|
87
86
|
# Setup class "instance" vars
|
88
87
|
@fields ||= []
|
@@ -95,7 +94,6 @@ module BitFields
|
|
95
94
|
|
96
95
|
# Define the attribute reader
|
97
96
|
class_eval "def #{name}; self.attributes[#{name.inspect}]; end;", __FILE__, __LINE__
|
98
|
-
# define_method(name) { self.fields[name] }
|
99
97
|
|
100
98
|
# There's a bit-structure too?
|
101
99
|
if block_given?
|
@@ -103,7 +101,7 @@ module BitFields
|
|
103
101
|
|
104
102
|
bit_fields_definitions_block.call
|
105
103
|
|
106
|
-
@bit_fields[name] = @_current_bit_fields
|
104
|
+
@bit_fields[name] = @_current_bit_fields.reverse
|
107
105
|
@_current_bit_fields = nil
|
108
106
|
end
|
109
107
|
end
|
@@ -118,7 +116,7 @@ module BitFields
|
|
118
116
|
raise "'bit_field' can be used only inside a 'field' block." if @_current_bit_fields.nil?
|
119
117
|
|
120
118
|
# Register the bit field definition
|
121
|
-
@_current_bit_fields << [name, width]
|
119
|
+
@_current_bit_fields << [name, width, bit_mask(width)]
|
122
120
|
|
123
121
|
# Define the attribute reader
|
124
122
|
class_eval "def #{name}; self.attributes[#{name.inspect}]; end\n", __FILE__, __LINE__
|
@@ -134,9 +132,14 @@ module BitFields
|
|
134
132
|
end
|
135
133
|
end
|
136
134
|
|
137
|
-
logger.debug { @_current_bit_fields.inspect }
|
138
135
|
end
|
139
136
|
|
137
|
+
def bit_mask size
|
138
|
+
2 ** size - 1
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
|
140
143
|
|
141
144
|
module InstanceMethods
|
142
145
|
# Contains the raw string
|
@@ -160,10 +163,10 @@ module BitFields
|
|
160
163
|
|
161
164
|
private
|
162
165
|
|
163
|
-
def eat_right_bits original_value, bits_number
|
166
|
+
def eat_right_bits original_value, bits_number, bit_mask
|
164
167
|
# Filter the original value with the
|
165
168
|
# proper bitmask to get the rightmost bits
|
166
|
-
new_value = original_value & bit_mask
|
169
|
+
new_value = original_value & bit_mask
|
167
170
|
|
168
171
|
# Eat those rightmost bits
|
169
172
|
# wich we have just consumed
|
@@ -178,40 +181,27 @@ module BitFields
|
|
178
181
|
@raw = raw
|
179
182
|
|
180
183
|
# Setup
|
181
|
-
|
182
|
-
logger.debug "Unpacking #{@raw.inspect} with #{unpack_recipe.inspect}"
|
183
|
-
@unpacked = @raw.unpack(unpack_recipe)
|
184
|
+
@unpacked = @raw.unpack( self.class.unpack_recipe )
|
184
185
|
@attributes ||= {}
|
185
186
|
|
186
|
-
logger.debug { "Parsing #{@raw.inspect} with fields #{self.class.fields.inspect}" }
|
187
187
|
self.class.fields.each_with_index do |name, position|
|
188
|
-
logger.debug { "Parsing field #{name.inspect}" }
|
189
188
|
|
190
|
-
attributes[name] = @unpacked[position]
|
189
|
+
@attributes[name] = @unpacked[position]
|
191
190
|
|
192
191
|
# We must extract bits from end since
|
193
192
|
# ruby doesn't have types (and fixed lengths)
|
194
|
-
if
|
195
|
-
logger.debug { "Parsing value #{attributes[name]} with bit fields #{bit_definitions.inspect}" }
|
193
|
+
if bit_fields = self.class.bit_fields[name]
|
196
194
|
|
197
195
|
bit_value = attributes[name]
|
198
|
-
|
199
|
-
|
200
|
-
bit_name
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
"#{bit_name}: #{attributes[bit_name]} 0b#{attributes[bit_name].to_s(2).rjust(16, '0')}"
|
205
|
-
}
|
196
|
+
bit_fields.each do |(bit_name, bits_number, bit_mask)|
|
197
|
+
# @attributes[bit_name], bit_value = eat_right_bits(bit_value, bits_number, bit_mask)
|
198
|
+
# logger.debug "#{bit_name.to_s.rjust(20)}: #{bit_value.to_s(2).rjust(40)} & #{bit_mask.to_s(2).rjust(20)} = #{(bit_value & bit_mask).to_s(2).rjust(20)}"
|
199
|
+
|
200
|
+
@attributes[bit_name] = bit_value & bit_mask
|
201
|
+
bit_value = bit_value >> bits_number
|
206
202
|
end
|
207
203
|
end
|
208
204
|
end
|
209
|
-
|
210
|
-
@parsed = true
|
211
|
-
end
|
212
|
-
|
213
|
-
def bit_mask size
|
214
|
-
2 ** size - 1
|
215
205
|
end
|
216
206
|
|
217
207
|
def to_s
|
data/lib/ccsds.rb
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
# This links the logger method to Rails.logger
|
2
|
+
require 'world_logger'
|
3
|
+
require 'io_string'
|
4
|
+
require 'bit_fields'
|
5
|
+
require 'active_support'
|
6
|
+
require 'string_nibbles'
|
7
|
+
|
8
|
+
module CCSDS
|
9
|
+
|
10
|
+
class Packet
|
11
|
+
|
12
|
+
# HEADER
|
13
|
+
|
14
|
+
class Header
|
15
|
+
extend BitFields
|
16
|
+
field :packet_identification, 'n' do
|
17
|
+
bit_field :version, 3
|
18
|
+
bit_field :type, 1
|
19
|
+
bit_field :data_header, 1
|
20
|
+
bit_field :apid, 11
|
21
|
+
end
|
22
|
+
field :packet_sequence_control, 'n' do
|
23
|
+
bit_field :segmentation_flags, 2
|
24
|
+
bit_field :ssc, 14
|
25
|
+
end
|
26
|
+
field :packet_length, 'n'
|
27
|
+
def data_size
|
28
|
+
packet_length + 1
|
29
|
+
end
|
30
|
+
|
31
|
+
SIZE = 6 # bytes
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
|
36
|
+
|
37
|
+
# DATA HEADER
|
38
|
+
|
39
|
+
# Data Header is different for each project,
|
40
|
+
# so we assume it isn't present but we provide builtin support for it.
|
41
|
+
#
|
42
|
+
# If the header has
|
43
|
+
#
|
44
|
+
# Example:
|
45
|
+
#
|
46
|
+
# class DataHeader
|
47
|
+
# extend BitFields
|
48
|
+
# field :unknown
|
49
|
+
# SIZE = 1 # bytes
|
50
|
+
# end
|
51
|
+
#
|
52
|
+
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
# ERRORS
|
57
|
+
|
58
|
+
class DataError < StandardError
|
59
|
+
attr_reader :packet
|
60
|
+
def initialize message, packet
|
61
|
+
@packet = packet
|
62
|
+
super(message)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
|
69
|
+
# ATTRIBUTES
|
70
|
+
|
71
|
+
attr_reader :data, :header, :data_header
|
72
|
+
|
73
|
+
# Delegate unknown methods to packet header.
|
74
|
+
def method_missing name, *args
|
75
|
+
if header.respond_to? name
|
76
|
+
header.send name, *args
|
77
|
+
else
|
78
|
+
super
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def raw
|
83
|
+
header.raw + data
|
84
|
+
end
|
85
|
+
|
86
|
+
def data= data
|
87
|
+
raise "Data already filled: #{@data.inspect}" unless @data.blank?
|
88
|
+
@data = data
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
# INITAILIZATION
|
95
|
+
|
96
|
+
def initialize raw, validate_now = true
|
97
|
+
raise DataError.new("Received no RAW data to build the CCSDS Packet: #{raw.inspect}", self) if raw.blank?
|
98
|
+
|
99
|
+
# logger.debug { "Parsing CCSDS header" }
|
100
|
+
# @header = Header.new(raw[0...Header::SIZE]) # Packet Header
|
101
|
+
@header = Header.new(raw) # Packet Header
|
102
|
+
@data = raw[Header::SIZE..-1] # Packet Payload
|
103
|
+
validate! if validate_now
|
104
|
+
|
105
|
+
if defined? DataHeader
|
106
|
+
raise "You should define CCSDS::Packet::DataHeader class" unless defined? DataHeader
|
107
|
+
|
108
|
+
@data_header = DataHeader.new( @data[0 ... DataHeader::SIZE] )
|
109
|
+
|
110
|
+
# Update the data contents excluding the Data Header
|
111
|
+
@data = @data[DataHeader::SIZE .. -1]
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
|
117
|
+
|
118
|
+
# VALIDATION
|
119
|
+
|
120
|
+
def validate
|
121
|
+
@errors = []
|
122
|
+
if data.size != header.data_size
|
123
|
+
@errors << "Available data (#{data.size} bytes) is different than "+
|
124
|
+
"specified by the CCSDS packet header (#{header.data_size} bytes)."+
|
125
|
+
"\nHeader #{header.raw.nibbles.inspect} dump: #{header.inspect}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def validate!
|
130
|
+
validate
|
131
|
+
raise DataError.new(@errors.first, self) unless @errors.blank?
|
132
|
+
end
|
133
|
+
|
134
|
+
def valid?
|
135
|
+
validate
|
136
|
+
return @errors.empty?
|
137
|
+
end
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
# PACKET EXTRACTION
|
143
|
+
|
144
|
+
class << self
|
145
|
+
include IndifferentReader
|
146
|
+
|
147
|
+
def extract_packet io_or_string, *errors_to_rescue
|
148
|
+
begin
|
149
|
+
packet = new( io_or_string.io.read(Header::SIZE), false )
|
150
|
+
packet.data = io_or_string.io.read(packet.data_size)
|
151
|
+
packet.validate!
|
152
|
+
return packet
|
153
|
+
rescue *errors_to_rescue
|
154
|
+
logger.info "Rescued error: (#{$!.class}) #{$!.to_s}"
|
155
|
+
return nil # just go on...
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def each_packet io_or_string, *errors_to_rescue
|
160
|
+
while packet = extract_packet(io_or_string, *errors_to_rescue)
|
161
|
+
yield packet
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|
167
|
+
end
|
data/lib/ccsds/cuc.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# CCSDS Unsegmented Time Code
|
2
|
+
|
3
|
+
|
4
|
+
module CCSDS
|
5
|
+
module CUC
|
6
|
+
|
7
|
+
# def cuc_time time
|
8
|
+
# secs, msecs = time.to_f.divmod(1) # split integer and fractional parts
|
9
|
+
# msecs = (msecs * 256).to_i
|
10
|
+
# [secs, msecs].pack('xN C') # cut off first byte: "@" skips a byte
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# def self.cuc_time_parse cuc
|
14
|
+
# secs, msecs = (0.chr + cuc).unpack('xN C')
|
15
|
+
# time = secs + (msecs / 256.0)
|
16
|
+
# Time.at(time)
|
17
|
+
# end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# coarse are seconds
|
21
|
+
# fine are milliseconds muliplied for 256
|
22
|
+
def parse coarse, fine
|
23
|
+
secs, usecs = coarse, ((fine * 15.0) / 1_000_000.0)
|
24
|
+
Time.at(secs + usecs)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module FileWithBufferedRead
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
READ_BUFFER_SIZE = 1 << 22
|
5
|
+
|
6
|
+
def buffered_read size
|
7
|
+
output = read_buffer.read(size)
|
8
|
+
until output.size == size or self.eof?
|
9
|
+
output << read_buffer.read(size - output.size)
|
10
|
+
end
|
11
|
+
return output
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def buffer_left
|
16
|
+
read_buffer.size - read_buffer.pos
|
17
|
+
end
|
18
|
+
|
19
|
+
def read_buffer
|
20
|
+
if @read_buffer.nil? or @read_buffer.eof?
|
21
|
+
# logger.debug{ "Buffering #{READ_BUFFER_SIZE} from #{self.inspect} current position: #{self.pos}" }
|
22
|
+
@read_buffer = StringIO.new(read(READ_BUFFER_SIZE))
|
23
|
+
# logger.debug{ "Buffered #{@read_buffer.size}, EOF:#{self.eof?} current position: #{self.pos}" }
|
24
|
+
@buffer_left = @read_buffer.size
|
25
|
+
end
|
26
|
+
@read_buffer
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module IndifferentReader
|
2
|
+
|
3
|
+
class DataError < StandardError
|
4
|
+
attr_reader :data
|
5
|
+
def initialize message, data
|
6
|
+
@data = data
|
7
|
+
super(message)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module IOString
|
12
|
+
require 'stringio'
|
13
|
+
def read size
|
14
|
+
@string_io ||= StringIO.new(self)
|
15
|
+
@string_io.read(size)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def read_from io_or_string, size
|
20
|
+
if io_or_string.kind_of? String
|
21
|
+
io_or_string.extend IOString
|
22
|
+
end
|
23
|
+
|
24
|
+
if io_or_string.respond_to? :read
|
25
|
+
result = io_or_string.read(size)
|
26
|
+
|
27
|
+
elsif io_or_string.nil?
|
28
|
+
raise DataError.new("Perhaps DATA has ended? check your FHP.", io_or_string)
|
29
|
+
else
|
30
|
+
raise "Unknown source: #{io_or_string.inspect}"
|
31
|
+
end
|
32
|
+
return result
|
33
|
+
end
|
34
|
+
|
35
|
+
extend self
|
36
|
+
end
|
data/lib/io_string.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
module IOString
|
4
|
+
|
5
|
+
module String
|
6
|
+
def io
|
7
|
+
@__io ||= StringIO.new(self)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module IO
|
12
|
+
def io
|
13
|
+
self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class String
|
20
|
+
include IOString::String
|
21
|
+
end
|
22
|
+
|
23
|
+
class StringIO
|
24
|
+
include IOString::IO
|
25
|
+
end
|
26
|
+
|
27
|
+
class IO
|
28
|
+
include IOString::IO
|
29
|
+
end
|
data/lib/sass_support.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
// Border-radius helps to make it easier to round the corners of your HTML elements
|
2
|
+
// Sample Usage:
|
3
|
+
// #container
|
4
|
+
// +border-radius("5px")
|
5
|
+
|
6
|
+
// All corners
|
7
|
+
=border-radius(!radius)
|
8
|
+
border-radius = !radius
|
9
|
+
-moz-border-radius = !radius
|
10
|
+
-webkit-border-radius = !radius
|
11
|
+
|
12
|
+
// Top Right
|
13
|
+
=border-radius-top-right(!radius)
|
14
|
+
+border-radius-top-right(!radius)
|
15
|
+
// Bottom Right
|
16
|
+
=border-radius-bottom-right(!radius)
|
17
|
+
+border-radius-bottom-right(!radius)
|
18
|
+
// Bottom Left
|
19
|
+
=border-radius-bottom-left(!radius)
|
20
|
+
+border-radius-bottom-left(!radius)
|
21
|
+
// Top Left
|
22
|
+
=border-radius-top-left(!radius)
|
23
|
+
+border-radius-top-left(!radius)
|
24
|
+
// Top
|
25
|
+
=border-radius-top(!radius)
|
26
|
+
+border-radius-top-left(!radius)
|
27
|
+
+border-radius-top-right(!radius)
|
28
|
+
// Right
|
29
|
+
=border-radius-right(!radius)
|
30
|
+
+border-radius-top-right(!radius)
|
31
|
+
+border-radius-bottom-right(!radius)
|
32
|
+
// Bottom
|
33
|
+
=border-radius-bottom(!radius)
|
34
|
+
+border-radius-bottom-right(!radius)
|
35
|
+
+border-radius-bottom-left(!radius)
|
36
|
+
// Left
|
37
|
+
=border-radius-left(!radius)
|
38
|
+
+border-radius-top-left(!radius)
|
39
|
+
+border-radius-bottom-left(!radius)
|
40
|
+
|
41
|
+
// Let's setup the rules so we don't have to repeat ourselves
|
42
|
+
// These are mixins for this mixin and are re-used above
|
43
|
+
=border-radius-top-right(!radius)
|
44
|
+
border-top-right-radius = !radius
|
45
|
+
-moz-border-radius-topright = !radius
|
46
|
+
-webkit-border-top-right-radius = !radius
|
47
|
+
|
48
|
+
=border-radius-bottom-right(!radius)
|
49
|
+
border-bottom-right-radius = !radius
|
50
|
+
-moz-border-radius-bottomright = !radius
|
51
|
+
-webkit-border-bottom-right-radius = !radius
|
52
|
+
|
53
|
+
=border-radius-bottom-left(!radius)
|
54
|
+
border-bottom-left-radius = !radius
|
55
|
+
-moz-border-radius-bottomleft = !radius
|
56
|
+
-webkit-border-bottom-left-radius = !radius
|
57
|
+
|
58
|
+
=border-radius-top-left(!radius)
|
59
|
+
border-top-left-radius = !radius
|
60
|
+
-moz-border-radius-topleft = !radius
|
61
|
+
-webkit-border-top-left-radius = !radius
|
@@ -0,0 +1,19 @@
|
|
1
|
+
.imgLink
|
2
|
+
cursor: pointer
|
3
|
+
|
4
|
+
|
5
|
+
=glider_container(!width=600px, !height=400px)
|
6
|
+
width= !width
|
7
|
+
height= !height
|
8
|
+
overflow: hidden
|
9
|
+
|
10
|
+
=glider_sections_container
|
11
|
+
width: 20000px
|
12
|
+
|
13
|
+
=glider_section(!width=600px, !height=400px)
|
14
|
+
width= !width
|
15
|
+
- unless !height == 'auto'
|
16
|
+
height: !height - 30px
|
17
|
+
overflow: hidden
|
18
|
+
float: left
|
19
|
+
padding: 10px
|
data/lib/slapp.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/env arch -i386 ruby
|
2
|
+
# coding: utf-8
|
3
|
+
|
4
|
+
|
5
|
+
# A WxRuby Shoes-like DSL
|
6
|
+
#
|
7
|
+
# #!/usr/bin/env arch -i386 ruby
|
8
|
+
# require 'rubygems'
|
9
|
+
# require 'slapp'
|
10
|
+
#
|
11
|
+
# Slapp.app {
|
12
|
+
# frame :title => "Wow!" do
|
13
|
+
# button :start_stop, :caption => "start/stop"
|
14
|
+
# end
|
15
|
+
# }
|
16
|
+
#
|
17
|
+
#
|
18
|
+
#
|
19
|
+
# OSX Snow Leopard users see: http://exceptionisarule.blogspot.com/2009/11/building-wxruby-201-on-snow-leopard.html
|
20
|
+
#
|
21
|
+
module Slapp
|
22
|
+
require 'wx'
|
23
|
+
module Sugar
|
24
|
+
include Wx
|
25
|
+
def frame options = {}, &block
|
26
|
+
elements[:frame] = Frame.new(nil, -1, options[:title])
|
27
|
+
block.call
|
28
|
+
elements[:frame].show
|
29
|
+
return elements[:frame]
|
30
|
+
end
|
31
|
+
|
32
|
+
def elements
|
33
|
+
@elements ||= {}
|
34
|
+
end
|
35
|
+
|
36
|
+
def button name, options = {}
|
37
|
+
elements[name] ||= Button.new elements[:frame], -1, options[:caption]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.app &block
|
42
|
+
Wx::App.app &block
|
43
|
+
Wx::App.run
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Wx::App
|
48
|
+
include Slapp::Sugar
|
49
|
+
def on_init
|
50
|
+
self.instance_eval &self.class.app
|
51
|
+
end
|
52
|
+
def self.app &block
|
53
|
+
if block_given?
|
54
|
+
then @on_init_proc = block
|
55
|
+
else @on_init_proc
|
56
|
+
end
|
57
|
+
end
|
58
|
+
def run
|
59
|
+
new.main_loop
|
60
|
+
end
|
61
|
+
end
|
data/lib/space_wire.rb
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'bit_fields'
|
2
|
+
require 'indifferent_reader'
|
3
|
+
require 'file_with_read_buffer'
|
4
|
+
|
5
|
+
module SpaceWire
|
6
|
+
|
7
|
+
|
8
|
+
# Reads the index file generated by the SpaceWire FEE
|
9
|
+
# along with the binary file.
|
10
|
+
class Index
|
11
|
+
|
12
|
+
# Each line of the Index is 9 bytes:
|
13
|
+
# * 1 for en of packet character
|
14
|
+
# * 8 indicating the byte position of the end of the
|
15
|
+
# packet inside of the binady file
|
16
|
+
class Record
|
17
|
+
extend BitFields
|
18
|
+
field :error_control, 'c'
|
19
|
+
field :end_position, 'Q'
|
20
|
+
|
21
|
+
alias bad_end_position end_position
|
22
|
+
def end_position
|
23
|
+
bad_end_position + 1
|
24
|
+
end
|
25
|
+
|
26
|
+
SIZE = 9
|
27
|
+
end
|
28
|
+
|
29
|
+
include IndifferentReader
|
30
|
+
attr_reader :records
|
31
|
+
|
32
|
+
def records
|
33
|
+
if @records.nil?
|
34
|
+
@records = []
|
35
|
+
each do |record|
|
36
|
+
@records << record
|
37
|
+
end
|
38
|
+
end
|
39
|
+
@records
|
40
|
+
end
|
41
|
+
|
42
|
+
# Takes a string, string io, or any io
|
43
|
+
def initialize(io_or_string)
|
44
|
+
@source = io_or_string
|
45
|
+
end
|
46
|
+
|
47
|
+
def each
|
48
|
+
if @records.nil?
|
49
|
+
@records = []
|
50
|
+
|
51
|
+
while line = @source.io.read(Record::SIZE)
|
52
|
+
record = Record.new(line)
|
53
|
+
@records << record
|
54
|
+
yield record if block_given?
|
55
|
+
end
|
56
|
+
else
|
57
|
+
block_given? ? records.each(&block) : records
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
class Data
|
64
|
+
attr_reader :file, :index
|
65
|
+
|
66
|
+
def initialize file_path, index_path
|
67
|
+
@file_path, @index_path = file_path, index_path
|
68
|
+
|
69
|
+
@file = File.open(@file_path)
|
70
|
+
@file.extend FileWithBufferedRead
|
71
|
+
|
72
|
+
@index = Index.new File.read(@index_path)
|
73
|
+
end
|
74
|
+
|
75
|
+
def each_packet
|
76
|
+
previous_end_position = 0
|
77
|
+
index.each do |packet_index|
|
78
|
+
packet_size = packet_index.end_position - previous_end_position
|
79
|
+
|
80
|
+
packet = file.buffered_read(packet_size).extend(Packet)
|
81
|
+
# packet = extract_packet(previous_end_position, packet_index.end_position)
|
82
|
+
yield packet
|
83
|
+
previous_end_position = packet_index.end_position
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def packets
|
88
|
+
if @packets.nil?
|
89
|
+
@packets = []
|
90
|
+
each_packet { |packet| @packets << packet }
|
91
|
+
end
|
92
|
+
@packets
|
93
|
+
end
|
94
|
+
|
95
|
+
def extract_packet start_position, end_position
|
96
|
+
previous_file_position = file.pos
|
97
|
+
file.seek start_position
|
98
|
+
packet = file.read(end_position - start_position)
|
99
|
+
file.seek previous_file_position
|
100
|
+
|
101
|
+
packet.extend Packet
|
102
|
+
packet.header_size = 4
|
103
|
+
packet
|
104
|
+
end
|
105
|
+
|
106
|
+
def [] position
|
107
|
+
if position == 0
|
108
|
+
then start_position = 0
|
109
|
+
else start_position = index.records[position - 1].end_position
|
110
|
+
end
|
111
|
+
|
112
|
+
end_position = index.records[ position ].end_position
|
113
|
+
extract_packet(start_position, end_position)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
module Packet
|
119
|
+
HEADER_SIZE = 4
|
120
|
+
def raw
|
121
|
+
self
|
122
|
+
end
|
123
|
+
|
124
|
+
def header
|
125
|
+
self[0 ... HEADER_SIZE]
|
126
|
+
end
|
127
|
+
|
128
|
+
def data
|
129
|
+
self[HEADER_SIZE ...-1]
|
130
|
+
end
|
131
|
+
|
132
|
+
def end_of_packet_char
|
133
|
+
self[-1].chr
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
def self.rote_quadrate
|
140
|
+
raise "È una doccia fredda!"
|
141
|
+
end
|
142
|
+
end
|
data/spec/lib/bit_fields_spec.rb
CHANGED
@@ -29,6 +29,8 @@ describe BitFields do
|
|
29
29
|
@object.char_value.should == 23
|
30
30
|
@object.secondary_header_flag.should == 0b1
|
31
31
|
@object.sync_flag.should == 0b0
|
32
|
+
@object.packet_order.should == 0b1
|
33
|
+
@object.segment_length_id.should == 0b00
|
32
34
|
@object.first_header_pointer.should == 0b111_11111111
|
33
35
|
end
|
34
36
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'indifferent_reader'
|
3
|
+
describe IndifferentReader do
|
4
|
+
include IndifferentReader
|
5
|
+
|
6
|
+
it 'should read a string' do
|
7
|
+
s = "asdf" * 200
|
8
|
+
|
9
|
+
pos = 0
|
10
|
+
[1,2,3,4,5,6,7].each do |n|
|
11
|
+
read_from(s, n).should == s[pos...(pos+n)]
|
12
|
+
pos += n
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should read from IO' do
|
17
|
+
fail
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should read from StringIO' do
|
21
|
+
fail
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
Binary file
|
Binary file
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
require 'space_wire'
|
3
|
+
require 'stringio'
|
4
|
+
|
5
|
+
describe SpaceWire do
|
6
|
+
before :all do
|
7
|
+
base_dir = File.dirname(__FILE__) + '/space_wire/'
|
8
|
+
|
9
|
+
@index_path = base_dir + '/index.bin'
|
10
|
+
@file_path = base_dir + '/data.bin'
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'should read SpaceWire indexes' do
|
14
|
+
last_end_position = 0
|
15
|
+
index = SpaceWire::Index.new(File.read(@index_path))
|
16
|
+
index.records.size.should == 100
|
17
|
+
index.records.each do |record|
|
18
|
+
record.end_position.should == last_end_position + 4117
|
19
|
+
record.error_control.should == 0
|
20
|
+
last_end_position = record.end_position
|
21
|
+
end
|
22
|
+
|
23
|
+
File.open(@index_path,'r') do |file|
|
24
|
+
last_end_position = 0
|
25
|
+
while index = file.read(9)
|
26
|
+
end_char, end_position = index.unpack('cQ')
|
27
|
+
end_position.should == last_end_position + 4117
|
28
|
+
end_char.should == 0
|
29
|
+
last_end_position = end_position
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should read packets from data file' do
|
35
|
+
space_wire_data = SpaceWire::Data.new(@file_path, @index_path)
|
36
|
+
|
37
|
+
packets = []
|
38
|
+
space_wire_data.each_packet do |packet|
|
39
|
+
packet.end_of_packet_char.should == 0.chr
|
40
|
+
packet.size.should == 4117
|
41
|
+
packet.header_size.should == 4
|
42
|
+
packet.header.size.should == packet.header_size
|
43
|
+
packets << packet
|
44
|
+
end
|
45
|
+
packets.size.should == 100
|
46
|
+
space_wire_data.packets.should == packets
|
47
|
+
|
48
|
+
100.times { |n|
|
49
|
+
space_wire_data[n].should == packets[n]
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: elia
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Elia Schito
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-12-
|
12
|
+
date: 2009-12-11 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -37,15 +37,30 @@ files:
|
|
37
37
|
- Rakefile
|
38
38
|
- VERSION
|
39
39
|
- lib/bit_fields.rb
|
40
|
+
- lib/ccsds.rb
|
41
|
+
- lib/ccsds/cuc.rb
|
40
42
|
- lib/elia.rb
|
43
|
+
- lib/file_with_read_buffer.rb
|
44
|
+
- lib/indifferent_reader.rb
|
45
|
+
- lib/io_string.rb
|
41
46
|
- lib/path_operator.rb
|
42
47
|
- lib/process_extensions.rb
|
48
|
+
- lib/sass_support.rb
|
49
|
+
- lib/sass_support/_border_radius.sass
|
50
|
+
- lib/sass_support/_glider.sass
|
51
|
+
- lib/slapp.rb
|
52
|
+
- lib/space_wire.rb
|
43
53
|
- lib/string_nibbles.rb
|
44
54
|
- lib/world_logger.rb
|
45
55
|
- spec/lib/bit_fields_spec.rb
|
56
|
+
- spec/lib/ccsds_spec.rb
|
46
57
|
- spec/lib/elia_spec.rb
|
58
|
+
- spec/lib/indifferent_reader_spec.rb
|
47
59
|
- spec/lib/path_operator_spec.rb
|
48
60
|
- spec/lib/process_extensions_spec.rb
|
61
|
+
- spec/lib/space_wire/data.bin
|
62
|
+
- spec/lib/space_wire/index.bin
|
63
|
+
- spec/lib/space_wire_spec.rb
|
49
64
|
- spec/lib/string_nibbles_spec.rb
|
50
65
|
- spec/spec.opts
|
51
66
|
- spec/spec_helper.rb
|
@@ -79,8 +94,11 @@ specification_version: 3
|
|
79
94
|
summary: Elia Schito's utility belt
|
80
95
|
test_files:
|
81
96
|
- spec/lib/bit_fields_spec.rb
|
97
|
+
- spec/lib/ccsds_spec.rb
|
82
98
|
- spec/lib/elia_spec.rb
|
99
|
+
- spec/lib/indifferent_reader_spec.rb
|
83
100
|
- spec/lib/path_operator_spec.rb
|
84
101
|
- spec/lib/process_extensions_spec.rb
|
102
|
+
- spec/lib/space_wire_spec.rb
|
85
103
|
- spec/lib/string_nibbles_spec.rb
|
86
104
|
- spec/spec_helper.rb
|