Server/Client in Python Socket program stalls in middle of execution - python

I am working on an assignment that entails socket-programming using Python. What I am trying to do is create a server called "dispatcher" and 3 clients that all run the same "car.py" file that will represent race cars. Each of the race cars will randomly select a speed between 0-120 mph every five seconds and send that speed to the server(aka dispatcher). The server will take the speeds of the three cars and compute how much distance is left until that car reaches the finish line. Once one or more cars reaches the finish line, the server will compute who the winner is and announce that to all three cars. The server will keep track of who is in the lead and will announce that to all three cars every five seconds.
The problem is that in the middle the program stalls and it seems that the server and one of the clients is both waiting for each other. Here is my code for the server:
import socket
import sys
import threading
from queue import Queue
NUMBER_OF_THREADS = 2
JOB_NUMBER = [1, 2]
queue = Queue()
all_connections = []
all_address = []
# Create a Socket ( connect two computers)
def create_socket():
try:
global host
global port
global s
host = '127.0.0.1'
port = 9999
s = socket.socket()
except socket.error as msg:
print("Socket creation error: " + str(msg))
# Binding the socket and listening for connections
def bind_socket():
try:
global host
global port
global s
print("Binding the Port: " + str(port))
s.bind((host, port))
s.listen(5)
except socket.error as msg:
print("Socket Binding error" + str(msg) + "\n" + "Retrying...")
bind_socket()
# Handling connection from multiple clients and saving to a list
# Closing previous connections when server.py file is restarted
def accepting_connections():
for c in all_connections:
c.close()
del all_connections[:]
del all_address[:]
while True:
try:
conn, address = s.accept()
s.setblocking(1) # prevents timeout
all_connections.append(conn)
all_address.append(address)
print("Connection has been established :" + address[0])
except:
print("Error accepting connections")
def start_turtle():
while True:
cmd = input('turtle> ')
if cmd == 'go':
start_race()
elif cmd == 'stop':
break
else:
print("Command not recognized")
# Starting the Race
def start_race():
# Setting the distance to the finish line of the three cars
distance1, distance2, distance3 = 50, 50, 50
try:
while True:
# Collecting Speed rates at MPH of the 3 cars
speed1 = all_connections[0].recv(4096)
speed2 = all_connections[1].recv(4096)
speed3 = all_connections[2].recv(4096)
print("\nSpeed of Car 1: " + str(speed1.decode("utf-8")))
print("Speed of Car 2: " + str(speed2.decode("utf-8")))
print("Speed of Car 3: " + str(speed3.decode("utf-8")) + "\n")
# Calculating the distance travelled by each car driving at the same speed for five minutes.
dist_travelled1 = int(speed1.decode("utf-8")) / 60 * 5
dist_travelled2 = int(speed2.decode("utf-8")) / 60 * 5
dist_travelled3 = int(speed3.decode("utf-8")) / 60 * 5
# The amount of distance that is left to reach the finish line.
distance1 -= round(dist_travelled1, 1)
distance2 -= round(dist_travelled2, 1)
distance3 -= round(dist_travelled3, 1)
# Seeing who is in the lead.
lead = min(distance1, distance2, distance3)
lead_flag = True
# Checking to see if Car1 won or not
if distance1 <= 0:
message1 = "You crossed the finish line!"
print("Car 1 crossed the finish line!")
all_connections[0].sendall(message1.encode("utf-8"))
lead_flag = False
else:
message1 = "You have " + str(round(distance1, 1)) + " more miles left to go."
print("Car 1 has " + str(round(distance1, 1)) + " more miles left to go.")
all_connections[0].sendall(message1.encode("utf-8"))
# Checking to see if Car2 won or not
if distance2 <= 0:
message2 = "You crossed the finish line!"
print("Car 2 crossed the finish line!")
all_connections[1].sendall(message2.encode("utf-8"))
lead_flag = False
else:
message2 = "You have " + str(round(distance2, 1)) + " more miles left to go."
print("Car 2 has " + str(round(distance2, 1)) + " more miles left to go.")
all_connections[1].sendall(message2.encode("utf-8"))
# Checking to see if Car3 won or not
if distance3 <= 0:
message3 = "You crossed the finish line!"
print("Car 3 crossed the finish line!")
all_connections[2].sendall(message3.encode("utf-8"))
lead_flag = False
else:
message3 = "You have " + str(round(distance3, 1)) + " more miles left to go."
print("Car 3 has " + str(round(distance3, 1)) + " more miles left to go.")
all_connections[2].sendall(message3.encode("utf-8"))
# Breaking from while loop if we have a winner.
if message1 == "You crossed the finish line!" or message2 == "You crossed the finish line!" or \
message3 == "You crossed the finish line!":
break
# Keeping track of who is in the lead
if lead_flag:
lead_message = ''
if lead == distance1:
lead_message = "\nCar 1 is in the lead!"
elif lead == distance2:
lead_message = "\nCar 2 is in the lead!"
elif lead == distance3:
lead_message = "\nCar 3 is in the lead!"
print(lead_message)
all_connections[0].sendall(lead_message.encode("utf-8"))
all_connections[1].sendall(lead_message.encode("utf-8"))
all_connections[2].sendall(lead_message.encode("utf-8"))
sys.stdout.flush()
# If multiple cars crossed the finish line during the last round, calculate who crossed the finish line first.
time_to_cross_finish1 = distance1 / (dist_travelled1 / 5)
time_to_cross_finish2 = distance2 / (dist_travelled2 / 5)
time_to_cross_finish3 = distance3 / (dist_travelled3 / 5)
# Determine the winner
winner = min(time_to_cross_finish1, time_to_cross_finish2, time_to_cross_finish3)
# Creating and sending messages to both winners and losers.
loser_message = "You Lost!"
winner_message = "You Won!"
if winner == time_to_cross_finish1:
print("Car 1 Won!")
all_connections[0].sendall(winner_message.encode("utf-8"))
all_connections[1].sendall(loser_message.encode("utf-8"))
all_connections[2].sendall(loser_message.encode("utf-8"))
elif winner == time_to_cross_finish2:
print("Car 2 Won!")
all_connections[0].sendall(loser_message.encode("utf-8"))
all_connections[1].sendall(winner_message.encode("utf-8"))
all_connections[2].sendall(loser_message.encode("utf-8"))
elif winner == time_to_cross_finish3:
print("Car 3 Won!")
all_connections[0].sendall(loser_message.encode("utf-8"))
all_connections[1].sendall(loser_message.encode("utf-8"))
all_connections[2].sendall(winner_message.encode("utf-8"))
except:
print("Error: Shutting Down")
# Create worker threads
def create_workers():
for _ in range(NUMBER_OF_THREADS):
t = threading.Thread(target=work)
t.daemon = True
t.start()
# Do next job that is in the queue (handle connections, send commands)
def work():
while True:
x = queue.get()
if x == 1:
create_socket()
bind_socket()
accepting_connections()
if x == 2:
start_turtle()
queue.task_done()
def create_jobs():
for x in JOB_NUMBER:
queue.put(x)
queue.join()
create_workers()
create_jobs()
And for the cars (All three clients run the same file):
import random
import time
import socket
import sys
# create an INET(IPv4), STREAMing(TCP) socket
try:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except socket.error:
print('Failed to create socket')
sys.exit()
print('Socket Created')
host = '127.0.0.1'
port = 9999
s.connect((host, port))
print('Socket Connected to IP' + host)
# Function for calculating current speed
def speed():
# Using random number to determine speed group
marker = random.randrange(1, 100)
speed_ratio = ''
# Speed groups are chosen before actual speed in order to balance speed selection and make the program more
# realistic.
if marker == 1:
speed_ratio = 'Crash'
elif marker < 5:
speed_ratio = 'Too_Slow'
elif marker < 15:
speed_ratio = 'Slow'
elif marker < 65:
speed_ratio = 'Steady'
elif marker < 90:
speed_ratio = 'Fast'
elif marker < 100:
speed_ratio = 'Ultra_Fast'
elif marker == 100:
speed_ratio = 'Max_Speed'
# Based on ratio, exact speed is determined in mph
speed_range = {'Crash': 0,
'Too_Slow': random.randrange(1, 29),
'Slow': random.randrange(30, 59),
'Steady': random.randrange(60, 79),
'Fast': random.randrange(80, 109),
'Ultra_Fast': random.randrange(110, 119),
'Max_Speed': 120}
# Current speed is printed and sent to the server
current_speed = speed_range[speed_ratio]
print("\nCurrent Speed: " + str(current_speed))
s.sendall(str(current_speed).encode("utf-8"))
# Waits to receive calculation of how close it is to the finish line.
reply = s.recv(4096)
message = reply.decode("utf-8")
print(message)
# Waits to receive news of who is in the lead or who the winner is.
reply = s.recv(4096)
message = reply.decode("utf-8")
print(message)
# Exit upon winning or losing
if message == "You Won!" or message == "You Lost!":
return False
return True
# Main program: Calculates speed every five seconds. Each second represents what would be a minute in real time.
flag = True
now = time.time()
future = now + 5
while flag:
if time.time() > future:
flag = speed()
now = time.time()
future = now + 5
Here is what the console reads from the server program:
turtle: Binding the Port: 9999 Connection has been established
:127.0.0.1 Connection has been established :127.0.0.1 Connection has
been established :127.0.0.1 go
Speed of Car 1: 20 Speed of Car 2: 85 Speed of Car 3: 4
Car 1 has 48.3 more miles left to go. Car 2 has 42.9 more miles left
to go. Car 3 has 49.7 more miles left to go.
Car 2 is in the lead!
Here are the three client terminals:
Car 1:
Socket Created Socket Connected to IP127.0.0.1
Current Speed: 20 You have 48.3 more miles left to go.
Car 2 is in the lead!
Current Speed: 113
Car 2:
Socket Created Socket Connected to IP127.0.0.1
Current Speed: 85 You have 42.9 more miles left to go.
Car 2 is in the lead!
Current Speed: 78
Car 3:
Socket Created Socket Connected to IP127.0.0.1
Current Speed: 4 You have 49.7 more miles left to go. Car 2 is in the
lead!
As you can see from the output, Car 1 and Car 2 have produced another speed that was sent to the server while Car 3 has not. It seems that the server is sitting and waiting for Car 3 and Car 3 is waiting for the server and I don't know why. Car 3 implements the same exact code as the other cars. When I rerun the program it usually gets stuck at Car 3 but will sometimes get stuck at Car 2 and even Car 1 in the same way.
I am baffled at what the problem could be. It actually worked one single time after repeatedly rerunning the program but after rerunning right away after that with no changes whatsoever, it went back to this same problem. Any help would be greatly appreciated.

Related

Exit loop with KeyboardInterrupt then begin another loop in python

I currently have a piece of code designed to communicate with two motors via a TCP Device Server which sends ASCII commands to them in order to trace sinusoidal paths. I wish to have the movement continue indefinitely and then immediately stop when KeyboardInterrupt is triggered, then have the motors move back to their defined home positions before the program ends.
This code can currently replicate sinusodial motion, but it currently does not stop immediately when KeyboardInterrupt is triggered, nor do the motors move back to their home positions. The sinusodial loop is designed such that when KeyboardInterrupt occurs, a global variable called move changes from True to False and this breaks the loop. The simplified code is given below:
import socket
import time
import numpy as np
import math
pi = math.pi
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("Failed to connect")
exit()
print("Sockets Created")
s1.connect(("192.168.177.200", 4001)) # Y motor
s2.connect(("192.168.177.200", 4002)) # X motor
# Disengage the motor to allow manual movement by wheel
s1.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DI\n".encode("ASCII"))
message = s1.recv(1024).decode()
homeposition = input("Are the motors centred? Press 'y' to confirm: ")
if homeposition == 'y':
s1.send("EN\n".encode("ASCII"))
s2.send("EN\n".encode("ASCII")) # energise the motors so they cannot be moved
print("Motors Engaged")
s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position
else:
print("Set home position and restart program")
exit()
#----ADD DATA FOR SAMPLING SINUSODIAL FUNCTIONS----
radius = input("Desired radius of movement (mm):")
radius = float(radius)
print("radius of circular path (mm): ", radius)
# need slightly different ratios for each motor due to different thread sizes
gearpositionlim_x = 20000 #one rotation equals 2.5mm (+ bearing ration on manipulator of 2:1)
gearpositionlim_y = 10000 #one rotation equals 2mm
# sample sine and cosine
step = 2*pi / 1000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim_x*np.cos(time_range)
y_motorrange = gearpositionlim_y*np.sin(time_range)
x_motorrange = ['la'+str(int(i)) for i in x_motorrange]
y_motorrange = ['la'+str(int(i)) for i in y_motorrange]
#print(x_motorrange)
x_motorrange_wcom = []
y_motorrange_wcom = []
{x_motorrange_wcom.extend([e, 'm', 'np']) for e in x_motorrange} # add movement prompts and wait for movement to complete
{y_motorrange_wcom.extend([e, 'm', 'np']) for e in y_motorrange} # add movement prompts and wait for movement to complete
# Set Acceleration and Deceleration of Motors
s1.send("AC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("AC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Acceleration set to 10 ")
s1.send("DEC10\n".encode("ASCII"))
message = s1.recv(1024).decode()
s2.send("DEC10\n".encode("ASCII"))
message = s2.recv(1024).decode()
print("Deceleration set to 10")
def setup(): #move to initial position before starting movement
s2.send(str(str(x_motorrange_wcom[0])+"\n").encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def end():
print("Movement ended, return to home position")
s1.send("la0\n".encode("ASCII"))
s1.send("m\n".encode("ASCII"))
s1.send("np\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
s1.send("DI\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
time.sleep(2)
s2.send("la0\n".encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
s2.send("DI\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def motormove():
global move
try:
for i in np.arange(0,len(x_motorrange)):
if (move == True):
s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
else:
break
except KeyboardInterrupt:
move = False
print(move)
end()
#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
print("Code Running: Press ctrl + c to end")
while (move == True):
motormove()
I believe my issue is with my function motormove(), but I am unsure of what I should do in order to achieve my desired operation. Does anyone know how this can be achieved?
Thanks in advance
Using library signal should be sufficient for your usecase. See code bellow.
import socket
import signal
import time
import numpy as np
import math
pi = math.pi
try:
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #TCP Server Connection
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
except:
print("Failed to connect")
exit()
print("Sockets Created")
s1.send("HO\n".encode("ASCII")) # set current position as home position
s2.send("HO\n".encode("ASCII")) # set current position as home position
gearpositionlim = int(10000)
# sample sine and cosine
step = 2*pi / 2000
time_range = np.arange(0,2*pi + step,step)
x_motorrange = gearpositionlim*np.sin(time_range)
y_motorrange = gearpositionlim*np.cos(time_range)
def handler(signum, frame):
res = input("Ctrl-c was pressed. Do you really want to exit? y/n ")
if res == 'y':
exit(1)
else:
#Do STH
def setup():
s2.send(y_motorrange[0])+"\n").encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def end():
print("Movement ended, return to home position")
s1.send("la0\n".encode("ASCII"))
s1.send("m\n".encode("ASCII"))
s1.send("np\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
s1.send("DI\n".encode("ASCII"))
s1.send("delay200\n".encode("ASCII"))
time.sleep(2)
s2.send("la0\n".encode("ASCII"))
s2.send("m\n".encode("ASCII"))
s2.send("np\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
s2.send("DI\n".encode("ASCII"))
s2.send("delay200\n".encode("ASCII"))
def motormove():
global move
try:
for i in np.arange(0,len(x_motorrange)):
if (move == True):
s1.send(str(str(x_motorrange[i])+"\n").encode("ASCII"))
s2.send(str(str(y_motorrange[i])+"\n").encode("ASCII"))
else:
break
except KeyboardInterrupt:
signal.signal(signal.SIGINT, handler)
#-------------------------------------------
setup()
name = input("Code Ready, press enter to proceed: ")
if name == "":
print("Code Running: Press ctrl + c to end")
while (move == True):
motormove()
This should be working just fine, note the signal function being called on KeyboardInterrupt, this redirects to signal function where, you can either exit or do something else.

While loop problem, or probably sth else?

Soo i am a pupil, and i am quite new to coding. I want to make an app that starts a timer when a game starts (specifically the game Valorant), which i get by searching if the process of the game is running. Then i get notifications by the app every 30 minutes. Finally, when i close the game, the app is supposed to pause the timer and tell me how long i was playing. When i close the game, though, the timer does not stop, and i have discovered that the app never understands that the process has stopped running, even though i use a while loop. This is the code: Thank u in advance!
from win10toast import ToastNotifier
import psutil
import time
import schedule
def show_name():
game = "VALORANT-Win64-Shipping.exe" in (i.name() for i in psutil.process_iter())
if game == True:
def timer():
game = "VALORANT-Win64-Shipping.exe" in (i.name() for i in psutil.process_iter())
m = 0
s = 0
while game == True:
time.sleep(1)
s += 1
print(m , s)
if s == 59:
m +=1
s = 0
if m == 30:
toast = ToastNotifier()
toast.show_toast("Hello!", "You have been playing for 30 minutes", duration=20)
elif m == 60:
toast = ToastNotifier()
toast.show_toast("Hello!", "You have been playing for an hour", duration=20)
elif m == 90:
toast = ToastNotifier()
toast.show_toast("Hello!", "You have been playing for 1 hour and 30 minutes", duration=20)
elif m == 120:
toast = ToastNotifier()
toast.show_toast("Hello!", "You have been playing for 2 hours", duration=20)
else:
toast = ToastNotifier()
toast.show_toast("Hello!", "You have played for " + str(m) + " minutes and " + str(s) + " seconds!", duration=20)
schedule.every(4).seconds.do(timer)
schedule.every(4).seconds.do(show_name)
while 1:
schedule.run_pending()
time.sleep(1)
The reason why the while loop won't break is you don't change the game variable within the while loop. It means if the game is True at the beginning, while game == True is the same as while True loop. You need to revalidate the game in every iteration.
try While"VALORANT-Win64-Shipping.exe" in (i.name() for i in psutil.process_iter()):
BTW, You can directly write While game: instead of While game == True

Client disconnects when another client connects to the server

I'm writing an Encrypted R-P-S (Rock, Paper, Scissors) Game with Python, and it works like this. The server is leading the game, and the two clients is just sending their choice to the server.
First, the server is waiting for 2 players to join, when 2 players have joined, he is starting the game and letting both of the clients to choice an option.
My problem is that when the first client connects, and then the another, the first client automatically disconnects.
So, I don't know how to handle both of the clients, and let the first client choose an option and then let the second choose option.
*Note: I'm using the same client file for both of the clients.
Server:
import socket
from Crypto.PublicKey import RSA
from Crypto.Cipher import PKCS1_OAEP
from time import sleep
def rules(first_choice, second_choice, mem1, mem2) -> str:
if (first_choice == 'R' and second_choice == 'P'
or first_choice == 'P' and second_choice == 'S'
or first_choice == 'S' and second_choice == 'R'):
return f'Result: Player 2 Won\nPlayer 1 Choice - {first_choice}\nPlayer 2 Choice - {second_choice}'
else:
return f'Result: Player 1 Won!\nPlayer 1 Choice - {first_choice}\nPlayer 2 Choice - {second_choice}'
class Connect:
def __init__(self):
players = 0
self.prikey = RSA.generate(1024)
self.pubkey = self.prikey.publickey()
self.token = PKCS1_OAEP.new(self.prikey)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.bind(('0.0.0.0', 21523))
sock.listen(2)
print('Waiting for at least 2 players, please wait.')
while True:
self.conn, self.addr = sock.accept()
players += 1
if players == 1:
print(f'Player 1 is {self.addr}')
self.player1 = self.addr
elif players == 2:
print(f'Player 2 is {self.addr}')
self.player2 = self.addr
self.connection()
def connection(self) -> None:
print('2 Players have joined, starting game in 5 seconds.\n')
sleep(5)
self.conn.send('Y'.encode())
self.game_play()
def game_play(self) -> None:
self.conn.send(self.pubkey.exportKey())
choice_1_cipher = self.conn.recv(1024)
choice_1_plain = self.token.decrypt(choice_1_cipher)
print('Got first choice, waiting for another choice..')
choice_2_cipher = self.conn.recv(1024)
choice_2_plain = self.token.decrypt(choice_2_cipher)
print('Got second answer, calculating winner!')
print(rules(choice_1_plain, choice_2_plain, self.player1, self.player2))
if __name__ == '__main__':
Connect()
Client:
import socket
import random
from Crypto.Cipher import PKCS1_OAEP
from Crypto.PublicKey import RSA
class Client:
def __init__(self):
self.prikey = RSA.generate(2048)
self.pubkey = self.prikey.publickey()
self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.sock.connect(('10.0.0.42', 21523))
data = self.sock.recv(1024).decode()
if data == 'Y':
self.start_game()
def start_game(self) -> None:
print('\n [R]ock | [P]aper | [S]cissors - ')
while True:
my_choice = input().upper()
if my_choice not in ['R', 'P', 'S']:
print('Invalid Input, input must be one of those R\\P\\S')
else:
user_pubkey = RSA.importKey(self.sock.recv(2048))
token = PKCS1_OAEP.new(user_pubkey)
cipher_choice = token.encrypt(my_choice.encode())
self.sock.send(cipher_choice)
if __name__ == '__main__':
try:
Client()
except Exception as e:
print(f'err: {e}')
except KeyboardInterrupt:
print('A player has pressed [Ctrl + C] to quit the game, game ended!')
self.conn in self.conn, self.addr = sock.accept() when the 2 client connects gets overwritten and the self.conn of the player1 is lost.
I guess you should assign the self.conn to self.player1_conn before returning to the beginning of the while loop waiting for the 2 player.
This is actually a recurrent problem in your script because when you say self.conn.send('Y'.encode()) self.conn is referring only to the second player connection (which i guess it's not what you intend to do).
You should separate the conn in player1_conn and player2_conn and then you'll be able to chose to which player send what you need.

Python Guess Game Server-Client

Well here is a python server - client guess game programm.Well here my problem is that all works but the loop doesnt.More specificly i can only put one guess from the user.I just want the user to input values and when he finds the right answer the program will close.Right now i can insert only one value for some reason .
Server:
import socket
import random
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.bind(("192.168.1.3",9000))
s.listen(5)
(c,a) = s.accept()
print ("Received connection from", a)
Hello=c.recv(10000).decode()
print(Hello)
greetings="Greetings!"
c.send((greetings+"\r\n").encode())
game=c.recv(10000).decode()
print (game)
ready="Ready For The Guess Game!"
c.send((ready+"\r\n").encode())
random_number = random.randint(1, 20)
running = 1
while running:
guess=c.recv(10000).decode()
guess=int(guess)
print(guess)
if guess <= random_number - 3:
far_message="Far!"
c.send((far_message+"\r\n").encode())
if guess >= random_number + 3:
far_message="Far!"
c.send((far_message+"\r\n").encode())
if guess == random_number - 2 or guess == random_number + 2 or guess == random_number + 1 or guess == random_number - 1:
close_message="close!"
c.send((close_message+"\r\n").encode())
if (guess==random_number):
correct_message="Correct!"
c.send((correct_message+"\r\n").encode())
running=0
c.close()
And the Client:
import socket
s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(('192.168.1.3',9000))
Hello="Hello"
s.send((Hello +"\r\n").encode())
greetings=s.recv(10000).decode()
print(greetings)
game="Guess Game Please"
s.send((game +"\r\n").encode())
game=s.recv(10000).decode()
print (game)
running=1
while running:
guess = input("Enter your guess: ")
s.send(guess.encode())
close_message = s.recv(10000).decode()
print (close_message)
far_message = s.recv(10000).decode()
print(far_message)
correct_message = s.recv(10000).decode()
print(correct_message)
running=0
s.close()
You need only one response listener on the client side
while running:
guess = input("Enter your guess: ")
s.send(guess.encode())
response = s.recv(10000).decode()
print(response)
if response.startswith("Correct"):
running = 0

Raspberry Pi Python loop stop to work

i manipulate a sensor : HC SR04 to capture a distance.
I'm a newbie in Python and RPI. My code work, I capture distance during a time but one moment the script stop...
My code :
GPIO.setmode(GPIO.BCM)
GPIO_TRIGGER = 23
GPIO_ECHO = 24
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
def main():
global state
print("ultrasonic")
while True:
print "1s second refresh.."
time.sleep(1)
i = 0
datas = []
average = 0
while i< 1:
GPIO.output(GPIO_TRIGGER, False)
time.sleep(C.time['count'])
GPIO.output(GPIO_TRIGGER, True)
time.sleep(0.00001)
GPIO.output(GPIO_TRIGGER, False)
while GPIO.input(GPIO_ECHO) == 0:
start = time.time()
while GPIO.input(GPIO_ECHO) == 1:
stop = time.time()
distance = (stop-start) * 17000
print "Distance : %.1f" % distance
average = F.getAverage(datas)
print "Average: %.1f" % average
GPIO.cleanup()
The code stop here
while GPIO.input(GPIO_ECHO) == 0:
start = time.time()
THE SOLUTION : with a sample timeout :
now = time()
while GPIO.input(self.gpio_echo) == 0 and time()-now<waitTime:
pass
I am also mucking about with this sensor. My code executes similar to yours and I need no timeout for it to work.
The one difference I can find is this:
while i< 1:
GPIO.output(GPIO_TRIGGER, False)
time.sleep(C.time['count'])
I don't know how long the sleep time is here, but it might be that that's causing the problem. If it would be similar to mine setting the Trigger to false would be directly after the setup of the in/out pins instead, and then there's a two second wait to eliminate noise. Your wait time might be lower, I can't tell. There should be no need to set the trigger to false again just before you send the pulse and, I don't know, but it might be causing a false start. I would change it to this to work similarly to mine and then remove the setting to false in the while loop.
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)
GPIO.output(GPIO_TRIGGER, False)
print("Waiting for sensor to settle\n")
time.sleep(2)
I'm not sure if this will solve the issue without the need for a timeout, but I don't seem to need one.
I've written a module for making an object of the sensor which then allows for some more readable scripting. I'm also quite new to python and not at all an experienced programmer so fun errors might be there somewhere, but it's here below if you want to use it or just compare code:
#! /usr/bin/python3
# dist.py this is a module for objectifying an ultrasonic distance sensor.
import RPi.GPIO as GPIO
import time
class Distancer(object):
#init takes an input of one GPIO for trigger and one for echo and creates the object,
#it searches for a calibration file in the working directory (name)Const.txt, if none
#is found it will initiate a calibration
def __init__(self, trig, cho, name):
self.trigger = trig
self.echo = cho
self.name = name
self.filename = self.name + 'Const.txt'
GPIO.setup(self.trigger, GPIO.OUT)
GPIO.setup(self.echo, GPIO.IN)
GPIO.output(self.trigger, False)
print("Waiting for sensor to calm down")
time.sleep(2)
try:
with open(self.filename, "r") as inConst:
self.theConst = int(inConst.read())
except (OSError, IOError) as e:
print("Not calibrated, initializing calibration")
self.calibrate()
with open(self.filename, "r") as inConst:
self.theConst = int(inConst.read())
#Returns the echo time
def measureTime(self):
GPIO.output(self.trigger, True)
time.sleep(0.00001)
GPIO.output(self.trigger, False)
while GPIO.input(self.echo) == 0:
pulse_start = time.time()
while GPIO.input(self.echo) == 1:
pulse_end = time.time()
pulse_duration = pulse_end - pulse_start
return pulse_duration
#Returns a distance in cm
def measure(self):
return self.measureTime() * self.theConst
#Makes you set up the sensor at 3 different distances in order to find the
#relation between pulse time and distance, it creates the file (name)Const.txt
#in the working directory and stores the constant there.
def calibrate(self):
ten = []
thirty = []
seventy = []
print("Make distance 10 cm, enter when ready")
input()
for i in range(30):
ten.append(10/self.measureTime())
time.sleep(0.2)
print("Make distance 30 cm, enter when ready")
input()
for i in range(30):
thirty.append(30/self.measureTime())
time.sleep(0.2)
print("Make distance 70 cm, enter when ready")
input()
for i in range(30):
seventy.append(70/self.measureTime())
time.sleep(0.2)
allTime = ten + thirty + seventy
theOne = 0.0
for i in range(90):
theOne = theOne + allTime[i]
theOne = theOne / 90
with open(self.filename, "w") as inConst:
inConst.write(str(round(theOne)))
#Will continually check distance with a given interval until something reaches the
#treshold (cm), takes an argument to set wether it should check for something being
#nearer(near) or farther(far) than the treashold. Returns True when treshold is reached.
def distWarn(self, nearfar, treashold):
if nearfar.lower() == "near":
while True:
if self.measure() < treashold:
return True
break
time.sleep(0.2)
if nearfar.lower() == "far":
while True:
if self.measure() > treashold:
return True
break
time.sleep(0.2)
#Will measure with a second interval and print the distance
def keepGoing(self):
while True:
try:
print(str(round(self.measure())) + ' cm')
time.sleep(1)
except KeyboardInterrupt:
print("Won't keep going")
break
I've run it with the code below to test it and everything seems to work. First time it's run it will prompt you to calibrate the sensor by putting it at different distances from something.
#! /usr/bin/python3
import RPi.GPIO as GPIO
import time
import dist as distancer
GPIO.setmode(GPIO.BOARD)
TRIG = 16
ECHO = 18
dist = distancer.Distancer(TRIG, ECHO, 'dist')
def main():
global dist
print(str(round(dist.measureTime(),5)) + ' s')
print(str(round(dist.measure())) + ' cm')
dist.distWarn('near', 10)
print('Warning, something nearer than 10 cm at ' + time.asctime( time.localtime(time.time()) ))
dist.distWarn('far', 10)
print('Warning, something further than 10 cm at ' + time.asctime( time.localtime(time.time()) ))
dist.keepGoing()
GPIO.cleanup()
print('Fin')
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt:
GPIO.cleanup()
print("Exiting")
time.sleep(1)
I am pretty sure you want
while GPIO.input(GPIO_ECHO)==GPIO.LOW:
start = time.time()
while GPIO.input(GPIO_ECHO) == GPIO.HIGH:
stop = time.time()
I don't think GPIO.input naturally returns zeros or ones, you can test that though.
Not really, I think that i lost the signal, i'll try a timeout in
while GPIO.input(GPIO_ECHO)==GPIO.LOW:
start = time.time()
I think that my program wait indefinitely a signal but he stay to 0
I know this is an old question. The cause of the problem was described in this question https://raspberrypi.stackexchange.com/questions/41159/...
The solution is to add a timeout, like the OP did, to the while loops similar to this:
# If a reschedule occurs or the object is very close
# the echo may already have been received in which case
# the following will loop continuously.
count=time.time()
while GPIO.input(GPIO_ECHO)==0 and time.time()-count<0.1:
start = time.time()
...
# if an object is not detected some devices do not
# lower the echo line in which case the following will
# loop continuously.
stop = time.time()
count=time.time()
while GPIO.input(GPIO_ECHO)==1 and time.time()-count<0.1:
stop = time.time()

Categories

Resources