Was die Absichten dieses Programms sind:Python Code nach Steckdosen Verbindung ausgeführt nur einmal
Ich mag einige Befehle von einem Client zu einem Server über Sockets senden, der Server dann diesen Befehl an einen Arduino mit serieller senden. Und eine andere Sache, die der Server in Zukunft tun soll, ist, dass er regelmäßig andere Befehle an den Arduino sendet, ohne dass er irgendwelche Eingaben vom Client erhält, also müssen die Sockets nicht blockierend sein oder es muss eine andere Möglichkeit geben, den Code auszuführen getrennt vom Socket-Code.
Das Problem ist, dass der Teil, der den Befehl an das Arduino senden soll, nur einmal ausgeführt wird.
Was ich nach dem Spielen mit dem Debugger in Pycharm herausgefunden habe, ist das Problem, dass die folgende Zeile blockiert, nachdem eine Verbindung hergestellt wurde, und damit den Rest des Codes nicht ausgeführt werden kann.
conn, addr = s.accept()
Ist das korrekt, oder stimmt etwas anderes nicht?
Ich habe versucht, den Sockel nicht blockierend zu setzen, aber wenn ich dies tue, erhalte ich einen Fehler.
Ich habe ein paar Grundkenntnisse in C/C++ und C# und bin neu in Python.
server.py
import socket
import serial
import sys
from _thread import *
import threading
import queue
# command that the client sends are "ON" and "OFF"
class serialConnect:
comPort =' '
baudrate = 115200
myserial = serial.Serial('COM5', baudrate)
def serialstart(self):
# self.comPort = input('Comport: ')
try:
self.myserial.open()
except IOError:
print('Port is already open!')
def serialRead(self):
data = self.myserial.read(16)
data.decode('UTF-8')
return data
def serialWrite(self, data):
data += '\n' #the arduino needs a \n after each command.
databytes = data.encode('UTF-8')
self.myserial.write(databytes)
print('send data: ', databytes)
def threaded_client(conn, dataqueue):
data = {bytes}
conn.send(str.encode('welcome, type your info \n'))
while True:
data = conn.recv(2048)
if not data:
break
reply = 'server output: ' + data.decode('UTF-8')
dataqueue.put(data.decode('UTF-8'))
print("Items in queue: ",dataqueue.qsize())
#conn.sendall(str.encode(reply))
print("Recieved data in threaded_client: ", data.decode('UTF-8') + '\n')
conn.close()
def Main():
ser = serialConnect()
host = ''
port = 5555
dataRecieved = 'hello'
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(2)
s.setblocking(1) #when set to non-blocking error occurs : "BlockingIOError: [WinError 10035] A non-blocking socket operation could not be completed immediately"
workQueue = queue.Queue(10)
try:
s.bind((host,port))
except socket.error as e:
print(str(e))
s.listen(5)
print('waiting for a connection')
while True:
try:
conn, addr = s.accept() #once connection is established it blocks?
print('connected to: ' + addr[0] + ':' + str())
t = threading.Thread(target=threaded_client, args=(conn, workQueue))
t.daemon = True
t.start()
except:
e = sys.exc_info()
print('Error:', e)
# This section of code is only run once, doesn't matter if put inside try block or not. :(
dataRecieved = workQueue.get()
print('The recieved data: ', dataRecieved)
ser.serialstart()
ser.serialWrite(dataRecieved)
if __name__ == '__main__':
Main()
client.py
import socket
def Main():
host = '127.0.0.1'
port = 5555
message = "<,R,G,B,>"
mySocket = socket.socket()
mySocket.connect((host, port))
while message != 'q':
message = input(" -> ")
mySocket.send(message.encode())
mySocket.close()
if __name__ == '__main__':
Main()
Arduino-Code
String inputString = ""; // a string to hold incoming data
boolean stringComplete = false; // whether the string is complete
int LEDpin = 10;
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin 13 as an output.
pinMode(10, OUTPUT);
Serial.begin(19200);
}
// the loop function runs over and over again forever
void loop() {
serialEvent();
if(stringComplete){
Serial.println(inputString);
if(inputString == "ON\n"){
digitalWrite(LEDpin, HIGH); // turn the LED on (HIGH is the voltage level)
}
if(inputString == "OFF\n"){
digitalWrite(LEDpin, LOW); // turn the LED off by making the voltage LOW
}
inputString = "";
stringComplete = false;
}
}
void serialEvent()
{
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag
// so the main loop can do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
Ihre Namenskonvention ist C# -Style. Python verwendet names_like_this für alles außer Klassen. Außerdem sollten Sie anstelle des expliziten '.close()' ' – Elazar
' accept' * sollten * eine Anweisung 'with' verwenden, bis Sie eine Verbindung erhalten. Sobald Sie eine erste Verbindung akzeptieren, erstellt Ihr Code einen separaten Thread, der diese Verbindung verarbeitet, aber dann wird der Hauptthread (einmal) durch den Rest seiner Schleife laufen und dann erneut "accept" ausführen. Und so wird es blockieren, bis du * eine andere * Verbindung hast. Wenn das nicht der Fall ist, müssen Sie Ihren Code neu strukturieren. –
Vielen Dank für Ihren Kommentar. Ich habe den Code überarbeitet und jetzt funktioniert es so, wie ich es möchte (zumindest jetzt). Siehe die Bearbeitung für den neuen Server-Code, der andere Code ist gleich geblieben. – MarkerDave