Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v1 finalization #67

Merged
merged 9 commits into from
Sep 9, 2019
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ language: python
python:
- "3.6"
before_install:
- pip install pydsdl
- pip install pydsdl>=0.7
script:
- ./test.py
58 changes: 41 additions & 17 deletions test.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@
import time
import string
import pydsdl
from functools import partial


MAX_SERIALIZED_BIT_LENGTH = 313 * 8 # See README
MAX_LINE_LENGTH = 120
NAMESPACES_EXEMPTED_FROM_HEADER_COMMENT_REQUIREMENT = 'uavcan.primitive', 'uavcan.si'
ALLOWED_CHARACTERS = set(string.digits + string.ascii_letters + string.punctuation + ' ')


def on_print(definition, line, value):
print('%s:%d: %s' % (definition.file_path, line, value),
file=sys.stderr)
def die_at(ty, line_index, *text):
prefix = '%s:%d:' % (ty.source_file_path, line_index + 1)
print(prefix, *text, file=sys.stderr)
sys.exit(1)


def on_print(file_path, line, value):
print('%s:%d: %s' % (file_path, line, value), file=sys.stderr)


def compute_max_num_frames_canfd(bit_length):
Expand All @@ -36,11 +43,11 @@ def compute_max_num_frames_canfd(bit_length):
num_frames_to_str = lambda x: str(x) if x > 1 else ' ' # Return empty for single-frame transfers
if isinstance(t, pydsdl.ServiceType):
max_canfd_frames = ' '.join([
num_frames_to_str(compute_max_num_frames_canfd(x.bit_length_range.max))
num_frames_to_str(compute_max_num_frames_canfd(max(x.bit_length_set)))
for x in (t.request_type, t.response_type)
])
else:
max_canfd_frames = num_frames_to_str(compute_max_num_frames_canfd(t.bit_length_range.max))
max_canfd_frames = num_frames_to_str(compute_max_num_frames_canfd(max(t.bit_length_set)))

print(str(t).ljust(58),
str(t.fixed_port_id if t.has_fixed_port_id else '').rjust(5),
Expand All @@ -51,36 +58,53 @@ def compute_max_num_frames_canfd(bit_length):

largest = None
for t in output:
for index, line in enumerate(open(t.source_file_path).readlines()):
text = open(t.source_file_path).read()
for index, line in enumerate(text.split('\n')):
line = line.strip('\r\n')
abort = partial(die_at, t, index)

# Check header comment
if index == 0 and line != '#':
if not any(map(lambda e: t.full_namespace.startswith(e),
NAMESPACES_EXEMPTED_FROM_HEADER_COMMENT_REQUIREMENT)):
abort('Every data type definition must have a header comment surrounded with "#\\n",',
'unless it is a member of:', NAMESPACES_EXEMPTED_FROM_HEADER_COMMENT_REQUIREMENT)

# Check trailing comment placement
# TODO: this test breaks on string literals containing "#"
if not line.startswith('#') and '#' in line and ' #' not in line:
thirtytwobits marked this conversation as resolved.
Show resolved Hide resolved
abort('Trailing line comments must be separated from the preceding text with at least two spaces')

if line != '#' and '#' in line and '# ' not in line:
abort('The text of a comment must be separated from the comment character with a single space')

if line.endswith(' '):
abort('Trailing spaces are not permitted')

# Check line length limit
if len(line) > MAX_LINE_LENGTH:
print('%s:%d: Line is too long:' % (t.source_file_path, index + 1),
len(line), '>', MAX_LINE_LENGTH, 'chars',
file=sys.stderr)
sys.exit(1)
abort('Line is too long:', len(line), '>', MAX_LINE_LENGTH, 'chars')

# Make sure we're not using any weird characters such as tabs or non-ASCII-printable
for char_index, char in enumerate(line):
if char not in ALLOWED_CHARACTERS:
print('%s:%d: Disallowed character' % (t.source_file_path, index + 1),
repr(char), 'code', ord(char), 'at column', char_index + 1,
file=sys.stderr)
sys.exit(1)
abort('Disallowed character', repr(char), 'code', ord(char), 'at column', char_index + 1)

if not text.endswith('\n') or text.endswith('\n' * 2):
abort('A file must contain exactly one blank line at the end')

if isinstance(t, pydsdl.ServiceType):
tt = t.request_type, t.response_type
else:
tt = t,

for t in tt:
largest = largest if largest and (largest.bit_length_range.max >= t.bit_length_range.max) else t
largest = largest if largest and (max(largest.bit_length_set) >= max(t.bit_length_set)) else t

if largest.bit_length_range.max > MAX_SERIALIZED_BIT_LENGTH:
if max(largest.bit_length_set) > MAX_SERIALIZED_BIT_LENGTH:
print('The largest data type', largest, 'exceeds the bit length limit of', MAX_SERIALIZED_BIT_LENGTH,
file=sys.stderr)
sys.exit(1)
else:
print('Largest data type is', largest, 'up to', (largest.bit_length_range.max + 7) // 8, 'bytes',
print('Largest data type is', largest, 'up to', (max(largest.bit_length_set) + 7) // 8, 'bytes',
file=sys.stderr)
4 changes: 2 additions & 2 deletions uavcan/file/409.Write.1.0.uavcan
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ truncated uint40 offset

Path.1.0 path

uint8[<=128] data
uint8[<=192] data # 192 = 128 + 64; the write protocol permits usage of smaller chunks.

@assert _offset_ % 8 == {0}
@assert _offset_.max / 8 <= 300
@assert _offset_.max / 8 <= 313

---

Expand Down
4 changes: 2 additions & 2 deletions uavcan/file/Error.1.0.uavcan
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ uint16 UNKNOWN_ERROR = 65535
uint16 NOT_FOUND = 2
uint16 IO_ERROR = 5
uint16 ACCESS_DENIED = 13
uint16 IS_DIRECTORY = 21 # I.e. attempted read/write on a path that points to a directory
uint16 INVALID_VALUE = 22 # E.g. file name is not valid for the target file system
uint16 IS_DIRECTORY = 21 # I.e., attempted read/write on a path that points to a directory
uint16 INVALID_VALUE = 22 # E.g., file name is not valid for the target file system
uint16 FILE_TOO_LARGE = 27
uint16 OUT_OF_SPACE = 28
uint16 NOT_SUPPORTED = 38
Expand Down
15 changes: 9 additions & 6 deletions uavcan/internet/udp/32750.OutgoingPacket.0.1.uavcan
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@
# Modem nodes are required to keep the NAT table entries alive for at least this amount of time, unless the
# table is overflowed, in which case they are allowed to remove least recently used entries in favor of
# newer ones. Modem nodes are required to be able to accommodate at least 100 entries in the NAT table.
uint32 NAT_ENTRY_MIN_TTL = 86400 # [second]
uint32 NAT_ENTRY_MIN_TTL = 24 * 60 * 60 # [second]

# This field is set to an arbitrary value by the transmitting node in order to be able to match the response
# with the locally kept context. The function of this field is virtually identical to that of UDP/IP port
Expand All @@ -105,10 +105,6 @@ uint16 session_id
# UDP destination port number.
uint16 destination_port

# Option flags.
bool use_masquerading # Expect data back (i.e. instruct the modem to use the NAT table)
void7

# Domain name or IP address where the payload should be forwarded to.
# Note that broadcast addresses are allowed here, for example, 255.255.255.255.
# Broadcasting with masquerading enabled works the same way as unicasting with masquerading enabled: the modem
Expand All @@ -126,10 +122,17 @@ void7
void2
uint8[<=45] destination_address

@assert _offset_ % 8 == {0}

# Option flags.
bool use_masquerading # Expect data back (i.e., instruct the modem to use the NAT table)
void6

# Effective payload. This data will be forwarded to the remote host verbatim.
# UDP packets that contain more than 508 bytes of payload may be dropped by some types of
# communication equipment. Refer to RFC 791 and 2460 for an in-depth review.
# UAVCAN further limits the maximum packet size to reduce the memory and traffic burden on the nodes.
uint8[<256] payload
uint8[<=261] payload

@assert _offset_ % 8 == {0}
@assert _offset_.max / 8 == 313
File renamed without changes.
20 changes: 11 additions & 9 deletions uavcan/pnp/32741.NodeIDAllocationData.0.1.uavcan
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,11 @@
# The allocatee-allocator exchange logic differs between allocators and allocatees. For allocators, the logic is
# trivial: upon reception of a request, the allocator performs an allocation and sends a response back. If the
# allocation could not be performed for any reason (e.g., the allocation table is full, or there was a failure),
# no response is sent back (i.e., the request is simply ignored). The allocator that could not complete an allocation
# for any reason is recommended to emit a diagnostic message with a human-readable description of the problem.
# For allocatees, the logic is described below.
# no response is sent back (i.e., the request is simply ignored); the recommended strategy for the allocatee is to
# continue sending new allocation requests until a response is granted or a higher-level system (e.g., a maintenance
# technician or some automation) intervenes to rectify the problem (e.g., by purging the allocation table).
# The allocator that could not complete an allocation for any reason is recommended to emit a diagnostic message
# with a human-readable description of the problem. For allocatees, the logic is described below.
#
# This message is used for PnP node-ID allocation on all transports where the maximum transmission unit size is
# sufficiently large. For low-MTU transports such as CAN 2.0 there is a dedicated message definition that takes into
Expand Down Expand Up @@ -160,7 +162,7 @@
# Rule B. On expiration of the Request Timer (started as per rules A, B, or C):
# 1. Request Timer restarts with a random interval of Trequest (chosen anew).
# 2. The allocatee broadcasts an allocation request message, where the fields are populated as follows:
# node_id - the preferred node-ID, or 125 if the allocatee doesn't have any specific preference.
# node_id - the preferred node-ID, or the highest valid value if the allocatee doesn't have any preference.
# unique_id - the 128-bit unique-ID of the allocatee, same value that is reported via uavcan.node.GetInfo.
#
# Rule C. On any allocation message, even if other rules also match:
Expand All @@ -180,18 +182,18 @@
# If the message transfer is anonymous (i.e., allocation request), this is the preferred ID.
# If the message transfer is non-anonymous (i.e., allocation response), this is the allocated ID.
#
# If the allocatee does not have any preference, it should request the highest possible node-ID, which is 125,
# because 126 and 127 are reserved for network maintenance tools. Requesting 126 and 127 is not prohibited,
# If the allocatee does not have any preference, it should request the highest possible node-ID. Keep in mind that
# the two highest node ID values are reserved for network maintenance tools; requesting those is not prohibited,
# but the allocator is recommended to avoid granting these node-ID, using nearest available lower value instead.
# The allocator will traverse the allocation table starting from the preferred node-ID upward,
# until a free node-ID is found (or the first ID reserved for network maintenance tools is reached).
# If a free node-ID could not be found, the allocator will restart the search from the preferred node-ID
# downward, until a free node-ID is found. In pseudocode:
#
# uint8_t findFreeNodeID(const uint8_t preferred) // Returns >127 on failure (valid node-ID range from 0 to 127)
# uint16_t findFreeNodeID(const uint16_t preferred) // Returns 0xFFFF on failure
thirtytwobits marked this conversation as resolved.
Show resolved Hide resolved
# {
# uint8_t candidate = preferred;
# while (candidate <= 125)
# while (candidate <= MAX_VALID_NODE_ID) // MAX_VALID_NODE_ID is transport-dependent
# {
# if (!isOccupied(candidate)) { return candidate; }
# candidate++;
Expand All @@ -202,7 +204,7 @@
# if (!isOccupied(candidate)) { return candidate; }
# candidate--;
# }
# return isOccupied(0) ? 255 : 0;
# return isOccupied(0) ? 0xFFFF : 0;
# }
uavcan.node.ID.1.0 node_id

Expand Down
1 change: 1 addition & 0 deletions uavcan/primitive/Empty.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
Expand Up @@ -75,13 +75,13 @@

# The name of the accessed register. Must not be empty.
# Use the List service to obtain the list of registers on the node.
Name.0.1 name
Name.1.0 name

@assert _offset_ % 8 == {0}

# Value to be written. Empty if no write is required.
void4
Value.0.1 value
Value.1.0 value

@assert _offset_.min % 8 == 0
@assert _offset_.max % 8 == 0
Expand Down Expand Up @@ -120,7 +120,7 @@ void2
# Empty value means that the register does not exist (in this case the flags should be cleared/ignored).
# By comparing the returned value against the write request the caller can determine whether the register
# was written successfully, unless write was not requested.
Value.0.1 value
Value.1.0 value

@assert _offset_.min % 8 == 0
@assert _offset_.max % 8 == 0
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ uint16 index
---

# Empty name in response means that the index is out of bounds, i.e., discovery is finished.
Name.0.1 name
Name.1.0 name

@assert _offset_ % 8 == {0}
File renamed without changes.
File renamed without changes.
3 changes: 0 additions & 3 deletions uavcan/si/acceleration/Scalar.1.0.uavcan

This file was deleted.

4 changes: 0 additions & 4 deletions uavcan/si/acceleration/Vector3.1.0.uavcan

This file was deleted.

4 changes: 0 additions & 4 deletions uavcan/si/angle/Quaternion.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/angle/Scalar.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/angular_velocity/Scalar.1.0.uavcan

This file was deleted.

4 changes: 0 additions & 4 deletions uavcan/si/angular_velocity/Vector3.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/duration/Scalar.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/duration/WideScalar.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/electric_charge/Scalar.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/electric_current/Scalar.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/energy/Scalar.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/length/Scalar.1.0.uavcan

This file was deleted.

4 changes: 0 additions & 4 deletions uavcan/si/length/Vector3.1.0.uavcan

This file was deleted.

4 changes: 0 additions & 4 deletions uavcan/si/length/WideVector3.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/magnetic_field_strength/Scalar.1.0.uavcan

This file was deleted.

4 changes: 0 additions & 4 deletions uavcan/si/magnetic_field_strength/Vector3.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/mass/Scalar.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/power/Scalar.1.0.uavcan

This file was deleted.

3 changes: 0 additions & 3 deletions uavcan/si/pressure/Scalar.1.0.uavcan

This file was deleted.

2 changes: 2 additions & 0 deletions uavcan/si/sample/acceleration/Scalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32 meter_per_second_per_second
3 changes: 3 additions & 0 deletions uavcan/si/sample/acceleration/Vector3.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32[3] meter_per_second_per_second
@assert _offset_ % 8 == {0}
3 changes: 3 additions & 0 deletions uavcan/si/sample/angle/Quaternion.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32[4] wxyz
@assert _offset_ % 8 == {0}
2 changes: 2 additions & 0 deletions uavcan/si/sample/angle/Scalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32 radian
2 changes: 2 additions & 0 deletions uavcan/si/sample/angular_velocity/Scalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32 radian_per_second
3 changes: 3 additions & 0 deletions uavcan/si/sample/angular_velocity/Vector3.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32[3] radian_per_second
@assert _offset_ % 8 == {0}
2 changes: 2 additions & 0 deletions uavcan/si/sample/duration/Scalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32 second
2 changes: 2 additions & 0 deletions uavcan/si/sample/duration/WideScalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float64 second
2 changes: 2 additions & 0 deletions uavcan/si/sample/electric_charge/Scalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32 coulomb
2 changes: 2 additions & 0 deletions uavcan/si/sample/electric_current/Scalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32 ampere
2 changes: 2 additions & 0 deletions uavcan/si/sample/energy/Scalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32 joule
2 changes: 2 additions & 0 deletions uavcan/si/sample/length/Scalar.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32 meter
3 changes: 3 additions & 0 deletions uavcan/si/sample/length/Vector3.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float32[3] meter
@assert _offset_ % 8 == {0}
3 changes: 3 additions & 0 deletions uavcan/si/sample/length/WideVector3.1.0.uavcan
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
uavcan.time.SynchronizedTimestamp.1.0 timestamp
float64[3] meter
@assert _offset_ % 8 == {0}
Loading