Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Homepage = "https://github.com/gijzelaerr/python-snap7"
Documentation = "https://python-snap7.readthedocs.io/en/latest/"

[project.optional-dependencies]
test = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-html", "mypy", "types-setuptools", "ruff", "tox", "tox-uv", "types-click", "uv"]
test = ["pytest", "pytest-asyncio", "pytest-cov", "pytest-html", "hypothesis", "mypy", "types-setuptools", "ruff", "tox", "tox-uv", "types-click", "uv"]
cli = ["rich", "click" ]
doc = ["sphinx", "sphinx_rtd_theme"]

Expand All @@ -52,6 +52,7 @@ markers =[
"client",
"common",
"e2e: end-to-end tests requiring a real PLC connection",
"hypothesis: property-based tests using Hypothesis",
"logo",
"mainloop",
"partner",
Expand Down
27 changes: 25 additions & 2 deletions snap7/util/getters.py
Original file line number Diff line number Diff line change
Expand Up @@ -660,15 +660,38 @@ def get_ldt(bytearray_: Buffer, byte_index: int) -> datetime:


def get_dtl(bytearray_: Buffer, byte_index: int) -> datetime:
"""Get DTL (Date and Time Long) value from bytearray.

Notes:
Datatype ``DTL`` consists of 12 bytes in the PLC:
- Bytes 0-1: Year (uint16, big-endian)
- Byte 2: Month (1-12)
- Byte 3: Day (1-31)
- Byte 4: Weekday (1=Sunday, 7=Saturday)
- Byte 5: Hour (0-23)
- Byte 6: Minute (0-59)
- Byte 7: Second (0-59)
- Bytes 8-11: Nanoseconds (uint32, big-endian)

Args:
bytearray_: buffer to read from.
byte_index: byte index from where to start reading.

Returns:
datetime value (microsecond precision; sub-microsecond nanoseconds are truncated).
"""
nanoseconds = struct.unpack(">I", bytearray_[byte_index + 8 : byte_index + 12])[0]
microsecond = nanoseconds // 1000

time_to_datetime = datetime(
year=int.from_bytes(bytearray_[byte_index : byte_index + 2], byteorder="big"),
month=int(bytearray_[byte_index + 2]),
day=int(bytearray_[byte_index + 3]),
hour=int(bytearray_[byte_index + 5]),
minute=int(bytearray_[byte_index + 6]),
second=int(bytearray_[byte_index + 7]),
microsecond=int(bytearray_[byte_index + 8]),
) # --- ? noch nicht genau genug
microsecond=microsecond,
)
if time_to_datetime > datetime(2554, 12, 31, 23, 59, 59):
raise ValueError("date_val is higher than specification allows.")
return time_to_datetime
Expand Down
10 changes: 8 additions & 2 deletions snap7/util/setters.py
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ def set_date(bytearray_: Buffer, byte_index: int, date_: date) -> Buffer:
elif date_ > date(2168, 12, 31):
raise ValueError("date is higher than specification allows.")
_days = (date_ - date(1990, 1, 1)).days
bytearray_[byte_index : byte_index + 2] = struct.pack(">h", _days)
bytearray_[byte_index : byte_index + 2] = struct.pack(">H", _days)
return bytearray_


Expand Down Expand Up @@ -595,6 +595,12 @@ def set_wstring(bytearray_: Buffer, byte_index: int, value: str, max_size: int =
if max_size > 16382:
raise ValueError(f"max_size: {max_size} > max. allowed 16382 chars")

if any(ord(c) > 0xFFFF for c in value):
raise ValueError(
"Value contains characters outside the Basic Multilingual Plane (codepoint > U+FFFF), "
"which are not supported by the PLC WSTRING type."
)

size = len(value)
if size > max_size:
raise ValueError(f"size {size} > max_size {max_size}")
Expand Down Expand Up @@ -632,7 +638,7 @@ def set_tod(bytearray_: Buffer, byte_index: int, tod: timedelta) -> Buffer:
"""
if tod.days >= 1 or tod < timedelta(0):
raise ValueError("TIME_OF_DAY must be between 00:00:00.000 and 23:59:59.999")
ms = int(tod.total_seconds() * 1000)
ms = (tod.days * 86400 + tod.seconds) * 1000 + tod.microseconds // 1000
bytearray_[byte_index : byte_index + 4] = ms.to_bytes(4, byteorder="big")
return bytearray_

Expand Down
Loading
Loading