Hallo zusammen, ich sitze vor einem kleinen großen Problem. Ich habe für die Uni im Rahmen meiner Abschlussarbeit ein Gerät gebaut, welches mit dem PC verbunden ist. Am PC läuft dazu eine von mir in C++ geschriebene Steuerungssoftware mit GUI um das Gerät zu bedienen. (Betriebssystem ist Windows 7) Nun nähert sich mein Projekt dem Ende und ein anderer Student möchte darauf aufbauend seine Arbeit beginnen. Ursprünglich war der Gedanke, dass spätere Studenten auf meinen Code in C++ aufbauen. Leider kann der aktuelle Nachfolger kein C++ und möchte seinen Teil in Python oder Matlab programmieren. Mein Betreuer hat ihm das nun auch zugesagt und irgendwie ist es nun meine Aufgabe geworden mein Programm aus diesen Sprachen ansprechbar zu machen. Mein Betreuer der Ansicht, dass man JEDES Programm aus der Kommandozeile mit Parametern bedienen kann (bitte keine Diskussion hierzu) und so muss auch meines bedienbar sein, sofern ich keine andere Möglichkeit biete. Leider ist mein Programm aber eben kein "Spaghetti-Code-einmal-duchlaufen-und fertig"-Programm, sondern leistet eine rege Interaktion mit der Hardware. Es ist notwendig, dass auf Inputs von der Hardware ebenso wie auf Inputs vom Benutzer/anderer Software reagiert wird. Um die Struktur noch einmal zu verdeutlichen habe ich das Bild in den Anhang gehängt. Meine Frage ist nun: Wie Programmiert man eine vernünftige Schnittstelle für andere Software und Skripte? Ich hatte schon daran gedacht, irgendwie einen weg zu suchen, das Hauptprogramm normal auszuführen und per Kommandozeile aufrufbare miniprogramme zu schrieben, welche das drücken von Buttons auf der GUI simulieren, oder gar die Ausführung eigener Funktionen im Hauptprogramm veranlassen. Events von der Hardware würden dann ein externes Programm (oder Skript) aufrufen, dessen Pfad und Parameter in einer Konfigurationsdatei hinterlegt sein könnten. Aber wie löst man sowas eigentlich? Also wenn man saubere Arbeit abliefern will? Wie ihr an meiner hoffentlich nicht all zu wirren und halbwegs verständlichen Fragestellung vielleicht schon erkennt, habe ich einfach gar keine Erfahrung wie das ohne GUI-Automatisierung funktionieren soll. Vielen Dank für alle Tips, Hinweise, Ideen und sonstigen hilfreichen Gedanken. Viele Grüße, Leo
Kommt drauf an was Dein C++ Code so alles macht. GUIs und COM Ports sind in Matlab wirklich überhaupt kein Problem. Und wenn die Funktionalität der PC Software (im Sinne der eigentlichen Algorithmik) eh schon steht, ist der Kram vielleicht relativ zügig nach Matlab portiert.
Wenn da ein Protokoll zwischen dem steuernden Programm (ganz links) und dem gesteuerten Programm (mitte) erforderlich ist, ist eine Kommandozeilensteuerung offensichtlich nicht das gelbe vom Ei. Unter Windows ist eine verbreitete Variante in solch einem Fall die Verwendung von (D)COM als Automationsschnittstelle. Das kann man aus jeder Programmiersprache heraus nutzen, die Automation beherrscht, angefangen beim VBScript (das jedes Windows von sich aus beherrscht). Das in Klammern gesetzte "D" steht für distributed, diese Programmierschnittstelle ist prinzipiell auch für den Netzwerkbetrieb geeignet (spätestens dann aber ein Krampf im Arsch, wenn es um das Debuggen oder sonstige Fehlersuche geht). Ein alternativer Ansatz wäre die Verwendung eines über Sockets transportierten Protokolls, je nach Komplexität der transportierten Daten auch als reine Textvariante (dann kann die Funktionalität mit einem simplen Telnet-Client getestet werden). Beispiele für diese Art von Kommunikation sind Email-Clients. Das verbreitete http-Protokoll ist hier ungünstig, da es für jeden Kommunikationsvorgang eine neue Verbindung herstellt, und nicht innerhalb einer Verbindung einen dauerhaften Dialog nutzt. Die Verwendung dieser Art von Socket-Schnittstelle böte automatisch die Netzwerkfähigkeit und im Gegensatz zum Automationsansatz auch die Plattformunabhängigkeit -- so einem Socket ist es herzlich wurscht, ob die einlaufenden Daten von einem Linux- oder Windows-System kommen. Andere Schnittstellen (DLLs, die wiederum irgendwelche Interprozesskommunikationsmechanismen kapseln) schränken die Auswahl der verwendbaren Programmiersprachen ein. Ein wichtiger Aspekt aber ist die Betrachtung der zu übertragenden Daten, welcher Art sind diese und in welchen Mengen treten sie auf, und in welchem Zeitrahmen sind sie zu übertragen?
Falls es nicht schon der Fall ist, würde ich die GUI und die Logik zum Steuern der Hardware in eine EXE für die GUI und eine DLL für die Hardwareansteuerung aufteilen. Die DLL exportiert ein C++-Interface, das die GUI-EXE benutzt. Jemand mit C++-Kenntnissen sollte nur die DLL (und das Header-File) benötigen, um die Hardware ansteuern zu können. Zusätzlich zum C++-Interface exportierst Du noch ein ggf. vereinfachtes C-Interface. In den meisten Scriptsprachen ist es möglich, C-Funktionen aus DLLs aufzurufen. Wie das genau mit der Wunschsprache Deines Nachfolgers funktioniert, sollte er aus meiner Sicht selber rausfinden. Falls das nicht reicht, musst Du ihm halt ensprechende Bindings für Matlab oder Python anbieten. Dazu gibts jede Menge Anleitungen, einfach mal "Call C funtion from Matlab/Python/whatever" googlen.
Leo B. schrieb: > eine rege Interaktion mit der Hardware. Frage: was soll der Kollege denn entwickeln? Als Minimum braucht er die kommunikation mit der Hardware, also was über die serielle Schnittstelle läuft, dann kann er sich aus jeder belibigen Sprache heraus mit deiner Hardware unterhalten. Und die Beschreibung des seriellen Protokolls solltest du eigentlich schon für dich selbst angefertigt haben. Leo B. schrieb: > Mein Betreuer der Ansicht, dass man JEDES Programm aus der Kommandozeile > mit Parametern bedienen kann Ja, aber halt nur einmal, nämlich beim Start (man kann auch tricksen und das Programm mehrfach aufrufen und so weitere Befehle übergeben, aber das greift dann schon tiefer in die Windows-Programmierung ein). Leo B. schrieb: > Ich hatte schon daran gedacht, irgendwie einen weg zu suchen, das > Hauptprogramm normal auszuführen und per Kommandozeile aufrufbare > miniprogramme zu schrieben Naja, wenn das so sein muss. Dazu muss man aber nicht verschiedene Programme schreiben, das geht auch in ein und demselben Programm, wenn das nicht ein zweitesmal startet, sondern sich mit seiner ersten Instanz in Verbindung setzt. Ob im selben Programm oder einem anderen, Windows bietet verschiedene Möglichkeiten der Inter-Prozess-Kommunikation, z.B. Pipes, dazu muss man sich halt einlesen. Egal wie, das bisherige Programm muss natürlich so gestaltet sein, dass es die Kommandos annimmt und beantwortet, aber da du sowieso ein Event-gesteuertes Programm hast, musst du bloss den Event "Remote Command" hinzufügen, und natürlich spezifizieren, was auf welches Kommando was passieren soll. Ein eigener Thread wäre für sowas nicht schlecht. Das lohnt sich natürlich nur, wenn dein Programm was sinnvolles treibt - wenn der Kollege was ganz anderes will, soll er sich doch gleich mit der Hardware direkt unterhalten. Hört sich so an wie eine Software die ich zur Überwachung, Speicherung und Auswertung von mehrtägigen Messreihen auf eigener Hardware geschrieben habe. Georg
Leo B. schrieb: > Ich hatte schon daran gedacht, irgendwie einen weg zu suchen, das > Hauptprogramm normal auszuführen und per Kommandozeile aufrufbare > miniprogramme zu schrieben, Ja, das ist ein gängiger Weg. Implementiere eine Client-Server Architektur. Das lang laufende Hauptprogramm ist der Server, ein kleines Kommandozeilentool (ein einziges reicht) ist der Client, es wertet beim Aufruf seine Kommnandozeilenparameter aus, kontaktiert dann den Server, sendet einen Befehl (evtl mit zusätzlichen Daten), wartet auf Antwort (evtl auch mit Daten), gibt dann das Ergebnis in einem einfach zu parsenden Format an stdout aus und beendet sich bei Erfolg mit exit code 0. Fehlermeldungen oder menschenlesbare Debuginformationen oder Fortschrittsbalken oder dergleichen sollen an stderr ausgegeben werden so daß der Parser des aufrufende Prozesses das einfach auseinander halten kann. Wenn Du es ganz geschickt anstellt kannst Du sogar später noch das Client-Server Protokoll erweitern ohne den Kommandozeilenclient anpassen zu müssen wenn Du es so gestaltest daß er beliebige Befehle absetzen und beliebige Antworten empfangen und an stdout wieder ausgeben kann. Als Protokoll zwischen Client und Server kannst Du alles nehmen was zur Interprozesskommunikation taugt, ich würde aber auf jeden Fall was plattformübergreifendes nehmen und etwas das auch über das Netzwerk funktioniert, am besten ein einfaches textbasiertes menschenles- (und schreib-) bares Protokoll über *TCP/IP*, so lässt sich das bereits während der Entwicklung mit Telnet ausprobieren und debuggen, noch bevor der Client überhaupt komplett fertig gestellt ist. Dieses Protokoll solltest Du genau dokumentieren und an Deinen Nachfolger weitergeben, dann kann seine Anwendung später auch selbst einen Client implementieren wenn sie weiter fortgeschritten ist und braucht nicht mehr das Kommandozeilentool.
:
Bearbeitet durch User
https://wiki.python.org/moin/boost.python/SimpleExample Eventuell hilft dir das, wenn du deine Logik vom Gui gut getrennt hast.
Vielen Dank für die vielen Hilfreichen Informationen. Ich muss zugeben ich bin damit gerade etwas überfordert. Zunächst zur Frage, was da kommuniziert werden muss. Das sind Kommandos wie Deckel auf, Deckel zu, Teller drehen. In die andere Richtung müssen Informationen weiter gereicht werden, wie SensorN aktiviert/deaktiviert. Von der Häufigkeit her nichts, was man als mensch nicht bewältigen kann, nur hat eben keiner Lust 24/7 vorm PC zu sitzen und Knöpfe zu drücken. Nach allem was ich jetzt so gelesen und von euch erfahren habe, gefällt mir eine solche inter-Prozess-Kommunikation mit einem "Server" (mein existierendes Programm) mit einem "Client" (ein Kommandozeilen-Tool) am besten. Das entspricht vermutlich auch am Besten der Vorstellung meines Betreuers. Allerdings muss ich mich in das Thema noch einarbeiten, weshalb ich für jedes Stichwort oder dergleichen noch dankbar bin. "Distributed" muss das nicht sein, vielleicht sogar besser wenn es nur lokal funktioniert, dann kann keiner (wenn auch evtl. nur versehentlich) Fehlfunktionen und Störungen verursachen. Was es da für COM-Schnittstellen gibt ist mir allerdings noch nicht klar. Ich könnte vielleicht eine lokale Netzwerkbasierte (UDP) Datenübertragung gestalten, aber ob das der "vorgesehene" weg ist? was gibt es da noch für Schnittstellen? Ach ja vielleicht noch eine ganz wichtige Hintergrundinformation: bisher habe ich alles mit Qt programmiert und bin leider auch selbst gar nicht so bewandert in Sachen dll erzeugen oder einbinden. Oder auch boost, gehört habe ich schon viel davon, aber verwendet noch nie. Das Konzept ist mir relativ unbekannt.
> Kommandos wie Deckel auf > inter-Prozess-Kommunikation mit einem "Server" Würde erst mal schauen, ob ein einfacher TCP-Socket und einfache Textzeilen ausreichen. Z.B. "set switch1 off\n" "get switch1\n" Dein Nachfolger kann dann mit Kommandozeilentools wie netcat arbeiten. Oder er kann in einer beliebigen Programmiersprache selbst Textzeilen hin-und-her schicken.
mir ist immernoch nicht klar wie wichtig dein bisheriges Programm auf dem PC für's betreiben der Peripherie ist. Warum reicht nicht einfach die Beschreibung des Protokolls auf der ser. Schnittstelle? (hab im Kopf das Modell Computer<->Wählmodem, das Protokoll hier "AT-commands" - trifft sowas nicht auch auf dein Fall zu?)
Leo B. schrieb: > bisher > habe ich alles mit Qt programmiert Da sollte es doch einfach sein mit den dort existierenden Komponenten (Qt ist ja fast wie LEGO® für Programmierer) mal eben eine TCP-Server zu instantiieren der seine Slots feuert wenn Ereignisse kommen. Der Vorteil von TCP und textbasiert wäre halt daß Du schon während der Entwicklung des Servers einfach mal ein telnet localhost machen kannst und dann machst Du in dieser Sitzung sowas:
1 | Verbunden mit Messtisch-Steuerung v1.0 |
2 | Schreibe hilfe um die Befehle aufzulisten |
3 | ok |
4 | > hilfe |
5 | Erlaubte Kommandos: |
6 | deckel [auf|zu] steuert den Deckel |
7 | tisch [links|rechts] steuert den Tisch |
8 | messung [foo|bar|baz] <anzahl> führt eine Messung aus |
9 | ende beendet die Sitzung |
10 | ok |
11 | > deckel auf |
12 | ok |
13 | > deckel zu |
14 | ok |
15 | > tisch links |
16 | ok |
17 | > messung foo 7 |
18 | 2.99, 3.01, 3.04, 2.98, 3.03, 3.01, 3.02 |
19 | ok |
20 | > |
21 | ende |
22 | und tschüss... |
23 | |
24 | connection reset by peer |
und so weiter. Und wenn das geht dann schreibst Du nen Client. Ne TCP-Verbindung zu nem Server zu öffnen ist in jeder Programmiersprache genauso simpel (und programmatisch genauso zu bedienen) wie ne Datei zum Lesen/Schreiben zu öffnen.
Am einfachsten wäre es, wenn die Logik von der GUI getrennt wäre und die Logik sich in einer DLL befinden würde. Das jetzt noch aufzuteilen müsste, wenn sauber programmiert, nicht viel Arbeit bedeuten. Dann aus Matlab die dll zu nutzen solle gehen und nicht mehr dein Problem sein. Bei einer Client-Server Architektur würde ich etwas wie json-rpc oder xml-rpc empfehlen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.