ich schreibe gerade ne Zeitschaltuhr mit html UI.
Dafür nutze ich den apscheduler, eine mysql Datenbank und websockets um Verbindung zum html UI herzustellen.
Aktuell bin ich gerade dabei das nach dem Neuanlegen eines Schaltplans das html UI per Websockets einen entsprechenden Befehl an das python Skript sendet.
So das selbiges den neuen Datensatz dann aus der mysql-Datenbank laden in im apscheduler speichern kann.
Das senden des entsprechenden Kommandos funktioniert auch, dann tauchen aber 2 große Probleme auf (und ich kann den verfluchten Fehler nicht finden):
1. Laut logging auf der Console wird der Befehl "load_one" 2x ausgeführt und ich verstehe einfach nicht warum. Ich suche und suche und finde nichts.
Über websockets kommt nur ein Befehl an, dann dürfte das Ganze auch nur 1 x ausgeführt werden.
2. Er bringt jedesmals diesen logging error.
Ich suche dann nach dem Fehler aber finde nichts. Noch besser, das Programm arbeitet trotz Fehler richtig und führt den neu angelegten Job trotzdem korrekt aus.
Ich verbringe jetzt schon ein paar Stunden mit der Suche nach dem Fehler, und so langsam verliere ich den Verstand.
Hauptprogramm
Code: Alles auswählen
import asyncio
from asyncio.queues import Queue
import logging
import json
import pymysql
import websockets
from lib_timerswitch import TimerSwitch
machine_ip = "192.168.127.30"
machine_port = 5555
consumers_gui = []
def send_to_usb(tmpname, tmpid, switch_to, loop):
logger.info('Timerswitch ... USB ID = %s switch to = %s' % (tmpname, switch_to))
if (switch_to is False) and (loop is False):
timer.delete_db(tmpid)
def send_to_radio(tmpname, tmpid, switch_to, loop):
logger.info('Timerswitch ... Funk ID = %s switch to = %s loop = %s' % (tmpname, switch_to, loop))
if switch_to == "False" and loop == "False":
timer.delete_db(tmpid)
def send_to_relais_tf(tmpname, tmpid, switch_to, loop):
logger.info('Timerswitch ... TF Relais ID = %s switch to = %s loop = %s' % (tmpname, switch_to, loop))
if switch_to == "False" and loop == "False":
timer.delete_db(tmpid)
@asyncio.coroutine
def sending_loop_gui(websocket):
# create sending-queue
loop = asyncio.get_event_loop()
sending_queue_gui = Queue()
logger.info('websockets .... GUI Queue startet')
def changed(tmp):
loop.call_soon_threadsafe(sending_queue_gui.put_nowait, tmp)
try:
consumers_gui.append(changed)
logger.info('websockets .... ein GUI-Client wurde in die Queue aufgenommen')
while True:
tmp_data = yield from sending_queue_gui.get()
yield from websocket.send(tmp_data)
logger.debug('websockets .... Sende json Daten -> GUI : %s' % tmp_data)
finally:
consumers_gui.remove(changed)
logger.info('websockets .... ein GUI-Client wurde aus der Queue entfernt')
@asyncio.coroutine
def socket_handler_gui(websocket, path):
# set up sending-queue
task = asyncio.async(sending_loop_gui(websocket))
while True:
# get message from client
message_rec = yield from websocket.recv()
# leave if client is disconnect
if message_rec is None:
break
# switch to different tasks
logger.debug('websockets .... Empfange json Daten von GUI-Client : %s' % message_rec)
tmp = gui_message_handler(message_rec)
# if tmp is not False:
# yield from websocket.send(tmp)
# close sending-queue if client discconect
task.cancel()
def gui_message_handler(_tmp):
# decode JSON String
_tmp_json = json.loads(_tmp)
# extract variables from json
json_usage = _tmp_json[0]
json_device_id = _tmp_json[1]
json_device_type = _tmp_json[2]
json_data_name = _tmp_json[3]
json_data_value = _tmp_json[4]
logger.debug(
'websockets .... GUI -> Nachricht %s von %s -> %s : %s = %s' % (
json_usage, json_device_id, json_device_type, json_data_name, json_data_value))
if json_usage == "timer_new":
timer.load_one(json_data_value)
logger.debug('AAAAA')
return False
elif json_usage == "timer_update":
timer.reload(json_data_value)
return False
elif json_usage == "timer_delete":
timer.delete_job(json_data_value)
return False
else:
return False
def set_logging():
console_handler = logging.StreamHandler()
formatter = logging.Formatter('%(asctime)s : %(message)s', '%Y-%m-%d %H:%M:%S')
console_handler.setFormatter(formatter)
logger.addHandler(console_handler)
if __name__ == '__main__':
#
# set up Logging Deamon
#
logger = logging.getLogger('Timerswitch')
logger.setLevel(logging.DEBUG)
set_logging()
logger.info('Timerswitch ... startet')
#
# set up MySQL Connection
#
mysql_connection = pymysql.connect(host="192.168.168.99", port=1234, user="python", passwd="python",
db="smartHome",
autocommit=True)
mysql_cursor = mysql_connection.cursor()
logger.info('mySQL ......... Verbindung online')
#
# set up TimerSwitch
#
methods = {'USB-Steckdose': send_to_usb, 'Funkschalter': send_to_radio, 'TF Relais': send_to_relais_tf}
timer = TimerSwitch(logger, mysql_cursor, methods)
timer.start()
#
# set up WebSocktes
#
gui_server = websockets.serve(socket_handler_gui, machine_ip, machine_port)
asyncio.get_event_loop().run_until_complete(gui_server)
logger.info('websockets .... System online')
asyncio.get_event_loop().run_forever()
Code: Alles auswählen
import datetime
from apscheduler.schedulers.background import BackgroundScheduler
class TimerSwitch:
_STANDARD_FUNCTION = "Funkschalter"
def __init__(self, logging_daemon, db_connection, methods):
self._scheduler = BackgroundScheduler()
self._methods = methods
self._logging_daemon = logging_daemon
self._db_connection = db_connection
self._logging_daemon.info('TimerSwitch ... initialisiert')
def _load_all(self):
self._db_connection.execute("SELECT * FROM schedulers")
results = self._db_connection.fetchall()
self._logging_daemon.info('Timerswitch ... Load All')
for result in results:
self._add(result)
def load_one(self, record_id):
self._db_connection.execute("SELECT * FROM schedulers WHERE id = %s" % record_id)
result = self._db_connection.fetchone()
while result is not None:
self._logging_daemon.info('Timerswitch ... Load One %s' % record_id)
self._add(result)
def _add(self, dataset):
# Daten einlesen
record_id = dataset[0]
record_title = dataset[1]
record_function = dataset[2]
record_date_start = dataset[3]
record_time_start = dataset[4]
record_time_stop = dataset[5]
record_date_stop_check = dataset[6]
record_date_stop = dataset[7]
record_duration = dataset[8]
record_intervall_number = dataset[9]
record_intervall_unit = dataset[10]
record_weekday_monday = dataset[11]
record_weekday_tuesday = dataset[12]
record_weekday_wednesday = dataset[13]
record_weekday_thursday = dataset[14]
record_weekday_friday = dataset[15]
record_weekday_saturday = dataset[16]
record_weekday_sunday = dataset[17]
# ID's für den python scheduler erzeugen
record_id_on = str(record_id) + 'on'
record_id_off = str(record_id) + 'off'
# falls keine Funktion angegeben wurde
if record_function is None or record_function not in self._methods:
record_function = self._STANDARD_FUNCTION
# Zeiten erzeugen
time_start_hour = int(record_time_start[0:record_time_start.find(":")])
time_start_minute = int(record_time_start[record_time_start.find(":") + 1:])
time_stop_hour = int(record_time_stop[0:record_time_stop.find(":")])
time_stop_minute = int(record_time_stop[record_time_stop.find(":") + 1:])
# Daten erzuegen
date_start_year = record_date_start.year
date_start_month = record_date_start.month
date_start_day = record_date_start.day
switch_start_on = datetime.datetime(date_start_year, date_start_month, date_start_day, time_start_hour,
time_start_minute, 0)
switch_start_off = datetime.datetime(date_start_year, date_start_month, date_start_day, time_stop_hour,
time_stop_minute, 0)
if (record_duration != 'einmalig') and record_date_stop_check:
date_stop_year = record_date_stop.year
date_stop_month = record_date_stop.month
date_stop_day = record_date_stop.day
switch_stop_on = datetime.datetime(date_stop_year, date_stop_month, date_stop_day, time_start_hour,
time_start_minute, 0)
switch_stop_off = datetime.datetime(date_stop_year, date_stop_month, date_stop_day, time_stop_hour,
time_stop_hour, 0)
else:
switch_stop_on = None
switch_stop_off = None
if (time_stop_hour < time_start_hour) or (
(time_stop_hour == time_start_hour) and (time_stop_minute < time_start_minute)):
switch_start_off = switch_start_off + datetime.timedelta(days=1)
if switch_stop_off is not None:
switch_stop_off = switch_stop_off + datetime.timedelta(days=1)
self._logging_daemon.info('Timerswitch ... Add New Timer: Name = %s Start = %s Stop = %s' % (
record_title, switch_start_on, switch_start_off))
interval_minutes = 0
interval_hours = 0
interval_days = 0
interval_weeks = 0
if record_intervall_unit == "Minuten":
interval_minutes = record_intervall_number
elif record_intervall_unit == "Stunden":
interval_hours = record_intervall_number
elif record_intervall_unit == "Tage":
interval_days = record_intervall_number
elif record_intervall_unit == "Wochen":
interval_weeks = record_intervall_number
week = ""
if record_weekday_monday:
week = "mon"
if record_weekday_tuesday:
week = ",".join((week, "tue"))
if record_weekday_wednesday:
week = ",".join((week, "wed"))
if record_weekday_thursday:
week = ",".join((week, "thu"))
if record_weekday_friday:
week = ",".join((week, "fri"))
if record_weekday_saturday:
week = ",".join((week, "sat"))
if record_weekday_sunday:
week = ",".join((week, "sun"))
if record_duration == 'einmalig':
self._scheduler.add_job(self._methods[record_function], 'date', run_date=switch_start_on,
args=[record_title, record_id, "True", "False"], id=record_id_on)
self._scheduler.add_job(self._methods[record_function], 'date', run_date=switch_start_off,
args=[record_title, record_id, "False", "False"], id=record_id_off)
elif record_duration == 'intervall':
self._scheduler.add_job(self._methods[record_function], 'interval', minutes=interval_minutes,
hours=interval_hours, days=interval_days, weeks=interval_weeks,
start_date=switch_start_on, end_date=switch_stop_on,
args=[record_title, record_id, "True", "True"],
id=record_id_on)
self._scheduler.add_job(self._methods[record_function], 'interval', minutes=interval_minutes,
hours=interval_hours, days=interval_days, weeks=interval_weeks,
start_date=switch_start_off, end_date=switch_stop_off,
args=[record_title, record_id, "False", "True"],
id=record_id_off)
elif record_duration == 'wochentag':
self._scheduler.add_job(self._methods[record_function], 'cron', day_of_week=week, hour=time_start_hour,
minute=time_start_minute, start_date=switch_start_on, end_date=switch_stop_on,
args=[record_title, record_id, "True", "True"], id=record_id_on)
self._scheduler.add_job(self._methods[record_function], 'cron', day_of_week=week, hour=time_stop_hour,
minute=time_stop_minute, start_date=switch_start_off, end_date=switch_stop_off,
args=[record_title, record_id, "False", "True"], id=record_id_off)
def reload(self, record_id):
self._scheduler.remove_job(record_id)
self.load_one(record_id)
self._logging_daemon.info('Timerswitch ... Reload ID = %s' % record_id)
def delete_job(self, record_id):
self._scheduler.remove_job(record_id)
self._logging_daemon.info('Timerswitch ... Delete Job ID = %s' % record_id)
def delete_db(self, record_id):
self._db_connection.execute("DELETE FROM schedulers WHERE id = %s" % record_id)
self._logging_daemon.info('Timerswitch ... Delete DB ID = %s' % record_id)
def start(self):
self._load_all()
self._scheduler.start()
Code: Alles auswählen
C:\Python34\python.exe D:/GoogleDrive/privat/Projekte/python/Ameisen/timerswitch.py
2015-08-10 00:37:40 : Timerswitch ... startet
2015-08-10 00:37:40 : mySQL ......... Verbindung online
2015-08-10 00:37:40 : TimerSwitch ... initialisiert
2015-08-10 00:37:40 : Timerswitch ... Load All
2015-08-10 00:37:40 : Timerswitch ... Add New Timer: Name = Pflanzenlicht Start = 2015-08-07 08:00:00 Stop = 2015-08-07 21:00:00
2015-08-10 00:37:40 : Timerswitch ... Add New Timer: Name = Blinker Start = 2015-08-09 21:30:00 Stop = 2015-08-09 21:31:00
2015-08-10 00:37:40 : Timerswitch ... Add New Timer: Name = qw Start = 2015-08-21 00:35:00 Stop = 2015-08-21 00:35:00
2015-08-10 00:37:40 : websockets .... System online
2015-08-10 00:37:43 : websockets .... GUI Queue startet
2015-08-10 00:37:43 : websockets .... ein GUI-Client wurde in die Queue aufgenommen
2015-08-10 00:37:44 : websockets .... Empfange json Daten von GUI-Client : ["timer_new","gui","","id",63]
2015-08-10 00:37:44 : websockets .... GUI -> Nachricht timer_new von gui -> : id = 63
2015-08-10 00:37:44 : Timerswitch ... Load One 63
2015-08-10 00:37:44 : Timerswitch ... Add New Timer: Name = qw Start = 2015-08-21 00:35:00 Stop = 2015-08-21 00:35:00
--- Logging error ---
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\websockets\server.py", line 69, in handler
yield from self.ws_handler(self, path)
File "D:/GoogleDrive/privat/Projekte/python/Ameisen/timerswitch.py", line 74, in socket_handler_gui
tmp = gui_message_handler(message_rec)
File "D:/GoogleDrive/privat/Projekte/python/Ameisen/timerswitch.py", line 97, in gui_message_handler
timer.load_one(json_data_value)
2015-08-10 00:38:23 : websockets .... GUI Queue startet
2015-08-10 00:38:23 : websockets .... ein GUI-Client wurde in die Queue aufgenommen
2015-08-10 00:38:54 : websockets .... ein GUI-Client wurde aus der Queue entfernt
2015-08-10 00:38:54 : websockets .... GUI Queue startet
2015-08-10 00:38:54 : websockets .... ein GUI-Client wurde in die Queue aufgenommen
2015-08-10 00:38:55 : websockets .... Empfange json Daten von GUI-Client : ["timer_new","gui","","id",64]
2015-08-10 00:38:55 : websockets .... GUI -> Nachricht timer_new von gui -> : id = 64
2015-08-10 00:38:55 : Timerswitch ... Load One 64
2015-08-10 00:38:55 : Timerswitch ... Add New Timer: Name = TEEEEST Start = 2015-08-10 00:40:00 Stop = 2015-08-10 00:41:00
2015-08-10 00:38:55 : Timerswitch ... Load One 64
2015-08-10 00:38:55 : Timerswitch ... Add New Timer: Name = TEEEEST Start = 2015-08-10 00:40:00 Stop = 2015-08-10 00:41:00
--- Logging error ---
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\websockets\server.py", line 69, in handler
yield from self.ws_handler(self, path)
File "D:/GoogleDrive/privat/Projekte/python/Ameisen/timerswitch.py", line 74, in socket_handler_gui
tmp = gui_message_handler(message_rec)
File "D:/GoogleDrive/privat/Projekte/python/Ameisen/timerswitch.py", line 97, in gui_message_handler
timer.load_one(json_data_value)
2015-08-10 00:40:00 : Timerswitch ... Funk ID = TEEEEST switch to = True loop = True
Process finished with exit code -1