Präsentationsunterstützungssystem mit Python3

Einführung

Es ist @ seigo2016 der N High School Programmierklasse 1. Jahr. Es wird [N High Adcare Day 8] sein (https://qiita.com/advent-calendar/2019/n-highschool). Ich habe mich gefragt, was ich schreiben soll, weil es ein richtiger Artikel ist, aber da ich viel über das aktuelle Hauptprojekt "Itokake Mandara Color Simulator" bei U22 usw. gesprochen habe, habe ich diesmal viel über das aktuelle Kurzzeitprojekt "PSS ~ Presentation Support" gesprochen. Ich werde über "System ~" sprechen.

Zweck von PSS ~ Presentation Support System ~

Ich denke, dass Sie häufig Präsentationen mit PowerPoint, Google Slide usw. halten, wenn Sie Leuten etwas erzählen. LT wird auch jeden Monat in der N High Programming Class (im Folgenden als Prokura bezeichnet) abgehalten. Deshalb habe ich beschlossen, ein System zur Unterstützung der Präsentation zu erstellen.

Funktion

  1. Kommentare fließen in Echtzeit
  2. Sie können die Folie von einem Smartphone usw. aus bedienen.
  3. Zeiger kann verwendet werden (nicht implementiert)

Umgebung

PSS.png

Webserver

Es ist der Teil, der Kommentare akzeptiert und aufzeichnet. Alles läuft auf Docker. Der Speicher ist 1 GB groß, funktioniert aber unerwartet.

Serverinformation

Teil Performance
VPN Vultr
CPU 1C/1T
Memory 1024MB
OS OS Debian 10 Buster

Docker-Container-Informationen

Ich benutze es auch, um Docker und Docker-Compose zu üben.

Containername Überblick
proxy Nginx Reverse Proxy
web Python3.6(Python ausführen)
mysql DB(Speichern Sie die Anmeldeinformationen)

Serverumgebung

Ich habe bcrypt verwendet, um das Passwort zu hashen, und die MySQL-Connector-Bibliothek, um eine Verbindung zu MySQL herzustellen. Zusätzlich zu den folgenden wurden SSL und Socket verwendet.

Python3


bcrypt==3.1.7
mysql-connector==2.2.9
pycrypto==2.6.1
PyYAML==5.2
tornado==6.0.3

Client-Umgebung

Ich habe Tkinter als Bibliothek zum Erstellen der GUI verwendet.

Python3


pdf2image==1.10.0
Pillow==6.2.1
progressbar2==3.47.0
PyYAML==5.2

Senden Sie Kommentare in Echtzeit

Dies ist der Hauptteil dieses Projekts. Das System selbst, in dem Kommentare in Echtzeit eingehen, wurde bereits von anderen professionellen Clubstudenten erstellt. Es gab jedoch viele Einschränkungen, z. B. die Nichtverwendung, wenn die Verbindungen zwischen Clients getrennt wurden. Daher haben wir beschlossen, ein neues System zu erstellen, das diese Teile verbessert. ** Dieses System verstößt nicht gegen das Patent des Kommentarsystems von Dongo, da die Montagemethode und die technischen Daten völlig unterschiedlich sind ** So funktioniert es.

Abgesehen davon gibt es mehrere Personen in meiner Umgebung, die Schwachstellen finden und melden möchten. Daher sind einige Sicherheitsmaßnahmen erforderlich, um zu verhindern, dass sie in die eigentliche Präsentation aufgenommen werden.

Server

Webfront

Dies ist der Teil, der Kommentare akzeptiert. Der Fluss ist wie folgt.

  1. Überprüfen Sie die erhaltenen Kommentare auf Sicherheitsprobleme
  2. Notieren Sie in der Datenbank, wenn ein Problem vorliegt
  3. Weisen Sie eine Variable zu, die von Threads gemeinsam genutzt wird.

server.py


def send_comment(comment):
    #Aktuelle Uhrzeit(JST)
    dt_now = dt.now(JST)
    #In Datenbank aufnehmen
    c = database.cursor()
    sql = "INSERT INTO comment (text, entertime) values(%s,%s)"
    c.execute(sql,
              (comment, dt_now,))
    database.commit()
    #Weisen Sie einer Variablen zu, die von Threads gemeinsam genutzt wird
    with commentbody.get_lock():
        commentbody.value = comment.encode()


class Comment(web.RequestHandler):
    def post(self):
        comment = self.get_argument("comment")
        comment = escape(comment)
        title = "Kommentar"
        if re.search(r'\S', comment) and len(comment) < 30:
            send_comment(comment)
            self.render('index.html', title=title)
        else:
            message = "Eingabe korrekt"
            self.render('index.html', title=title, message=message)

An Kunden senden

Als nächstes ist es der Teil, der den empfangenen Kommentar per Socket-Kommunikation an den Client (Präsentator-PC) sendet. Der Fluss ist wie folgt.

  1. Warten Sie auf die Socket-Verbindung an Port 10023
  2. Überprüfen Sie die Benutzerinformationen, falls verbunden
  3. Wenn die empfangenen Informationen mit den Benutzerinformationen in der Datenbank übereinstimmen, setzen Sie die Verbindung fort.
  4. Senden Sie anschließend den empfangenen Kommentar entsprechend an den Client. Wir prüfen vorab, ob die ID und das Kennwort der gesendeten Daten mit der in der Datenbank registrierten ID und dem Kennwort-Hash übereinstimmen. ~~ ** Ist das Nest nicht tief? ** ~~

server.py


def connect_socket():  #Socket-Kommunikation
    print("SocketStart")
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind(('0.0.0.0', 10023))  #Öffnen Sie an Port 10023
        while True:
            s.listen(1)
            print("Waitng ....")
            conn, addr = s.accept()
            flg = False
            while True:
                try:
                    conn = context.wrap_socket(conn, server_side=3)
                    with conn:
                        while True:
                            try:
                                print("Connecting")
                                data = conn.recv(1024).decode()
                                if not data:
                                    break
                                elif ":" in data:
                                    loginuser = data.split(":")[0]
                                    loginpass = data.split(":")[1]
                                    sql = "SELECT id, name, pass FROM users WHERE name = %s"
                                    c.execute(sql, (loginuser,))
                                    userdata = c.fetchall()
                                    if len(userdata) and bcrypt.checkpw(loginpass.encode(), userdata[0][2].encode()):
                                        print("Connected")
                                        conn.sendall("Verbindung hergestellt".encode("utf-8"))
                                        flg = True
                                    else:
                                        conn.sendall("Authentifizierungsfehler".encode("utf-8"))
                                        conn.close()
                                        flg = False
                                elif flg:
                                    comment = commentbody.value
                                    with commentbody.get_lock():
                                        commentbody.value = "".encode()
                                    if len(comment):
                                        conn.sendall(comment)
                                        comment = ""
                            except socket.error:
                                flg = False
                                break
                except Exception as e:
                    flg = False
                    print("Disconnected\n{}".format(e))
        s.close()

Client (Präsentator-PC)

Erhalten Sie Kommentare

Nach dem Herstellen einer Verbindung zum Server, dem Senden der Authentifizierungsinformationen und dem Anmelden erhält der Client (Präsentations-PC) den Kommentar.

client.py


def rcv_comment():
    #Einstellungen für die Socket-Kommunikation
    context = ssl.create_default_context()
    context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
    context.verify_mode = ssl.CERT_NONE
    context.check_hostname = False
    conn = context.wrap_socket(socket.socket(socket.AF_INET),
                               server_hostname=host)
    conn.connect((host, port))
    #Bereiten Sie Authentifizierungsinformationen vor(Das Format ist Benutzer:pass)
    idpass = "{}:{}".format(user_name, user_pass).encode()
    conn.sendall(idpass)
    manager = CommentManager(canvas)
    while True:
        try:
            data = conn.recv(1024)
            if len(data):
                comment = data.decode('utf-8')
                print("recv:" + comment)
                #Wenn ein Authentifizierungsfehler zurückgegeben wird, schließen Sie das Programm ab
                if comment == "Authentifizierungsfehler":
                    break
                #Andernfalls übergeben Sie den Kommentar an das Zeichnungsteil
                manager.add_text(comment)
        except KeyboardInterrupt:
            break

Kommentarzeichnung

Zeichnen Sie den erhaltenen Kommentar auf Tkinters Leinwand.

client.py


class CommentManager: #Zeichnungskommentare verwalten
    def __init__(self, canvas):
        self.canvas_text_list = []
        self.canvas = canvas
        root.after(1, self.update)

    def add_text(self, comment): #Fügen Sie einen Kommentar zum Flow hinzu
    #Generieren Sie Text mit einer x-Koordinate am Rand des Bildschirms und einer zufälligen y-Koordinate
        text = self.canvas.create_text(
            w, random.uniform(2.0, 18.0) * 100, text=comment, font=comment_font) 
        self.canvas_text_list.append(text)

    def update(self): #Gehe nach links
        new_list = []
        #Verschieben Sie Kommentare in der Liste nach links.(Es scheint besser, alles auf einmal mit Tags zu tun)
        for canvas_text in self.canvas_text_list: 
            self.canvas.move(canvas_text, -15, 0)
            x, y = self.canvas.coords(canvas_text)
            if x > -10:
                new_list.append(canvas_text)
            else: #Nach dem Umzug zum linken Ende
                self.canvas.delete(canvas_text)
        self.canvas_text_list = new_list
        root.after(20, self.update)

Schiebebetrieb

Da die Folie selbst in Tkinters Canvas geladen wird, aktualisieren Sie einfach das Bild

client.py


def next(event): #Folie senden
    global page
    if pagemax - 1 > page:
        canvas.itemconfig(labelimg, image=img[page])
        page += 1


def prev(event): #Bewegen Sie den Schlitten zurück
    global page
    if 0 <= page:
        canvas.itemconfig(labelimg, image=img[page])
        page -= 1

# ~Unterlassung~ # 
if __name__ == '__main__':
    th = Thread(target=rcv_comment)
    th.setDaemon(True)
    th.start()
    root.bind("<Key-n>", next) #Schlüssel hier zuweisen
    root.bind("<Key-p>", prev)
    root.mainloop()

Implementierung der Zeigerfunktion

Es ist nicht implementiert, da ich mir Sorgen mache, welches als Zeigergerät verwendet werden soll. Ich werde es hinzufügen, sobald es implementiert ist. Ist ein Smartphone doch gut?

Aufgabe

Am Ende

Ich schreibe wütenden Code, der überhaupt nicht gepackt ist ... Die Leistung ist nicht gut, wenn eine große Anzahl von Kommentaren fließt. Ich denke, es wäre ratsam, es als Overlay anzuzeigen.

Recommended Posts

Präsentationsunterstützungssystem mit Python3
Erstellen Sie ein Empfehlungssystem mit Python
Systemhandel ab Python3: langfristige Investition
FizzBuzz in Python3
Scraping mit Python
Statistik mit Python
Scraping mit Python
Python mit Go
"Systemhandel beginnt mit Python3" Lesememo
Twilio mit Python
In Python integrieren
Spielen Sie mit 2016-Python
AES256 mit Python
Getestet mit Python
Python beginnt mit ()
mit Syntax (Python)
Bingo mit Python
Zundokokiyoshi mit Python
Excel mit Python
Mikrocomputer mit Python
Mit Python besetzen
Zip mit Python extrahieren (unterstützt japanische Dateinamen)
Systemhandel ab Python 3: Investition und Risiko
Serielle Kommunikation mit Python
Zip, entpacken mit Python
Django 1.11 wurde mit Python3.6 gestartet
Primzahlbeurteilung mit Python
Python mit Eclipse + PyDev.
Socket-Kommunikation mit Python
Datenanalyse mit Python 2
Scraping in Python (Vorbereitung)
Versuchen Sie es mit Python.
Python lernen mit ChemTHEATER 03
Sequentielle Suche mit Python
"Objektorientiert" mit Python gelernt
Führen Sie Python mit VBA aus
Umgang mit Yaml mit Python
Löse AtCoder 167 mit Python
[Python] Verwenden Sie JSON mit Python
Python lernen mit ChemTHEATER 05-1
Lerne Python mit ChemTHEATER
Führen Sie prepDE.py mit python3 aus
1.1 Erste Schritte mit Python
Tweets mit Python sammeln
Binarisierung mit OpenCV / Python
3. 3. KI-Programmierung mit Python
Nicht blockierend mit Python + uWSGI
Scraping mit Python + PhantomJS
Tweets mit Python posten
Fahren Sie WebDriver mit Python
Verwenden Sie Mecab mit Python 3
[Python] Mit CGIHTTPServer umleiten
Sprachanalyse mit Python
Denken Sie an Yaml mit Python
Kinesis mit Python betreiben
Erste Schritte mit Python
Verwenden Sie DynamoDB mit Python
Behandle Excel mit Python
Ohmsches Gesetz mit Python
Primzahlbeurteilung mit Python
Führen Sie Blender mit Python aus