我试着写一个modbustcp服务器软件连接到一个数据库。我用pymodbus库来完成这个任务。那个库有一个更新服务器的例子。通过使用该代码,我将代码编写为:
'''
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))
基本上,我试图实现的是服务器上下文与数据库同步。我尝试将值从数据库读取到上下文,然后将上次更新的上下文值读取到数据库。我成功地将数据从数据库获取到上下文。因为当我使用位于另一台局域网计算机上的modbus客户端请求值时,我成功地在那里获得了请求的数据。但是,我不能通过tcp服务器写入数据库。在另一台局域网计算机上使用同一个modbus客户机时,我将请求发送到服务器上下文中的一些寄存器,然后将其写入数据库。在这一点上我失败了。我无法将服务器上下文的最新更新情况写入数据库。我想,我可能会受益于pymodbus文档中的“数据库数据存储示例”,但我不知道如何做到这一点。所以我需要你对这项任务的想法。
最佳答案
您没有为游标c2调用“commit()”。你只是在关闭连接。因此,您的更改不会写入数据库。sqlite文档清楚地提到了这一点。见here。在关闭连接之前尝试执行c2.commit(),看看数据是否被写入。
如果这不起作用,请分享你得到的错误。这将有助于理解这个问题。
希望能有帮助!