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

viewer with CAN-FD, print packets with variable DLC but same ID in different lines #1737

Open
kgmuzungu opened this issue Jan 31, 2024 · 1 comment

Comments

@kgmuzungu
Copy link

Is your feature request related to a problem? Please describe.

I am reading the CAN-FD bus of BOSCH SMART SYSTEM ebikes. For example packets with ID 0x507 can have data lengths of 20, 24, 32 ,48. They are written on top of each other in the console output of the viewer script and count is reset.

Describe the solution you'd like

Use a separate line for a packet with same ID and same DLC. Note that CAN FD there can be various DLCs for same IDs

Describe alternatives you've considered

Additional context

I am reading the CAN-FD bus of BOSCH SMART SYSTEM ebikes. For example packets with ID 0x507 can have data lengths of 20, 24, 32 ,48.

@kgmuzungu
Copy link
Author

I have here a simple solution:

in viewre.py replace the function def draw_can_bus_message(self, msg, sorting=False):
with the code below. I could integrate this switched as an option if others would be interested.

   def draw_can_bus_message(self, msg, sorting=False):
        # Use the CAN-Bus ID as the key in the dict

        # inlcude dlc in the key
        key = str(msg.arbitration_id) + str(msg.dlc)
        #key = msg.arbitration_id + msg.dlc  #?? strings or ints
        #key = msg.arbitration_id

        # Sort the extended IDs at the bottom by setting the 32-bit high
        #if msg.is_extended_id:
        #    key |= 1 << 32

        new_key_added, length_changed = False, False
        if not sorting:
            # Check if it is a new message or if the length is not the same
            if key not in self.ids:
                new_key_added = True
                # Set the start time when the first message has been received
                if not self.start_time:
                    self.start_time = msg.timestamp
            '''
            elif msg.dlc != self.ids[key]["msg"].dlc:
                length_changed = True

                # Clear the old data bytes when the length of the new message is shorter
                if msg.dlc < self.ids[key]["msg"].dlc:
                    self.draw_line(
                        self.ids[key]["row"],
                        # Start drawing at the last byte that is not in the new message
                        52 + msg.dlc * 3,
                        # Draw spaces where the old bytes were drawn
                        " " * ((self.ids[key]["msg"].dlc - msg.dlc) * 3 - 1),
                    )
            '''

            if new_key_added or length_changed:
                # Increment the index if it was just added, but keep it if the length just changed
                row = len(self.ids) + 1 if new_key_added else self.ids[key]["row"]

                # It's a new message ID or the length has changed, so add it to the dict
                # The first index is the row index, the second is the frame counter,
                # the third is a copy of the CAN-Bus frame
                # and the forth index is the time since the previous message
                self.ids[key] = {"row": row, "count": 0, "msg": msg, "dt": 0}
            else:
                # Calculate the time since the last message and save the timestamp
                self.ids[key]["dt"] = msg.timestamp - self.ids[key]["msg"].timestamp

                # Copy the CAN-Bus frame - this is used for sorting
                self.ids[key]["msg"] = msg

            # Increment frame counter
            self.ids[key]["count"] += 1

        # Format the CAN-Bus ID as a hex value
        arbitration_id_string = (
            "0x{0:0{1}X}".format(  # pylint: disable=consider-using-f-string
                msg.arbitration_id,
                8 if msg.is_extended_id else 3,
            )
        )

        # Use red for error frames
        if msg.is_error_frame:
            color = curses.color_pair(1)
        else:
            color = curses.color_pair(0)

        # Now draw the CAN-Bus message on the terminal window
        self.draw_line(self.ids[key]["row"], 0, str(self.ids[key]["count"]), color)
        self.draw_line(
            self.ids[key]["row"],
            8,
            f"{self.ids[key]['msg'].timestamp - self.start_time:.6f}",
            color,
        )
        self.draw_line(self.ids[key]["row"], 23, f"{self.ids[key]['dt']:.6f}", color)
        self.draw_line(self.ids[key]["row"], 35, arbitration_id_string, color)
        self.draw_line(self.ids[key]["row"], 47, str(msg.dlc), color)

        try:
            previous_byte_values = self.previous_values[key]
        except KeyError:  # no row of previous values exists for the current message ID
            # initialise a row to store the values for comparison next time
            self.previous_values[key] = {}
            previous_byte_values = self.previous_values[key]
        for i, b in enumerate(msg.data):
            col = 52 + i * 3
            if col > self.x - 2:
                # Data does not fit
                self.draw_line(self.ids[key]["row"], col - 4, "...", color)
                break
            if self.highlight_changed_bytes:
                try:
                    if b != previous_byte_values[i]:
                        # set colour to highlight a changed value
                        data_color = curses.color_pair(2)
                    else:
                        data_color = color
                except KeyError:
                    # previous entry for byte didn't exist - default to rest of line colour
                    data_color = color
                finally:
                    # write the new value to the previous values dict for next time
                    previous_byte_values[i] = b
            else:
                data_color = color
            text = f"{b:02X}"
            self.draw_line(self.ids[key]["row"], col, text, data_color)

        if self.data_structs:
            try:
                values_list = []
                for x in self.unpack_data(
                    msg.arbitration_id, self.data_structs, msg.data
                ):
                    if isinstance(x, float):
                        values_list.append(f"{x:.6f}")
                    else:
                        values_list.append(str(x))
                values_string = " ".join(values_list)
                self.ids[key]["values_string_length"] = len(values_string)
                values_string += " " * (self.x - len(values_string))

                self.draw_line(self.ids[key]["row"], 77, values_string, color)
            except (ValueError, struct.error):
                pass

        return self.ids[key]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant