Skip to content

Commit

Permalink
move decoder and add test
Browse files Browse the repository at this point in the history
  • Loading branch information
drunsinn committed May 30, 2024
1 parent 7a9fb1a commit 0f78d28
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 22 deletions.
30 changes: 9 additions & 21 deletions pyLSV2/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -1366,35 +1366,23 @@ def read_plc_memory(
)
return plc_values

def read_plc_address(self, value_address: str) -> Union[None, int, float, str]:
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 value_address: address of the plc memory location in the format used by the nc like W1090, M0 or S20
: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
"""
if result := re.fullmatch(r"(?P<type>[MBWDS])(?P<num>\d+)", value_address):
if result.group("type") == "M":
val_num = int(result.group("num"))
val_type = lc.MemoryType.MARKER
elif result.group("type") == "B":
val_num = int(result.group("num"))
val_type = lc.MemoryType.BYTE
elif result.group("type") == "W":
val_num = int(result.group("num")) / 2
val_type = lc.MemoryType.WORD
elif result.group("type") == "D":
val_num = int(result.group("num")) / 4
val_type = lc.MemoryType.DWORD
else: # "S"
val_num = int(result.group("num"))
val_type = lc.MemoryType.STRING
else:
return None
return self.read_plc_memory(int(val_num), val_type, 1)[0]

m_type, m_num = lm.decode_plc_memory_address(address)

if m_type is None or m_num is None:
raise ValueError()

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

def set_keyboard_access(self, unlocked: bool) -> bool:
"""
Expand Down
44 changes: 43 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,44 @@ 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 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 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)

0 comments on commit 0f78d28

Please sign in to comment.