Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP server: allow discriminating responses upon requests's starting address #74

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
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
117 changes: 93 additions & 24 deletions umodbus/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down
20 changes: 12 additions & 8 deletions umodbus/route.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions umodbus/server/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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::

Expand All @@ -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
Expand Down