1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| import time
import pymysql.cursors
from pymodbus.constants import Endian
from pymodbus.payload import BinaryPayloadDecoder
from threading import Thread, Lock
from pyModbusTCP.client import ModbusClient
# connect database
sqlconnection = pymysql.connect(host='127.0.0.1',
user='root',
password='',
database='database',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
# read devices informations (ID, IP, Port, Register address)
with sqlconnection:
with sqlconnection.cursor() as cursor:
sql = "SELECT `dev_id`, H0.hw_address, H0.hw_port FROM `devicestatus` LEFT JOIN `hardware` H0 ON H0.hw_id = devicestatus.dev_hw_id WHERE H0.hw_enabled = 1 AND devicestatus.dev_used = 1 ORDER BY H0.hw_address, dev_name"
cursor.execute(sql,)
result = cursor.fetchall()
#print(result)
#exemple : [{'dev_id': 7, 'hw_address': '192.168.100.202', 'hw_port': 502}, {'dev_id': 8, 'hw_address': '192.168.100.202', 'hw_port': 502}, {'dev_id': 9, 'hw_address': '192.168.100.202', 'hw_port': 502}, {'dev_id': 10, 'hw_address': '192.168.100.202', 'hw_port': 502}, {'dev_id': 11, 'hw_address': '192.168.100.202', 'hw_port': 502}, {'dev_id': 12, 'hw_address': '192.168.100.202', 'hw_port': 502}]
# set global variables
regs = []
decoded_value = 0
# init a thread lock
regs_lock = Lock()
# modbus polling thread
def polling_thread():
global regs
# polling loop
while True:
# purger le dictionnaire :
regs = []
# définir le registre de départ :
REGISTER_ADDRESS = 100 #Start register address
# For each list of the dictionnary, "extract" each value of element : information useful to launch Modbus requests, one per device.
for val in result:
# purger la liste :
resultat = {}
# set modbusTCP variables :
READ_DEV_ID = val['dev_id']
SERVER_HOST = val['hw_address']
SERVER_PORT = val['hw_port']
SERVER_ID = 1
REGISTER_COUNT = 2
#print("Target :", SERVER_HOST, SERVER_PORT, REGISTER_ADDRESS)
client = ModbusClient(host=SERVER_HOST, port=int(SERVER_PORT), unit_id=int(SERVER_ID), auto_open=True, auto_close=True, timeout=2)
# keep TCP open
if not client.is_open():
client.open()
# do modbus reading on socket
reg_read = client.read_holding_registers(REGISTER_ADDRESS, REGISTER_COUNT)
# if read is ok, store result in regs (with thread lock synchronization)
if reg_read:
# decode the 2 registers into a 32 bit integer
decoder = BinaryPayloadDecoder.fromRegisters(reg_read, byteorder=Endian.Big, wordorder=Endian.Little)
decoded_value = decoder.decode_32bit_int()
# On mets à jour la liste
resultat['dev_id'] = READ_DEV_ID
resultat['meter_value'] = decoded_value
with regs_lock:
# On ajoute la liste au dictionnaire
regs.append(resultat)
#print(regs)
REGISTER_ADDRESS = REGISTER_ADDRESS + 2 # Increment registrer address for next read
# 1s before next polling
time.sleep(1)
# start polling thread
tp = Thread(target=polling_thread)
# set daemon: polling thread will exit if main thread exit
tp.daemon = True
tp.start()
# display loop (in main thread)
while True:
# print regs (with thread lock synchronization)
with regs_lock:
print("Données à envoyer en base de données : ")
#print(regs)
# For each list of the dictionnary, "extract" each value of element :
for val2 in regs:
print('dev_id', val2['dev_id'], ':', val2['meter_value'])
# connect database
sqlconnection = pymysql.connect(host='127.0.0.1',
user='root',
password='',
database='database',
charset='utf8mb4',
cursorclass=pymysql.cursors.DictCursor)
with sqlconnection:
with sqlconnection.cursor() as cursor:
sql = "INSERT INTO `meter` (`meter_devlog_id`,`meter_value`,`meter_usage`) VALUES (%s, %s, %s)"
cursor.execute(sql, (val2['dev_id'], val2['meter_value'], 0))
sqlconnection.commit()
#print(" --- Données de la boucle en tâche de fond : ")
# 1s before next print
time.sleep(3) |