diff --git a/Logger.py b/Logger.py
new file mode 100644
index 0000000..1b58462
--- /dev/null
+++ b/Logger.py
@@ -0,0 +1,150 @@
+import machine
+import os
+import TimeUtils
+
+class Logger():
+ def __init__(self, hk_days):
+ self.hk_days = hk_days
+ self.TimeUtils = TimeUtils.TimeUtils()
+ self.tempLogFile = True
+ self.tempSoilFile = True
+ if not "logs" in os.listdir():
+ os.mkdir("/logs")
+ if not "soil" in os.listdir():
+ os.mkdir("/soil")
+
+ def LogMessage(self, message):
+ print(message)
+ lfname = "/logs/temp.txt"
+ if not self.tempLogFile:
+ dt = machine.RTC().datetime()
+ lfname = ("/logs/%04d-%02d-%02d.txt" % (dt[0], dt[1], dt[2]))
+ dt = machine.RTC().datetime()
+ file = open(lfname, "a")
+ file.write(self.TimeUtils.DateTimeNow() + ";" + message + "\n")
+ file.close()
+
+ def LogSoil(self, message):
+ print(message)
+ lfname = "/soil/temp.txt"
+ if not self.tempSoilFile:
+ dt = machine.RTC().datetime()
+ lfname = ("/soil/%04d-%02d-%02d.txt" % (dt[0], dt[1], dt[2]))
+ dt = machine.RTC().datetime()
+ file = open(lfname, "a")
+ file.write(self.TimeUtils.DateTimeNow() + ";" + str(message) + "\n")
+ file.close()
+
+ def Housekeeping(self):
+ for file in os.listdir("/logs"):
+ if (file.endswith(".txt")) and not (file == "temp.txt"):
+ fd = file.split('.')[0].split('-')
+ if (self.TimeUtils.IsOlderThanDays(fd, self.hk_days)):
+ os.remove("/logs/" + file)
+ self.LogMessage("Housekeeping: deleted logfile " + file)
+ for file in os.listdir("/soil"):
+ if (file.endswith(".txt")) and not (file == "temp.txt"):
+ fd = file.split('.')[0].split('-')
+ if (self.TimeUtils.IsOlderThanDays(fd, self.hk_days)):
+ os.remove("/soil/" + file)
+ self.LogMessage("Housekeeping: deleted soilfile " + file)
+
+ def LastLogs(self, lines):
+ logfilename = "/logs/temp.txt"
+ if not self.tempLogFile:
+ dt = machine.RTC().datetime()
+ logfilename = ("/logs/%04d-%02d-%02d.txt" % (dt[0], dt[1], dt[2]))
+ bufsize = 4096
+ fsize = os.stat(logfilename)[6]
+ iter = 0
+ with open(logfilename, "r") as logfile:
+ line_count = 0
+ for line in logfile:
+ line_count += 1
+ if (lines > line_count):
+ lines = line_count
+ #todo if lines from todays logfile are less than the number of requested lines, read missing lines from yesterdays logfile - only if not tempLogFile!
+ if bufsize > fsize:
+ bufsize = fsize - 1
+ fetched_lines = []
+ while True:
+ iter += 1
+ try:
+ logfile.seek(fsize - bufsize * iter)
+ fetched_lines.extend(logfile.readlines())
+ except:
+ return "eof"
+ break
+ if len(fetched_lines) >= lines or logfile.tell() == 0:
+ return "
".join(fetched_lines[-lines:])
+ break
+
+ def LastSoils(self, lines):
+ logfilename = "/soil/temp.txt"
+ if not self.tempLogFile:
+ dt = machine.RTC().datetime()
+ logfilename = ("/soil/%04d-%02d-%02d.txt" % (dt[0], dt[1], dt[2]))
+ bufsize = 4096
+ fsize = os.stat(logfilename)[6]
+ iter = 0
+ with open(logfilename, "r") as logfile2:
+ line_count = 0
+ for line in logfile2:
+ line_count += 1
+ if (lines > line_count):
+ lines = line_count
+ #todo if lines from todays logfile are less than the number of requested lines, read missing lines from yesterdays logfile - only if not tempLogFile!
+ if bufsize > fsize:
+ bufsize = fsize - 1
+ fetched_lines = []
+ while True:
+ iter += 1
+ try:
+ logfile2.seek(fsize - bufsize * iter)
+ fetched_lines.extend(logfile2.readlines())
+ except:
+ return "eof"
+ break
+ if len(fetched_lines) >= lines or logfile2.tell() == 0:
+ return "
".join(fetched_lines[-lines:])
+ break
+
+ def MergeTempLogfile(self):
+ if not self.tempLogFile:
+ tempLines = 0
+ try:
+ with open("/logs/temp.txt", "r") as tempfile:
+ tlines = tempfile.readlines()
+ dt = machine.RTC().datetime()
+ with open(("/logs/%04d-%02d-%02d.txt" % (dt[0], dt[1], dt[2])), "a") as logfile:
+ for line in tlines:
+ tempLines += 1
+ logfile.write(line)
+ os.remove("/logs/temp.txt")
+ self.LogMessage("Merged " + str(tempLines) + " lines from temp-logfile into this logfile")
+ except OSError:
+ pass
+
+ def MergeTempSoilfile(self):
+ if not self.tempSoilFile:
+ tempLines = 0
+ try:
+ with open("/soil/temp.txt", "r") as tempfile:
+ tlines = tempfile.readlines()
+ dt = machine.RTC().datetime()
+ with open(("/soil/%04d-%02d-%02d.txt" % (dt[0], dt[1], dt[2])), "a") as logfile:
+ for line in tlines:
+ tempLines += 1
+ logfile.write(line)
+ os.remove("/soil/temp.txt")
+ self.LogMessage("Merged " + str(tempLines) + " lines from temp-soilfile into todays soilfile")
+ except OSError:
+ pass
+
+ def DisableTempLogfile(self):
+ self.tempLogFile = False
+ self.MergeTempLogfile()
+
+ def DisableTempSoilfile(self):
+ self.tempSoilFile = False
+ self.MergeTempSoilfile()
\ No newline at end of file
diff --git a/NTP.py b/NTP.py
new file mode 100644
index 0000000..004e167
--- /dev/null
+++ b/NTP.py
@@ -0,0 +1,38 @@
+import utime as time
+import socket
+import ustruct as struct
+import machine
+
+class NTP():
+ def __init__(self, Logger):
+ self.Logger = Logger
+
+ def SetRTCTimeFromNTP(self, host, gmt_offset, auto_summertime):
+ self.Logger.LogMessage("getting date and time from NTP " + host)
+ NTP_DELTA = 2208988800
+ NTP_QUERY = bytearray(48)
+ NTP_QUERY[0] = 0x1B
+ addr = socket.getaddrinfo(host, 123)[0][-1]
+ s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+ try:
+ s.settimeout(5)
+ res = s.sendto(NTP_QUERY, addr)
+ msg = s.recv(48)
+ except Exception as err:
+ self.Logger.LogMessage("Error: " + str(err))
+ return False
+ finally:
+ s.close()
+ ntp_time = struct.unpack("!I", msg[40:44])[0] + (3600 * gmt_offset) #gmt offset from config
+ tm = time.gmtime(ntp_time - NTP_DELTA)
+ if (auto_summertime):
+ self.Logger.LogMessage("performing auto_summertime adjustment")
+ #Time of March change for the current year
+ t1 = time.mktime((tm[0],3,(31-(int(5*tm[0]/4+4))%7),1,0,0,0,0))
+ #Time of October change for the current year
+ t2 = time.mktime((tm[0],10,(31-(int(5*tm[0]/4+1))%7),1,0,0,0,0))
+ t = time.mktime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))
+ if t >= t1 and t < t2:
+ tm = time.gmtime(ntp_time - NTP_DELTA + 3600)
+ machine.RTC().datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))
+ return True
\ No newline at end of file
diff --git a/Networking.py b/Networking.py
new file mode 100644
index 0000000..0b477b8
--- /dev/null
+++ b/Networking.py
@@ -0,0 +1,79 @@
+import network
+import ubinascii
+import Logger
+import machine
+import time
+
+wlan = network.WLAN(network.STA_IF)
+led = machine.Pin('LED', machine.Pin.OUT)
+
+class Networking():
+ def __init__(self, Logger, ssid, pw):
+ self.ssid = ssid
+ self.pw = pw
+ self.Logger = Logger
+
+ def Connect(self, disable_wifi_powersavingmode):
+ global wlan
+ wlan.active(True)
+ #wlan.config(hostname=configs['hostname'])
+ if (disable_wifi_powersavingmode):
+ wlan.config(pm = 0xa11140)
+ self.Logger.LogMessage("mac = " + self.GetMACAddress())
+ self.Logger.LogMessage("channel = " + str(wlan.config('channel')))
+ self.Logger.LogMessage("essid = " + str(wlan.config('essid')))
+ self.Logger.LogMessage("txpower = " + str(wlan.config('txpower')))
+ wlan.connect(self.ssid, self.pw)
+ timeout = 30
+ while timeout > 0:
+ if wlan.status() < 0 or wlan.status() >= 3:
+ break
+ timeout -= 1
+ self.Logger.LogMessage('Waiting for connection...')
+ time.sleep(1)
+
+ # Wlan Status on LED
+ # Handle connection error
+ # Error meanings
+ # 0 Link Down
+ # 1 Link Join
+ # 2 Link NoIp
+ # 3 Link Up
+ # -1 Link Fail
+ # -2 Link NoNet
+ # -3 Link BadAuth
+ def Status(self):
+ global wlan
+ wlan_status = wlan.status()
+ self.BlinkOnboardLED(wlan_status)
+ if wlan_status != 3:
+ #raise RuntimeError('Wi-Fi connection failed')
+ return False
+ else:
+ self.Logger.LogMessage('Connected')
+ status = wlan.ifconfig()
+ self.Logger.LogMessage('ip = ' + status[0])
+ return True
+
+ # Blinkfunktion der Onboard-LED für Errorcodes
+ def BlinkOnboardLED(self, num_blinks):
+ global led
+ for i in range(num_blinks):
+ led.on()
+ time.sleep(.2)
+ led.off()
+ time.sleep(.2)
+
+ def GetMACAddress(self):
+ return ubinascii.hexlify(network.WLAN().config('mac'),':').decode()
+
+ def GetIPAddress(self):
+ global wlan
+ return wlan.ifconfig()[0]
+
+ def IsWifiConnected(self):
+ global wlan
+ if wlan.status() == 3:
+ return "W"
+ else:
+ return " "
\ No newline at end of file
diff --git a/TimeUtils.py b/TimeUtils.py
new file mode 100644
index 0000000..f8a6f66
--- /dev/null
+++ b/TimeUtils.py
@@ -0,0 +1,16 @@
+import utime as time
+
+class TimeUtils():
+ def __init__(self):
+ pass
+
+ def DateTimeNow(self):
+ tm = time.gmtime()
+ return "%02d.%02d.%04d,%02d:%02d" % (tm[2], tm[1], tm[0], tm[3], tm[4])
+
+ def IsOlderThanDays(self, date, days):
+ fdate = time.mktime((int(date[0]), int(date[1]), int(date[2]), 0, 0, 0, 0, 0))
+ if (fdate + (int(days) * 86400) <= time.time()):
+ return True
+ else:
+ return False
\ No newline at end of file