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
6 changes: 6 additions & 0 deletions pymodbus/datastore/simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,13 +662,17 @@ def action_increment(cls, registers, inx, cell, minval=None, maxval=None):
value = reg.value + 1
if maxval and value > maxval:
value = minval
if minval and value < minval:
value = minval
reg.value = value
elif cell.type == CellType.FLOAT32:
tmp_reg = [reg.value, reg2.value]
value = cls.build_value_from_registers(tmp_reg, False)
value += 1.0
if maxval and value > maxval:
value = minval
if minval and value < minval:
value = minval
new_regs = cls.build_registers_from_value(value, False)
reg.value = new_regs[0]
reg2.value = new_regs[1]
Expand All @@ -678,6 +682,8 @@ def action_increment(cls, registers, inx, cell, minval=None, maxval=None):
value += 1
if maxval and value > maxval:
value = minval
if minval and value < minval:
value = minval
new_regs = cls.build_registers_from_value(value, True)
reg.value = new_regs[0]
reg2.value = new_regs[1]
Expand Down
97 changes: 91 additions & 6 deletions test/test_simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class TestSimulator:
"addr": [19, 20],
"value": 14661,
"action": "increment",
"args": {"min": 1, "max": 100},
"args": {"minval": 1, "maxval": 100},
},
],
"uint32": [
Expand All @@ -79,7 +79,7 @@ class TestSimulator:
"addr": [31, 32],
"value": 50,
"action": "random",
"kwargs": {"min": 10, "max": 80},
"kwargs": {"minval": 10, "maxval": 80},
},
],
"float32": [
Expand Down Expand Up @@ -126,7 +126,9 @@ class TestSimulator:
Cell(type=CellType.NEXT, value=17320),
Cell(type=CellType.UINT32, value=5, action=1),
Cell(type=CellType.NEXT, value=17320), # 30
Cell(type=CellType.UINT32, action=2, action_kwargs={"min": 10, "max": 80}),
Cell(
type=CellType.UINT32, action=2, action_kwargs={"minval": 10, "maxval": 80}
),
Cell(type=CellType.NEXT, value=50),
Cell(type=CellType.FLOAT32, access=True, value=72),
Cell(type=CellType.NEXT, access=True, value=17221),
Expand Down Expand Up @@ -386,7 +388,7 @@ def test_simulator_get_text(self):
"31-32",
Cell(
type=Label.type_uint32,
action="random({'min': 10, 'max': 80})",
action="random({'minval': 10, 'maxval': 80})",
value="50",
),
),
Expand Down Expand Up @@ -435,7 +437,7 @@ def test_simulator_actions(self, func, addr, action):
assert values[0] or values[1]

def test_simulator_action_timestamp(self):
"""Test action random"""
"""Test action timestamp"""
exc_setup = copy.deepcopy(self.default_config)
exc_simulator = ModbusSimulatorContext(exc_setup, None)
addr = 12
Expand All @@ -445,7 +447,7 @@ def test_simulator_action_timestamp(self):
exc_simulator.getValues(FX_READ_REG, addr, 1)

def test_simulator_action_reset(self):
"""Test action random"""
"""Test action reset"""
exc_setup = copy.deepcopy(self.default_config)
exc_simulator = ModbusSimulatorContext(exc_setup, None)
addr = 12
Expand All @@ -454,3 +456,86 @@ def test_simulator_action_reset(self):
]
with pytest.raises(RuntimeError):
exc_simulator.getValues(FX_READ_REG, addr, 1)

@pytest.mark.parametrize(
("celltype", "minval", "maxval", "value", "expected"),
[
(CellType.BITS, 50, 75, 73, (74, 75, 50)),
(CellType.BITS, 50, 75, 45, (50, 51, 52)),
(CellType.UINT16, 50, 15075, 15073, (15074, 15075, 50)),
(CellType.UINT16, 50, 75, 45, (50, 51, 52)),
(CellType.UINT32, 50, 63075, 63073, (63074, 63075, 50)),
(CellType.UINT32, 50, 75, 45, (50, 51, 52)),
(CellType.FLOAT32, 27.0, 16100.5, 16098.0, (16099.0, 16100.0, 27.0)),
(CellType.FLOAT32, 27.0, 75.5, 24.0, (27.0, 28.0, 29.0)),
],
)
def test_simulator_action_increment(
self, celltype, minval, maxval, value, expected
):
"""Test action increment"""
exc_setup = copy.deepcopy(self.default_config)
exc_simulator = ModbusSimulatorContext(exc_setup, None)
action = exc_simulator.action_name_to_id[Label.increment]
kwargs = {
"minval": minval,
"maxval": maxval,
}
exc_simulator.registers[30].type = celltype
exc_simulator.registers[30].action = action
exc_simulator.registers[30].action_kwargs = kwargs
exc_simulator.registers[31].type = CellType.NEXT

is_int = celltype != CellType.FLOAT32
reg_count = 1 if celltype in (CellType.BITS, CellType.UINT16) else 2
regs = (
[value, 0]
if reg_count == 1
else ModbusSimulatorContext.build_registers_from_value(value, is_int)
)
exc_simulator.registers[30].value = regs[0]
exc_simulator.registers[31].value = regs[1]
for expect_value in expected:
regs = exc_simulator.getValues(FX_READ_REG, 30, reg_count)
if reg_count == 1:
assert expect_value == regs[0], f"type({celltype})"
else:
new_value = ModbusSimulatorContext.build_value_from_registers(
regs, is_int
)
assert expect_value == new_value, f"type({celltype})"

@pytest.mark.parametrize(
("celltype", "minval", "maxval"),
[
(CellType.BITS, 50, 75),
(CellType.UINT16, 50, 15075),
(CellType.UINT32, 50, 63075),
(CellType.FLOAT32, 27.0, 16100.5),
(CellType.FLOAT32, 65.0, 78.0),
],
)
def test_simulator_action_random(self, celltype, minval, maxval):
"""Test action random"""
exc_setup = copy.deepcopy(self.default_config)
exc_simulator = ModbusSimulatorContext(exc_setup, None)
action = exc_simulator.action_name_to_id[Label.random]
kwargs = {
"minval": minval,
"maxval": maxval,
}
exc_simulator.registers[30].type = celltype
exc_simulator.registers[30].action = action
exc_simulator.registers[30].action_kwargs = kwargs
exc_simulator.registers[31].type = CellType.NEXT
is_int = celltype != CellType.FLOAT32
reg_count = 1 if celltype in (CellType.BITS, CellType.UINT16) else 2
for _i in range(100):
regs = exc_simulator.getValues(FX_READ_REG, 30, reg_count)
if reg_count == 1:
new_value = regs[0]
else:
new_value = ModbusSimulatorContext.build_value_from_registers(
regs, is_int
)
assert minval <= new_value <= maxval