Skip to content

Commit

Permalink
fix(plc4py/umas): Add Read Memory Block, need to implement little end…
Browse files Browse the repository at this point in the history
…ian reading/writing
  • Loading branch information
hutcheb committed Jan 24, 2024
1 parent a0045f0 commit 87d9276
Show file tree
Hide file tree
Showing 13 changed files with 436 additions and 24 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -229,10 +229,10 @@ class ${type.name}<#if type.isDiscriminatedParentTypeDefinition()></#if>(<#if ty

# Discriminator Field (${discriminatorField.name}) (Used as input to a switch field)
<#if typedField.type.isEnumTypeReference()>
write_buffer.${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}, logical_name="${namedField.name}", ${helper.getFieldOptions(typedField, parserArguments)})
write_buffer.${helper.getEnumDataWriterCall(typedField.type, namedField.name, "value")}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}, logical_name="${namedField.name}" ${helper.getFieldOptions(typedField, parserArguments)})
<#else>
<#assign simpleTypeReference = discriminatorField.type.asSimpleTypeReference().orElseThrow()>
write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}, logical_name="${namedField.name}", bit_length=${simpleTypeReference.sizeInBits}, ${helper.getFieldOptions(typedField, parserArguments)})
write_buffer.${helper.getDataWriterCall(typedField.type, namedField.name)}(self.${helper.camelCaseToSnakeCase(discriminatorField.name)}, logical_name="${namedField.name}", bit_length=${simpleTypeReference.sizeInBits} ${helper.getFieldOptions(typedField, parserArguments)})
</#if>
<#break>
<#case "enum">
Expand Down
14 changes: 12 additions & 2 deletions protocols/umas/src/main/resources/protocols/umas/umas.mspec
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
]
]

[type UmasPDUItem(uint 8 umasRequestFunctionKey)
[type UmasPDUItem(uint 8 umasRequestFunctionKey) byteOrder='LITTLE_ENDIAN'
[simple uint 8 pairingKey]
[discriminator uint 8 umasFunctionKey]
[typeSwitch umasFunctionKey, umasRequestFunctionKey
Expand All @@ -75,6 +75,13 @@
]
['0x04' UmasPDUPlcStatusRequest
]
['0x20' UmasPDUReadMemoryBlockRequest
[simple uint 8 unknownObject]
[simple uint 16 blockNumber]
[simple uint 16 offset]
[simple uint 16 unknownObject1]
[simple uint 16 numberOfBytes]
]

['0xFE', '0x01' UmasInitCommsResponse
[simple uint 16 maxFrameSize]
Expand Down Expand Up @@ -102,7 +109,10 @@
[simple uint 24 notUsed]
[simple uint 8 numberOfBlocks]
[array uint 32 blocks count 'numberOfBlocks']

]
['0xFE', '0x20' UmasPDUReadMemoryBlockResponse
[simple uint 16 numberOfBytes]
[array uint 8 block count 'numberOfBlocks']
]
]
]
Expand Down
47 changes: 43 additions & 4 deletions sandbox/plc4py/plc4py/drivers/umas/UmasDevice.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,18 @@
import logging
from asyncio import Transport, AbstractEventLoop
from dataclasses import dataclass, field
from typing import Dict
from typing import Dict, List

from plc4py.protocols.umas.readwrite.PlcMemoryBlockIdent import PlcMemoryBlockIdent
from plc4py.protocols.umas.readwrite.UmasPDUPlcIdentResponse import (
UmasPDUPlcIdentResponse,
)

from plc4py.protocols.umas.readwrite.UmasPDUReadMemoryBlockRequest import (
UmasPDUReadMemoryBlockRequestBuilder,
)

from plc4py.protocols.umas.readwrite.UmasInitCommsResponse import UmasInitCommsResponse

from plc4py.protocols.umas.readwrite.UmasPDUPlcStatusResponse import (
UmasPDUPlcStatusResponse,
Expand Down Expand Up @@ -55,14 +66,16 @@ class UmasDevice:
_configuration: UmasConfiguration
tags: Dict[str, PlcValue] = field(default_factory=lambda: {})
project_crc: int = -1
max_frame_size: int = -1
memory_blocks: List[PlcMemoryBlockIdent] = field(default_factory=lambda: [])

async def connect(self, transport: Transport):
# Create future to be returned when a value is returned
loop = asyncio.get_running_loop()
await self._send_plc_ident(transport, loop)
await self._send_init_comms(transport, loop)
await self._send_project_info(transport, loop)
pass
await self._send_read_memory_block(transport, loop)

async def _send_plc_ident(self, transport: Transport, loop: AbstractEventLoop):
message_future = loop.create_future()
Expand All @@ -77,7 +90,8 @@ async def _send_plc_ident(self, transport: Transport, loop: AbstractEventLoop):
)

await message_future
ident_result = message_future.result()
ident_result: UmasPDUPlcIdentResponse = message_future.result()
self.memory_blocks = ident_result.memory_idents

async def _send_init_comms(self, transport: Transport, loop: AbstractEventLoop):
message_future = loop.create_future()
Expand All @@ -92,7 +106,8 @@ async def _send_init_comms(self, transport: Transport, loop: AbstractEventLoop):
)

await message_future
init_result = message_future.result()
init_result: UmasInitCommsResponse = message_future.result()
self.max_frame_size = init_result.max_frame_size

async def _send_project_info(self, transport: Transport, loop: AbstractEventLoop):
message_future = loop.create_future()
Expand All @@ -113,6 +128,30 @@ async def _send_project_info(self, transport: Transport, loop: AbstractEventLoop
logging.debug("Received Valid Project CRC Response")
self.project_crc = project_info_result.blocks[3]

async def _send_read_memory_block(
self, transport: Transport, loop: AbstractEventLoop
):
message_future = loop.create_future()

request_pdu = UmasPDUReadMemoryBlockRequestBuilder(
block_number=0x30,
offset=0,
number_of_bytes=0x21,
unknown_object=0,
unknown_object1=0,
).build(pairing_key=0)

protocol = transport.protocol
protocol.write_wait_for_response(
request_pdu,
transport,
message_future,
)

await message_future
memory_block_result: UmasPDUPlcStatusResponse = message_future.result()
pass

async def read(
self, request: PlcReadRequest, transport: Transport
) -> PlcReadResponse:
Expand Down
10 changes: 2 additions & 8 deletions sandbox/plc4py/plc4py/protocols/modbus/readwrite/ModbusPDU.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,11 @@ def serialize(self, write_buffer: WriteBuffer):
write_buffer.push_context("ModbusPDU")

# Discriminator Field (errorFlag) (Used as input to a switch field)
write_buffer.write_bit(
self.error_flag,
logical_name="errorFlag",
bit_length=1,
)
write_buffer.write_bit(self.error_flag, logical_name="errorFlag", bit_length=1)

# Discriminator Field (functionFlag) (Used as input to a switch field)
write_buffer.write_unsigned_byte(
self.function_flag,
logical_name="functionFlag",
bit_length=7,
self.function_flag, logical_name="functionFlag", bit_length=7
)

# Switch field (Serialize the sub-type)
Expand Down
10 changes: 2 additions & 8 deletions sandbox/plc4py/plc4py/protocols/umas/readwrite/ModbusPDU.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,11 @@ def serialize(self, write_buffer: WriteBuffer):
write_buffer.push_context("ModbusPDU")

# Discriminator Field (errorFlag) (Used as input to a switch field)
write_buffer.write_bit(
self.error_flag,
logical_name="errorFlag",
bit_length=1,
)
write_buffer.write_bit(self.error_flag, logical_name="errorFlag", bit_length=1)

# Discriminator Field (functionFlag) (Used as input to a switch field)
write_buffer.write_unsigned_byte(
self.function_flag,
logical_name="functionFlag",
bit_length=7,
self.function_flag, logical_name="functionFlag", bit_length=7
)

# Switch field (Serialize the sub-type)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from plc4py.protocols.umas.readwrite.UmasPDUItem import UmasPDUItem
from plc4py.spi.generation.ReadBuffer import ReadBuffer
from plc4py.spi.generation.WriteBuffer import WriteBuffer
from plc4py.utils.GenericTypes import ByteOrder
from typing import ClassVar
import math

Expand Down Expand Up @@ -65,6 +66,7 @@ def static_parse_builder(read_buffer: ReadBuffer, umas_request_function_key: int
unknown_object: int = read_buffer.read_unsigned_byte(
logical_name="unknownObject",
bit_length=8,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from plc4py.protocols.umas.readwrite.UmasPDUItem import UmasPDUItem
from plc4py.spi.generation.ReadBuffer import ReadBuffer
from plc4py.spi.generation.WriteBuffer import WriteBuffer
from plc4py.utils.GenericTypes import ByteOrder
from typing import ClassVar
import math

Expand Down Expand Up @@ -104,36 +105,42 @@ def static_parse_builder(read_buffer: ReadBuffer, umas_request_function_key: int
max_frame_size: int = read_buffer.read_unsigned_short(
logical_name="maxFrameSize",
bit_length=16,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

firmware_version: int = read_buffer.read_unsigned_short(
logical_name="firmwareVersion",
bit_length=16,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

not_sure: int = read_buffer.read_unsigned_int(
logical_name="notSure",
bit_length=32,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

internal_code: int = read_buffer.read_unsigned_int(
logical_name="internalCode",
bit_length=32,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

hostname_length: int = read_buffer.read_unsigned_byte(
logical_name="hostnameLength",
bit_length=8,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

hostname: str = read_buffer.read_str(
logical_name="hostname",
bit_length=hostname_length * int(8),
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

Expand Down
20 changes: 20 additions & 0 deletions sandbox/plc4py/plc4py/protocols/umas/readwrite/UmasPDUItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
from plc4py.api.messages.PlcMessage import PlcMessage
from plc4py.spi.generation.ReadBuffer import ReadBuffer
from plc4py.spi.generation.WriteBuffer import WriteBuffer
from plc4py.utils.GenericTypes import ByteOrder
import math


Expand Down Expand Up @@ -58,6 +59,7 @@ def serialize(self, write_buffer: WriteBuffer):
self.umas_function_key,
logical_name="umasFunctionKey",
bit_length=8,
byte_order=ByteOrder.LITTLE_ENDIAN,
)

# Switch field (Serialize the sub-type)
Expand Down Expand Up @@ -111,12 +113,14 @@ def static_parse_context(read_buffer: ReadBuffer, umas_request_function_key: int
pairing_key: int = read_buffer.read_unsigned_byte(
logical_name="pairingKey",
bit_length=8,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

umas_function_key: int = read_buffer.read_unsigned_byte(
logical_name="umasFunctionKey",
bit_length=8,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

Expand Down Expand Up @@ -154,6 +158,14 @@ def static_parse_context(read_buffer: ReadBuffer, umas_request_function_key: int
builder = UmasPDUPlcStatusRequest.static_parse_builder(
read_buffer, umas_request_function_key
)
from plc4py.protocols.umas.readwrite.UmasPDUReadMemoryBlockRequest import (
UmasPDUReadMemoryBlockRequest,
)

if umas_function_key == int(0x20):
builder = UmasPDUReadMemoryBlockRequest.static_parse_builder(
read_buffer, umas_request_function_key
)
from plc4py.protocols.umas.readwrite.UmasInitCommsResponse import (
UmasInitCommsResponse,
)
Expand All @@ -178,6 +190,14 @@ def static_parse_context(read_buffer: ReadBuffer, umas_request_function_key: int
builder = UmasPDUPlcStatusResponse.static_parse_builder(
read_buffer, umas_request_function_key
)
from plc4py.protocols.umas.readwrite.UmasPDUReadMemoryBlockResponse import (
UmasPDUReadMemoryBlockResponse,
)

if umas_function_key == int(0xFE) and umas_request_function_key == int(0x20):
builder = UmasPDUReadMemoryBlockResponse.static_parse_builder(
read_buffer, umas_request_function_key
)
if builder is None:
raise ParseException(
"Unsupported case for discriminated type"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
from plc4py.protocols.umas.readwrite.UmasPDUItem import UmasPDUItem
from plc4py.spi.generation.ReadBuffer import ReadBuffer
from plc4py.spi.generation.WriteBuffer import WriteBuffer
from plc4py.utils.GenericTypes import ByteOrder
from typing import Any
from typing import ClassVar
from typing import List
Expand Down Expand Up @@ -153,73 +154,85 @@ def static_parse_builder(read_buffer: ReadBuffer, umas_request_function_key: int
range: int = read_buffer.read_unsigned_byte(
logical_name="range",
bit_length=8,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

ident: int = read_buffer.read_unsigned_int(
logical_name="ident",
bit_length=32,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

model: int = read_buffer.read_unsigned_short(
logical_name="model",
bit_length=16,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

com_version: int = read_buffer.read_unsigned_short(
logical_name="comVersion",
bit_length=16,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

com_patch: int = read_buffer.read_unsigned_short(
logical_name="comPatch",
bit_length=16,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

int_version: int = read_buffer.read_unsigned_short(
logical_name="intVersion",
bit_length=16,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

hardware_version: int = read_buffer.read_unsigned_short(
logical_name="hardwareVersion",
bit_length=16,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

crash_code: int = read_buffer.read_unsigned_int(
logical_name="crashCode",
bit_length=32,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

hostname_length: int = read_buffer.read_unsigned_int(
logical_name="hostnameLength",
bit_length=32,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

hostname: str = read_buffer.read_str(
logical_name="hostname",
bit_length=hostname_length * int(8),
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

number_of_memory_banks: int = read_buffer.read_unsigned_byte(
logical_name="numberOfMemoryBanks",
bit_length=8,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

memory_idents: List[Any] = read_buffer.read_array_field(
logical_name="memoryIdents",
read_function=PlcMemoryBlockIdent.static_parse,
count=number_of_memory_banks,
byte_order=ByteOrder.LITTLE_ENDIAN,
umas_request_function_key=umas_request_function_key,
)

Expand Down
Loading

0 comments on commit 87d9276

Please sign in to comment.