Skip to content

Commit

Permalink
datastore: change remote_datastore to be async
Browse files Browse the repository at this point in the history
  • Loading branch information
ilkka-ollakka committed Mar 30, 2024
1 parent c6d4acc commit 9a193ad
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 58 deletions.
73 changes: 31 additions & 42 deletions pymodbus/datastore/remote.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
"""Remote datastore."""

from pymodbus.datastore import ModbusBaseSlaveContext
from pymodbus.exceptions import NotImplementedException
from pymodbus.logging import Log
Expand Down Expand Up @@ -38,25 +39,37 @@ def validate(self, _fc_as_hex, _address, _count):
"""
return True

def getValues(self, fc_as_hex, _address, _count=1):
async def async_getValues(self, fc_as_hex, address, count=1):
"""Get values from real call in validate."""
if fc_as_hex in self._write_fc:
return [0]
group_fx = self.decode(fc_as_hex)
func_fc = self.__get_callbacks[group_fx]
self.result = func_fc(_address, _count)
kwargs = {}
if self.slave:
kwargs["slave"] = self.slave
self.result = await getattr(self._client, func_fc)(address, count, **kwargs)
return self.__extract_result(self.decode(fc_as_hex), self.result)

def setValues(self, fc_as_hex, address, values):
async def async_setValues(self, fc_as_hex, address, values):
"""Set the datastore with the supplied values."""
group_fx = self.decode(fc_as_hex)
if fc_as_hex not in self._write_fc:
raise ValueError(f"setValues() called with an non-write function code {fc_as_hex}")
raise ValueError(
f"setValues() called with an non-write function code {fc_as_hex}"
)
func_fc = self.__set_callbacks[f"{group_fx}{fc_as_hex}"]
kwargs = {}
if self.slave:
kwargs["slave"] = self.slave
if fc_as_hex in {0x0F, 0x10}: # Write Multiple Coils, Write Multiple Registers
self.result = func_fc(address, values)
self.result = await getattr(self._client, func_fc)(
address, values, **kwargs
)
else:
self.result = func_fc(address, values[0])
self.result = await getattr(self._client, func_fc)(
address, values[0], **kwargs
)
if self.result.isError():
return self.result
return None
Expand All @@ -74,44 +87,20 @@ def __build_mapping(self):
if self.slave:
kwargs["slave"] = self.slave
self.__get_callbacks = {
"d": lambda a, c: self._client.read_discrete_inputs(
a, c, **kwargs
),
"c": lambda a, c: self._client.read_coils(
a, c, **kwargs
),
"h": lambda a, c: self._client.read_holding_registers(
a, c, **kwargs
),
"i": lambda a, c: self._client.read_input_registers(
a, c, **kwargs
),
"d": "read_discrete_inputs",
"c": "read_coils",
"h": "read_holding_registers",
"i": "read_input_registers",
}
self.__set_callbacks = {
"d5": lambda a, v: self._client.write_coil(
a, v, **kwargs
),
"d15": lambda a, v: self._client.write_coils(
a, v, **kwargs
),
"c5": lambda a, v: self._client.write_coil(
a, v, **kwargs
),
"c15": lambda a, v: self._client.write_coils(
a, v, **kwargs
),
"h6": lambda a, v: self._client.write_register(
a, v, **kwargs
),
"h16": lambda a, v: self._client.write_registers(
a, v, **kwargs
),
"i6": lambda a, v: self._client.write_register(
a, v, **kwargs
),
"i16": lambda a, v: self._client.write_registers(
a, v, **kwargs
),
"d5": "write_coil",
"d15": "write_coils",
"c5": "write_coil",
"c15": "write_coils",
"h6": "write_register",
"h16": "write_registers",
"i6": "write_register",
"i16": "write_registers",
}
self._write_fc = (0x05, 0x06, 0x0F, 0x10)

Expand Down
23 changes: 7 additions & 16 deletions test/test_remote_datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ def test_remote_slave_context(self):

async def test_remote_slave_set_values(self):
"""Test setting values against a remote slave context."""
client = mock.MagicMock()
client.write_coils = mock.MagicMock(return_value=WriteMultipleCoilsResponse())
client.write_registers = mock.MagicMock(
client = mock.AsyncMock()
client.write_coils = mock.AsyncMock(return_value=WriteMultipleCoilsResponse())
client.write_registers = mock.AsyncMock(
return_value=ExceptionResponse(0x10, 0x02)
)

Expand All @@ -36,39 +36,30 @@ async def test_remote_slave_set_values(self):
result = await context.async_setValues(0x10, 1, [1])
assert result.exception_code == 0x02
assert result.function_code == 0x90
result = context.setValues(0x10, 1, [1])
assert result.exception_code == 0x02
assert result.function_code == 0x90

async def test_remote_slave_get_values(self):
"""Test getting values from a remote slave context."""
client = mock.MagicMock()
client.read_coils = mock.MagicMock(return_value=ReadCoilsResponse([1] * 10))
client.read_input_registers = mock.MagicMock(
client = mock.AsyncMock()
client.read_coils = mock.AsyncMock(return_value=ReadCoilsResponse([1] * 10))
client.read_input_registers = mock.AsyncMock(
return_value=ReadInputRegistersResponse([10] * 10)
)
client.read_holding_registers = mock.MagicMock(
client.read_holding_registers = mock.AsyncMock(
return_value=ExceptionResponse(0x15)
)

context = RemoteSlaveContext(client)
context.validate(1, 0, 10)
result = await context.async_getValues(1, 0, 10)
assert result == [1] * 10
result = context.getValues(1, 0, 10)
assert result == [1] * 10

context.validate(4, 0, 10)
result = await context.async_getValues(4, 0, 10)
assert result == [10] * 10
result = context.getValues(4, 0, 10)
assert result == [10] * 10

context.validate(3, 0, 10)
result = await context.async_getValues(3, 0, 10)
assert result != [10] * 10
result = context.getValues(3, 0, 10)
assert result != [10] * 10

def test_remote_slave_validate_values(self):
"""Test validating against a remote slave context."""
Expand Down

0 comments on commit 9a193ad

Please sign in to comment.