hardbyte / python-can

The can package provides controller area network support for Python developers
https://python-can.readthedocs.io
GNU Lesser General Public License v3.0
1.31k stars 604 forks source link

Timestamp synchronization between interface hardware and local time #1861

Open mdabrowski1990 opened 2 months ago

mdabrowski1990 commented 2 months ago

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

As a user, I would like to have synchronization between hardware time (currently I am using Kvaser, but it relates to all interfaces) and local time, so I can tell when certain frame was received/transmitted in local computer time.

This code shows the problem I am facing:

from time import time

from can import BufferedReader, Bus, Message, Notifier

if __name__ == "__main__":
    kvaser_interface_1 = Bus(interface="kvaser", channel=0, fd=True, receive_own_messages=True)
    kvaser_interface_2 = Bus(interface="kvaser", channel=1, fd=True, receive_own_messages=True)  # connected with bus 1 to aknowledge frames

    buffered_reader = BufferedReader()
    notifier = Notifier(bus=kvaser_interface_1, listeners=[buffered_reader])

    message = Message(data=[0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0], arbitration_id=0x100)

    for _ in range(10):
        timestamp_before_send = time()
        kvaser_interface_1.send(message)
        sent_message = buffered_reader.get_message(timeout=1)
        timestamp_after_send = time()

        print(f"-----------------------------------------------\n"
              f"Result:\n"
              f"Timestamp before send: {timestamp_before_send}\n"
              f"Message timestamp: {sent_message.timestamp}\n"
              f"Current timestamp: {timestamp_after_send}\n"
              f"Message timestamp - Timestamp before send: {sent_message.timestamp - timestamp_before_send} (expected > 0)\n"
              f"Current timestamp - Message timestamp: {timestamp_after_send - sent_message.timestamp} (expected > 0)\n"
              f"Timestamp before send <= Message timestamp <= Current timestamp: {timestamp_before_send <= sent_message.timestamp <= timestamp_after_send} (expected `True`)")

    kvaser_interface_1.shutdown()
    kvaser_interface_2.shutdown()

Example result:

Result:
Timestamp before send: 1726742267.3760204
Message timestamp: 1726735815.9516842
Current timestamp: 1726742267.3770118
Message timestamp - Timestamp before send: -6451.424336194992 (expected > 0)
Current timestamp - Message timestamp: 6451.425327539444 (expected > 0)
Timestamp before send <= Message timestamp <= Current timestamp: False (expected `True`)

Describe the solution you'd like

I would like to have a variable that provides local hardware time. Example:

from time import time

from can import Bus

if __name__ == "__main__":
    kvaser_interface_1 = Bus(interface="kvaser", channel=0, fd=True, receive_own_messages=True)
    kvaser_interface_1.time() != time()

Describe alternatives you've considered

Synchronize Message.timestamp with local time.

Additional context

Related to https://github.com/mdabrowski1990/uds/issues/228 in my project which uses python-can as handler for CAN communication.