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

Nativ plc addressing #68

Merged
merged 6 commits into from
Jun 24, 2024
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
20 changes: 19 additions & 1 deletion pyLSV2/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1377,6 +1377,24 @@ def read_plc_memory(
)
return plc_values

def read_plc_address(self, address: str) -> Union[None, int, float, str]:
"""
read from plc memory using the nativ addressing scheme of the control
Requires access level ``PLCDEBUG`` to work.

:param address: address of the plc memory location in the format used by the nc like W1090, M0 or S20

:raises LSV2InputException: if unknowns memory type is requested or if the to many elements are requested
:raises LSV2DataException: if number of received values does not match the number of expected
"""

m_type, m_num = lm.decode_plc_memory_address(address)

if m_type is None or m_num is None:
raise LSV2InputException("could not translate address %s to valid memory location" % address)

return self.read_plc_memory(m_num, m_type, 1)[0]

def set_keyboard_access(self, unlocked: bool) -> bool:
"""
Enable or disable the keyboard on the control.
Expand Down Expand Up @@ -1629,7 +1647,7 @@ def get_file_list(self, path: str = "", descend: bool = True, pattern: str = "")
return []

if self.change_directory(path) is False:
self._logger.warning("could not change to directory %s" % path)
self._logger.warning("could not change to directory %s", path)
return []

if len(pattern) == 0:
Expand Down
50 changes: 49 additions & 1 deletion pyLSV2/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
# -*- coding: utf-8 -*-
"""misc helper functions for pyLSV2"""
import struct
import re
from datetime import datetime
from pathlib import Path
from typing import Union, List, Dict

from . import dat_cls as ld
from .const import BIN_FILES, PATH_SEP, ControlType
from .const import BIN_FILES, PATH_SEP, ControlType, MemoryType
from .err import LSV2DataException


Expand Down Expand Up @@ -328,3 +329,50 @@ def decode_timestamp(data_set: bytearray) -> datetime:
"""
timestamp = struct.unpack("!L", data_set[0:4])[0]
return datetime.fromtimestamp(timestamp)


def decode_plc_memory_address(address: str):
"""
Decode memory address location from the format used by the plc program to
sequential representation.
"""
val_num = None
val_type = None
if result := re.fullmatch(r"(?P<m_type>[MBWDSIO])(?P<s_type>[WD])?(?P<num>\d+)", address):
m_type = result.group("m_type")
s_type = result.group("s_type")
num = int(result.group("num"))
val_num = num

if m_type == "M" and s_type is None:
val_type = MemoryType.MARKER
elif m_type == "B" and s_type is None:
val_type = MemoryType.BYTE
elif m_type == "W" and s_type is None:
val_num = int(val_num / 2)
val_type = MemoryType.WORD
elif m_type == "D" and s_type is None:
val_num = int(val_num / 4)
val_type = MemoryType.DWORD
elif m_type == "I":
if s_type is None:
val_type = MemoryType.INPUT
elif s_type == "W":
val_num = int(val_num / 2)
val_type = MemoryType.INPUT_WORD
elif s_type == "D":
val_num = int(val_num / 4)
val_type = MemoryType.INPUT_DWORD
elif m_type == "O":
if s_type is None:
val_type = MemoryType.OUTPUT
elif s_type == "W":
val_num = int(val_num / 2)
val_type = MemoryType.OUTPUT_WORD
elif s_type == "D":
val_num = int(val_num / 4)
val_type = MemoryType.OUTPUT_DWORD
elif m_type == "S" and s_type is None:
val_type = MemoryType.STRING

return val_type, val_num
28 changes: 28 additions & 0 deletions tests/test_misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import tempfile
from pathlib import Path
import pyLSV2
import pyLSV2.misc


def test_grab_screen_dump(address: str, timeout: float):
Expand All @@ -18,3 +19,30 @@ def test_grab_screen_dump(address: str, timeout: float):
assert local_bmp_path.stat().st_size > 1

lsv2.disconnect()


def test_plc_address_decode():
"""test the decode function for plc memory addresses"""

assert pyLSV2.misc.decode_plc_memory_address("M0001") == (pyLSV2.const.MemoryType.MARKER, 1)
assert pyLSV2.misc.decode_plc_memory_address("M0") == (pyLSV2.const.MemoryType.MARKER, 0)
assert pyLSV2.misc.decode_plc_memory_address("M1") == (pyLSV2.const.MemoryType.MARKER, 1)
assert pyLSV2.misc.decode_plc_memory_address("M1234") == (pyLSV2.const.MemoryType.MARKER, 1234)

assert pyLSV2.misc.decode_plc_memory_address("B0") == (pyLSV2.const.MemoryType.BYTE, 0)
assert pyLSV2.misc.decode_plc_memory_address("W0") == (pyLSV2.const.MemoryType.WORD, 0)
assert pyLSV2.misc.decode_plc_memory_address("D0") == (pyLSV2.const.MemoryType.DWORD, 0)

assert pyLSV2.misc.decode_plc_memory_address("B4") == (pyLSV2.const.MemoryType.BYTE, 4)
assert pyLSV2.misc.decode_plc_memory_address("W4") == (pyLSV2.const.MemoryType.WORD, 2)
assert pyLSV2.misc.decode_plc_memory_address("D4") == (pyLSV2.const.MemoryType.DWORD, 1)

assert pyLSV2.misc.decode_plc_memory_address("B16") == (pyLSV2.const.MemoryType.BYTE, 16)
assert pyLSV2.misc.decode_plc_memory_address("W16") == (pyLSV2.const.MemoryType.WORD, 8)
assert pyLSV2.misc.decode_plc_memory_address("D16") == (pyLSV2.const.MemoryType.DWORD, 4)

assert pyLSV2.misc.decode_plc_memory_address("O8") == (pyLSV2.const.MemoryType.OUTPUT, 8)
assert pyLSV2.misc.decode_plc_memory_address("OW8") == (pyLSV2.const.MemoryType.OUTPUT_WORD, 4)

assert pyLSV2.misc.decode_plc_memory_address("I8") == (pyLSV2.const.MemoryType.INPUT, 8)
assert pyLSV2.misc.decode_plc_memory_address("IW8") == (pyLSV2.const.MemoryType.INPUT_WORD, 4)
29 changes: 29 additions & 0 deletions tests/test_plc_read.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,32 @@ def test_comapare_values(address: str, timeout: float):
assert v1 == v2

lsv2.disconnect()


def test_plc_mem_access(address: str, timeout: float):
"""test to see if reading via plc address and plc memory returns the same value"""

lsv2 = pyLSV2.LSV2(address, port=19000, timeout=timeout, safe_mode=False)
lsv2.connect()

for mem_address in [0, 1, 2, 4, 8, 12, 68, 69, 151, 300, 420]:
v1 = lsv2.read_plc_memory(mem_address, pyLSV2.MemoryType.DWORD, 1)[0]
v2 = lsv2.read_plc_address("D%d" % (mem_address * 4))
assert v1 == v2

for mem_address in [0, 1, 2, 4, 8, 12, 68, 69, 151, 300, 420]:
v1 = lsv2.read_plc_memory(mem_address, pyLSV2.MemoryType.WORD, 1)[0]
v2 = lsv2.read_plc_address("W%d" % (mem_address * 2))
assert v1 == v2

for mem_address in [0, 1, 2, 4, 8, 12, 68, 69, 151, 300, 420]:
v1 = lsv2.read_plc_memory(mem_address, pyLSV2.MemoryType.BYTE, 1)[0]
v2 = lsv2.read_plc_address("B%d" % (mem_address * 1))
assert v1 == v2

for mem_address in [0, 1, 2, 4, 8, 12, 68, 69, 151, 300, 420]:
v1 = lsv2.read_plc_memory(mem_address, pyLSV2.MemoryType.MARKER, 1)[0]
v2 = lsv2.read_plc_address("M%d" % (mem_address * 1))
assert v1 == v2

lsv2.disconnect()
Loading