Um bei meiner Hausautomation von mehreren Rechnern gleichzeitig über eine HTML-Schnittstelle auf die Schalter- und Sensor-Variablen in der mySQL-Datenbank zugreifen zu können habe ich einen xml-Server erstellt, der mittels Threading auch den Zugriff von mehreren Clients gleichzeitig erlaubt (erlauben sollte)
Solange ich nur mit einem Rechner bzw. nacheinander auf den xml-Server zugreife, funktioniert alles so wie es soll.
Wenn ich aber gleichzeitig zugreifen möchte, so bricht eine Verbindung ab. Und ein Rechner zeigt nicht mehr alle Variablen.
Fehlermeldungen:
- 2055: Lost connection to MySQL server at 'localhost:3306', system error: 9 Bad file descriptor
- bytearray index out of range
Und hier der Server-Code der dauerhaft auf meinem Server (Synology DSM 5.2) läuft:
Code: Alles auswählen
#!/usr/bin/python3
from socketserver import ThreadingMixIn
from xmlrpc.server import SimpleXMLRPCServer
import ser_module.xml_module as xml
class SimpleThreadingXMLRPCServer(ThreadingMixIn,SimpleXMLRPCServer):
pass
class XmlrpcHandler:
def _dispatch(self,method,params):
try:
return getattr(xml,method)(*params)
except Exception as e:
print (e)
return False
if __name__=="__main__":
xml.DB_Main("start")
if xml.conn:
xml.Ereignis("XML-RPC-Server und Datenbankzugriff wurden gestartet.")
server = SimpleThreadingXMLRPCServer(("127.0.0.1", 55072))
server.register_instance(XmlrpcHandler())
server.serve_forever()
else:
xml.Warnung("Der Server wurde nicht gestartet, da keine Verbindung zur Datenbank",email_only=1)
Ich denke, dass ich hier noch einen Denkfehler habe bzgl. der globalen / lokalen Variablen oder der Lock-Funktion.
Code: Alles auswählen
import mysql.connector as mysql
from threading import Lock
from ser_module._config import config #modul mit einem Dictionary mit festen Variablen
conn=False
connLock=Lock()
def DB_Main(command="start"):
"""Datenbank Öffnen/Schliesen"""
global conn
try:
if command=="start":
connLock.acquire()
conn=mysql.connect()
connLock.release()
else:
connLock.acquire()
conn.close()
conn=False
connLock.release()
except Exception as e:
connLock.acquire()
conn=False
connLock.release()
def DB_Connect():
"""Datenbank verbinden"""
global conn
try:
with open(config("db.pw"), "r") as z: #Zugangsdaten aus einer externen Datei
zugang=[line.strip() for line in z]
connLock.acquire()
conn.connect(host=zugang[0],user=zugang[1],password=zugang[2], database=zugang[3])
connLock.release()
return True
except Exception as e:
return False
def DB_Command(comm,values=0):
"""Datenbank-Befehl"""
global conn
if conn==False:
DB_Main("start")
if conn.is_connected()==False:
if DB_Connect()==False:
return False
try:
c=conn.cursor()
c.execute(comm,values)
if comm[:6]=="SELECT":
data=c.fetchall()
c.close()
return(data)
else:
conn.commit()
c.close()
return True
except Exception as e:
return False
Code: Alles auswählen
from xmlrpc.client import ServerProxy,ProtocolError
cli=ServerProxy(config("xml_server")) # in config()sind meine WEB-Variablen gespeichert hier die IP-Adresse und der Port für den xml-Server
Geschoss_ID=1
c=cli.DB_Command(
"SELECT a.ID, r.Raum, a.Name, a.Hardware, a.Zustand, h.Max_Wert, a.gesperrt, a.x_Achse, a.y_Achse, a.Lage_Text "+
"FROM DG_Home.Aktoren a, DG_Home.Geschoss g, DG_Home.Raum r, DG_Home.Hardware h "+
"WHERE a.Geschoss=g.ID AND a.Raum=r.ID AND a.Hardware=h.ID AND a.Geschoss=%s "+
"ORDER BY r.Raum, a.Name",
(Geschoss_ID,)
)
if c!=False:
for row in c:
# ... ab hier werden mit print() html-Codes aufgebaut, die mir die Schalter erstellen.
Vielen Dank!
Dirk 1972