Wie kann man eine Pyserial Klasse aus Commando shell aufrufen?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
MyPy17
User
Beiträge: 18
Registriert: Mittwoch 19. April 2023, 12:40

Ich habe einen seriellen Port den ich benutzen möchte um die Controllines (RTS etc.) zu benutzen. Das klappt auch wenn das Pythonskript direkt aus der IDLE aufgerufen wird. Nun habe ich jedoch die Anforderung dass das Skript von einer externen Applikation gestartet werden muss. Das heisst ich möchte nun zum Beispiel per Command CMD (Windows) dieses Pythonskript aufrufen und danach zu jedem beliebigen Zeitpunkt die RTS Leitung ein- oder ausschalten.

Was momentan geht ist jedoch lediglich die IDLE aufzurufen welche mir dann die Klasse instanziert. Danach ist die IDLE offen und ich kann nur noch in der IDLE weitere Methoden dann aufrufen. ich möchte jedoch an dieser Stelle von der externen Applikation die Methode aufrufen, was aber irgendwie nicht so funktioniert.

Hier mein Skript:

Code: Alles auswählen

from ast import If
import sys
import serial
import datetime
import time
import logging
import fire


from serial import Serial


class Russ_GPIO(object):
    def __init__(self, port="COM4", baud=57600, timeout=0.1, parity=serial.PARITY_NONE, do_not_open=False):
        
        self.com4 = serial.Serial("COM4", baud, rtscts=False, dsrdtr=False, timeout=timeout, parity=parity)
        self.com4.break_condition = False
        self.com4.setDTR(0)
        self.com4.setRTS(0)

    
    def set_gpio(self, chn, state):            
        print("first:  ", chn, state)
        if chn == 0:
            if state == 0: 
                self.com4.break_condition = False
                self.com4.setDTR(False)
                self.com4.setRTS(False)
                
                
                
x= Russ_GPIO()

                

Der Aufruf im Command Shell ist dann einfach:

Code: Alles auswählen

python -m idlelib -r ComPort.py

Das öffnet (und bleibt dann offen) die IDLE von welcher ich dann die Methode aufrufen kann. Aber eben die Frage ist wie könnte ich dies auch von einem externen Programm aus machen (mit oder ohne IDLE)?

Danke
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Da ist einiges schief im Code:

- Du definierst port als Argument, aber benutzt dann hartkodiert "COM4"
- Das die Verbindung self.com4 heisst, ist auch schlecht. Was, wenn die mal com3 ist? Ein einfacher Name wie self._com oder self._connection ist besser.
- Der Computer hat ausreichend Platz, abgekuerzte Namen wie chn sind unnoetig, und erschweren das lesen.
- Statt if-Anweisungen zu verschachteln, solltest du and benutzen: if channel == 0 and state == 0
- Ich vermute mal state kann 0 oder 1 sein? Besser sind True/False, und dann ein simples self.com4.break_condition = state etc pp.
- PEP8-Verletzungen, wie zB Russ_GPIO - das sollte RussGpio oder RussGPIO sein. namen_mit_unterstrich fuer Bezeichner, also Variablen, Methoden, Parameter. CamelCase fuer Klassennamen.
- Ableitung von (object) ist schon lange Geschichte, braucht es nicht.

Aber jetzt zu deinem Problem: das geht mit etwas das sich IPC - Inter Process Communication - nennt. Und was sich da anbietet, haengt von der ominoesen externen Anwendung ab. Wer ist das, und was kann die? Kann die beliebigen Code ausfuehren? Dann schreib das Ding in der Anwendung selbst. Kann die externe Kommandos ausfuehren? Dann schreib einen Service, der zB mit SimpleHTTPServer eine kleine API bereitstellt, und dann eine Reihe von Skripten, die dann die eigentlichen Schaltfunktionen ausfuehren.

Es gibt auch weitere Moeglichkeiten, aber wie gesagt: das haengt vom Mystery-Program X ab.
MyPy17
User
Beiträge: 18
Registriert: Mittwoch 19. April 2023, 12:40

ja vielen Dank für die schnelle Antwort und die guten Bemerkungen. Nun das Program kann beliebige Batchfiles oder Pythonskript aufrufen. Beim Pythonskript sehe ich momentan das Problem dass ich dann den Port nur beim Aufruf kurz öffnen kann und dann der Port mit den Controllines gleich wieder auf den Defaultwert zurückspringt da sich die Instanz auch gleich wiede schliesst.
Darum habe ich den Ansatz mit dem Batchfile versucht der aber irgendwie in die gleiche Richtung geht.

Das Ganze wird für ein externes Gerät (ohne grosse Logik) verwendet welches mir eine Schnittstelle freischaltet je nach Controllinestate (0 oder 1). Das heisst ich kann dies nicht im Gerät umsetzen und deshalb der Ansatz via Python. Ich würde dann den "Service" automatisieren wollen sprich zum Beispiel in Windows integrieren wenn dieses hochfährt oder jeweils um 12 Uhr ein- oder auschaltet.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Klar springt der zurück. Das Programm darf sich nicht beenden. Du musst dann eben zb https://docs.python.org/3/library/http.server.html benutzen, und einen lokalen Webservice bauen. Ein anderes Skript kann dann Argumente entgegennehmen & den Webservice entsprechend aufrufen.
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

MyPy17 hat geschrieben: Mittwoch 19. April 2023, 13:55Ich würde dann den "Service" automatisieren wollen sprich zum Beispiel in Windows integrieren wenn dieses hochfährt oder jeweils um 12 Uhr ein- oder auschaltet.
@MyPy17: jetzt solll das Programm plötzlich im Hintergrund laufen und gar nicht mehr mit einem anderen Programm interagieren?
Dann schreib doch einfach einen Windows-Service mit Python.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

@Sirius3: wo ist der Widerspruch? Den Service braucht es doch, um die Schnittstelle zu bedienen. Die batches/Skripte um mit der zu reden.
Sirius3
User
Beiträge: 18250
Registriert: Sonntag 21. Oktober 2012, 17:20

@__deets__: der Service soll aber jetzt automatisch etwas machen, etwa um eine bestimme Uhrzeit. Also sind die batch-Skripte überflüssig, weil man alles innerhalb des selben Python-Programms machen kann.
MyPy17
User
Beiträge: 18
Registriert: Mittwoch 19. April 2023, 12:40

Danke für eure Antworten. Ich denke die Lösung wie diese von __deets__ vorgeschlagen wurde war der zentrale Punkt (Lösung) für mein Problem. Man kann es dann mit einem batch Skript bedienen bzw. das ganze dann wohl auch gleich innerhalb desselben Programms machen so wie dies @Sirius3 vorgeschlagen hat.

Danke!
Antworten