elia 1.1.0 → 1.2.0
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/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
|