4

I try to write a ModbusTCP server software connected wıth a database. I used pyModbus library for that task. That library has an Updating Server Example. By using that code, I wrote my code as :

'''
Pymodbus Server With Updating Thread
--------------------------------------------------------------------------
This is an example of having a background thread updating the
context while the server is operating. This can also be done with
a python thread::
    from threading import Thread
    thread = Thread(target=updating_writer, args=(context,))
    thread.start()
'''
#---------------------------------------------------------------------------# 
# import the modbus libraries we need
#---------------------------------------------------------------------------# 
from pymodbus.server.async import StartTcpServer
from pymodbus.device import ModbusDeviceIdentification
from pymodbus.datastore import ModbusSequentialDataBlock
from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer

#---------------------------------------------------------------------------# 
# import the twisted libraries we need
#---------------------------------------------------------------------------# 
from twisted.internet.task import LoopingCall

#---------------------------------------------------------------------------# 
# configure the service logging
#---------------------------------------------------------------------------# 
import logging
logging.basicConfig()
log = logging.getLogger()
log.setLevel(logging.DEBUG)

#---------------------------------------------------------------------------# 
# for database reading
#---------------------------------------------------------------------------# 

import sqlite3
import sys

sqlite_file = 'ModbusTable.db'

thermostats = 25
registers_per_thermostat = 3

global total_registers
total_registers = thermostats * registers_per_thermostat

#---------------------------------------------------------------------------# 
# define your callback process
#---------------------------------------------------------------------------# 
def updating_writer(a):
    ''' A worker process that runs every so often and
    updates live values of the context. It should be noted
    that there is a race condition for the update.
    :param arguments: The input arguments to the call
    '''
    log.debug("updating the context")
    context  = a[0]
    functioncode = 3 
    slave_id = 0x01 # slave address
    address  = 0x10 # start register : 400017

    values = []

    # Connecting to the database file
    conn = sqlite3.connect(sqlite_file)
    c1 = conn.cursor()

    c1.execute("""SELECT ID, SetPoint, ActualTemp FROM ModbusData""")

    registers = c1.fetchall()

    c1.close()

    for register in registers:
        for value in register:
            values.append(value)

    log.debug("values from database: " + str(values))

    context[slave_id].setValues(functioncode, address, values)

    values = context[slave_id].getValues(functioncode, address, count=total_registers)

    log.debug("values to be written to database: " + str(values))

    c2 = conn.cursor()

    for index in range(len(values)):
        if (index+2)<len(values):
            column1 = values[index]
            column2 = values[index+1]
            column3 = values[index+2]
            c2.execute("""UPDATE ModbusData set SetPoint = ?, ActualTemp = ? where ID=?""",[column2, column3, column1])

    # Committing changes and closing the connection to the database file
    c2.close()
    conn.close()



#---------------------------------------------------------------------------# 
# initialize your data store
#---------------------------------------------------------------------------# 
store = ModbusSlaveContext(
    di = ModbusSequentialDataBlock(0, [17]*total_registers),
    co = ModbusSequentialDataBlock(0, [17]*total_registers),
    hr = ModbusSequentialDataBlock(0, [17]*total_registers),
    ir = ModbusSequentialDataBlock(0, [17]*total_registers))
context = ModbusServerContext(slaves=store, single=True)

#---------------------------------------------------------------------------# 
# initialize the server information
#---------------------------------------------------------------------------# 
identity = ModbusDeviceIdentification()
identity.VendorName  = 'pymodbus'
identity.ProductCode = 'PM'
identity.VendorUrl   = 'http://github.com/bashwork/pymodbus/'
identity.ProductName = 'pymodbus Server'
identity.ModelName   = 'pymodbus Server'
identity.MajorMinorRevision = '1.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
StartTcpServer(context, identity=identity, address=("", 5007))

Basically, what i try to achieve is that server context is synced with database. I try to read values from database to context and then last updated context values to database. I am successful at getting data from database to context. Because when I request values with a modbus client located on another lan computer , I successfuly get requested data there. However, I cant write to database through TCP server. With the same modbus client on another lan computer, I send request to write to some registers in server context and then write it to database. At this point I fail. I cant write the latest updated situation of server context to database. I thought, I could possibly benefit from "Database Datastore Example" located in pymodbus documentation but I could not figure out how to do it. So I need your ideas about this task.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Şansal Birbaş
  • 443
  • 1
  • 6
  • 14

1 Answers1

2

You are not calling "commit()" for cursor C2. You are simply closing the connection. As a result of this your changes won't be written to the database.The sqlite documentation clearly mentions this. See here. Try doing a c2.commit() before closing the connection and see if the data is getting written or not.

If this does not work, please share the error you are getting. It will be helpful in understanding the problem.

Hope that helps!

Community
  • 1
  • 1
iamjoebloggs
  • 46
  • 1
  • 8