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

Remove ModbusExceptions enum. #2467

Merged
merged 1 commit into from
Nov 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
6 changes: 3 additions & 3 deletions examples/client_custom_msg.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

from pymodbus import FramerType
from pymodbus.client import AsyncModbusTcpClient as ModbusClient
from pymodbus.pdu import ExceptionResponse, ModbusExceptions, ModbusPDU
from pymodbus.pdu import ExceptionResponse, ModbusPDU
from pymodbus.pdu.bit_message import ReadCoilsRequest


Expand Down Expand Up @@ -85,9 +85,9 @@ def decode(self, data):
def execute(self, context):
"""Execute."""
if not 1 <= self.count <= 0x7D0:
return ExceptionResponse(self.function_code, ModbusExceptions.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not context.validate(self.function_code, self.address, self.count):
return ExceptionResponse(self.function_code, ModbusExceptions.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
values = context.getValues(self.function_code, self.address, self.count)
return CustomModbusPDU(values)

Expand Down
3 changes: 1 addition & 2 deletions pymodbus/pdu/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@
"ExceptionResponse",
"ExceptionResponse",
"FileRecord",
"ModbusExceptions",
"ModbusPDU",
]

from pymodbus.pdu.decoders import DecodePDU
from pymodbus.pdu.file_message import FileRecord
from pymodbus.pdu.pdu import ExceptionResponse, ModbusExceptions, ModbusPDU
from pymodbus.pdu.pdu import ExceptionResponse, ModbusPDU
5 changes: 2 additions & 3 deletions pymodbus/pdu/bit_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from pymodbus.constants import ModbusStatus
from pymodbus.datastore import ModbusSlaveContext
from pymodbus.pdu.pdu import ExceptionResponse, ModbusPDU
from pymodbus.pdu.pdu import ModbusExceptions as merror
from pymodbus.utilities import pack_bitstring, unpack_bitstring


Expand Down Expand Up @@ -95,7 +94,7 @@ class WriteSingleCoilRequest(WriteSingleCoilResponse):
async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
"""Run a request against a datastore."""
if not context.validate(self.function_code, self.address, 1):
return ExceptionResponse(self.function_code, merror.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
await context.async_setValues(self.function_code, self.address, self.bits)
values = cast(list[bool], await context.async_getValues(self.function_code, self.address, 1))
return WriteSingleCoilResponse(address=self.address, bits=values, slave_id=self.slave_id, transaction_id=self.transaction_id)
Expand Down Expand Up @@ -131,7 +130,7 @@ async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
"""Run a request against a datastore."""
count = len(self.bits)
if not context.validate(self.function_code, self.address, count):
return ExceptionResponse(self.function_code, merror.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
await context.async_setValues(
self.function_code, self.address, self.bits
)
Expand Down
5 changes: 2 additions & 3 deletions pymodbus/pdu/mei_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from pymodbus.datastore import ModbusSlaveContext
from pymodbus.device import DeviceInformationFactory, ModbusControlBlock
from pymodbus.pdu.pdu import ExceptionResponse, ModbusPDU
from pymodbus.pdu.pdu import ModbusExceptions as merror


_MCB = ModbusControlBlock()
Expand Down Expand Up @@ -55,9 +54,9 @@ def decode(self, data: bytes) -> None:
async def update_datastore(self, _context: ModbusSlaveContext) -> ModbusPDU:
"""Run a read exception status request against the store."""
if not 0x00 <= self.object_id <= 0xFF:
return ExceptionResponse(self.function_code, merror.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not 0x00 <= self.read_code <= 0x04:
return ExceptionResponse(self.function_code, merror.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)

information = DeviceInformationFactory.get(_MCB, self.read_code, self.object_id)
return ReadDeviceInformationResponse(read_code=self.read_code, information=information, slave_id=self.slave_id, transaction_id=self.transaction_id)
Expand Down
13 changes: 4 additions & 9 deletions pymodbus/pdu/pdu.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import asyncio
import struct
from abc import abstractmethod
from enum import Enum
from typing import cast

from pymodbus.exceptions import NotImplementedException
Expand Down Expand Up @@ -100,8 +99,10 @@ def calculateRtuFrameSize(cls, data: bytes) -> int:
)


class ModbusExceptions(int, Enum):
"""An enumeration of the valid modbus exceptions."""
class ExceptionResponse(ModbusPDU):
"""Base class for a modbus exception PDU."""

rtu_frame_size = 5

ILLEGAL_FUNCTION = 0x01
ILLEGAL_ADDRESS = 0x02
Expand All @@ -114,12 +115,6 @@ class ModbusExceptions(int, Enum):
GATEWAY_PATH_UNAVIABLE = 0x0A
GATEWAY_NO_RESPONSE = 0x0B


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

rtu_frame_size = 5

def __init__(
self,
function_code: int,
Expand Down
25 changes: 12 additions & 13 deletions pymodbus/pdu/register_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from pymodbus.datastore import ModbusSlaveContext
from pymodbus.exceptions import ModbusIOException
from pymodbus.pdu.pdu import ExceptionResponse, ModbusPDU
from pymodbus.pdu.pdu import ModbusExceptions as merror


class ReadHoldingRegistersRequest(ModbusPDU):
Expand Down Expand Up @@ -36,7 +35,7 @@ def get_response_pdu_size(self) -> int:
async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
"""Run a read holding request against a datastore."""
if not context.validate(self.function_code, self.address, self.count):
return ExceptionResponse(self.function_code, merror.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
values = cast(list[int], await context.async_getValues(
self.function_code, self.address, self.count
))
Expand Down Expand Up @@ -137,15 +136,15 @@ def decode(self, data: bytes) -> None:
async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
"""Run a write single register request against a datastore."""
if not (1 <= self.read_count <= 0x07D):
return ExceptionResponse(self.function_code, merror.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not 1 <= self.write_count <= 0x079:
return ExceptionResponse(self.function_code, merror.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not context.validate(
self.function_code, self.write_address, self.write_count
):
return ExceptionResponse(self.function_code, merror.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
if not context.validate(self.function_code, self.read_address, self.read_count):
return ExceptionResponse(self.function_code, merror.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
await context.async_setValues(
self.function_code, self.write_address, self.write_registers
)
Expand Down Expand Up @@ -190,9 +189,9 @@ class WriteSingleRegisterRequest(WriteSingleRegisterResponse):
async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
"""Run a write single register request against a datastore."""
if not 0 <= self.registers[0] <= 0xFFFF:
return ExceptionResponse(self.function_code, merror.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not context.validate(self.function_code, self.address, 1):
return ExceptionResponse(self.function_code, merror.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)

await context.async_setValues(
self.function_code, self.address, self.registers
Expand Down Expand Up @@ -232,9 +231,9 @@ def decode(self, data: bytes) -> None:
async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
"""Run a write single register request against a datastore."""
if not 1 <= self.count <= 0x07B:
return ExceptionResponse(self.function_code, merror.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not context.validate(self.function_code, self.address, self.count):
return ExceptionResponse(self.function_code, merror.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)

await context.async_setValues(
self.function_code, self.address, self.registers
Expand Down Expand Up @@ -287,11 +286,11 @@ def decode(self, data: bytes) -> None:
async def update_datastore(self, context: ModbusSlaveContext) -> ModbusPDU:
"""Run a mask write register request against the store."""
if not 0x0000 <= self.and_mask <= 0xFFFF:
return ExceptionResponse(self.function_code, merror.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not 0x0000 <= self.or_mask <= 0xFFFF:
return ExceptionResponse(self.function_code, merror.ILLEGAL_VALUE)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_VALUE)
if not context.validate(self.function_code, self.address, 1):
return ExceptionResponse(self.function_code, merror.ILLEGAL_ADDRESS)
return ExceptionResponse(self.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
values = (await context.async_getValues(self.function_code, self.address, 1))[0]
values = (values & self.and_mask) | (self.or_mask & ~self.and_mask)
await context.async_setValues(
Expand Down
7 changes: 3 additions & 4 deletions pymodbus/server/async_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from pymodbus.framer import FRAMER_NAME_TO_CLASS, FramerBase, FramerType
from pymodbus.logging import Log
from pymodbus.pdu import DecodePDU
from pymodbus.pdu import ModbusExceptions as merror
from pymodbus.pdu.pdu import ExceptionResponse
from pymodbus.transport import CommParams, CommType, ModbusProtocol

Expand Down Expand Up @@ -127,7 +126,7 @@ async def inner_handle(self):
except ModbusException:
pdu = ExceptionResponse(
40,
exception_code=merror.ILLEGAL_FUNCTION
exception_code=ExceptionResponse.ILLEGAL_FUNCTION
)
self.server_send(pdu, 0)
pdu = None
Expand Down Expand Up @@ -198,14 +197,14 @@ async def _async_execute(self, request, *addr):
Log.error("requested slave does not exist: {}", request.slave_id)
if self.server.ignore_missing_slaves:
return # the client will simply timeout waiting for a response
response = ExceptionResponse(0x00, merror.GATEWAY_NO_RESPONSE)
response = ExceptionResponse(0x00, ExceptionResponse.GATEWAY_NO_RESPONSE)
except Exception as exc: # pylint: disable=broad-except
Log.error(
"Datastore unable to fulfill request: {}; {}",
exc,
traceback.format_exc(),
)
response = ExceptionResponse(0x00, merror.SLAVE_FAILURE)
response = ExceptionResponse(0x00, ExceptionResponse.SLAVE_FAILURE)
# no response when broadcasting
if not broadcast:
response.transaction_id = request.transaction_id
Expand Down
3 changes: 1 addition & 2 deletions test/framer/generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
FramerTLS,
)
from pymodbus.pdu import DecodePDU, ExceptionResponse
from pymodbus.pdu import ModbusExceptions as merror
from pymodbus.pdu.register_message import (
ReadHoldingRegistersRequest,
ReadHoldingRegistersResponse,
Expand Down Expand Up @@ -36,7 +35,7 @@ def set_calls():
result = server.buildFrame(response)
print(f" response --> {result}")
print(f" response --> {result.hex()}")
exception = ExceptionResponse(request.function_code, merror.ILLEGAL_ADDRESS)
exception = ExceptionResponse(request.function_code, ExceptionResponse.ILLEGAL_ADDRESS)
exception.transaction_id = tid
exception.slave_id = dev_id
result = server.buildFrame(exception)
Expand Down
4 changes: 2 additions & 2 deletions test/pdu/test_bit.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Bit Message Test Fixture."""

import pymodbus.pdu.bit_message as bit_msg
from pymodbus.pdu import ModbusExceptions
from pymodbus.pdu import ExceptionResponse


class TestModbusBitMessage:
Expand Down Expand Up @@ -97,7 +97,7 @@ async def test_write_single_coil_update_datastore(self, mock_context):
context = mock_context(False, default=True)
request = bit_msg.WriteSingleCoilRequest(address=2, bits=[True])
result = await request.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_ADDRESS
assert result.exception_code == ExceptionResponse.ILLEGAL_ADDRESS

context.valid = True
result = await request.update_datastore(context)
Expand Down
12 changes: 6 additions & 6 deletions test/pdu/test_register_read_messages.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pytest

from pymodbus.exceptions import ModbusIOException
from pymodbus.pdu import ModbusExceptions
from pymodbus.pdu import ExceptionResponse
from pymodbus.pdu.register_message import (
ReadHoldingRegistersRequest,
ReadHoldingRegistersResponse,
Expand Down Expand Up @@ -101,7 +101,7 @@ async def test_register_read_requests_count_errors(self):
]
for request in requests:
result = await request.update_datastore(None)
assert result.exception_code == ModbusExceptions.ILLEGAL_VALUE
assert result.exception_code == ExceptionResponse.ILLEGAL_VALUE

async def test_register_read_requests_validate_errors(self, mock_context):
"""This tests that the register request messages.
Expand All @@ -117,7 +117,7 @@ async def test_register_read_requests_validate_errors(self, mock_context):
]
for request in requests:
result = await request.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_ADDRESS
assert result.exception_code == ExceptionResponse.ILLEGAL_ADDRESS

async def test_register_read_requests_update_datastore(self, mock_context):
"""This tests that the register request messages.
Expand Down Expand Up @@ -150,15 +150,15 @@ async def test_read_write_multiple_registers_validate(self, mock_context):
read_address=1, read_count=10, write_address=2, write_registers=[0x00]
)
await request.update_datastore(context)
#assert response.exception_code == ModbusExceptions.ILLEGAL_ADDRESS
#assert response.exception_code == ExceptionResponse.ILLEGAL_ADDRESS

context.validate = lambda f, a, c: a == 2
await request.update_datastore(context)
#assert response.exception_code == ModbusExceptions.ILLEGAL_ADDRESS
#assert response.exception_code == ExceptionResponse.ILLEGAL_ADDRESS

request.write_byte_count = 0x100
await request.update_datastore(context)
#assert response.exception_code == ModbusExceptions.ILLEGAL_VALUE
#assert response.exception_code == ExceptionResponse.ILLEGAL_VALUE

def test_serializing_to_string(self):
"""Test serializing to string."""
Expand Down
16 changes: 8 additions & 8 deletions test/pdu/test_register_write_messages.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""Test register write messages."""
from pymodbus.payload import BinaryPayloadBuilder, Endian
from pymodbus.pdu import ModbusExceptions
from pymodbus.pdu import ExceptionResponse
from pymodbus.pdu.register_message import (
MaskWriteRegisterRequest,
MaskWriteRegisterResponse,
Expand Down Expand Up @@ -83,11 +83,11 @@ async def test_write_single_register_request(self, mock_context):
context = mock_context()
request = WriteSingleRegisterRequest(address=0x00, registers=[0xF0000])
result = await request.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_VALUE
assert result.exception_code == ExceptionResponse.ILLEGAL_VALUE

request.registers[0] = 0x00FF
result = await request.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_ADDRESS
assert result.exception_code == ExceptionResponse.ILLEGAL_ADDRESS

context.valid = True
result = await request.update_datastore(context)
Expand All @@ -98,11 +98,11 @@ async def test_write_multiple_register_request(self, mock_context):
context = mock_context()
request = WriteMultipleRegistersRequest(address=0x00, registers=[0x00] * 10)
result = await request.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_ADDRESS
assert result.exception_code == ExceptionResponse.ILLEGAL_ADDRESS

request.count = 0x800 # outside of range
result = await request.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_VALUE
assert result.exception_code == ExceptionResponse.ILLEGAL_VALUE

context.valid = True
request = WriteMultipleRegistersRequest(address=0x00, registers=[0x00] * 10)
Expand Down Expand Up @@ -151,15 +151,15 @@ async def test_mask_write_register_request_invalid_update_datastore(self, mock_c
context = mock_context(valid=False, default=0x0000)
handle = MaskWriteRegisterRequest(0x0000, -1, 0x1010)
result = await handle.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_VALUE
assert result.exception_code == ExceptionResponse.ILLEGAL_VALUE

handle = MaskWriteRegisterRequest(0x0000, 0x0101, -1)
result = await handle.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_VALUE
assert result.exception_code == ExceptionResponse.ILLEGAL_VALUE

handle = MaskWriteRegisterRequest(0x0000, 0x0101, 0x1010)
result = await handle.update_datastore(context)
assert result.exception_code == ModbusExceptions.ILLEGAL_ADDRESS
assert result.exception_code == ExceptionResponse.ILLEGAL_ADDRESS

# -----------------------------------------------------------------------#
# Mask Write Register Response
Expand Down