diff --git a/umodbus/functions.py b/umodbus/functions.py index fff53ac..1719163 100644 --- a/umodbus/functions.py +++ b/umodbus/functions.py @@ -95,6 +95,17 @@ GET_COM_EVENT_LOG = 12 REPORT_SERVER_ID = 17 +def fit_kwargs(func, **kwargs): + """ Runs a function removing not wanted kwargs + :param func: function + :param kwargs: key,value arguments + + :return: what original function is supposed to return + """ + if func == None: + raise TypeError + fitted_kwargs = {k:v for k,v in kwargs.items() if k in func.__code__.co_varnames} + return func(**fitted_kwargs) def pdu_to_function_code_or_raise_error(resp_pdu): """ Parse response PDU and return of :class:`ModbusFunction` or @@ -362,9 +373,15 @@ def execute(self, slave_id, route_map): for address in range(self.starting_address, self.starting_address + self.quantity): endpoint = route_map.match(slave_id, self.function_code, - address) - values.append(endpoint(slave_id=slave_id, address=address, - function_code=self.function_code)) + address, self.starting_address, + self.quantity) + all_kwargs= {"slave_id":slave_id, "address":address, + "function_code": self.function_code, + "starting_address":self.starting_address, + "quantity":self.quantity} + + values.append(fit_kwargs(endpoint, **all_kwargs)) + return values @@ -575,9 +592,15 @@ def execute(self, slave_id, route_map): for address in range(self.starting_address, self.starting_address + self.quantity): endpoint = route_map.match(slave_id, self.function_code, - address) - values.append(endpoint(slave_id=slave_id, address=address, - function_code=self.function_code)) + address, self.starting_address, + self.quantity) + all_kwargs = {"slave_id":slave_id, "address":address, + "function_code": self.function_code, + "starting_address":self.starting_address, + "quantity":self.quantity} + + values.append(fit_kwargs(endpoint, **all_kwargs)) + return values @@ -755,9 +778,15 @@ def execute(self, slave_id, route_map): for address in range(self.starting_address, self.starting_address + self.quantity): endpoint = route_map.match(slave_id, self.function_code, - address) - values.append(endpoint(slave_id=slave_id, address=address, - function_code=self.function_code)) + address, self.starting_address, + self.quantity) + all_kwargs= {"slave_id":slave_id, "address":address, + "function_code": self.function_code, + "starting_address":self.starting_address, + "quantity":self.quantity} + + values.append(fit_kwargs(endpoint, **all_kwargs)) + return values @@ -933,9 +962,14 @@ def execute(self, slave_id, route_map): for address in range(self.starting_address, self.starting_address + self.quantity): endpoint = route_map.match(slave_id, self.function_code, - address) - values.append(endpoint(slave_id=slave_id, address=address, - function_code=self.function_code)) + address, self.starting_address, + self.quantity) + all_kwargs= {"slave_id":slave_id, "address":address, + "function_code": self.function_code, + "starting_address":self.starting_address, + "quantity":self.quantity} + + values.append(fit_kwargs(endpoint, **all_kwargs)) return values @@ -1093,10 +1127,20 @@ def execute(self, slave_id, route_map): :param slave_id: Slave id. :param eindpoint: Instance of modbus.route.Map. """ - endpoint = route_map.match(slave_id, self.function_code, self.address) + starting_address = self.address + quantity = 1 + endpoint = route_map.match(slave_id, self.function_code, self.address, + starting_address, quantity) try: - endpoint(slave_id=slave_id, address=self.address, value=self.value, - function_code=self.function_code) + all_kwargs= {"slave_id":slave_id, "address":self.address, + "value":self.value, + "function_code": self.function_code, + "starting_address":starting_address, + "quantity":quantity} + + fit_kwargs(endpoint, **all_kwargs) + + # route_map.match() returns None if no match is found. Calling None # results in TypeError. except TypeError: @@ -1237,10 +1281,20 @@ def execute(self, slave_id, route_map): :param slave_id: Slave id. :param eindpoint: Instance of modbus.route.Map. """ - endpoint = route_map.match(slave_id, self.function_code, self.address) + starting_address = self.address + quantity = 1 + endpoint = route_map.match(slave_id, self.function_code, self.address, + starting_address, quantity=1) try: - endpoint(slave_id=slave_id, address=self.address, value=self.value, - function_code=self.function_code) + all_kwargs= {"slave_id":slave_id, "address":self.address, + "value":self.value, + "function_code": self.function_code, + "starting_address":starting_address, + "quantity":quantity} + + fit_kwargs(endpoint, **all_kwargs) + + # route_map.match() returns None if no match is found. Calling None # results in TypeError. except TypeError: @@ -1453,11 +1507,18 @@ def execute(self, slave_id, route_map): """ for index, value in enumerate(self.values): address = self.starting_address + index - endpoint = route_map.match(slave_id, self.function_code, address) + endpoint = route_map.match(slave_id, self.function_code, address, + self.starting_address, self.quantity) try: - endpoint(slave_id=slave_id, address=address, value=value, - function_code=self.function_code) + all_kwargs= {"slave_id":slave_id, "address":address, + "value":value, + "function_code": self.function_code, + "starting_address":self.starting_address, + "quantity":self.quantity} + + fit_kwargs(endpoint, **all_kwargs) + # route_map.match() returns None if no match is found. Calling None # results in TypeError. except TypeError: @@ -1605,11 +1666,19 @@ def execute(self, slave_id, route_map): """ for index, value in enumerate(self.values): address = self.starting_address + index - endpoint = route_map.match(slave_id, self.function_code, address) + quantity = len(self.values) + endpoint = route_map.match(slave_id, self.function_code, address, + self.starting_address, quantity) try: - endpoint(slave_id=slave_id, address=address, value=value, - function_code=self.function_code) + all_kwargs = {"slave_id":slave_id, "address":address, + "value":value, + "function_code": self.function_code, + "starting_address":self.starting_address, + "quantity":quantity} + + fit_kwargs(endpoint, **all_kwargs) + # route_map.match() returns None if no match is found. Calling None # results in TypeError. except TypeError: diff --git a/umodbus/route.py b/umodbus/route.py index b95e6f4..8c1483a 100644 --- a/umodbus/route.py +++ b/umodbus/route.py @@ -2,27 +2,31 @@ class Map: def __init__(self): self._rules = [] - def add_rule(self, endpoint, slave_ids, function_codes, addresses): + def add_rule(self, endpoint, slave_ids, function_codes, addresses, starting_address=None, quantities=None): self._rules.append(DataRule(endpoint, slave_ids, function_codes, - addresses)) + addresses, starting_address, quantities)) - def match(self, slave_id, function_code, address): + def match(self, slave_id, function_code, address, starting_address, quantity): for rule in self._rules: - if rule.match(slave_id, function_code, address): + if rule.match(slave_id, function_code, address, starting_address, quantity): return rule.endpoint class DataRule: - def __init__(self, endpoint, slave_ids, function_codes, addresses): + def __init__(self, endpoint, slave_ids, function_codes, addresses, starting_address, quantities): self.endpoint = endpoint self.slave_ids = slave_ids self.function_codes = function_codes self.addresses = addresses + self.starting_address = starting_address + self.quantities = quantities - def match(self, slave_id, function_code, address): - if slave_id in self.slave_ids and\ + def match(self, slave_id, function_code, address, starting_address, quantity): + if slave_id in self.slave_ids and \ function_code in self.function_codes and \ + (True if self.starting_address is None else starting_address == self.starting_address) and \ + (True if self.quantities is None else quantity in self.quantities) and \ address in self.addresses: - return True + return True return False diff --git a/umodbus/server/__init__.py b/umodbus/server/__init__.py index 842e455..307ef46 100644 --- a/umodbus/server/__init__.py +++ b/umodbus/server/__init__.py @@ -11,7 +11,7 @@ pack_exception_pdu, recv_exactly) -def route(self, slave_ids=None, function_codes=None, addresses=None): +def route(self, slave_ids=None, function_codes=None, addresses=None, starting_address=None, quantity=None): """ A decorator that is used to register an endpoint for a given rule:: @@ -24,7 +24,7 @@ def read_single_bit_values(slave_id, address): :param addresses: A list or set with addresses. """ def inner(f): - self.route_map.add_rule(f, slave_ids, function_codes, addresses) + self.route_map.add_rule(f, slave_ids, function_codes, addresses, starting_address, quantity) return f return inner