Skip to content

Commit b6481ec

Browse files
authored
Add support for read/write unsigned value from bytearray (#316)
* add support for read/write unsigned int values from bytearray * add support for read/write unsigned dint values from bytearray * Add uint and udint types to ROW API
1 parent b4f01cf commit b6481ec

File tree

1 file changed

+120
-3
lines changed

1 file changed

+120
-3
lines changed

snap7/util.py

Lines changed: 120 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -306,6 +306,60 @@ def get_int(bytearray_: bytearray, byte_index: int) -> int:
306306
return value
307307

308308

309+
def set_uint(bytearray_: bytearray, byte_index: int, _int: int):
310+
"""Set value in bytearray to unsigned int
311+
312+
Notes:
313+
An datatype `uint` in the PLC consists of two `bytes`.
314+
315+
Args:
316+
bytearray_: buffer to write on.
317+
byte_index: byte index to start writing from.
318+
_int: int value to write.
319+
320+
Returns:
321+
Buffer with the written value.
322+
323+
Examples:
324+
>>> data = bytearray(2)
325+
>>> snap7.util.set_uint(data, 0, 65535)
326+
bytearray(b'\\xff\\xff')
327+
"""
328+
# make sure were dealing with an int
329+
_int = int(_int)
330+
_bytes = struct.unpack('2B', struct.pack('>H', _int))
331+
bytearray_[byte_index:byte_index + 2] = _bytes
332+
return bytearray_
333+
334+
335+
def get_uint(bytearray_: bytearray, byte_index: int) -> int:
336+
"""Get unsigned int value from bytearray.
337+
338+
Notes:
339+
Datatype `uint` in the PLC is represented in two bytes
340+
Maximum posible value is 65535.
341+
Lower posible value is 0.
342+
343+
Args:
344+
bytearray_: buffer to read from.
345+
byte_index: byte index to start reading from.
346+
347+
Returns:
348+
Value read.
349+
350+
Examples:
351+
>>> data = bytearray([255, 255])
352+
>>> snap7.util.get_uint(data, 0)
353+
65535
354+
"""
355+
data = bytearray_[byte_index:byte_index + 2]
356+
data[1] = data[1] & 0xff
357+
data[0] = data[0] & 0xff
358+
packed = struct.pack('2B', *data)
359+
value = struct.unpack('>H', packed)[0]
360+
return value
361+
362+
309363
def set_real(bytearray_: bytearray, byte_index: int, real) -> bytearray:
310364
"""Set Real value
311365
@@ -528,6 +582,57 @@ def set_dint(bytearray_: bytearray, byte_index: int, dint: int):
528582
bytearray_[byte_index + i] = b
529583

530584

585+
def get_udint(bytearray_: bytearray, byte_index: int) -> int:
586+
"""Get unsigned dint value from bytearray.
587+
588+
Notes:
589+
Datatype `udint` consists in 4 bytes in the PLC.
590+
Maximum possible value is 4294967295.
591+
Minimum posible value is 0.
592+
593+
Args:
594+
bytearray_: buffer to read.
595+
byte_index: byte index from where to start reading.
596+
597+
Returns:
598+
Value read.
599+
600+
Examples:
601+
>>> import struct
602+
>>> data = bytearray(4)
603+
>>> data[:] = struct.pack(">I", 4294967295)
604+
>>> snap7.util.get_udint(data, 0)
605+
4294967295
606+
"""
607+
data = bytearray_[byte_index:byte_index + 4]
608+
dint = struct.unpack('>I', struct.pack('4B', *data))[0]
609+
return dint
610+
611+
612+
def set_udint(bytearray_: bytearray, byte_index: int, dint: int):
613+
"""Set value in bytearray to unsigned dint
614+
615+
Notes:
616+
Datatype `dint` consists in 4 bytes in the PLC.
617+
Maximum possible value is 4294967295.
618+
Minimum posible value is 0.
619+
620+
Args:
621+
bytearray_: buffer to write.
622+
byte_index: byte index from where to start writing.
623+
624+
Examples:
625+
>>> data = bytearray(4)
626+
>>> snap7.util.set_udint(data, 0, 4294967295)
627+
>>> data
628+
bytearray(b'\\xff\\xff\\xff\\xff')
629+
"""
630+
dint = int(dint)
631+
_bytes = struct.unpack('4B', struct.pack('>I', dint))
632+
for i, b in enumerate(_bytes):
633+
bytearray_[byte_index + i] = b
634+
635+
531636
def get_s5time(bytearray_: bytearray, byte_index: int) -> str:
532637
micro_to_milli = 1000
533638
data_bytearray = bytearray_[byte_index:byte_index + 2]
@@ -1096,9 +1201,15 @@ def get_value(self, byte_index: Union[str, int], type_: str) -> Union[ValueError
10961201
elif type_ == 'DWORD':
10971202
return get_dword(bytearray_, byte_index)
10981203

1204+
elif type_ == 'UDINT':
1205+
return get_udint(bytearray_, byte_index)
1206+
10991207
elif type_ == 'DINT':
11001208
return get_dint(bytearray_, byte_index)
11011209

1210+
elif type_ == 'UINT':
1211+
return get_uint(bytearray_, byte_index)
1212+
11021213
elif type_ == 'INT':
11031214
return get_int(bytearray_, byte_index)
11041215

@@ -1173,9 +1284,15 @@ def set_value(self, byte_index: Union[str, int], type: str, value: Union[bool, s
11731284
elif type == 'DWORD' and isinstance(value, int):
11741285
return set_dword(bytearray_, byte_index, value)
11751286

1287+
elif type == 'UDINT' and isinstance(value, int):
1288+
return set_udint(bytearray_, byte_index, value)
1289+
11761290
elif type == 'DINT' and isinstance(value, int):
11771291
return set_dint(bytearray_, byte_index, value)
11781292

1293+
elif type == 'UINT' and isinstance(value, int):
1294+
return set_uint(bytearray_, byte_index, value)
1295+
11791296
elif type == 'INT' and isinstance(value, int):
11801297
return set_int(bytearray_, byte_index, value)
11811298

@@ -1188,13 +1305,13 @@ def set_value(self, byte_index: Union[str, int], type: str, value: Union[bool, s
11881305
elif type == 'SINT' and isinstance(value, int):
11891306
return set_sint(bytearray_, byte_index, value)
11901307

1191-
if type == 'USINT' and isinstance(value, int):
1308+
elif type == 'USINT' and isinstance(value, int):
11921309
return set_usint(bytearray_, byte_index, value)
11931310

1194-
if type == 'SINT' and isinstance(value, int):
1311+
elif type == 'SINT' and isinstance(value, int):
11951312
return set_sint(bytearray_, byte_index, value)
11961313

1197-
if type == 'TIME' and isinstance(value, str):
1314+
elif type == 'TIME' and isinstance(value, str):
11981315
return set_time(bytearray_, byte_index, value)
11991316

12001317
raise ValueError

0 commit comments

Comments
 (0)