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
8 changes: 4 additions & 4 deletions pymodbus/pdu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
__all__ = [
"DecodePDU",
"ExceptionResponse",
"ExceptionResponse",
"FileRecord",
"ModbusPDU",
]

from pymodbus.pdu.decoders import DecodePDU
from pymodbus.pdu.file_message import FileRecord
from pymodbus.pdu.pdu import ExceptionResponse, ModbusPDU
from .decoders import DecodePDU
from .exceptionresponse import ExceptionResponse
from .file_message import FileRecord
from .pdu import ModbusPDU
3 changes: 2 additions & 1 deletion pymodbus/pdu/bit_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from pymodbus.constants import ModbusStatus
from pymodbus.datastore import ModbusDeviceContext

from .pdu import ExceptionResponse, ModbusPDU, pack_bitstring, unpack_bitstring
from .exceptionresponse import ExceptionResponse
from .pdu import ModbusPDU, pack_bitstring, unpack_bitstring


class ReadCoilsRequest(ModbusPDU):
Expand Down
3 changes: 2 additions & 1 deletion pymodbus/pdu/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@
from collections import OrderedDict

from pymodbus.constants import DeviceInformation
from pymodbus.pdu.events import ModbusEvent
from pymodbus.utilities import dict_property

from .events import ModbusEvent


# ---------------------------------------------------------------------------#
# Modbus Plus Statistics
Expand Down
2 changes: 1 addition & 1 deletion pymodbus/pdu/diag_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

from pymodbus.constants import ModbusPlusOperation
from pymodbus.datastore import ModbusDeviceContext
from pymodbus.pdu.device import ModbusControlBlock

from .device import ModbusControlBlock
from .pdu import ModbusPDU, pack_bitstring


Expand Down
51 changes: 51 additions & 0 deletions pymodbus/pdu/exceptionresponse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
"""Contains exceptionResponse class for modbus."""
from __future__ import annotations

import struct

from .pdu import ModbusPDU


class ExceptionResponse(ModbusPDU):
"""Base class for a modbus exception PDU."""

rtu_frame_size = 5

ILLEGAL_FUNCTION = 0x01
ILLEGAL_ADDRESS = 0x02
ILLEGAL_VALUE = 0x03
DEVICE_FAILURE = 0x04
ACKNOWLEDGE = 0x05
DEVICE_BUSY = 0x06
NEGATIVE_ACKNOWLEDGE = 0x07
MEMORY_PARITY_ERROR = 0x08
GATEWAY_PATH_UNAVIABLE = 0x0A
GATEWAY_NO_RESPONSE = 0x0B

def __init__(
self,
function_code: int,
exception_code: int = 0,
device_id: int = 1,
transaction: int = 0) -> None:
"""Initialize the modbus exception response."""
super().__init__(transaction_id=transaction, dev_id=device_id)
self.function_code = function_code | 0x80
self.exception_code = exception_code

def __str__(self) -> str:
"""Build a representation of an exception response."""
return (
f"{self.__class__.__name__}("
f"dev_id={self.dev_id}, "
f"function_code={self.function_code}, "
f"exception_code={self.exception_code})"
)

def encode(self) -> bytes:
"""Encode a modbus exception response."""
return struct.pack(">B", self.exception_code)

def decode(self, data: bytes) -> None:
"""Decode a modbus exception response."""
self.exception_code = int(data[0])
3 changes: 2 additions & 1 deletion pymodbus/pdu/file_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@

from pymodbus.datastore import ModbusDeviceContext
from pymodbus.exceptions import ModbusException
from pymodbus.pdu.pdu import ModbusPDU

from .pdu import ModbusPDU


@dataclass
Expand Down
6 changes: 4 additions & 2 deletions pymodbus/pdu/mei_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@

from pymodbus.constants import DeviceInformation, MoreData
from pymodbus.datastore import ModbusDeviceContext
from pymodbus.pdu.device import DeviceInformationFactory, ModbusControlBlock
from pymodbus.pdu.pdu import ExceptionResponse, ModbusPDU

from .device import DeviceInformationFactory, ModbusControlBlock
from .exceptionresponse import ExceptionResponse
from .pdu import ModbusPDU


_MCB = ModbusControlBlock()
Expand Down
5 changes: 3 additions & 2 deletions pymodbus/pdu/other_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@

from pymodbus.constants import ModbusStatus
from pymodbus.datastore import ModbusDeviceContext
from pymodbus.pdu.device import DeviceInformationFactory, ModbusControlBlock
from pymodbus.pdu.pdu import ModbusPDU

from .device import DeviceInformationFactory, ModbusControlBlock
from .pdu import ModbusPDU


_MCB = ModbusControlBlock()
Expand Down
4 changes: 3 additions & 1 deletion pymodbus/pdu/pdu.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ def decode(self, data: bytes) -> None:
async def update_datastore(self, context: ModbusDeviceContext) -> ModbusPDU:
"""Run request against a datastore."""
_ = context
return ExceptionResponse(0, 0)
raise NotImplementedException(
f"update datastore called wrongly {self.__class__.__name__}"
)

@classmethod
def calculateRtuFrameSize(cls, data: bytes) -> int:
Expand Down
4 changes: 3 additions & 1 deletion pymodbus/pdu/register_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

from pymodbus.datastore import ModbusDeviceContext
from pymodbus.exceptions import ModbusIOException
from pymodbus.pdu.pdu import ExceptionResponse, ModbusPDU

from .exceptionresponse import ExceptionResponse
from .pdu import ModbusPDU


class ReadHoldingRegistersRequest(ModbusPDU):
Expand Down
3 changes: 2 additions & 1 deletion test/pdu/test_pdu.py
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,8 @@ async def test_pdu_default_datastore(self, mock_context):
"""Test that all PDU types can be created."""
pdu = ModbusPDU()
context = mock_context()
assert await pdu.update_datastore(context)
with pytest.raises(NotImplementedException):
assert await pdu.update_datastore(context)

@pytest.mark.parametrize(
("bytestream", "bitlist"),
Expand Down