Part-san überprüft täglich den Betriebsstatus von Kommunikationsgeräten auf einem speziellen Bildschirm, erstellt einen Bericht und sendet ihn per E-Mail. Ich denke, dass es für jedes Unternehmen durchaus üblich ist, ähnliche Arbeiten auszuführen, aber aus Sicht eines Ingenieurs ist eine solche Routine unmöglich, deshalb habe ich ein kleines Tool geschrieben.
Wir wissen, dass sich alle zugrunde liegenden Informationen in der Datenbank befinden.
Daher sollte ** ein Programm, das eine aus der Datenbank generierte PDF-Datei an eine E-Mail anhängt und diese sendet **, auf der Serverseite implementiert und auch in cron
registriert werden.
Ich dachte darüber nach, mit Pythons ** OpenPyXL ** -Modul in eine Excel-Datei auszugeben. [Erstellen Sie ein PDF im Lebenslaufformat mit Python + Reportlab] Inspiriert von diesem Artikel habe ich beschlossen, eine PDF-Datei mit dem Modul ** ReportLab ** auszugeben.
Installation
pip3 install reportlab
Es gibt verschiedene Möglichkeiten, eine Verbindung von Python zu MySQL herzustellen, aber ich hatte zufällig ** MySQLdb ** auf dem Server, also habe ich es verwendet. Ich werde es ohne große Änderungen veröffentlichen, aber ich denke, das Schema ist einigermaßen vielseitig, also beziehen Sie sich bitte darauf.
Python
"""
Generieren Sie einen Bericht im PDF-Format aus der Datenbank, hängen Sie ihn an eine E-Mail an und senden Sie ihn
"""
__author__ = "MindWood"
__version__ = "1.00"
__date__ = "31 Oct 2019"
import MySQLdb
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.lib import colors
from reportlab.lib.pagesizes import A4, portrait
from reportlab.lib.units import mm
from reportlab.platypus import Table, TableStyle
import smtplib
from email import encoders
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email.mime.multipart import MIMEMultipart
import os
import datetime
def setup_page():
"""Registrieren Sie die Schriftart und legen Sie die Kopf- und Fußzeile fest"""
pdfmetrics.registerFont(UnicodeCIDFont(font_name)) #Schriftregistrierung
#Kopfzeilenzeichnung
c.setFont(font_name, 18)
c.drawString(10*mm, height - 15*mm, "Betriebsstatusbericht der Kommunikationsausrüstung")
c.setFont(font_name, 9)
c.drawString(width - 58*mm, height - 10*mm, header_date)
#Fußzeilenzeichnung
c.drawString(10*mm, 16*mm, "Die Terminal-IDs, die innerhalb der letzten 8 Stunden Daten empfangen haben, werden grün angezeigt.")
global page_count
c.drawString(width - 15*mm, 5*mm, "{}Seite".format(page_count)) #Seitenzahl zeichnen
page_count += 1
def control_break():
"""Kontrollpause nach Kundenname"""
if ctrl_break_key == "": return
c.showPage()
setup_page()
def page_break(n):
"""Seitenumbruchverarbeitung"""
n += 1
if n < 28: return n
c.showPage()
setup_page()
return 0
#Einstellen des Basisdatums und der Basiszeit
dt = datetime.datetime.now()
header_date = "{:%Y Jahr%-m Monat%-d Tag%-Uhr%-M Minuten jetzt}".format(dt)
safe_date = "{:%Y/%m/%d %H:%M}".format(dt + datetime.timedelta(hours=-8)) #vor 8 Stunden
#Initialisierung der PDF-Datei
pdf_filename = "report{:%y%m}.pdf".format(dt)
c = canvas.Canvas(pdf_filename, pagesize=portrait(A4)) #PDF-Dateiname und Papiergröße
width, height = A4 #Holen Sie sich Papiergröße
c.setAuthor("MindWood")
c.setTitle("IoT gateway Working report")
c.setSubject("")
font_name = "HeiseiKakuGo-W5" #Schriftartenname
page_count = customer_no = 1
setup_page()
ctrl_break_key = ""
#Stellen Sie eine Verbindung zu MySQL her
conn = MySQLdb.connect(host="localhost", user="xxxxxx", passwd="yyyyyy", db="zzzzzz", charset="utf8")
cursor = conn.cursor(MySQLdb.cursors.DictCursor)
#Erfassung von Stamminformationen von Kommunikationsgeräten
cursor.execute('''
SELECT c.Name as CustName, d.Name as DeptName, a.Code, a.Area, hex(a.MacAddress) as MacAddress
FROM table0001 a
LEFT JOIN table0002 c ON a.CustomerID = c.CustomerID
LEFT JOIN table0003 d ON a.CustomerID = d.CustomerID AND a.DeptID = d.DeptID
ORDER BY c.CustomerID, d.DeptID, MacAddress;
''')
gws = cursor.fetchall()
for row_gw in gws:
#Seitenumbruch, wenn sich der Kundenname ändert
if ctrl_break_key != row_gw["CustName"]:
control_break()
ctrl_break_key = row_gw["CustName"]
c.setFont(font_name, 15)
c.drawString(10*mm, height - 36*mm, "{}. {}".format(customer_no, ctrl_break_key))
customer_no += 1
data = [ [ "Abteilungsname", "Verwaltungscode", "Installationsbereich", "MAC-Adresse" ] ] #Überschrift des Kommunikationsgeräts
table = Table(data, colWidths=(70*mm, 40*mm, 40*mm, 40*mm), rowHeights=8*mm) #Eine Tabelle erstellen
table.setStyle(TableStyle([
("FONT", (0, 0), (-1, -1), font_name, 11), #Schriftart
("BOX", (0, 0), (-1, -1), 1, colors.black), #Außengrenze
("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black), #Innenrand
("VALIGN", (0, 0), (-1, -1), "MIDDLE"), #Richten Sie die Zeichen vertikal in der Mitte aus
("BACKGROUND", (0, 0), (-1, -1), colors.lightgrey), #Mit Grau füllen
]))
table.wrapOn(c, 10*mm, height - 50*mm) #Tischposition
table.drawOn(c, 10*mm, height - 50*mm) #Tischposition
line_count = 1
styles = [
("FONT", (0, 0), (-1, -1), font_name, 11),
("BOX", (0, 0), (-1, -1), 1, colors.black),
("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
]
MacAddress = row_gw["MacAddress"]
if os.uname()[1] == "ip-172-35-10-XX": #Für einen bestimmten Server
MacAddress = "XXXXXXXXXXXX"
styles.append(("BACKGROUND", (3, 0), (3, 0), colors.yellow)) #Mit Gelb füllen
data = [ [ row_gw["DeptName"], row_gw["Code"], row_gw["Area"], MacAddress ] ] #Detaillierte Daten der Kommunikationsausrüstung
table = Table(data, colWidths=(70*mm, 40*mm, 40*mm, 40*mm), rowHeights=8*mm)
table.setStyle(TableStyle(styles))
table.wrapOn(c, 10*mm, height - 50*mm - 8*mm * line_count)
table.drawOn(c, 10*mm, height - 50*mm - 8*mm * line_count)
line_count = page_break(line_count)
#Erfassung von Datum und Uhrzeit des Datenempfangs
cursor.execute('''
SELECT hex(TermID) as TermID, from_unixtime(min(Time),"%Y/%m/%d %H:%i:%S") as from_date, from_unixtime(max(Time),"%Y/%m/%d %H:%i:%S") as to_date FROM table0005
WHERE MacAddress=0x{} GROUP BY TermID ORDER BY to_date;
'''.format(MacAddress))
terms = cursor.fetchall()
for row_term in terms:
data = [ [ "Zeitraum", row_term["from_date"] + " ~ " + row_term["to_date"], "Terminal ID", row_term["TermID"] ] ] #Detaillierte Daten des Terminals
table = Table(data, colWidths=(25*mm, 100*mm, 25*mm, 40*mm), rowHeights=8*mm)
styles = [
("FONT", (0, 0), (-1, -1), font_name, 11),
("BOX", (0, 0), (-1, -1), 1, colors.black),
("INNERGRID", (0, 0), (-1, -1), 0.25, colors.black),
("VALIGN", (0, 0), (-1, -1), "MIDDLE"),
("BACKGROUND", (0, 0), (0, 0), colors.lightgrey),
("BACKGROUND", (2, 0), (2, 0), colors.lightgrey),
]
if row_term["to_date"] > safe_date: #Wenn das Datum und die Uhrzeit des letzten Empfangs innerhalb der letzten 8 Stunden liegen
styles.append(("BACKGROUND", (3, 0), (3, 0), colors.palegreen))
table.setStyle(TableStyle(styles))
table.wrapOn(c, 10*mm, height - 50*mm - 8*mm*line_count)
table.drawOn(c, 10*mm, height - 50*mm - 8*mm*line_count)
line_count = page_break(line_count)
#Trennen Sie MySQL
cursor.close()
conn.close()
#In PDF-Datei speichern
c.showPage()
c.save()
#PDF-Datei per E-Mail senden
from_addr = "[email protected]"
to_addr = "[email protected]"
bcc_addr = "[email protected]" #Mehrere Angaben können durch Kommas getrennt angegeben werden
rcpt = bcc_addr.split(",") + [to_addr]
msg = MIMEMultipart()
msg["Subject"] = "Betriebsstatusbericht der Kommunikationsausrüstung{:%Y Jahr%-m Monat}".format(dt)
msg["From"] = from_addr
msg["To"] = to_addr
msg.attach(MIMEText("""
Diese E-Mail wird automatisch vom System gesendet.
Der Systembetriebsstatus des XXXX-Servers ist angehängt.
""".strip()))
attachment = MIMEBase("application", "pdf")
file = open(pdf_filename, "rb+")
attachment.set_payload(file.read())
file.close()
encoders.encode_base64(attachment)
attachment.add_header("Content-Disposition", "attachment", filename=pdf_filename)
msg.attach(attachment)
smtp = smtplib.SMTP("smtp.xxxxxx.com", 587) #SMTP-Server
smtp.starttls()
smtp.login(from_addr, "PASSWORD") #Passwort
smtp.sendmail(from_addr, rcpt, msg.as_string())
smtp.close()