We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Forwarder example sends each request twice
### Versions

* Python: 3.10.5
* OS: Windows 11 x64
* Pymodbus: 1.5.2, 2.5.3, 3.0.0.dev4
* Modbus Hardware (if used): 

### Pymodbus Specific
* Server: **tcp**/rtu/ascii - **sync**/async
* Client: **tcp**/rtu/ascii - **sync**/async

### Description

Running the [forwarder example](https://github.com/riptideio/pymodbus/blob/dev/examples/contrib/serial_forwarder.py) with tcp slave and tcp server each request to the server is sent twice to the slave when it should be sent once.

### Code and Logs

For testing purposed I created the forwarder like this (unit 248 --> 247):
```python
context = ModbusServerContext(slaves={248: RemoteSlaveContext(client, unit=247)}, single=False)
```

Now when a client asks the forwarder to read first holding register, this is what happens at the forwarder:
```python
 # code and logs here.
03:59:19,280 MainThread DEBUG    sync           :215      Connection to Modbus server established. Socket ('192.168.178.53', 52413)
04:05:06,214 MainThread DEBUG    sync           :348      Started thread to serve client at ('127.0.0.1', 52754)
04:05:06,214 Thread-1 ( DEBUG    sync           :46       Client Connected [127.0.0.1:52754]
04:05:06,214 Thread-1 ( DEBUG    sync           :199      Handling data: 0x0 0x1 0x0 0x0 0x0 0x6 0xf8 0x3 0x0 0x0 0x0 0x1
04:05:06,214 Thread-1 ( DEBUG    socket_framer  :147      Processing: 0x0 0x1 0x0 0x0 0x0 0x6 0xf8 0x3 0x0 0x0 0x0 0x1
04:05:06,214 Thread-1 ( DEBUG    factory        :137      Factory Request[ReadHoldingRegistersRequest: 3]
04:05:06,214 Thread-1 ( DEBUG    remote         :42       validate[3] 0:1
04:05:06,214 Thread-1 ( DEBUG    transaction    :139      Current transaction state - IDLE
04:05:06,214 Thread-1 ( DEBUG    transaction    :144      Running transaction 1
04:05:06,214 Thread-1 ( DEBUG    transaction    :273      SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0xf7 0x3 0x0 0x0 0x0 0x1
04:05:06,214 Thread-1 ( DEBUG    sync           :76       New Transaction state 'SENDING'
04:05:06,214 Thread-1 ( DEBUG    transaction    :287      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
04:05:06,399 Thread-1 ( DEBUG    transaction    :375      Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
04:05:06,399 Thread-1 ( DEBUG    transaction    :297      RECV: 0x0 0x1 0x0 0x0 0x0 0x5 0xf7 0x3 0x2 0x15 0xc5
04:05:06,399 Thread-1 ( DEBUG    socket_framer  :147      Processing: 0x0 0x1 0x0 0x0 0x0 0x5 0xf7 0x3 0x2 0x15 0xc5
04:05:06,399 Thread-1 ( DEBUG    factory        :266      Factory Response[ReadHoldingRegistersResponse: 3]
04:05:06,399 Thread-1 ( DEBUG    transaction    :454      Adding transaction 1
04:05:06,399 Thread-1 ( DEBUG    transaction    :465      Getting transaction 1
04:05:06,399 Thread-1 ( DEBUG    transaction    :224      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
04:05:06,399 Thread-1 ( DEBUG    remote         :55       get values[3] 0:1
04:05:06,399 Thread-1 ( DEBUG    transaction    :139      Current transaction state - TRANSACTION_COMPLETE
04:05:06,399 Thread-1 ( DEBUG    transaction    :144      Running transaction 2
04:05:06,399 Thread-1 ( DEBUG    transaction    :273      SEND: 0x0 0x2 0x0 0x0 0x0 0x6 0xf7 0x3 0x0 0x0 0x0 0x1
04:05:06,399 Thread-1 ( DEBUG    sync           :76       New Transaction state 'SENDING'
04:05:06,399 Thread-1 ( DEBUG    transaction    :287      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'
04:05:06,524 Thread-1 ( DEBUG    transaction    :375      Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'
04:05:06,524 Thread-1 ( DEBUG    transaction    :297      RECV: 0x0 0x2 0x0 0x0 0x0 0x5 0xf7 0x3 0x2 0x15 0xc5
04:05:06,524 Thread-1 ( DEBUG    socket_framer  :147      Processing: 0x0 0x2 0x0 0x0 0x0 0x5 0xf7 0x3 0x2 0x15 0xc5
04:05:06,524 Thread-1 ( DEBUG    factory        :266      Factory Response[ReadHoldingRegistersResponse: 3]
04:05:06,524 Thread-1 ( DEBUG    transaction    :454      Adding transaction 2
04:05:06,524 Thread-1 ( DEBUG    transaction    :465      Getting transaction 2
04:05:06,524 Thread-1 ( DEBUG    transaction    :224      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'
04:05:06,524 Thread-1 ( DEBUG    sync           :229      send: [ReadHoldingRegistersResponse (1)]- b'000100000005f8030215c5'
04:05:06,540 Thread-1 ( DEBUG    sync           :199      Handling data:
04:05:06,540 Thread-1 ( DEBUG    socket_framer  :147      Processing:
04:05:06,540 Thread-1 ( DEBUG    sync           :54       Client Disconnected [127.0.0.1:52754]
```
I can confirm the actual slave receives the request **twice** as well. This is true for **pymodbus 1.5.2, 2.5.3 as well as 3.0.0.dev4**.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pymodbus/datastore/remote.py`
Content:
```
1 """Remote datastore."""
2 # pylint: disable=missing-type-doc
3 import logging
4 
5 from pymodbus.exceptions import NotImplementedException
6 from pymodbus.interfaces import IModbusSlaveContext
7 
8 # ---------------------------------------------------------------------------#
9 #  Logging
10 # ---------------------------------------------------------------------------#
11 _logger = logging.getLogger(__name__)
12 
13 
14 # ---------------------------------------------------------------------------#
15 #  Context
16 # ---------------------------------------------------------------------------#
17 class RemoteSlaveContext(IModbusSlaveContext):
18     """TODO.
19 
20     This creates a modbus data model that connects to
21     a remote device (depending on the client used)
22     """
23 
24     def __init__(self, client, unit=None):
25         """Initialize the datastores.
26 
27         :param client: The client to retrieve values with
28         :param unit: Unit ID of the remote slave
29         """
30         self._client = client
31         self.unit = unit
32         self.__build_mapping()
33 
34     def reset(self):
35         """Reset all the datastores to their default values."""
36         raise NotImplementedException()
37 
38     def validate(self, fc_as_hex, address, count=1):
39         """Validate the request to make sure it is in range.
40 
41         :param fc_as_hex: The function we are working with
42         :param address: The starting address
43         :param count: The number of values to test
44         :returns: True if the request in within range, False otherwise
45         """
46         txt = f"validate[{fc_as_hex}] {address}:{count}"
47         _logger.debug(txt)
48         result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)
49         return not result.isError()
50 
51     def getValues(self, fc_as_hex, address, count=1):
52         """Get `count` values from datastore.
53 
54         :param fc_as_hex: The function we are working with
55         :param address: The starting address
56         :param count: The number of values to retrieve
57         :returns: The requested values from a:a+c
58         """
59         # TODO deal with deferreds # pylint: disable=fixme
60         txt = f"get values[{fc_as_hex}] {address}:{count}"
61         _logger.debug(txt)
62         result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)
63         return self.__extract_result(self.decode(fc_as_hex), result)
64 
65     def setValues(self, fc_as_hex, address, values):
66         """Set the datastore with the supplied values.
67 
68         :param fc_as_hex: The function we are working with
69         :param address: The starting address
70         :param values: The new values to be set
71         """
72         # TODO deal with deferreds # pylint: disable=fixme
73         txt = f"set values[{fc_as_hex}] {address}:{len(values)}"
74         _logger.debug(txt)
75         self.__set_callbacks[self.decode(fc_as_hex)](address, values)
76 
77     def __str__(self):
78         """Return a string representation of the context.
79 
80         :returns: A string representation of the context
81         """
82         return f"Remote Slave Context({self._client})"
83 
84     def __build_mapping(self):
85         """Build the function code mapper."""
86         kwargs = {}
87         if self.unit:
88             kwargs["unit"] = self.unit
89         self.__get_callbacks = {
90             "d": lambda a, c: self._client.read_discrete_inputs(  # pylint: disable=unnecessary-lambda
91                 a, c, **kwargs
92             ),
93             "c": lambda a, c: self._client.read_coils(  # pylint: disable=unnecessary-lambda
94                 a, c, **kwargs
95             ),
96             "h": lambda a, c: self._client.read_holding_registers(  # pylint: disable=unnecessary-lambda
97                 a, c, **kwargs
98             ),
99             "i": lambda a, c: self._client.read_input_registers(  # pylint: disable=unnecessary-lambda
100                 a, c, **kwargs
101             ),
102         }
103         self.__set_callbacks = {
104             "d": lambda a, v: self._client.write_coils(  # pylint: disable=unnecessary-lambda
105                 a, v, **kwargs
106             ),
107             "c": lambda a, v: self._client.write_coils(  # pylint: disable=unnecessary-lambda
108                 a, v, **kwargs
109             ),
110             "h": lambda a, v: self._client.write_registers(  # pylint: disable=unnecessary-lambda
111                 a, v, **kwargs
112             ),
113             "i": lambda a, v: self._client.write_registers(  # pylint: disable=unnecessary-lambda
114                 a, v, **kwargs
115             ),
116         }
117 
118     def __extract_result(self, fc_as_hex, result):
119         """Extract the values out of a response.
120 
121         TODO make this consistent (values?)
122         """
123         if not result.isError():
124             if fc_as_hex in {"d", "c"}:
125                 return result.bits
126             if fc_as_hex in {"h", "i"}:
127                 return result.registers
128         else:
129             return result
130         return None
131
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/pymodbus/datastore/remote.py b/pymodbus/datastore/remote.py
--- a/pymodbus/datastore/remote.py
+++ b/pymodbus/datastore/remote.py
@@ -29,7 +29,10 @@
         """
         self._client = client
         self.unit = unit
+        self.result = None
         self.__build_mapping()
+        if not self.__set_callbacks:
+            _logger.error("Init went wrong.")
 
     def reset(self):
         """Reset all the datastores to their default values."""
@@ -45,34 +48,18 @@
         """
         txt = f"validate[{fc_as_hex}] {address}:{count}"
         _logger.debug(txt)
-        result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)
-        return not result.isError()
+        self.result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)
+        return not self.result.isError()
 
     def getValues(self, fc_as_hex, address, count=1):
-        """Get `count` values from datastore.
-
-        :param fc_as_hex: The function we are working with
-        :param address: The starting address
-        :param count: The number of values to retrieve
-        :returns: The requested values from a:a+c
-        """
-        # TODO deal with deferreds # pylint: disable=fixme
-        txt = f"get values[{fc_as_hex}] {address}:{count}"
-        _logger.debug(txt)
-        result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)
-        return self.__extract_result(self.decode(fc_as_hex), result)
+        """Get values from real call in validate"""
+        return self.__extract_result(self.decode(fc_as_hex), self.result)
 
     def setValues(self, fc_as_hex, address, values):
         """Set the datastore with the supplied values.
 
-        :param fc_as_hex: The function we are working with
-        :param address: The starting address
-        :param values: The new values to be set
+        Already done in validate
         """
-        # TODO deal with deferreds # pylint: disable=fixme
-        txt = f"set values[{fc_as_hex}] {address}:{len(values)}"
-        _logger.debug(txt)
-        self.__set_callbacks[self.decode(fc_as_hex)](address, values)
 
     def __str__(self):
         """Return a string representation of the context.

{"golden_diff": "diff --git a/pymodbus/datastore/remote.py b/pymodbus/datastore/remote.py\n--- a/pymodbus/datastore/remote.py\n+++ b/pymodbus/datastore/remote.py\n@@ -29,7 +29,10 @@\n         \"\"\"\n         self._client = client\n         self.unit = unit\n+        self.result = None\n         self.__build_mapping()\n+        if not self.__set_callbacks:\n+            _logger.error(\"Init went wrong.\")\n \n     def reset(self):\n         \"\"\"Reset all the datastores to their default values.\"\"\"\n@@ -45,34 +48,18 @@\n         \"\"\"\n         txt = f\"validate[{fc_as_hex}] {address}:{count}\"\n         _logger.debug(txt)\n-        result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)\n-        return not result.isError()\n+        self.result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)\n+        return not self.result.isError()\n \n     def getValues(self, fc_as_hex, address, count=1):\n-        \"\"\"Get `count` values from datastore.\n-\n-        :param fc_as_hex: The function we are working with\n-        :param address: The starting address\n-        :param count: The number of values to retrieve\n-        :returns: The requested values from a:a+c\n-        \"\"\"\n-        # TODO deal with deferreds # pylint: disable=fixme\n-        txt = f\"get values[{fc_as_hex}] {address}:{count}\"\n-        _logger.debug(txt)\n-        result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)\n-        return self.__extract_result(self.decode(fc_as_hex), result)\n+        \"\"\"Get values from real call in validate\"\"\"\n+        return self.__extract_result(self.decode(fc_as_hex), self.result)\n \n     def setValues(self, fc_as_hex, address, values):\n         \"\"\"Set the datastore with the supplied values.\n \n-        :param fc_as_hex: The function we are working with\n-        :param address: The starting address\n-        :param values: The new values to be set\n+        Already done in validate\n         \"\"\"\n-        # TODO deal with deferreds # pylint: disable=fixme\n-        txt = f\"set values[{fc_as_hex}] {address}:{len(values)}\"\n-        _logger.debug(txt)\n-        self.__set_callbacks[self.decode(fc_as_hex)](address, values)\n \n     def __str__(self):\n         \"\"\"Return a string representation of the context.\n", "issue": "Forwarder example sends each request twice\n### Versions\r\n\r\n* Python: 3.10.5\r\n* OS: Windows 11 x64\r\n* Pymodbus: 1.5.2, 2.5.3, 3.0.0.dev4\r\n* Modbus Hardware (if used): \r\n\r\n### Pymodbus Specific\r\n* Server: **tcp**/rtu/ascii - **sync**/async\r\n* Client: **tcp**/rtu/ascii - **sync**/async\r\n\r\n### Description\r\n\r\nRunning the [forwarder example](https://github.com/riptideio/pymodbus/blob/dev/examples/contrib/serial_forwarder.py) with tcp slave and tcp server each request to the server is sent twice to the slave when it should be sent once.\r\n\r\n### Code and Logs\r\n\r\nFor testing purposed I created the forwarder like this (unit 248 --> 247):\r\n```python\r\ncontext = ModbusServerContext(slaves={248: RemoteSlaveContext(client, unit=247)}, single=False)\r\n```\r\n\r\nNow when a client asks the forwarder to read first holding register, this is what happens at the forwarder:\r\n```python\r\n # code and logs here.\r\n03:59:19,280 MainThread DEBUG    sync           :215      Connection to Modbus server established. Socket ('192.168.178.53', 52413)\r\n04:05:06,214 MainThread DEBUG    sync           :348      Started thread to serve client at ('127.0.0.1', 52754)\r\n04:05:06,214 Thread-1 ( DEBUG    sync           :46       Client Connected [127.0.0.1:52754]\r\n04:05:06,214 Thread-1 ( DEBUG    sync           :199      Handling data: 0x0 0x1 0x0 0x0 0x0 0x6 0xf8 0x3 0x0 0x0 0x0 0x1\r\n04:05:06,214 Thread-1 ( DEBUG    socket_framer  :147      Processing: 0x0 0x1 0x0 0x0 0x0 0x6 0xf8 0x3 0x0 0x0 0x0 0x1\r\n04:05:06,214 Thread-1 ( DEBUG    factory        :137      Factory Request[ReadHoldingRegistersRequest: 3]\r\n04:05:06,214 Thread-1 ( DEBUG    remote         :42       validate[3] 0:1\r\n04:05:06,214 Thread-1 ( DEBUG    transaction    :139      Current transaction state - IDLE\r\n04:05:06,214 Thread-1 ( DEBUG    transaction    :144      Running transaction 1\r\n04:05:06,214 Thread-1 ( DEBUG    transaction    :273      SEND: 0x0 0x1 0x0 0x0 0x0 0x6 0xf7 0x3 0x0 0x0 0x0 0x1\r\n04:05:06,214 Thread-1 ( DEBUG    sync           :76       New Transaction state 'SENDING'\r\n04:05:06,214 Thread-1 ( DEBUG    transaction    :287      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :375      Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :297      RECV: 0x0 0x1 0x0 0x0 0x0 0x5 0xf7 0x3 0x2 0x15 0xc5\r\n04:05:06,399 Thread-1 ( DEBUG    socket_framer  :147      Processing: 0x0 0x1 0x0 0x0 0x0 0x5 0xf7 0x3 0x2 0x15 0xc5\r\n04:05:06,399 Thread-1 ( DEBUG    factory        :266      Factory Response[ReadHoldingRegistersResponse: 3]\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :454      Adding transaction 1\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :465      Getting transaction 1\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :224      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'\r\n04:05:06,399 Thread-1 ( DEBUG    remote         :55       get values[3] 0:1\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :139      Current transaction state - TRANSACTION_COMPLETE\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :144      Running transaction 2\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :273      SEND: 0x0 0x2 0x0 0x0 0x0 0x6 0xf7 0x3 0x0 0x0 0x0 0x1\r\n04:05:06,399 Thread-1 ( DEBUG    sync           :76       New Transaction state 'SENDING'\r\n04:05:06,399 Thread-1 ( DEBUG    transaction    :287      Changing transaction state from 'SENDING' to 'WAITING FOR REPLY'\r\n04:05:06,524 Thread-1 ( DEBUG    transaction    :375      Changing transaction state from 'WAITING FOR REPLY' to 'PROCESSING REPLY'\r\n04:05:06,524 Thread-1 ( DEBUG    transaction    :297      RECV: 0x0 0x2 0x0 0x0 0x0 0x5 0xf7 0x3 0x2 0x15 0xc5\r\n04:05:06,524 Thread-1 ( DEBUG    socket_framer  :147      Processing: 0x0 0x2 0x0 0x0 0x0 0x5 0xf7 0x3 0x2 0x15 0xc5\r\n04:05:06,524 Thread-1 ( DEBUG    factory        :266      Factory Response[ReadHoldingRegistersResponse: 3]\r\n04:05:06,524 Thread-1 ( DEBUG    transaction    :454      Adding transaction 2\r\n04:05:06,524 Thread-1 ( DEBUG    transaction    :465      Getting transaction 2\r\n04:05:06,524 Thread-1 ( DEBUG    transaction    :224      Changing transaction state from 'PROCESSING REPLY' to 'TRANSACTION_COMPLETE'\r\n04:05:06,524 Thread-1 ( DEBUG    sync           :229      send: [ReadHoldingRegistersResponse (1)]- b'000100000005f8030215c5'\r\n04:05:06,540 Thread-1 ( DEBUG    sync           :199      Handling data:\r\n04:05:06,540 Thread-1 ( DEBUG    socket_framer  :147      Processing:\r\n04:05:06,540 Thread-1 ( DEBUG    sync           :54       Client Disconnected [127.0.0.1:52754]\r\n```\r\nI can confirm the actual slave receives the request **twice** as well. This is true for **pymodbus 1.5.2, 2.5.3 as well as 3.0.0.dev4**.\n", "before_files": [{"content": "\"\"\"Remote datastore.\"\"\"\n# pylint: disable=missing-type-doc\nimport logging\n\nfrom pymodbus.exceptions import NotImplementedException\nfrom pymodbus.interfaces import IModbusSlaveContext\n\n# ---------------------------------------------------------------------------#\n#  Logging\n# ---------------------------------------------------------------------------#\n_logger = logging.getLogger(__name__)\n\n\n# ---------------------------------------------------------------------------#\n#  Context\n# ---------------------------------------------------------------------------#\nclass RemoteSlaveContext(IModbusSlaveContext):\n    \"\"\"TODO.\n\n    This creates a modbus data model that connects to\n    a remote device (depending on the client used)\n    \"\"\"\n\n    def __init__(self, client, unit=None):\n        \"\"\"Initialize the datastores.\n\n        :param client: The client to retrieve values with\n        :param unit: Unit ID of the remote slave\n        \"\"\"\n        self._client = client\n        self.unit = unit\n        self.__build_mapping()\n\n    def reset(self):\n        \"\"\"Reset all the datastores to their default values.\"\"\"\n        raise NotImplementedException()\n\n    def validate(self, fc_as_hex, address, count=1):\n        \"\"\"Validate the request to make sure it is in range.\n\n        :param fc_as_hex: The function we are working with\n        :param address: The starting address\n        :param count: The number of values to test\n        :returns: True if the request in within range, False otherwise\n        \"\"\"\n        txt = f\"validate[{fc_as_hex}] {address}:{count}\"\n        _logger.debug(txt)\n        result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)\n        return not result.isError()\n\n    def getValues(self, fc_as_hex, address, count=1):\n        \"\"\"Get `count` values from datastore.\n\n        :param fc_as_hex: The function we are working with\n        :param address: The starting address\n        :param count: The number of values to retrieve\n        :returns: The requested values from a:a+c\n        \"\"\"\n        # TODO deal with deferreds # pylint: disable=fixme\n        txt = f\"get values[{fc_as_hex}] {address}:{count}\"\n        _logger.debug(txt)\n        result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)\n        return self.__extract_result(self.decode(fc_as_hex), result)\n\n    def setValues(self, fc_as_hex, address, values):\n        \"\"\"Set the datastore with the supplied values.\n\n        :param fc_as_hex: The function we are working with\n        :param address: The starting address\n        :param values: The new values to be set\n        \"\"\"\n        # TODO deal with deferreds # pylint: disable=fixme\n        txt = f\"set values[{fc_as_hex}] {address}:{len(values)}\"\n        _logger.debug(txt)\n        self.__set_callbacks[self.decode(fc_as_hex)](address, values)\n\n    def __str__(self):\n        \"\"\"Return a string representation of the context.\n\n        :returns: A string representation of the context\n        \"\"\"\n        return f\"Remote Slave Context({self._client})\"\n\n    def __build_mapping(self):\n        \"\"\"Build the function code mapper.\"\"\"\n        kwargs = {}\n        if self.unit:\n            kwargs[\"unit\"] = self.unit\n        self.__get_callbacks = {\n            \"d\": lambda a, c: self._client.read_discrete_inputs(  # pylint: disable=unnecessary-lambda\n                a, c, **kwargs\n            ),\n            \"c\": lambda a, c: self._client.read_coils(  # pylint: disable=unnecessary-lambda\n                a, c, **kwargs\n            ),\n            \"h\": lambda a, c: self._client.read_holding_registers(  # pylint: disable=unnecessary-lambda\n                a, c, **kwargs\n            ),\n            \"i\": lambda a, c: self._client.read_input_registers(  # pylint: disable=unnecessary-lambda\n                a, c, **kwargs\n            ),\n        }\n        self.__set_callbacks = {\n            \"d\": lambda a, v: self._client.write_coils(  # pylint: disable=unnecessary-lambda\n                a, v, **kwargs\n            ),\n            \"c\": lambda a, v: self._client.write_coils(  # pylint: disable=unnecessary-lambda\n                a, v, **kwargs\n            ),\n            \"h\": lambda a, v: self._client.write_registers(  # pylint: disable=unnecessary-lambda\n                a, v, **kwargs\n            ),\n            \"i\": lambda a, v: self._client.write_registers(  # pylint: disable=unnecessary-lambda\n                a, v, **kwargs\n            ),\n        }\n\n    def __extract_result(self, fc_as_hex, result):\n        \"\"\"Extract the values out of a response.\n\n        TODO make this consistent (values?)\n        \"\"\"\n        if not result.isError():\n            if fc_as_hex in {\"d\", \"c\"}:\n                return result.bits\n            if fc_as_hex in {\"h\", \"i\"}:\n                return result.registers\n        else:\n            return result\n        return None\n", "path": "pymodbus/datastore/remote.py"}], "after_files": [{"content": "\"\"\"Remote datastore.\"\"\"\n# pylint: disable=missing-type-doc\nimport logging\n\nfrom pymodbus.exceptions import NotImplementedException\nfrom pymodbus.interfaces import IModbusSlaveContext\n\n# ---------------------------------------------------------------------------#\n#  Logging\n# ---------------------------------------------------------------------------#\n_logger = logging.getLogger(__name__)\n\n\n# ---------------------------------------------------------------------------#\n#  Context\n# ---------------------------------------------------------------------------#\nclass RemoteSlaveContext(IModbusSlaveContext):\n    \"\"\"TODO.\n\n    This creates a modbus data model that connects to\n    a remote device (depending on the client used)\n    \"\"\"\n\n    def __init__(self, client, unit=None):\n        \"\"\"Initialize the datastores.\n\n        :param client: The client to retrieve values with\n        :param unit: Unit ID of the remote slave\n        \"\"\"\n        self._client = client\n        self.unit = unit\n        self.result = None\n        self.__build_mapping()\n        if not self.__set_callbacks:\n            _logger.error(\"Init went wrong.\")\n\n    def reset(self):\n        \"\"\"Reset all the datastores to their default values.\"\"\"\n        raise NotImplementedException()\n\n    def validate(self, fc_as_hex, address, count=1):\n        \"\"\"Validate the request to make sure it is in range.\n\n        :param fc_as_hex: The function we are working with\n        :param address: The starting address\n        :param count: The number of values to test\n        :returns: True if the request in within range, False otherwise\n        \"\"\"\n        txt = f\"validate[{fc_as_hex}] {address}:{count}\"\n        _logger.debug(txt)\n        self.result = self.__get_callbacks[self.decode(fc_as_hex)](address, count)\n        return not self.result.isError()\n\n    def getValues(self, fc_as_hex, address, count=1):\n        \"\"\"Get values from real call in validate\"\"\"\n        return self.__extract_result(self.decode(fc_as_hex), self.result)\n\n    def setValues(self, fc_as_hex, address, values):\n        \"\"\"Set the datastore with the supplied values.\n\n        Already done in validate\n        \"\"\"\n\n    def __str__(self):\n        \"\"\"Return a string representation of the context.\n\n        :returns: A string representation of the context\n        \"\"\"\n        return f\"Remote Slave Context({self._client})\"\n\n    def __build_mapping(self):\n        \"\"\"Build the function code mapper.\"\"\"\n        kwargs = {}\n        if self.unit:\n            kwargs[\"unit\"] = self.unit\n        self.__get_callbacks = {\n            \"d\": lambda a, c: self._client.read_discrete_inputs(  # pylint: disable=unnecessary-lambda\n                a, c, **kwargs\n            ),\n            \"c\": lambda a, c: self._client.read_coils(  # pylint: disable=unnecessary-lambda\n                a, c, **kwargs\n            ),\n            \"h\": lambda a, c: self._client.read_holding_registers(  # pylint: disable=unnecessary-lambda\n                a, c, **kwargs\n            ),\n            \"i\": lambda a, c: self._client.read_input_registers(  # pylint: disable=unnecessary-lambda\n                a, c, **kwargs\n            ),\n        }\n        self.__set_callbacks = {\n            \"d\": lambda a, v: self._client.write_coils(  # pylint: disable=unnecessary-lambda\n                a, v, **kwargs\n            ),\n            \"c\": lambda a, v: self._client.write_coils(  # pylint: disable=unnecessary-lambda\n                a, v, **kwargs\n            ),\n            \"h\": lambda a, v: self._client.write_registers(  # pylint: disable=unnecessary-lambda\n                a, v, **kwargs\n            ),\n            \"i\": lambda a, v: self._client.write_registers(  # pylint: disable=unnecessary-lambda\n                a, v, **kwargs\n            ),\n        }\n\n    def __extract_result(self, fc_as_hex, result):\n        \"\"\"Extract the values out of a response.\n\n        TODO make this consistent (values?)\n        \"\"\"\n        if not result.isError():\n            if fc_as_hex in {\"d\", \"c\"}:\n                return result.bits\n            if fc_as_hex in {\"h\", \"i\"}:\n                return result.registers\n        else:\n            return result\n        return None\n", "path": "pymodbus/datastore/remote.py"}]}