Ansprechen einer Kamera mit Python

Sockets, TCP/IP, (XML-)RPC und ähnliche Themen gehören in dieses Forum
Antworten
Hermann90
User
Beiträge: 6
Registriert: Mittwoch 26. Oktober 2016, 11:42
Wohnort: Niedersachsen

Hallo zusammen,

ich bin absoluter Neuling in der Programmierung sowie in Python. Für ein studentisches Projekt muss ich eine Kamera über Python (durch Telnet-Befehle) ansprechen und für meinen Anwendungsfall die Koordinaten, welche die Kamera aufnimmt in Python ausgeben. Grund: Die Kamera soll später mit einem Roboter kommunizieren, welcher ein entsprechendes Bauteil durch Übermittlung von Kamerakoordinaten aufheben kann.

Die Kamera besitzt bereits ein eigenes Programm, welches durch Eingabe von Telnetbefehlen auch funktioniert. In meinem Fall konnte das Programm bereits geprüft werden (durch das Programm "SocketTest"). Hier ist eine Übergabe von Telnet Befehlen und die Ausgabe der gewünschten Koordinaten bereits erfolgreich durchgeführt.

Nun soll die manuelle Eingabe der Befehle durch Python ersetzt werden.

Eine Verbindung konnte ich bereits herstellen. Doch es scheitert an der Übergabe der ersten Telnet Befehle hier "WFW 10108" zum Auslesen der x-Koordinate... Das ist mein vorhandener Code:


import sys
import socket


host = '192.168.100.300'
port = 9999

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))
print(s.recv(1024))

print ('Socket bereit')

s.send('WFW 10108')
print(s.recv(1024))


s.shutdown
s.close()

Das Programm gibt Socket bereit aus, jedoch scheitere ich an der Übergabe von Telnet Befehlen. Kann mir jemand helfen?
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Hermann90: das TCP-Protokoll garantiert nur sehr wenig, nämlich nur dass Daten, die gesendet wurden, in der selben Reihenfolge ankommen, wie sie gesendet worden sind. Ob und wieviele Bytes gesendet werden, steht nicht fest. Daher gibt es auch sendall, das wenigstens garantiert, dass alles gesendet wird. Hier ist aber das Problem, dass Telnet normalerweise einen Zeilenumbruch erwartet:

Code: Alles auswählen

import sys
import socket

host = '192.168.100.300' 
port = 9999 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host,port))

print(s.recv(1024)) # Hier sollte solange gelesen werden, bis irgendein Input-Prompt kommt.

print ('Socket bereit')
s.sendall('WFW 10108\r\n')

print(s.recv(1024)) # Hier sollte solange gelesen werden, bis irgendein Input-Prompt kommt.
s.close()
Hermann90
User
Beiträge: 6
Registriert: Mittwoch 26. Oktober 2016, 11:42
Wohnort: Niedersachsen

@Sirius3 Danke für deine schnelle Antwort.

der Befehl in Zeile 10 gibt auch bereits eine Rückmeldung der Kamera aus und zwar das diese verfügbar ist. Jedoch haperte es an der Übermittlung der Telnet Befehle.

Da das System in der Universität steht habe ich nur bedingt Zugriff. Ich werden den geänderten Code so bald wie möglich testen.
Ich muss eine Reihe von Befehlen an die Kamera übermitteln, um die entsprechenden Koordinaten zu erhalten.
BlackJack

@Hermann90: Wenn es sich vermeiden lässt, dann sollte man möglichst weit weg von den Sockets gehen. Bei Telnet zum Beispiel mal das `telnetlib`-Modul aus der Standardbibliothek anschauen.
Hermann90
User
Beiträge: 6
Registriert: Mittwoch 26. Oktober 2016, 11:42
Wohnort: Niedersachsen

@BlackJack

wäre der von mir umgesetzte Code übertragen auf die telnetbib denn so korrekt?

Code: Alles auswählen

import sys
import telnetlib


host = '192.168.100.300' 
port = 9999 


tn = telnetlib.Telnet(HOST) #Verbindung zur Kamera herstellen

print(tn.read_all(1024)) #Rückmeldung der Kamera empfangen 
print ('Socket bereit') #Bestätigung wenn Rückmeldung erfolgreich


tn.sendall('WFW 10108\r\n') #Ersten Telnet Befehl an die Kamera übermitteln
print(tn.read_all(1024)) #Rückmeldung auf Telnet Befehl von Kamera erhalten

#usw.


tn.close()
Zuletzt geändert von Anonymous am Freitag 28. Oktober 2016, 11:57, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
BlackJack

@Hermann90: Ganz offensichtlich ist `HOST` undefiniert und `read_all()` erwartet kein Argument. Ohne wäre es die falsche Methode weil die *alles* liest was von der Gegenseite kommt und erst zurückkehrt und das Ergebnis liefert wenn die Gegenseite die Verbindung geschlossen hat, denn nur dann weiss man auch das sie alles gesendet hat und nichts mehr kommen wird.

Wenn Du einen Dialog mit der Gegenseite führen willst, dann wirst Du `expect()` und/oder `read_until()` verwenden müssen um zum Beispiel auf einen Prompt zu warten bevor Du neue Befehle absetzt, und eventuell auch die Rückgaben auswerten um zu entscheiden welche Befehle abgesetzt werden oder um auf Fehlermeldungen zu reagieren.

Das kann man schlecht als ”Trockenübung” machen. Dafür müsste man schon eine sehr exakte Beschreibung des ”Protokolls” haben. Wenn man das nicht hat, muss man am ”lebenden Objekt” forschen was bei welchen Eingaben und Randbedingungen passiert und worauf man reagieren muss.
Hermann90
User
Beiträge: 6
Registriert: Mittwoch 26. Oktober 2016, 11:42
Wohnort: Niedersachsen

@BlackJack

das Problem kann ich verstehen. Aber für die Umsetzung fehlt es mir leider an entsprechenden Kenntnissen.... :( die konkrete Abfolge der Befehle habe ich durch das Programm SocketTest bereits durchführen können. Ich habe im Bild (siehe Link) die Telnet Befehle aufgaführt sowie die entsprechenden Rückmeldungen der Kamera.

https://www.dropbox.com/s/d08ofq379j8e4 ... t.png?dl=0

Bild

ist so ein Programmablauf, der die Koordinaten einlesen kann überhaupt mit Python möglich?
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Hermann90: in Deinem schönen Bildchen (das man hier übrigens auch als Text hätte einfügen können) sieht man ja, dass der Eingabeprompt »S: « ist, also Du einfach read_until mit "\nS: " aufrufen kannst.
Hermann90
User
Beiträge: 6
Registriert: Mittwoch 26. Oktober 2016, 11:42
Wohnort: Niedersachsen

heute konnte ich das Programm testen. Habe nun auch die Koordinaten in Python erhalten :D

Code: Alles auswählen

import sys
import socket 


host = '192.168.100.300'   
port = 9999                

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect(('192.168.100.300',9999))
print(s.recv(1024)) 
print ('Socket successfully created')


s.send(b'S: WFW 0,0\r\n') 
print(s.recv(1024))
s.send(b'S: WFW 0,1\r\n')
print(s.recv(1024))
s.send(b'S: RFW 10108\r\n')
print(s.recv(1024))
s.send(b'S: RFW 10208\r\n')
print(s.recv(1024))


s.close()
kann man auch ausschließlich die X und Y Werte ausgeben lassen? im Beispiel 96.315 und -296.705

aktuell bekomme ich diese Meldungen ausgegeben:

b'20 SBOx-Q-ZEWAS: no authentication required.\r\n'
Socket successfully created
b'1 OK: operation successful.\r\n'
b'1 OK: operation successful.\r\n'
b'96.315\r\n'
b'-296.705\r\n'

falls ja wie genau kann ich das realisieren?
Zuletzt geändert von Anonymous am Montag 31. Oktober 2016, 13:42, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Codebox-Tags gesetzt.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@Hermann90: Das "S: " ist jetzt plötzlich Teil der Anfrage? Ich weiß nicht, wie oft wir das noch wiederholen sollen, aber recv funktioniert hier nur rein zufällig, mach es richtig und nutze telnetlib.
Hermann90
User
Beiträge: 6
Registriert: Mittwoch 26. Oktober 2016, 11:42
Wohnort: Niedersachsen

Ja das habe ich auch versucht, nur funktioniert es nicht. Habe mit der recv bislang den "größten Erfolg"
Antworten