10 from __future__
import division, absolute_import, print_function, unicode_literals
19 import collections.abc
20 MutableSequence = collections.abc.MutableSequence
23 MutableSequence = collections.MutableSequence
35 if sys.version_info[0] < 3:
48 if not isinstance(obj, CompoundValue):
49 raise ValueError(
'Only CompoundValue can be union')
56 raise ValueError(
'Object is not a union')
58 return obj._union_field
63 raise ValueError(
'Object is not a union')
65 obj._union_field = value
69 if not isinstance(obj, CompoundValue):
70 raise ValueError(
'Only CompoundValue can have fields')
76 if not isinstance(obj, CompoundValue):
77 raise ValueError(
'Only CompoundValue can have constants')
84 return obj._mode ==
'request'
89 return obj._mode ==
'response'
93 return "".join(
format(c,
"08b")
for c
in s)
97 return bytearray(
int(s[i:i + 8], 2)
for i
in range(0, len(s), 8))
102 raise ValueError(
"Not enough bits; need {0} but got {1}".
format(bitlen, len(s)))
103 elif len(s) > bitlen:
106 return "".join([s[i:i + 8]
for i
in range(0, len(s), 8)][::-1])
111 raise ValueError(
"Not enough bits; need {0} but got {1}".
format(bitlen, len(s)))
112 elif len(s) > bitlen:
113 s = s[len(s) - bitlen:]
115 return "".join([s[
max(0, i - 8):i]
for i
in range(len(s), 0, -8)])
119 return " ".join(s[i:i + 8]
for i
in range(0, len(s), 8))
123 return int(math.ceil(math.log(num_elements, 2)))
126 return int(math.ceil(math.log(max_size+1, 2)))
130 Returns a generator over iterable that tells whether the current item is the last one.
132 >>> iterable = range(10)
133 >>> for index, is_last, item in enum_mark_last(iterable):
134 >>> print(index, item, end='\n' if is_last else ', ')
140 except StopIteration:
143 yield count,
False, last
146 yield count,
True, last
151 Yes we've got ourselves a tiny little union here:
152 union FloatIntegerUnion
160 def __init__(self, integer=None, floating_point=None):
162 if integer
is not None:
163 assert floating_point
is None
165 if floating_point
is not None:
166 self.
f = float(floating_point)
170 return struct.unpack(
"=f", self.
_bytes)[0]
174 assert isinstance(value, float)
175 self.
_bytes = struct.pack(
"=f", value)
179 return struct.unpack(
"=I", self.
_bytes)[0]
183 assert isinstance(value, (int, long))
184 self.
_bytes = struct.pack(
"=I", value)
193 sign_mask = 0x80000000
196 sign = inval.u & sign_mask
199 if inval.u >= f32infty.u:
200 out = 0x7FFF
if inval.u > f32infty.u
else 0x7C00
202 inval.u &= round_mask
204 inval.u -= round_mask
205 if inval.u > f16infty.u:
207 out = (inval.u >> 13) & 0xFFFF
209 return out | (sign >> 16) & 0xFFFF
219 if out.f >= was_inf_nan.f:
221 out.u |= (float16 & 0x8000) << 16
227 if dtype.cast_mode == dsdl.PrimitiveType.CAST_MODE_SATURATED:
228 if value > dtype.value_range[1]:
229 value = dtype.value_range[1]
230 elif value < dtype.value_range[0]:
231 value = dtype.value_range[0]
233 elif dtype.cast_mode == dsdl.PrimitiveType.CAST_MODE_TRUNCATED
and dtype.kind == dsdl.PrimitiveType.KIND_FLOAT:
234 if not math.isnan(value)
and value > dtype.value_range[1]:
235 value = float(
"+inf")
236 elif not math.isnan(value)
and value < dtype.value_range[0]:
237 value = float(
"-inf")
239 elif dtype.cast_mode == dsdl.PrimitiveType.CAST_MODE_TRUNCATED:
240 return value & ((1 << dtype.bitlen) - 1)
242 raise ValueError(
"Invalid cast_mode: " + repr(dtype))
247 def __init__(self, _uavcan_type, *_args, **_kwargs):
252 if self.
_type.bitlen:
254 return stream[self.
_type.bitlen:]
262 return "0" * self.
_type.bitlen
267 return stream[self.
_type.bitlen:]
270 return "0" * self.
_type.bitlen
275 super(PrimitiveValue, self).
__init__(_uavcan_type, *args, **kwargs)
280 return repr(self.
value)
288 if self.
_type.kind == dsdl.PrimitiveType.KIND_BOOLEAN:
289 return bool(int_value)
290 elif self.
_type.kind == dsdl.PrimitiveType.KIND_UNSIGNED_INT:
292 elif self.
_type.kind == dsdl.PrimitiveType.KIND_SIGNED_INT:
293 if int_value >= (1 << (self.
_type.bitlen - 1)):
294 int_value = -((1 << self.
_type.bitlen) - int_value)
296 elif self.
_type.kind == dsdl.PrimitiveType.KIND_FLOAT:
297 if self.
_type.bitlen == 16:
299 elif self.
_type.bitlen == 32:
300 return struct.unpack(
"<f", struct.pack(
"<L", int_value))[0]
301 elif self.
_type.bitlen == 64:
302 return struct.unpack(
"<d", struct.pack(
"<Q", int_value))[0]
304 raise ValueError(
'Bad float')
308 if new_value
is None:
309 raise ValueError(
"Can't serialize a None value")
310 elif self.
_type.kind == dsdl.PrimitiveType.KIND_BOOLEAN:
311 self.
_bits =
"1" if new_value
else "0"
312 elif self.
_type.kind == dsdl.PrimitiveType.KIND_UNSIGNED_INT:
315 elif self.
_type.kind == dsdl.PrimitiveType.KIND_SIGNED_INT:
318 new_value += 2 ** self.
_type.bitlen
320 elif self.
_type.kind == dsdl.PrimitiveType.KIND_FLOAT:
322 if self.
_type.bitlen == 16:
324 elif self.
_type.bitlen == 32:
325 int_value = struct.unpack(
"<L", struct.pack(
"<f", new_value))[0]
326 elif self.
_type.bitlen == 64:
327 int_value = struct.unpack(
"<Q", struct.pack(
"<d", new_value))[0]
329 raise ValueError(
'Bad float, no donut')
336 super(ArrayValue, self).
__init__(_uavcan_type, *args, **kwargs)
345 if self.
_type.mode == dsdl.ArrayType.MODE_STATIC:
354 if self.
_type.is_string_like:
363 if isinstance(self.
__items[idx], PrimitiveValue):
369 if idx >= self.
_type.max_size:
370 raise IndexError(
"Index {0} too large (max size {1})".
format(idx, self.
_type.max_size))
372 self.
__items[idx].value = value
383 if isinstance(other, str):
384 return self.
decode() == other
386 return list(self) == other
399 if idx >= self.
_type.max_size:
400 raise IndexError(
"Index {0} too large (max size {1})".
format(idx, self.
_type.max_size))
401 elif len(self) == self.
_type.max_size:
402 raise IndexError(
"Array already full (max size {0})".
format(self.
_type.max_size))
405 new_item.value = value
411 if self.
_type.mode == dsdl.ArrayType.MODE_STATIC:
415 elif tao
and self.
_type.value_type.get_min_bitlen() >= 8:
417 while len(stream) >= 8:
419 stream = new_item._unpack(stream,
False)
427 stream = stream[count_width:]
430 stream = new_item._unpack(stream, tao
and last)
438 if self.
_type.mode == dsdl.ArrayType.MODE_STATIC:
439 while len(self) < self.
_type.max_size:
443 elif tao
and self.
_type.value_type.get_min_bitlen() >= 8:
444 return ''.join(i._pack(
False)
for i
in self.
__items)
453 for byte
in bytearray(value):
457 return bytes(bytearray(item.value
for item
in self.
__items if item._bits))
459 def encode(self, value, errors='strict'):
460 if not self.
_type.is_string_like:
461 raise ValueError(
'encode() can be used only with string-like arrays')
463 value = bytearray(value, encoding=
"utf-8", errors=errors)
468 if not self.
_type.is_string_like:
469 raise ValueError(
'decode() can be used only with string-like arrays')
470 return bytearray(item.value
for item
in self.
__items if item._bits).
decode(encoding)
475 def __init__(self, _uavcan_type, _mode=None, *args, **kwargs):
476 self.__dict__[
"_fields"] = collections.OrderedDict()
477 self.__dict__[
"_constants"] = {}
478 super(CompoundValue, self).
__init__(_uavcan_type, *args, **kwargs)
480 if self.
_type.kind == dsdl.CompoundType.KIND_SERVICE:
481 if _mode ==
"request":
482 source_fields = self.
_type.request_fields
483 source_constants = self.
_type.request_constants
485 elif _mode ==
"response":
486 source_fields = self.
_type.response_fields
487 source_constants = self.
_type.response_constants
490 raise ValueError(
"mode must be either 'request' or 'response' for service types")
492 if _mode
is not None:
493 raise ValueError(
"mode is not applicable for message types")
494 source_fields = self.
_type.fields
495 source_constants = self.
_type.constants
501 for constant
in source_constants:
502 self._constants[constant.name] = constant.value
504 for idx, field
in enumerate(source_fields):
510 self._fields[field.name] =
ArrayValue(field.type)
514 for name, value
in kwargs.items():
515 if name.startswith(
'_'):
516 raise NameError(
'%r is not a valid field name' % name)
517 setattr(self, name, value)
521 field = self.
_union_field or list(self._fields.keys())[0]
522 fields =
"{0}={1!r}".
format(field, self._fields[field])
524 fields =
", ".join(
"{0}={1!r}".
format(f, v)
for f, v
in self._fields.items()
if not f.startswith(
"_void_"))
525 return "{0}({1})".
format(self.
_type.full_name, fields)
530 result = cls.__new__(cls)
531 result.__dict__.update(self.__dict__)
537 result = cls.__new__(cls)
538 memo[id(self)] = result
539 for k, v
in self.__dict__.items():
541 result.__dict__[k] = copy.deepcopy(v, memo)
545 if attr
in self._constants:
546 return self._constants[attr]
547 elif attr
in self._fields:
550 raise AttributeError(attr)
554 if isinstance(self._fields[attr], PrimitiveValue):
555 return self._fields[attr].value
557 return self._fields[attr]
559 raise AttributeError(attr)
562 if attr
in self._constants:
563 raise AttributeError(attr +
" is read-only")
564 elif attr
in self._fields:
567 raise AttributeError(attr)
572 attr_type = self._fields[attr]._type
575 self._fields[attr].value = value
578 if not isinstance(value, CompoundValue):
579 raise AttributeError(
'Invalid type of the value, expected CompoundValue, got %r' % type(value))
581 raise AttributeError(
'Incompatible type of the value, expected %r, got %r' %
583 self._fields[attr] = copy.copy(value)
586 self._fields[attr].clear()
588 if isinstance(value, str):
589 self._fields[attr].encode(value)
592 self._fields[attr].append(item)
593 except Exception
as ex:
595 raise AttributeError(
'Array field could not be constructed from the provided value', ex)
598 raise AttributeError(attr +
" cannot be set directly")
600 super(CompoundValue, self).
__setattr__(attr, value)
605 self.
_union_field = list(self._fields.keys())[
int(stream[0:tag_len], 2)]
609 stream = field._unpack(stream, tao
and last)
614 keys = list(self._fields.keys())
616 tag = keys.index(field)
618 return format(tag,
'0' +
str(tag_len) +
'b') + self._fields[field].
_pack(tao)
620 return ''.join(field._pack(tao
and last)
for _, last, field
in enum_mark_last(self._fields.values()))
624 def __init__(self, message_id, data, ts_monotonic=None, ts_real=None):
638 return bool(self.
bytes[-1] & 0x20)
if self.
bytes else False
642 return bool(self.
bytes[-1] & 0x40)
if self.
bytes else False
646 return bool(self.
bytes[-1] & 0x80)
if self.
bytes else False
654 DEFAULT_TRANSFER_PRIORITY = 31
661 transfer_priority=None,
662 request_not_response=False,
663 service_not_message=False,
678 payload_bits = payload._pack()
679 if len(payload_bits) & 7:
680 payload_bits +=
"0" * (8 - (len(payload_bits) & 7))
694 return "Transfer(id={0}, source_node_id={1}, dest_node_id={2}, transfer_priority={3}, payload={4!r})"\
742 remaining_payload = self.
payload
746 if len(remaining_payload) > 7:
747 crc = common.crc16_from_bytes(self.
payload,
749 remaining_payload = bytearray([crc & 0xFF, crc >> 8]) + remaining_payload
755 tail = ((0x80
if len(out_frames) == 0
else 0) |
756 (0x40
if len(remaining_payload) <= 7
else 0) |
757 ((tail ^ 0x20) & 0x20) |
759 out_frames.append(
Frame(message_id=self.
message_id, data=remaining_payload[0:7] +
bchr(tail)))
760 remaining_payload = remaining_payload[7:]
761 if not remaining_payload:
769 self.
ts_real = frames[0].ts_real
773 expected_transfer_id = frames[0].bytes[-1] & 0x1F
774 for idx, f
in enumerate(frames):
776 if (tail & 0x1F) != expected_transfer_id:
777 raise TransferError(
"Transfer ID {0} incorrect, expected {1}".
format(tail & 0x1F, expected_transfer_id))
778 elif idx == 0
and not (tail & 0x80):
779 raise TransferError(
"Start of transmission not set on frame 0")
780 elif idx > 0
and tail & 0x80:
782 elif idx == len(frames) - 1
and not (tail & 0x40):
783 raise TransferError(
"End of transmission not set on last frame")
784 elif idx < len(frames) - 1
and (tail & 0x40):
786 elif (tail & 0x20) != expected_toggle:
787 raise TransferError(
"Toggle bit value {0} incorrect on frame {1}".
format(tail & 0x20, idx))
789 expected_toggle ^= 0x20
793 payload_bytes = bytearray(b
''.join(bytes(f.bytes[0:-1])
for f
in frames))
797 kind = dsdl.CompoundType.KIND_SERVICE
799 kind = dsdl.CompoundType.KIND_MESSAGE
800 datatype = pyuavcan_v0.DATATYPES.get((self.
data_type_id, kind))
807 transfer_crc = payload_bytes[0] + (payload_bytes[1] << 8)
808 payload_bytes = payload_bytes[2:]
809 crc = common.crc16_from_bytes(payload_bytes, initial=datatype.base_crc)
810 if crc != transfer_crc:
811 raise TransferError(
"CRC mismatch: expected {0:x}, got {1:x} for payload {2!r} (DTID {3:d})"
832 transfer.request_not_response
and
850 key = frame.transfer_key
853 if frame.start_of_transfer:
860 if frame.end_of_transfer:
870 for key
in transfer_keys: