Skip to content

Commit

Permalink
Merge pull request #127 from danielhrisca/master
Browse files Browse the repository at this point in the history
use win-precise-time package on Windows and Python >=3.7
  • Loading branch information
christoph2 committed Feb 2, 2023
2 parents 44c2e7c + 59a9480 commit d959b9a
Show file tree
Hide file tree
Showing 14 changed files with 66 additions and 138 deletions.
2 changes: 1 addition & 1 deletion .bumpversion.cfg
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[bumpversion]
current_version = 0.19.9
current_version = 0.20.0
commit = True
tag = False

Expand Down
6 changes: 3 additions & 3 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
image: Visual Studio 2019
image: Visual Studio 2022

environment:

Expand All @@ -9,16 +9,16 @@ environment:
# The list here is complete (excluding Python 2.6, which
# isn't covered by this document) at the time of writing.

- PYTHON: "C:\\Python36"
- PYTHON: "C:\\Python37"
- PYTHON: "C:\\Python38"
- PYTHON: "C:\\Python39"
- PYTHON: "C:\\Python310"
- PYTHON: "C:\\Python36-x64"
- PYTHON: "C:\\Python311"
- PYTHON: "C:\\Python37-x64"
- PYTHON: "C:\\Python38-x64"
- PYTHON: "C:\\Python39-x64"
- PYTHON: "C:\\Python310-x64"
- PYTHON: "C:\\Python311-x64"

install:
# We need wheel installed to build wheels
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,13 @@ dependencies = [
"uptime>=3.0.1",
]
name = "pyxcp"
version = "0.19.9"
version = "0.20.0"
readme = "README.md"
description = "Universal Calibration Protocol for Python"
keywords = ["automotive", "ecu", "xcp", "asam", "autosar"]
license = {file = "LICENSE"}
classifiers = [
"Development Status :: 4 - Beta",
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers", "Topic :: Software Development",
"Topic :: Scientific/Engineering",
"License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)",
Expand Down
18 changes: 17 additions & 1 deletion pyxcp/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Universal Calibration Protocol for Python"""
import sys

if sys.platform == 'win32' and sys.version_info[:2] < (3, 11):
# patch the time module with the high resolution alternatives
try:
from win_precise_time import sleep as wpsleep
from win_precise_time import time as wptime

import time
time.sleep = wpsleep
time.time = wptime

except ImportError:
pass


from .master import Master
from .transport import Can
from .transport import Eth
from .transport import SxI
from .transport import Usb

# if you update this manually, do not forget to update .bumpversion.cfg
__version__ = "0.19.9"
__version__ = "0.20.0"
4 changes: 2 additions & 2 deletions pyxcp/master/master.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from pyxcp.master.errorhandler import disable_error_handling
from pyxcp.master.errorhandler import wrapped
from pyxcp.transport.base import createTransport
from pyxcp.utils import delay
from pyxcp.utils import delay, SHORT_SLEEP


def broadcasted(func: Callable):
Expand Down Expand Up @@ -452,7 +452,7 @@ def upload(self, length: int):
response += data[1 : rem + 1]
rem = length - len(response)
else:
sleep(0.001)
sleep(SHORT_SLEEP)

return response

Expand Down
20 changes: 5 additions & 15 deletions pyxcp/transport/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import threading
from collections import deque
from datetime import datetime
from time import get_clock_info
from time import sleep
from time import time

Expand All @@ -13,7 +12,7 @@
from ..timing import Timing
from ..utils import flatten
from ..utils import hexDump
from ..utils import time_perfcounter_correlation
from ..utils import SHORT_SLEEP
from pyxcp.config import Configuration


Expand All @@ -30,7 +29,7 @@ def get(q, timeout, restart_event):
restart_event.clear()
if time() - start > timeout:
raise Empty
sleep(0.001)
sleep(SHORT_SLEEP)

item = q.popleft()
return item
Expand Down Expand Up @@ -86,18 +85,9 @@ def __init__(self, config=None):
self.cro_callback = None

self.first_daq_timestamp = None
if get_clock_info("time").resolution > 1e-5:
ts, pc = time_perfcounter_correlation()
self.timestamp_origin = ts
self.datetime_origin = datetime.fromtimestamp(ts)
self.perf_counter_origin = pc
else:
self.timestamp_origin = time()
self.datetime_origin = datetime.fromtimestamp(self.timestamp_origin)

# we will later use this to know if the current platform has a high
# resolution time.time implementation
self.perf_counter_origin = -1
self.timestamp_origin = time()
self.datetime_origin = datetime.fromtimestamp(self.timestamp_origin)

self.pre_send_timestamp = time()
self.post_send_timestamp = time()
Expand Down Expand Up @@ -233,7 +223,7 @@ def block_receive(self, length_required: int) -> bytes:
else:
if time() - start > self.timeout:
raise types.XcpTimeoutError("Response timed out [block_receive].") from None
sleep(0.001)
sleep(SHORT_SLEEP)
return block_response

@abc.abstractmethod
Expand Down
13 changes: 3 additions & 10 deletions pyxcp/transport/can.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,16 +343,9 @@ def send(self, frame):
if self.max_dlc_required:
frame = padFrame(frame, self.padding_value, self.padding_len)
# send the request
if self.perf_counter_origin < 0:
self.pre_send_timestamp = time()
self.canInterface.transmit(payload=frame)
self.post_send_timestamp = time()
else:
pre_send_timestamp = perf_counter()
self.canInterface.transmit(payload=frame)
post_send_timestamp = perf_counter()
self.pre_send_timestamp = self.timestamp_origin + pre_send_timestamp - self.perf_counter_origin
self.post_send_timestamp = self.timestamp_origin + post_send_timestamp - self.perf_counter_origin
self.pre_send_timestamp = time()
self.canInterface.transmit(payload=frame)
self.post_send_timestamp = time()

def closeConnection(self):
if hasattr(self, "canInterface"):
Expand Down
25 changes: 6 additions & 19 deletions pyxcp/transport/eth.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import threading
from collections import deque
from pyxcp.transport.base import BaseTransport
from pyxcp.utils import SHORT_SLEEP
from time import perf_counter
from time import sleep
from time import time
Expand Down Expand Up @@ -100,10 +101,6 @@ def _packet_listen(self):
socket_fileno = self.sock.fileno
select = self.selector.select

high_resolution_time = self.perf_counter_origin < 0
timestamp_origin = self.timestamp_origin
perf_counter_origin = self.perf_counter_origin

_packets = self._packets

if use_tcp:
Expand All @@ -118,10 +115,7 @@ def _packet_listen(self):
sel = select(0.02)
for _, events in sel:
if events & EVENT_READ:
if high_resolution_time:
recv_timestamp = time()
else:
recv_timestamp = timestamp_origin + perf_counter() - perf_counter_origin
recv_timestamp = time()

if use_tcp:
response = sock_recv(RECV_SIZE)
Expand Down Expand Up @@ -164,7 +158,7 @@ def listen(self):
count = len(_packets)

if not count:
sleep(0.002)
sleep(SHORT_SLEEP)
continue

for _ in range(count):
Expand Down Expand Up @@ -199,16 +193,9 @@ def listen(self):
break

def send(self, frame):
if self.perf_counter_origin < 0:
self.pre_send_timestamp = time()
self.sock.send(frame)
self.post_send_timestamp = time()
else:
pre_send_timestamp = perf_counter()
self.sock.send(frame)
post_send_timestamp = perf_counter()
self.pre_send_timestamp = self.timestamp_origin + pre_send_timestamp - self.perf_counter_origin
self.post_send_timestamp = self.timestamp_origin + post_send_timestamp - self.perf_counter_origin
self.pre_send_timestamp = time()
self.sock.send(frame)
self.post_send_timestamp = time()

def closeConnection(self):
if not self.invalidSocket:
Expand Down
22 changes: 5 additions & 17 deletions pyxcp/transport/sxi.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,14 @@ def flush(self):
self.commPort.flush()

def listen(self):
high_resolution_time = self.perf_counter_origin < 0
timestamp_origin = self.timestamp_origin
perf_counter_origin = self.perf_counter_origin

while True:
if self.closeEvent.isSet():
return
if not self.commPort.inWaiting():
continue
if high_resolution_time:
recv_timestamp = time()
else:
recv_timestamp = timestamp_origin + perf_counter() - perf_counter_origin

recv_timestamp = time()
length, counter = self.HEADER.unpack(self.commPort.read(self.HEADER_SIZE))

response = self.commPort.read(length)
Expand All @@ -82,16 +77,9 @@ def listen(self):
self.processResponse(response, length, counter, recv_timestamp)

def send(self, frame):
if self.perf_counter_origin < 0:
self.pre_send_timestamp = time()
self.commPort.write(frame)
self.post_send_timestamp = time()
else:
pre_send_timestamp = perf_counter()
self.commPort.write(frame)
post_send_timestamp = perf_counter()
self.pre_send_timestamp = self.timestamp_origin + pre_send_timestamp - self.perf_counter_origin
self.post_send_timestamp = self.timestamp_origin + post_send_timestamp - self.perf_counter_origin
self.pre_send_timestamp = time()
self.commPort.write(frame)
self.post_send_timestamp = time()

def closeConnection(self):
if hasattr(self, "commPort") and self.commPort.isOpen():
Expand Down
51 changes: 16 additions & 35 deletions pyxcp/transport/usb_transport.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from array import array
from collections import deque
from pyxcp.transport.base import BaseTransport
from pyxcp.utils import SHORT_SLEEP
from time import perf_counter
from time import sleep
from time import time
Expand Down Expand Up @@ -94,10 +95,6 @@ def _packet_listen(self):

close_event_set = self.closeEvent.isSet

high_resolution_time = self.perf_counter_origin < 0
timestamp_origin = self.timestamp_origin
perf_counter_origin = self.perf_counter_origin

_packets = self._packets
read = self.reply_endpoint.read

Expand All @@ -110,18 +107,15 @@ def _packet_listen(self):
return

try:
if high_resolution_time:
recv_timestamp = time()
else:
recv_timestamp = timestamp_origin + perf_counter() - perf_counter_origin
recv_timestamp = time()
read_count = read(buffer, 100) # 100ms timeout
if read_count != RECV_SIZE:
_packets.append((buffer_view[:read_count].tobytes(), recv_timestamp))
else:
_packets.append((buffer.tobytes(), recv_timestamp))
except BaseException:
# print(format_exc())
sleep(0.001)
sleep(SHORT_SLEEP)
continue

except BaseException:
Expand Down Expand Up @@ -151,7 +145,7 @@ def listen(self):
count = len(_packets)

if not count:
sleep(0.001)
sleep(SHORT_SLEEP)
last_sleep = perf_counter()
continue

Expand All @@ -164,7 +158,7 @@ def listen(self):

while True:
if perf_counter() - last_sleep >= 0.005:
sleep(0.001)
sleep(SHORT_SLEEP)
last_sleep = perf_counter()

if length is None:
Expand All @@ -191,30 +185,17 @@ def listen(self):
break

def send(self, frame):
if self.perf_counter_origin < 0:
self.pre_send_timestamp = time()
try:
self.command_endpoint.write(frame)
except BaseException:
# sometimes usb.core.USBError: [Errno 5] Input/Output Error is raised
# even though the command is send and a reply is received from the device.
# Ignore this here since a Timeout error will be raised anyway if
# the device does not respond
pass
self.post_send_timestamp = time()
else:
pre_send_timestamp = perf_counter()
try:
self.command_endpoint.write(frame)
except BaseException:
# sometimes usb.core.USBError: [Errno 5] Input/Output Error is raised
# even though the command is send and a reply is received from the device.
# Ignore this here since a Timeout error will be raised anyway if
# the device does not respond
pass
post_send_timestamp = perf_counter()
self.pre_send_timestamp = self.timestamp_origin + pre_send_timestamp - self.perf_counter_origin
self.post_send_timestamp = self.timestamp_origin + post_send_timestamp - self.perf_counter_origin

self.pre_send_timestamp = time()
try:
self.command_endpoint.write(frame)
except BaseException:
# sometimes usb.core.USBError: [Errno 5] Input/Output Error is raised
# even though the command is send and a reply is received from the device.
# Ignore this here since a Timeout error will be raised anyway if
# the device does not respond
pass
self.post_send_timestamp = time()

def closeConnection(self):
if self.device is not None:
Expand Down

0 comments on commit d959b9a

Please sign in to comment.