""" NMEA2000 Nachricht """ import can import struct from math import ceil from .pgntype import pgntype class Message(): def __init__(self, bus, source, data=None): self._bus = bus self._source = source self._priority = 5 if data: print("msg: set data: ", type(data)) self._data = data else: self._data = bytearray() self.pgn = None #self.sequence = 0xff self.sequence = 0 def set_pgn(self, pgn): self.pgn = pgn def set_priority(self, priority): self._priority = priority def get_fast_frames(self, rawdata, sc): # Erstelle ein Liste von Frames aufgrund vorliegender Rohdaten # zum transferieren von bis zu 223 Bytes über eine fast-Message # Der sequence-counter muß extern inkrementiert werden, er hat # 3 Bit Länge. Der Framecounter fc hat eine Länge von 5 Bit. # Der erste Frame kann 6 Bytes aufnehmen # Alle weiteren Frames jeweils 7 Bytes datalen = len(rawdata) if datalen > 223: raise ValueError("data for fast packet too long") if datalen < 7: raise ValueError("data for fast packet too short") nf = ceil((datalen - 6) / 7 + 1) # number of frames fc = 0 # frame counter, nibble 2 frames = list() # Frame 1 data = bytearray() data.append((sc << 5) + fc) data.append(datalen) for b in rawdata[:6]: data.append(b) frames.append(data) nf -= 1 # Frame 2..n p = 6 while nf > 0: data = bytearray() fc += 1 data.append((sc << 5) + fc) for b in rawdata[p:p+7]: data.append(b) frames.append(data) p += 7 nf -= 1 print("message:get_fast_frames") print(frames) return frames def send_single(self): msg = can.Message( arbitration_id = (((self._priority << 18) + self.pgn) << 8) + self._source, data = self._data, is_extended_id = True ); try: self._bus.send(msg) except can.CanError: print(f"Message {self.pgn} NOT sent") return False return True def send_fast(self): id = (((self._priority << 18) + self.pgn) << 8) + self._source try: for frame in self.get_fast_frames(self._data, self.sequence): msg = can.Message( arbitration_id = id, data = frame, is_extended_id = True ); self._bus.send(msg) except can.CanError: print(f"Message {self.pgn} NOT sent") return False finally: self.sequence += 1 self.sequence %= 8 print("send fast: adjusted sequence {}".format(self.sequence)) return True def send(self): if pgntype(self.pgn) == "S": self.send_single() else: self.send_fast()