Skip to content

Commit

Permalink
Bump version to 2.2.0
Browse files Browse the repository at this point in the history
Fix #366 Update failures in sql context

Update Changelog

Fix major minor version in example codes
  • Loading branch information
dhoomakethu committed Jan 14, 2019
1 parent b3281fe commit 2e169b6
Show file tree
Hide file tree
Showing 13 changed files with 67 additions and 49 deletions.
12 changes: 11 additions & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
Version 2.1.1
Version 2.2.0
-----------------------------------------------------------
**NOTE: Supports python 3.7, async client is now moved to pymodbus/client/asychronous**
```
from pymodbus.client.asynchronous import ModbusTcpClient
```

* Support Python 3.7
* Fix `AttributeError` when setting `interCharTimeout` for serial clients.
* Provide an option to disable inter char timeouts with Modbus RTU.
* Fix SQLDbcontext always returning InvalidAddress error.
* Fix SQLDbcontext update failure
* Fix Binary payload example for endianess.

Version 2.1.0
-----------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion examples/common/asynchronous_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def run_async_server():
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '1.5'
identity.MajorMinorRevision = '2.2.0'

# ----------------------------------------------------------------------- #
# run the server you want
Expand Down
2 changes: 1 addition & 1 deletion examples/common/callback_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def run_callback_server():
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName = 'pymodbus Server'
identity.MajorMinorRevision = '1.0'
identity.MajorMinorRevision = '2.2.0'

# ----------------------------------------------------------------------- #
# run the server you want
Expand Down
2 changes: 1 addition & 1 deletion examples/common/custom_datablock.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def run_custom_db_server():
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName = 'pymodbus Server'
identity.MajorMinorRevision = '1.0'
identity.MajorMinorRevision = '2.2.0'

# ----------------------------------------------------------------------- #
# run the server you want
Expand Down
6 changes: 4 additions & 2 deletions examples/common/dbstore_update_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ def updating_writer(a):
rand_addr = random.randint(0, 65000)
log.debug("Writing to datastore: {}, {}".format(rand_addr, rand_value))
# import pdb; pdb.set_trace()
context[slave_id].setValues(writefunction, rand_addr, [rand_value])
context[slave_id].setValues(writefunction, rand_addr, [rand_value],
update=False)
values = context[slave_id].getValues(readfunction, rand_addr, count)
log.debug("Values from datastore: " + str(values))

Expand All @@ -85,14 +86,15 @@ def run_dbstore_update_server():
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName = 'pymodbus Server'
identity.MajorMinorRevision = '1.0'
identity.MajorMinorRevision = '2.2.0'

# ----------------------------------------------------------------------- #
# run the server you want
# ----------------------------------------------------------------------- #
time = 5 # 5 seconds delay
loop = LoopingCall(f=updating_writer, a=(context,))
loop.start(time, now=False) # initially delay by time
loop.stop()
StartTcpServer(context, identity=identity, address=("", 5020))


Expand Down
2 changes: 1 addition & 1 deletion examples/common/modbus_payload_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def run_payload_server():
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '1.5'
identity.MajorMinorRevision = '2.2.0'
# ----------------------------------------------------------------------- #
# run the server you want
# ----------------------------------------------------------------------- #
Expand Down
2 changes: 1 addition & 1 deletion examples/common/synchronous_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def run_server():
identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '1.5'
identity.MajorMinorRevision = '2.2.0'

# ----------------------------------------------------------------------- #
# run the server you want
Expand Down
2 changes: 1 addition & 1 deletion examples/common/updating_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def run_updating_server():
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName = 'pymodbus Server'
identity.MajorMinorRevision = '1.0'
identity.MajorMinorRevision = '2.2.0'

# ----------------------------------------------------------------------- #
# run the server you want
Expand Down
2 changes: 1 addition & 1 deletion examples/contrib/deviceinfo_showcase_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def run_server():
identity.VendorUrl = 'http://github.com/riptideio/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '1.5'
identity.MajorMinorRevision = '2.2.0'

# ----------------------------------------------------------------------- #
# Add an example which is long enough to force the ReadDeviceInformation
Expand Down
2 changes: 1 addition & 1 deletion examples/gui/bottle/frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def RunDebugModbusFrontend(server, port=8080):
identity.VendorUrl = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'Pymodbus Server'
identity.ModelName = 'Pymodbus Server'
identity.MajorMinorRevision = '1.0'
identity.MajorMinorRevision = '2.2.0'

# ------------------------------------------------------------
# initialize the datastore
Expand Down
72 changes: 38 additions & 34 deletions pymodbus/datastore/database/sql_datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,87 +7,91 @@
from pymodbus.exceptions import NotImplementedException
from pymodbus.interfaces import IModbusSlaveContext

#---------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# Logging
#---------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
import logging
_logger = logging.getLogger(__name__)


#---------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
# Context
#---------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
class SqlSlaveContext(IModbusSlaveContext):
'''
"""
This creates a modbus data model with each data access
stored in its own personal block
'''
"""

def __init__(self, *args, **kwargs):
''' Initializes the datastores
""" Initializes the datastores
:param kwargs: Each element is a ModbusDataBlock
'''
"""
self.table = kwargs.get('table', 'pymodbus')
self.database = kwargs.get('database', 'sqlite:///pymodbus.db')
self._db_create(self.table, self.database)

def __str__(self):
''' Returns a string representation of the context
""" Returns a string representation of the context
:returns: A string representation of the context
'''
"""
return "Modbus Slave Context"

def reset(self):
''' Resets all the datastores to their default values '''
""" Resets all the datastores to their default values """
self._metadata.drop_all()
self._db_create(self.table, self.database)

def validate(self, fx, address, count=1):
''' Validates the request to make sure it is in range
""" Validates the request to make sure it is in range
:param fx: The function we are working with
:param address: The starting address
:param count: The number of values to test
:returns: True if the request in within range, False otherwise
'''
"""
address = address + 1 # section 4.4 of specification
_logger.debug("validate[%d] %d:%d" % (fx, address, count))
return self._validate(self.decode(fx), address, count)

def getValues(self, fx, address, count=1):
''' Get `count` values from datastore
""" Get `count` values from datastore
:param fx: 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
'''
"""
address = address + 1 # section 4.4 of specification
_logger.debug("get-values[%d] %d:%d" % (fx, address, count))
return self._get(self.decode(fx), address, count)

def setValues(self, fx, address, values):
''' Sets the datastore with the supplied values
def setValues(self, fx, address, values, update=True):
""" Sets the datastore with the supplied values
:param fx: The function we are working with
:param address: The starting address
:param values: The new values to be set
'''
:param update: Update existing register in the db
"""
address = address + 1 # section 4.4 of specification
_logger.debug("set-values[%d] %d:%d" % (fx, address, len(values)))
self._set(self.decode(fx), address, values)
if update:
self._update(self.decode(fx), address, values)
else:
self._set(self.decode(fx), address, values)

#--------------------------------------------------------------------------#
# ----------------------------------------------------------------------- #
# Sqlite Helper Methods
#--------------------------------------------------------------------------#
# ----------------------------------------------------------------------- #
def _db_create(self, table, database):
''' A helper method to initialize the database and handles
""" A helper method to initialize the database and handles
:param table: The table name to create
:param database: The database uri to use
'''
"""
self._engine = sqlalchemy.create_engine(database, echo=False)
self._metadata = sqlalchemy.MetaData(self._engine)
self._table = sqlalchemy.Table(table, self._metadata,
Expand All @@ -99,12 +103,12 @@ def _db_create(self, table, database):
self._connection = self._engine.connect()

def _get(self, type, offset, count):
'''
"""
:param type: The key prefix to use
:param offset: The address offset to start at
:param count: The number of bits to read
:returns: The resulting values
'''
"""
query = self._table.select(and_(
self._table.c.type == type,
self._table.c.index >= offset,
Expand All @@ -115,13 +119,13 @@ def _get(self, type, offset, count):
return [row.value for row in result]

def _build_set(self, type, offset, values, prefix=''):
''' A helper method to generate the sql update context
""" A helper method to generate the sql update context
:param type: The key prefix to use
:param offset: The address offset to start at
:param values: The values to set
:param prefix: Prefix fields index and type, defaults to empty string
'''
"""
result = []
for index, value in enumerate(values):
result.append({
Expand All @@ -136,12 +140,12 @@ def _check(self, type, offset, values):
return False if len(result) > 0 else True

def _set(self, type, offset, values):
'''
"""
:param key: The type prefix to use
:param offset: The address offset to start at
:param values: The values to set
'''
"""
if self._check(type, offset, values):
context = self._build_set(type, offset, values)
query = self._table.insert()
Expand All @@ -151,27 +155,27 @@ def _set(self, type, offset, values):
return False

def _update(self, type, offset, values):
'''
"""
:param type: The type prefix to use
:param offset: The address offset to start at
:param values: The values to set
'''
"""
context = self._build_set(type, offset, values, prefix='x_')
query = self._table.update().values(name='value')
query = self._table.update().values(value='value')
query = query.where(and_(
self._table.c.type == bindparam('x_type'),
self._table.c.index == bindparam('x_index')))
result = self._connection.execute(query, context)
return result.rowcount == len(values)

def _validate(self, type, offset, count):
'''
"""
:param key: The key prefix to use
:param offset: The address offset to start at
:param count: The number of bits to read
:returns: The result of the validation
'''
"""
query = self._table.select(and_(
self._table.c.type == type,
self._table.c.index >= offset,
Expand Down
2 changes: 1 addition & 1 deletion pymodbus/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ def __str__(self):
return '[%s, version %s]' % (self.package, self.short())


version = Version('pymodbus', 2, 1, 1)
version = Version('pymodbus', 2, 2, 0)


version.__name__ = 'pymodbus' # fix epydoc error
Expand Down
8 changes: 5 additions & 3 deletions test/test_datastore.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,8 @@ def testSetValues(self):
self.slave._set = MagicMock()

for key, value in self.function_map.items():
self.slave.setValues(key, self.mock_addr, self.mock_values)
self.slave.setValues(key, self.mock_addr,
self.mock_values, update=False)
self.slave._set.assert_called_with(
value, self.mock_addr + 1, self.mock_values
)
Expand Down Expand Up @@ -365,8 +366,9 @@ def testUpdateFailure(self):
self.slave._update(self.mock_type, self.mock_offset, self.mock_values)
)

#---------------------------------------------------------------------------#

# --------------------------------------------------------------------------- #
# Main
#---------------------------------------------------------------------------#
# --------------------------------------------------------------------------- #
if __name__ == "__main__":
unittest.main()

0 comments on commit 2e169b6

Please sign in to comment.