Files
Solax/myenv/lib/python3.12/site-packages/pymodbus/client/modbusclientprotocol.py
2024-09-13 09:46:28 +02:00

82 lines
2.7 KiB
Python

"""ModbusProtocol implementation for all clients."""
from __future__ import annotations
from collections.abc import Callable
from typing import cast
from pymodbus.factory import ClientDecoder
from pymodbus.framer import FRAMER_NAME_TO_CLASS, FramerType, ModbusFramer
from pymodbus.logging import Log
from pymodbus.transaction import ModbusTransactionManager
from pymodbus.transport import CommParams, ModbusProtocol
class ModbusClientProtocol(ModbusProtocol):
"""**ModbusClientProtocol**.
:mod:`ModbusClientProtocol` is normally not referenced outside :mod:`pymodbus`.
"""
def __init__(
self,
framer: FramerType,
params: CommParams,
on_connect_callback: Callable[[bool], None] | None = None,
) -> None:
"""Initialize a client instance."""
ModbusProtocol.__init__(
self,
params,
False,
)
self.on_connect_callback = on_connect_callback
# Common variables.
self.framer = FRAMER_NAME_TO_CLASS.get(
framer, cast(type[ModbusFramer], framer)
)(ClientDecoder(), self)
self.transaction = ModbusTransactionManager()
def _handle_response(self, reply):
"""Handle the processed response and link to correct deferred."""
if reply is not None:
tid = reply.transaction_id
if handler := self.transaction.getTransaction(tid):
reply.request = handler
if not handler.fut.done():
handler.fut.set_result(reply)
else:
Log.debug("Unrequested message: {}", reply, ":str")
def callback_new_connection(self):
"""Call when listener receive new connection request."""
def callback_connected(self) -> None:
"""Call when connection is succcesfull."""
if self.on_connect_callback:
self.loop.call_soon(self.on_connect_callback, True)
self.framer.resetFrame()
def callback_disconnected(self, exc: Exception | None) -> None:
"""Call when connection is lost."""
Log.debug("callback_disconnected called: {}", exc)
if self.on_connect_callback:
self.loop.call_soon(self.on_connect_callback, False)
def callback_data(self, data: bytes, addr: tuple | None = None) -> int:
"""Handle received data.
returns number of bytes consumed
"""
self.framer.processIncomingPacket(data, self._handle_response, 0)
return len(data)
def __str__(self):
"""Build a string representation of the connection.
:returns: The string representation
"""
return (
f"{self.__class__.__name__} {self.comm_params.host}:{self.comm_params.port}"
)