Online game give the error "("ConnectionAbortedError: [WinError 10053] " - python

I made a game in python with pygame and socket, my game works perfectly in local server, but when i want to try it with my friend it give me these errors :
("ConnectionAbortedError: [WinError 10053] An established connection was aborted by the software in your host machine
and
Traceback (most recent call last
File "C:/Users/Zahraa Rached/Desktop/Poké-aim/client.py", line 54, in <module>
game = n.send("get")
File "C:\Users\Zahraa Rached\Desktop\Poké-aim\network.py", line 25, in send
return pickle.loads(self.client.recv(4096))EOFError: Ran out of input
My port are frowarded and i arleady played a game that i have coded on different pc (with my friends)
so the problem should not be my server host
(i tried a lot of different things like disabling my firewall and my antivirus)
network class:
class Network:
def __init__(self):
self.client=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.server="my public ip"
self.port=50
self.addr=(self.server,self.port)
self.p=self.connect()
def getP(self):
return self.p
def connect(self):
try:
self.client.connect(self.addr)
return self.client.recv(4096).decode()
except:
pass
def send(self,data):
try:
self.client.send(str.encode(data))
return pickle.loads(self.client.recv(4096))
except socket.error as e:
print(e)
server
import socket
from _thread import*
import pickle
from game import*
g=Game()
clientnb=0
server="192.168.1.43"
port=50
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
try:
s.bind((server,port))
except socket.error as e:
print(e)
s.listen()
print("J'attend une connexion, Dresseur de Pokémon")
def thread(conn,p):
global clientnb
global g
print(clientnb)
g.pos[p]=(0,0)
conn.send(str.encode(str(p)))
r=False
reply=""
while True:
if g.ready == clientnb and clientnb > 1:
g.start=True
else:
g.start=False
try:
data=conn.recv(4096).decode()
if data=="ready":
r=True
g.ready+=1
elif data=="clik":
print("x")
print(g.ball)
g.changepos()
g.changeball()
print(g.ball)
elif data=="reset":
g.reset()
elif data=="win":
g.end=True
elif data!="get":
co=eval(data)
g.pos[p]=co
elif not data:
print("oh")
if r:
g.ready-=1
clientnb-=1
del g.pos[p]
break
reply = g
conn.sendall(pickle.dumps(reply))
except:
print("ohh")
if r:
g.ready -= 1
clientnb -= 1
g.reset()
break
conn.close()
while True:
conn,addr=s.accept()
print(addr)
p = clientnb
start_new_thread(thread,(conn,p))
clientnb+=1
client:
import pygame
import pickle
import sys
from network import Network
import time
import socket
pygame.font.init()
pygame.mixer.pre_init(44100, -16, 2, 512)
pygame.mixer.init()
pygame.init()
run=True
timevar=False
pygame.mixer.music.load("music.mp3")
pygame.mixer.music.set_volume(0.1)
myscore=0
w=1280
h=720
screen= pygame.display.set_mode((w,h))
pygame.display.set_caption("Poké-Aim")
n=Network()
fond_color=(0,0,0)
color1 = (255, 0, 0)
click=pygame.mixer.Sound("click.ogg")
ball=pygame.transform.scale(pygame.image.load("ball.png").convert_alpha(),(71,62))
master=pygame.transform.scale(pygame.image.load("master.png").convert_alpha(),(35,31))
bigmaster=pygame.transform.scale(pygame.image.load("master.png").convert_alpha(),(71,62))
cursor=pygame.transform.scale(pygame.image.load("cursor.png").convert_alpha(),(48,48))
other_cursor=pygame.transform.scale(pygame.image.load("black_cursor.png").convert_alpha(),(48,48))
playing=False
loosing=False
winning=False
def find_key(v):
for k, val in pos.items():
if v == val:
return k
clock=pygame.time.Clock()
ready=False
start=False
p=int(n.getP())
print(p)
pygame.mouse.set_visible(False)
while run:
clock.tick(60)
screen.fill(fond_color)
try:
game = n.send("get")
except socket.error as e:
print(e)
run=False
print("Connexion perdue")
break
if game!=None:
start=game.start
name=game.name
bol=game.ball
pos=game.pos
end=game.end
if game.ready==0:
ready=False
if not start:
if not ready:
color1=(255,0,0)
font = pygame.font.Font("Pokemon Classic.ttf", 20)
sc=font.render("= 1 pts", 1,(255,255,255) )
sc2=font.render("= 3pts", 1,(255,255,255) )
screen.blit(sc,(w/2,150))
screen.blit(sc2, (w / 2, 215))
screen.blit(ball,((w/2-80),140))
screen.blit(bigmaster, ((w / 2 - 80), 200))
text = font.render("Clique sur l'écran pour te mettre prêt !", 1,color1 )
screen.blit(text, ((w - text.get_width()) / 2, (h - text.get_height()) / 2))
elif start:
screen.fill((255,244,10))
if not playing:
pygame.mixer.music.play()
playing=True
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit()
if event.type == pygame.MOUSEBUTTONUP:
if event.button == 1:
while not ready and not timevar:
color1 = (0,255, 0)
screen.blit(text, ((w - text.get_width()) / 2, (h - text.get_height()) / 2))
n.send("ready")
click.play()
ready=True
if start:
if name=="P":
if (bol[0]) <= (pygame.mouse.get_pos()[0] ) <= (bol[0] + 71):
if pygame.mouse.get_pos()[1]>= (bol[1]) and pygame.mouse.get_pos()[1] <= (bol[1] + 62):
click.play()
n.send("clik")
click.play()
myscore+=1
else:
if (bol[0]) <= (pygame.mouse.get_pos()[0] ) <= (bol[0] + 35):
if (pygame.mouse.get_pos()[1]) >= (bol[1]) and (pygame.mouse.get_pos()[1] )<= (bol[1] + 31):
click.play()
n.send("clik")
myscore+=3
try:
n.client.send(str.encode(str(pygame.mouse.get_pos())))
except :
pass
if start:
if name=="P":
screen.blit(ball, (bol[0], bol[1]))
else:
screen.blit(master, (bol[0], bol[1]))
for e in pos.values():
if find_key(e) != p:
if find_key(e) != p:
screen.blit(other_cursor, (e[0]-24,e[1]-24))
score = font.render(str(myscore), 1, (0,0,0))
screen.blit(score, (5,0))
if myscore >= 1:
pygame.mixer.music.stop()
screen.fill((0, 0, 0))
wintext = font.render("T'as gagné sale bg !", 1, color1)
screen.blit(wintext, ((w - wintext.get_width()) / 2, (h - wintext.get_height()) / 2))
pygame.display.update()
n.send("win")
if not timevar:
chrono=time.time()
timevar=True
if round(time.time()-chrono)>4:
n.send("reset")
color1 = (255, 0, 0)
start = False
ready = False
playing = False
myscore = 0
timevar=False
end = False
elif end:
pygame.mixer.music.stop()
screen.fill((0, 0, 0))
loosetext = font.render("T'as perdu t'es trop nul sérieux !", 1, (255,0,0))
screen.blit(loosetext, ((w - loosetext.get_width()) / 2, (h - loosetext.get_height()) / 2))
pygame.display.update()
if not timevar:
chrono = time.time()
timevar = True
if round(time.time() - chrono) > 4:
color1 = (255, 0, 0)
start = False
ready = False
playing = False
myscore = 0
timevar = False
end = False
screen.blit(cursor,(pygame.mouse.get_pos()[0]-24,pygame.mouse.get_pos()[1]-24))
pygame.display.update()
game_class:
import random
h=720
w=1280
class Game:
def __init__(self):
self.name="P"
self.pos= {}
self.ball=[w/2,h/2]
self.ready=0
self.start=False
self.end=False
def changepos(self):
if self.name=="P":
self.ball[0]=random.randrange(0+71,w-71)
self.ball[1]=random.randrange(0,h-62)
else:
self.ball[0] = random.randrange(0 + 35, w- 35)
self.ball[1] = random.randrange(0, h - 31)
def changeball(self):
self.name=random.choice("MPPPPPPPPPP")
def reset(self):
self.name = "P"
self.ball = [w / 2, h / 2]
self.ready=0
self.start = False
self.end = False

A quick read of the manual about socket.recv() tells us that self.client.recv(4096) uses that 4096 buf_size parameter as:
The maximum amount of data to be received at once is specified by [...]
So, it's the maximum, not the minimum. Your .recv() will never receive more than 4096 bytes. That's all.
But the code is assuming it will always recv() enough bytes:
return pickle.loads( self.client.recv(4096) ) # gambling a crash on Rx size
On your current network set-up, something is causing smaller packets to arrive at the recv(), and not a full "pickle-worth". This is always an issue with network communications, it may be temporary, it may be permanent. Maybe a damp connection is causing packet loss, maybe maybe maybe. It was working before because the network/computers behaved differently.
So what do you do? The solution is check to see if any bytes have arrived. If bytes have arrived, add them to an "incoming-buffer". If there's enough bytes in the buffer, unpack it.
Pickling a data structure for sending over the network is probably an OK method, but I would first transmit the data-size of the pickled object, so the receiving client can know whether enough bytes have arrived to unpack it. Sure you can try..catch the un-pickling, but that's grossly inefficient.
I would use struct.pack to send the pickle-buffer size as a 4-byte integer (in network-byte order). Receive those 4 bytes first, then wait for the further N bytes to arrive.
EDIT: More details on struct, etc.
import struct
import pickle
def sendData( server_sock, object ):
result = True
data = pickle.dumps( object )
data_size = struct.pack( '!I', len( data ) ) # good for 2^32 bytes
try:
server_sock.sendall( data_size ) # send the size of the pickled obj
server_sock.sendall( data ) # send the obj
except:
sys.stderr.write( "Error sending data to server\n" )
result = False
return result
And then to receive the data, read the 4-byte size field and then the pickle data. Something like the below should work (note: this is not tested code, I'm just answering off the top of my head)
def recvData( client_sock ):
""" Try to receive a picked data-structure from the socket.
Returns True and an unpicked object, or False and None """
result = False
packet = None
expected = -1
# First we read a 4-byte pickle size, and following that is /N/ bytes
# of pickled structure data.
# Read the 4-byte packet size first
buffer = bytes()
while ( len( buffer ) < 4 ):
try:
some_data = client_sock.recv( 4 - len( buffer ) )
if ( some_data ):
buffer.append( some_data )
if ( len( buffer ) == 4 ):
expected = struct.unpack( '!I', buffer )
except:
# TODO: work out which sort of exceptions are OK
break
# If we received a buffer size, try to receive the buffer
if ( expected > 0 ):
buffer = bytes()
while ( len( buffer ) < expected ):
try:
some_data = client_sock.recv( expected - len( buffer ) )
if ( some_data ):
buffer.append( some_data )
# Have we received the full data-set yet?
if ( len( buffer ) == expected ):
packet = pickle.loads( buffer )
result = True # success
except:
# TODO: work out which sort of exceptions are OK
break
return result, packet
To be honest if you're just sending fixed amounts all the time (like a pair of x/y co-ordinates), it might be easier to just pack and unpack everything, using fixed-size datagrams. Maybe that's not "pythonic" enough though ;)
Anyway, what makes good network code is handling all the little rough edges. Sometimes (for a hundred different reasons), data does not arrive in nicely sized blocks, or your network blocks for a second or so. Simply handling this with a buffer, and non-blocking code solves 99% of the ills.
Really the recv() above should be non-blocking code, but this is left as an exercise for the reader. I like to use select() for this, but that's a bit old-fashioned.

Related

serial data buffering up in socat channel [duplicate]

I have a USB controller that I'm trying to get inputs from, a Microsoft® SideWinder® Plug & Play Game Pad. I'm having difficulties trying to figure out how to receive its inputs correctly. Unfortunately, I cannot use pygame as it requires a window to receive inputs from, but I have to generate a pyglet window (via PsychoPy) to run my program. With pygame it can connect and show the state of buttons, but it cannot receive inputs without creating a window. I tried looking for other libraries, but all I encountered was Inputs, which isn't compatible with my controller (doesn't detect the device after installing). The controller itself works as I've tested it with an online gamepad tester. PsychoPy's joystick API is currently broken and does not work, so no luck there either.
I was really hoping anyone had advice on how to receive inputs from my controller/gamepad into my program?
For Windows you can use the WINMM.dll directly.
Use the ctypes library to load the dll (see Loading shared libraries). Use ctypes.WINFUNCTYPE to create prototypes for the function:
joyGetNumDevs
joyGetDevCapsW
joyGetPosEx
import ctypes
winmmdll = ctypes.WinDLL('winmm.dll')
# [joyGetNumDevs](https://learn.microsoft.com/en-us/windows/win32/api/joystickapi/nf-joystickapi-joygetnumdevs)
"""
UINT joyGetNumDevs();
"""
joyGetNumDevs_proto = ctypes.WINFUNCTYPE(ctypes.c_uint)
joyGetNumDevs_func = joyGetNumDevs_proto(("joyGetNumDevs", winmmdll))
# [joyGetDevCaps](https://learn.microsoft.com/en-us/windows/win32/api/joystickapi/nf-joystickapi-joygetdevcaps)
"""
MMRESULT joyGetDevCaps(UINT uJoyID, LPJOYCAPS pjc, UINT cbjc);
32 bit: joyGetDevCapsA
64 bit: joyGetDevCapsW
sizeof(JOYCAPS): 728
"""
joyGetDevCaps_proto = ctypes.WINFUNCTYPE(ctypes.c_uint, ctypes.c_uint, ctypes.c_void_p, ctypes.c_uint)
joyGetDevCaps_param = (1, "uJoyID", 0), (1, "pjc", None), (1, "cbjc", 0)
joyGetDevCaps_func = joyGetDevCaps_proto(("joyGetDevCapsW", winmmdll), joyGetDevCaps_param)
# [joyGetPosEx](https://learn.microsoft.com/en-us/windows/win32/api/joystickapi/nf-joystickapi-joygetposex)
"""
MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji);
sizeof(JOYINFOEX): 52
"""
joyGetPosEx_proto = ctypes.WINFUNCTYPE(ctypes.c_uint, ctypes.c_uint, ctypes.c_void_p)
joyGetPosEx_param = (1, "uJoyID", 0), (1, "pji", None)
joyGetPosEx_func = joyGetPosEx_proto(("joyGetPosEx", winmmdll), joyGetPosEx_param)
Create the python function joyGetNumDevs, joyGetDevCaps and joyGetPosEx which delegate to the DLL. And create classes for the types JOYCAPS respectively JOYINFOEX:
# joystickapi - joyGetNumDevs
def joyGetNumDevs():
try:
num = joyGetNumDevs_func()
except:
num = 0
return num
# joystickapi - joyGetDevCaps
def joyGetDevCaps(uJoyID):
try:
buffer = (ctypes.c_ubyte * JOYCAPS.SIZE_W)()
p1 = ctypes.c_uint(uJoyID)
p2 = ctypes.cast(buffer, ctypes.c_void_p)
p3 = ctypes.c_uint(JOYCAPS.SIZE_W)
ret_val = joyGetDevCaps_func(p1, p2, p3)
ret = (False, None) if ret_val != JOYERR_NOERROR else (True, JOYCAPS(buffer))
except:
ret = False, None
return ret
# joystickapi - joyGetPosEx
def joyGetPosEx(uJoyID):
try:
buffer = (ctypes.c_uint32 * (JOYINFOEX.SIZE // 4))()
buffer[0] = JOYINFOEX.SIZE
buffer[1] = JOY_RETURNALL
p1 = ctypes.c_uint(uJoyID)
p2 = ctypes.cast(buffer, ctypes.c_void_p)
ret_val = joyGetPosEx_func(p1, p2)
ret = (False, None) if ret_val != JOYERR_NOERROR else (True, JOYINFOEX(buffer))
except:
ret = False, None
return ret
JOYERR_NOERROR = 0
JOY_RETURNX = 0x00000001
JOY_RETURNY = 0x00000002
JOY_RETURNZ = 0x00000004
JOY_RETURNR = 0x00000008
JOY_RETURNU = 0x00000010
JOY_RETURNV = 0x00000020
JOY_RETURNPOV = 0x00000040
JOY_RETURNBUTTONS = 0x00000080
JOY_RETURNRAWDATA = 0x00000100
JOY_RETURNPOVCTS = 0x00000200
JOY_RETURNCENTERED = 0x00000400
JOY_USEDEADZONE = 0x00000800
JOY_RETURNALL = (JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | \
JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | \
JOY_RETURNPOV | JOY_RETURNBUTTONS)
# joystickapi - JOYCAPS
class JOYCAPS:
SIZE_W = 728
OFFSET_V = 4 + 32*2
def __init__(self, buffer):
ushort_array = (ctypes.c_uint16 * 2).from_buffer(buffer)
self.wMid, self.wPid = ushort_array
wchar_array = (ctypes.c_wchar * 32).from_buffer(buffer, 4)
self.szPname = ctypes.cast(wchar_array, ctypes.c_wchar_p).value
uint_array = (ctypes.c_uint32 * 19).from_buffer(buffer, JOYCAPS.OFFSET_V)
self.wXmin, self.wXmax, self.wYmin, self.wYmax, self.wZmin, self.wZmax, \
self.wNumButtons, self.wPeriodMin, self.wPeriodMax, \
self.wRmin, self.wRmax, self.wUmin, self.wUmax, self.wVmin, self.wVmax, \
self.wCaps, self.wMaxAxes, self.wNumAxes, self.wMaxButtons = uint_array
# joystickapi - JOYINFOEX
class JOYINFOEX:
SIZE = 52
def __init__(self, buffer):
uint_array = (ctypes.c_uint32 * (JOYINFOEX.SIZE // 4)).from_buffer(buffer)
self.dwSize, self.dwFlags, \
self.dwXpos, self.dwYpos, self.dwZpos, self.dwRpos, self.dwUpos, self.dwVpos, \
self.dwButtons, self.dwButtonNumber, self.dwPOV, self.dwReserved1, self.dwReserved2 = uint_array
See the simple example to test the API:
import joystickapi
import msvcrt
import time
print("start")
num = joystickapi.joyGetNumDevs()
ret, caps, startinfo = False, None, None
for id in range(num):
ret, caps = joystickapi.joyGetDevCaps(id)
if ret:
print("gamepad detected: " + caps.szPname)
ret, startinfo = joystickapi.joyGetPosEx(id)
break
else:
print("no gamepad detected")
run = ret
while run:
time.sleep(0.1)
if msvcrt.kbhit() and msvcrt.getch() == chr(27).encode(): # detect ESC
run = False
ret, info = joystickapi.joyGetPosEx(id)
if ret:
btns = [(1 << i) & info.dwButtons != 0 for i in range(caps.wNumButtons)]
axisXYZ = [info.dwXpos-startinfo.dwXpos, info.dwYpos-startinfo.dwYpos, info.dwZpos-startinfo.dwZpos]
axisRUV = [info.dwRpos-startinfo.dwRpos, info.dwUpos-startinfo.dwUpos, info.dwVpos-startinfo.dwVpos]
if info.dwButtons:
print("buttons: ", btns)
if any([abs(v) > 10 for v in axisXYZ]):
print("axis:", axisXYZ)
if any([abs(v) > 10 for v in axisRUV]):
print("roation axis:", axisRUV)
print("end")
The api binding and example is provided in the GitHub repository python_windows_joystickapi

How to get USB controller/gamepad to work with python

I have a USB controller that I'm trying to get inputs from, a Microsoft® SideWinder® Plug & Play Game Pad. I'm having difficulties trying to figure out how to receive its inputs correctly. Unfortunately, I cannot use pygame as it requires a window to receive inputs from, but I have to generate a pyglet window (via PsychoPy) to run my program. With pygame it can connect and show the state of buttons, but it cannot receive inputs without creating a window. I tried looking for other libraries, but all I encountered was Inputs, which isn't compatible with my controller (doesn't detect the device after installing). The controller itself works as I've tested it with an online gamepad tester. PsychoPy's joystick API is currently broken and does not work, so no luck there either.
I was really hoping anyone had advice on how to receive inputs from my controller/gamepad into my program?
For Windows you can use the WINMM.dll directly.
Use the ctypes library to load the dll (see Loading shared libraries). Use ctypes.WINFUNCTYPE to create prototypes for the function:
joyGetNumDevs
joyGetDevCapsW
joyGetPosEx
import ctypes
winmmdll = ctypes.WinDLL('winmm.dll')
# [joyGetNumDevs](https://learn.microsoft.com/en-us/windows/win32/api/joystickapi/nf-joystickapi-joygetnumdevs)
"""
UINT joyGetNumDevs();
"""
joyGetNumDevs_proto = ctypes.WINFUNCTYPE(ctypes.c_uint)
joyGetNumDevs_func = joyGetNumDevs_proto(("joyGetNumDevs", winmmdll))
# [joyGetDevCaps](https://learn.microsoft.com/en-us/windows/win32/api/joystickapi/nf-joystickapi-joygetdevcaps)
"""
MMRESULT joyGetDevCaps(UINT uJoyID, LPJOYCAPS pjc, UINT cbjc);
32 bit: joyGetDevCapsA
64 bit: joyGetDevCapsW
sizeof(JOYCAPS): 728
"""
joyGetDevCaps_proto = ctypes.WINFUNCTYPE(ctypes.c_uint, ctypes.c_uint, ctypes.c_void_p, ctypes.c_uint)
joyGetDevCaps_param = (1, "uJoyID", 0), (1, "pjc", None), (1, "cbjc", 0)
joyGetDevCaps_func = joyGetDevCaps_proto(("joyGetDevCapsW", winmmdll), joyGetDevCaps_param)
# [joyGetPosEx](https://learn.microsoft.com/en-us/windows/win32/api/joystickapi/nf-joystickapi-joygetposex)
"""
MMRESULT joyGetPosEx(UINT uJoyID, LPJOYINFOEX pji);
sizeof(JOYINFOEX): 52
"""
joyGetPosEx_proto = ctypes.WINFUNCTYPE(ctypes.c_uint, ctypes.c_uint, ctypes.c_void_p)
joyGetPosEx_param = (1, "uJoyID", 0), (1, "pji", None)
joyGetPosEx_func = joyGetPosEx_proto(("joyGetPosEx", winmmdll), joyGetPosEx_param)
Create the python function joyGetNumDevs, joyGetDevCaps and joyGetPosEx which delegate to the DLL. And create classes for the types JOYCAPS respectively JOYINFOEX:
# joystickapi - joyGetNumDevs
def joyGetNumDevs():
try:
num = joyGetNumDevs_func()
except:
num = 0
return num
# joystickapi - joyGetDevCaps
def joyGetDevCaps(uJoyID):
try:
buffer = (ctypes.c_ubyte * JOYCAPS.SIZE_W)()
p1 = ctypes.c_uint(uJoyID)
p2 = ctypes.cast(buffer, ctypes.c_void_p)
p3 = ctypes.c_uint(JOYCAPS.SIZE_W)
ret_val = joyGetDevCaps_func(p1, p2, p3)
ret = (False, None) if ret_val != JOYERR_NOERROR else (True, JOYCAPS(buffer))
except:
ret = False, None
return ret
# joystickapi - joyGetPosEx
def joyGetPosEx(uJoyID):
try:
buffer = (ctypes.c_uint32 * (JOYINFOEX.SIZE // 4))()
buffer[0] = JOYINFOEX.SIZE
buffer[1] = JOY_RETURNALL
p1 = ctypes.c_uint(uJoyID)
p2 = ctypes.cast(buffer, ctypes.c_void_p)
ret_val = joyGetPosEx_func(p1, p2)
ret = (False, None) if ret_val != JOYERR_NOERROR else (True, JOYINFOEX(buffer))
except:
ret = False, None
return ret
JOYERR_NOERROR = 0
JOY_RETURNX = 0x00000001
JOY_RETURNY = 0x00000002
JOY_RETURNZ = 0x00000004
JOY_RETURNR = 0x00000008
JOY_RETURNU = 0x00000010
JOY_RETURNV = 0x00000020
JOY_RETURNPOV = 0x00000040
JOY_RETURNBUTTONS = 0x00000080
JOY_RETURNRAWDATA = 0x00000100
JOY_RETURNPOVCTS = 0x00000200
JOY_RETURNCENTERED = 0x00000400
JOY_USEDEADZONE = 0x00000800
JOY_RETURNALL = (JOY_RETURNX | JOY_RETURNY | JOY_RETURNZ | \
JOY_RETURNR | JOY_RETURNU | JOY_RETURNV | \
JOY_RETURNPOV | JOY_RETURNBUTTONS)
# joystickapi - JOYCAPS
class JOYCAPS:
SIZE_W = 728
OFFSET_V = 4 + 32*2
def __init__(self, buffer):
ushort_array = (ctypes.c_uint16 * 2).from_buffer(buffer)
self.wMid, self.wPid = ushort_array
wchar_array = (ctypes.c_wchar * 32).from_buffer(buffer, 4)
self.szPname = ctypes.cast(wchar_array, ctypes.c_wchar_p).value
uint_array = (ctypes.c_uint32 * 19).from_buffer(buffer, JOYCAPS.OFFSET_V)
self.wXmin, self.wXmax, self.wYmin, self.wYmax, self.wZmin, self.wZmax, \
self.wNumButtons, self.wPeriodMin, self.wPeriodMax, \
self.wRmin, self.wRmax, self.wUmin, self.wUmax, self.wVmin, self.wVmax, \
self.wCaps, self.wMaxAxes, self.wNumAxes, self.wMaxButtons = uint_array
# joystickapi - JOYINFOEX
class JOYINFOEX:
SIZE = 52
def __init__(self, buffer):
uint_array = (ctypes.c_uint32 * (JOYINFOEX.SIZE // 4)).from_buffer(buffer)
self.dwSize, self.dwFlags, \
self.dwXpos, self.dwYpos, self.dwZpos, self.dwRpos, self.dwUpos, self.dwVpos, \
self.dwButtons, self.dwButtonNumber, self.dwPOV, self.dwReserved1, self.dwReserved2 = uint_array
See the simple example to test the API:
import joystickapi
import msvcrt
import time
print("start")
num = joystickapi.joyGetNumDevs()
ret, caps, startinfo = False, None, None
for id in range(num):
ret, caps = joystickapi.joyGetDevCaps(id)
if ret:
print("gamepad detected: " + caps.szPname)
ret, startinfo = joystickapi.joyGetPosEx(id)
break
else:
print("no gamepad detected")
run = ret
while run:
time.sleep(0.1)
if msvcrt.kbhit() and msvcrt.getch() == chr(27).encode(): # detect ESC
run = False
ret, info = joystickapi.joyGetPosEx(id)
if ret:
btns = [(1 << i) & info.dwButtons != 0 for i in range(caps.wNumButtons)]
axisXYZ = [info.dwXpos-startinfo.dwXpos, info.dwYpos-startinfo.dwYpos, info.dwZpos-startinfo.dwZpos]
axisRUV = [info.dwRpos-startinfo.dwRpos, info.dwUpos-startinfo.dwUpos, info.dwVpos-startinfo.dwVpos]
if info.dwButtons:
print("buttons: ", btns)
if any([abs(v) > 10 for v in axisXYZ]):
print("axis:", axisXYZ)
if any([abs(v) > 10 for v in axisRUV]):
print("roation axis:", axisRUV)
print("end")
The api binding and example is provided in the GitHub repository python_windows_joystickapi

python pyparrot image processing question

I'm trying to build code that wants to fly a drone with a camera with demoMamboVisionGUI.py below. When the code is executed, the camera screen comes up and press the button to start the flight. The code above displays four cam screens and detects a straight line while detecting a specified color value, blue (BGR2HSV). Using these two codes, the camera recognizes the blue straight line and flies forward little by little, and turns left and right at a certain angle, recognizes the bottom of the specified color (red), lands, and starts flying with another button. I want to make a code that recognizes green and lands. I would appreciate it if you could throw a simple hint.
enter image description here
import cv2
import numpy as np
def im_trim(img):
x = 160
y = 50
w = 280
h = 180
img_trim = img[y:y + h, x:x + w]
return img_trim
def go():
minimum = 9999;
min_theta=0;
try:
cap = cv2.VideoCapture(0)
except:
return
while True:
ret, P = cap.read()
img1 = P
cv2.imshow('asdf',img1)
img_HSV = cv2.cvtColor(img1, cv2.COLOR_BGR2HSV)
img_h, img_s, img_v = cv2.split(img_HSV)
cv2.imshow("HSV", img_HSV)
lower_b = np.array([100, 80, 100])
upper_b = np.array([120, 255, 255])
blue = cv2.inRange(img_HSV, lower_b, upper_b)
cv2.imshow('root',blue)
edges = cv2.Canny(blue, 50, 150, apertureSize =3)
lines = cv2.HoughLines(edges, 1, np.pi/180, threshold = 100)
if lines is not None:
for line in lines:
r, theta = line[0]
#if (r<minimum and r>0) and (np.rad2deg(theta)>-90 and np.rad2deg(theta)<90):
#minimum = r
#min_theta = theta
#if (r > 0 and r < 250) and (np.rad2deg(theta) > 170 or np.rad2deg(theta) < 10):
# self.drone_object.fly_direct(pitch=0, roll=-7, yaw=0, vertical_movement=0,
# duration=1)
#print("right")
#elif (r > 400 and r < 650) and (np.rad2deg(theta) > 170 or np.rad2deg(theta) < 10):
# self.drone_object.fly_direct(pitch=0, roll=7, yaw=0, vertical_movement=0,
# duration=1)
print(r, np.rad2deg(theta))
#이하 if문을 while 문을 통해 반복하여 길 경로를 직진경로로 만든 이후 진행
#if(np.rad2deg(min_theta)>=몇도이상 or 이하):
# 이하 -> 왼쪽턴, 이상 -> 오른쪽턴, 사이 -> 직진
a = np.cos(theta)
b = np.sin(theta)
x0 = a * r
y0 = b * r
x1 = int(x0 + 1000 * (-b))
y1 = int(y0 + 1000 * a)
x2 = int(x0 - 1000 * (-b))
y2 = int(y0 - 1000 * a)
cv2.line(img1, (x1,y1), (x2,y2), (0,255,0), 3)
cv2.imshow('hough',img1)
k = cv2.waitKey(1)
if k == 27:
break
cv2.destroyAllWindows()
if __name__ == "__main__":
go()
print("??")
================================================================================================
"""
Demo of the Bebop vision using DroneVisionGUI that relies on libVLC. It is a different
multi-threaded approach than DroneVision
Author: Amy McGovern
"""
from pyparrot.Minidrone import Mambo
from pyparrot.DroneVisionGUI import DroneVisionGUI
import cv2
# set this to true if you want to fly for the demo
testFlying = True
class UserVision:
def __init__(self, vision):
self.index = 0
self.vision = vision
def save_pictures(self, args):
# print("in save pictures on image %d " % self.index)
img = self.vision.get_latest_valid_picture()
if (img is not None):
filename = "test_image_%06d.png" % self.index
# uncomment this if you want to write out images every time you get a new one
#cv2.imwrite(filename, img)
self.index +=1
#print(self.index)
def demo_mambo_user_vision_function(mamboVision, args):
"""
Demo the user code to run with the run button for a mambo
:param args:
:return:
"""
mambo = args[0]
if (testFlying):
print("taking off!")
mambo.safe_takeoff(5)
if (mambo.sensors.flying_state != "emergency"):
print("flying state is %s" % mambo.sensors.flying_state)
print("Flying direct: going up")
mambo.fly_direct(roll=0, pitch=0, yaw=0, vertical_movement=15, duration=2)
print("flip left")
print("flying state is %s" % mambo.sensors.flying_state)
success = mambo.flip(direction="left")
print("mambo flip result %s" % success)
mambo.smart_sleep(5)
print("landing")
print("flying state is %s" % mambo.sensors.flying_state)
mambo.safe_land(5)
else:
print("Sleeeping for 15 seconds - move the mambo around")
mambo.smart_sleep(15)
# done doing vision demo
print("Ending the sleep and vision")
mamboVision.close_video()
mambo.smart_sleep(5)
print("disconnecting")
mambo.disconnect()
if __name__ == "__main__":
# you will need to change this to the address of YOUR mambo
mamboAddr = "B0:FC:36:F4:37:F9"
# make my mambo object
# remember to set True/False for the wifi depending on if you are using the wifi or the BLE to connect
mambo = Mambo(mamboAddr, use_wifi=True)
print("trying to connect to mambo now")
success = mambo.connect(num_retries=3)
print("connected: %s" % success)
if (success):
# get the state information
print("sleeping")
mambo.smart_sleep(1)
mambo.ask_for_state_update()
mambo.smart_sleep(1)
print("Preparing to open vision")
mamboVision = DroneVisionGUI(mambo, is_bebop=False, buffer_size=200,
user_code_to_run=demo_mambo_user_vision_function, user_args=(mambo, ))
userVision = UserVision(mamboVision)
mamboVision.set_user_callback_function(userVision.save_pictures, user_callback_args=None)
mamboVision.open_video()
==========================================================================

How can i get bytes data using TCPSocket?

I want to use tcpsocket to send nv21 images between smartphone and server and convert it to rgb.I use Qt for android make the smartphone application and use python in server. When i use QByteArray to send the data, the picture is (1920*1080) so the size of data is 3110400. However i only receive 335620 bytes at server.
I want to know how can i send bypes correctly?
//QT client
void came::processFrame(const QVideoFrame& frame)
{
QVideoFrame f(frame);
QImage img;
f.map(QAbstractVideoBuffer::ReadOnly);
output.append((char*)f.bits(),f.mappedBytes());
tcpSocket->write(output,output.size());
}
//Python server
def recvfromTcpSocket(sock, blockSize=4096, accept_addr=None):
''' a function to lisen TCP socket,
and rece bytes till buffer has no more. '''
d = ''
while True:
print ("Got tcp connection: " + str(tcpServerAddr))
if accept_addr is None:
break
elif accept_addr == tcpServerAddr[0]:
break
else :
sock.close()
continue
while True:
block = sock.recv(blockSize)
d += block
if len(block) < blockSize and len(block)!=0:
print ("TCP recv done, all size: " + str(len(d)))
break
return d
if __name__ == '__main__':
data = recvfromTcpSocket(tcpServerSocket)
bin_y = data[0:rows * cols]
num_y = np.fromstring(bin_y, np.uint8)
img_y = np.reshape(num_y, (rows, cols))
bin_u = data[rows * cols::2]
num_u = np.fromstring(bin_u, np.uint8)
img_u = np.reshape(num_u, (rows / 2, cols / 2))
bin_v = data[rows * cols+1::2]
num_v = np.fromstring(bin_v, np.uint8)
img_v = np.reshape(num_v, (rows / 2, cols / 2))
enlarge_u = cv2.resize(img_u, dsize=(cols, rows), interpolation=cv2.INTER_CUBIC)
enlarge_v = cv2.resize(img_v, dsize=(cols, rows), interpolation=cv2.INTER_CUBIC)
dst = cv2.merge([img_y, enlarge_u, enlarge_v])
bgr = cv2.cvtColor(dst, cv2.COLOR_YUV2BGR)

Python Script for Art Museum Installation intermittently locks up, Removing Thermal Camera Sensor read function seems to work?

I have a python script for an installation in an art museum that is meant to run continuously playing sounds, driving an LED matrix, and sensing people via OpennCV and a thermal camera.
Each of the parts of the script work and all of them work together but randomly the script locks up and I need to restart it. I want to script to not lock up so no one has to reset it during the exhibition.
I have the code running on a spare Raspberry Pi and a spare LED matrix and it continues to cycle through fine. The only changes that I made were commenting out the start of a thread to check the IR sensor and a call to a function to get the max temp from the sensor.
To be clear, if I leave these bits of code in the script runs fine 1 -3 or sometimes 10 times. But it seems to lock up in the first "state" when IRcount = 0
I am stuck. Any help is greatly appreciated.
```
#!/usr/bin/python
import glob
import queue
import sys
import pygame
import cv2
import random
import math
import colorsys
import time
from rpi_ws281x import *
from PIL import Image
import numpy as np
import threading
global thresh
sys.path.insert(0, "/home/pi/irpython/build/lib.linux-armv7l-3.5")
import MLX90640 as mlx
currentTime = int(round(time.time() * 1000))
InflateWait = int(round(time.time() * 1000))
minTime = 6000
maxTime = 12000
lineHeight1 = 0
lineHue1 = float(random.randrange(1,360))/255
# IR Functions
# Function to just grab the Max Temp detected. If over threshold then start
# the sequence, if not stay in state 0
def maxTemp():
mlx.setup(8) #set frame rate of MLX90640
f = mlx.get_frame()
mlx.cleanup()
# get max and min temps from sensor
# v_min = min(f)
v_max = int(max(f))
return v_max
# Function to detect individual people's heat blob group of pixels
# run in a thread only at the end of the script
def irCounter():
img = Image.new( 'L', (24,32), "black") # make IR image
mlx.setup(8) #set frame rate of MLX90640
f = mlx.get_frame()
mlx.cleanup()
for x in range(24):
row = []
for y in range(32):
val = f[32 * (23-x) + y]
row.append(val)
img.putpixel((x, y), (int(val)))
# convert raw temp data to numpy array
imgIR = np.array(img)
# increase the 24x32 px image to 240x320px for ease of seeing
bigIR = cv2.resize(depth_uint8, dsize=(240,320), interpolation=cv2.INTER_CUBIC)
# Use a bilateral filter to blur while hopefully retaining edges
brightBlurIR = cv2.bilateralFilter(bigIR,9,150,150)
# Threshold the image to black and white
retval, threshIR = cv2.threshold(brightBlurIR, 26, 255, cv2.THRESH_BINARY)
# Define kernal for erosion and dilation and closing operations
kernel = np.ones((5,5),np.uint8)
erosionIR = cv2.erode(threshIR,kernel,iterations = 1)
dilationIR = cv2.dilate(erosionIR,kernel,iterations = 1)
closingIR = cv2.morphologyEx(dilationIR, cv2.MORPH_CLOSE, kernel)
# Detect countours
contours, hierarchy = cv2.findContours(closingIR, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
# Get the number of contours ( contours count when touching edge of image while blobs don't)
ncontours = str(len(contours))
# Show images in window during testing
cv2.imshow("Combined", closingIR)
cv2.waitKey(1)
#initialize pygame
pygame.init()
pygame.mixer.init()
pygame.mixer.set_num_channels(30)
print("pygame initialized")
# assign sound chennels for pygame
channel0 = pygame.mixer.Channel(0)
channel1 = pygame.mixer.Channel(1)
channel2 = pygame.mixer.Channel(2)
channel3 = pygame.mixer.Channel(3)
channel4 = pygame.mixer.Channel(4)
channel5 = pygame.mixer.Channel(5)
channel6 = pygame.mixer.Channel(6)
channel7 = pygame.mixer.Channel(7)
channel8 = pygame.mixer.Channel(8)
channel9 = pygame.mixer.Channel(9)
channel10 = pygame.mixer.Channel(10)
channel11 = pygame.mixer.Channel(11)
channel12 = pygame.mixer.Channel(12)
channel13 = pygame.mixer.Channel(13)
channel14 = pygame.mixer.Channel(14)
channel15 = pygame.mixer.Channel(15)
channel16 = pygame.mixer.Channel(16)
channel17 = pygame.mixer.Channel(17)
channel18 = pygame.mixer.Channel(18)
channel19 = pygame.mixer.Channel(19)
channel20 = pygame.mixer.Channel(20)
channel21 = pygame.mixer.Channel(21)
channel22 = pygame.mixer.Channel(22)
channel23 = pygame.mixer.Channel(23)
channel24 = pygame.mixer.Channel(24)
channel25 = pygame.mixer.Channel(25)
channel26 = pygame.mixer.Channel(26)
channel27 = pygame.mixer.Channel(27)
channel28 = pygame.mixer.Channel(28)
# load soundfiles
echoballs = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/echo balls FIX.ogg")
organbounce = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/ORGAN BOUNCE fix.ogg")
jar = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/jar whoop fix.ogg")
garland = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/GARLAND_fix.ogg")
dribble= pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/dribble.ogg")
cowbell = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/cowbell fix.ogg")
clackyballs = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/clacky balls boucne.ogg")
burpees = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/burpees_fix.ogg")
brokensynth = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/broken synth bounce.ogg")
woolballs = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/wool balls in jar FIX.ogg")
wiimoye = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/wiimoye_fix.ogg")
warpyorgan = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/warpy organ bounce#.2.ogg")
vibrate = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/vibrate fix.ogg")
turtlesbounce = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/turtles fix.ogg")
timer = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/timer.ogg")
tape = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/tape fix.ogg")
tambourine = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/TAMBOURINE.ogg")
springybounce = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/springy bounce.ogg")
smash3 = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/smash fix.ogg")
bristle2 = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/BRISTLE FIX.ogg")
blackkeys = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/black keys FIX.ogg")
zipper = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/zipper.ogg")
presatisfactionsweep = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/pre-satisfaction sweep .ogg")
satisfaction = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/SATISFACTION.ogg")
altsatisfaction = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/alt_satisfaction_trimmed.ogg")
solosatisfaction = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/SOLO_SATISFACTION.ogg")
print("sound files loaded")
# initializing sounds list
soundsList = [echoballs, organbounce, zipper, jar, garland, dribble, cowbell, clackyballs, burpees, brokensynth, woolballs,
wiimoye, warpyorgan, vibrate, turtlesbounce, timer, tambourine, springybounce, smash3, bristle2, blackkeys, zipper ]
IRcount = 0 # define initial state for main loop
pygame.display.set_mode((32, 8))
print("pygame dispaly open")
# LED strip configuration:
LED_COUNT = 256 # Number of LED pixels.
LED_PIN = 18 # GPIO pin connected to the pixels (18 uses PWM!).
#LED_PIN = 10 # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
LED_FREQ_HZ = 800000 # LED signal frequency in hertz (usually 800khz)
LED_DMA = 10 # DMA channel to use for generating signal (try 10)
LED_BRIGHTNESS = 100 # Set to 0 for darkest and 255 for brightest
LED_INVERT = False # True to invert the signal (when using NPN transistor level shift)
LED_CHANNEL = 0 # set to '1' for GPIOs 13, 19, 41, 45 or 53
# Define functions which animate LEDs in various ways.
# PNG to LED function used to shuffle througfh folders of numbered PNGs exported
# from animations created
def pngToLED (strip, pngfile):
RGBimage = Image.open(pngfile).convert('RGB')
np_image = np.array(RGBimage)
colours = [Color(x[0],x[1],x[2]) for rows in np_image for x in rows]
colours2d = np.reshape(colours, (32, 8), order='F')
colours2d[1::2, :] = colours2d[1::2, ::-1]
pic = colours2d.flatten('C')
for i in range( 0, strip.numPixels(), 1 ):# iterate over all LEDs - range(start_value, end_value, step)
strip.setPixelColor(i, int(pic[ i ]))
strip.show()
def colorWipe(strip, color,wait_ms=10):
"""Wipe color across display a pixel at a time."""
for i in range(strip.numPixels()):
strip.setPixelColor(i, color)
strip.show()
time.sleep(1)
def theaterChase(strip, color, wait_ms, iterations=10):
"""Movie theater light style chaser animation."""
for j in range(iterations):
for q in range(3):
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, color)
strip.show()
time.sleep(wait_ms/1000.0)
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, 0)
def wheel(pos):
"""Generate rainbow colors across 0-255 positions."""
if pos < 85:
return Color(pos * 3, 255 - pos * 3, 0)
elif pos < 170:
pos -= 85
return Color(255 - pos * 3, 0, pos * 3)
else:
pos -= 170
return Color(0, pos * 3, 255 - pos * 3)
def rainbow(strip, wait_ms=20, iterations=1):
"""Draw rainbow that fades across all pixels at once."""
for j in range(256*iterations):
for i in range(strip.numPixels()):
strip.setPixelColor(i, wheel((i+j) & 255))
strip.show()
time.sleep(wait_ms/1000.0)
def rainbowCycle(strip, wait_ms=20, iterations=5):
"""Draw rainbow that uniformly distributes itself across all pixels."""
for j in range(256*iterations):
for i in range(strip.numPixels()):
strip.setPixelColor(i, wheel((int(i * 256 / strip.numPixels()) + j) & 255))
strip.show()
time.sleep(wait_ms/1000.0)
def theaterChaseRainbow(strip, wait_ms=90):
"""Rainbow movie theater light style chaser animation."""
for j in range(256):
for q in range(3):
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, wheel((i+j) % 255))
strip.show()
time.sleep(wait_ms/1000.0)
for i in range(0, strip.numPixels(), 3):
strip.setPixelColor(i+q, 0)
# Plasma LED Function from Root 42
def plasmaLED (plasmaTime):
h = 8
w = 32
out = [ Color( 0, 0, 0 ) for x in range( h * w ) ]
plasmaBright = 100.0
for x in range( h ):
for y in range( w ):
hue = (4.0 + math.sin( plasmaTime + x ) + math.sin( plasmaTime + y / 4.5 ) \
+ math.sin( x + y + plasmaTime ) + math.sin( math.sqrt( ( x + plasmaTime ) ** 2.0 + ( y + 1.5 * plasmaTime ) ** 2.0 ) / 4.0 ))/8
hsv = colorsys.hsv_to_rgb( hue , 1, 1 )
if y % 2 == 0: #even
out[ x + (h * y)] = Color( *[ int( round( c * plasmaBright ) ) for c in hsv ] )
else: #odd
out[ (y * h) + (h -1 -x) ] = Color( *[ int( round( c * plasmaBright ) ) for c in hsv ] )
for i in range( 0, strip.numPixels(), 1 ):# iterate over all LEDs - range(start_value, end_value, step)
strip.setPixelColor(i, out[ i ]) # set pixel to color in picture
strip.show()
# variables for plasma
plasmaTime = 5.0 # time
plasmaSpeed = 0.05 # speed of time
# thread for IRcounter function
class TempTask:
def __init__(self):
self.ir_temp = 0
self.lock = threading.Lock() #control concurrent access for safe multi thread access
self.thread = threading.Thread(target=self.update_temp)
def update_temp(self):
while True:
with self.lock:
self.ir_temp = irCounter()
time.sleep(0.1)
def start(self):
self.thread.start()
# Millis timer count function
def CheckTime( lastTime, wait):
if currentTime - lastTime >= wait:
lastTime += wait
return True
return False
# Main program logic follows:
if __name__ == '__main__':
# not currently starting the trhead because program is locking up without it
# want to figure out initial problem first
#start thread
#task = TempTask()
#task.start()
# Create NeoPixel object with appropriate configuration.
strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)
# Intialize the library (must be called once before other functions).
strip.begin()
print ('Press Ctrl-C to quit.')
try:
while True:
currentTime = int(round(time.time() * 1000))
if IRcount == 0:
#random solid color
colorWipe(strip, Color(random.randint(60,255), random.randint(60,255), random.randint(60,255)))
# use random.sample() to shuffle sounds list
shuffledSounds = random.sample(soundsList, len(soundsList))
if pygame.mixer.Channel(0).get_busy() == False: channel0.play(shuffledSounds[0],loops = -1)
thresh = 0
'''
# the threshold check below is the only thing I have taken out of
# Program on my test Raspberry Pi. It seems to not lock up without it
# not sure why this would be a problem.
thresh = int(maxTemp())
print (thresh)
if thresh >= 27:
InflateWait = int(round(time.time() * 1000))
print (thresh)
IRcount = 1
print("Threshold Temp Detected: Begin Sound Sequence")
else:
IRcount = 0
'''
if CheckTime(InflateWait,random.randint(minTime, maxTime)):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
elif IRcount == 1:
LEDimages = glob.glob("/home/pi/ruff-wavs/Crystal_Mirror/*.png")
for LEDimage in sorted(LEDimages):
pngToLED (strip, LEDimage)
if pygame.mixer.Channel(1).get_busy() == False:
channel1.play(shuffledSounds[1],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
elif IRcount == 2:
LEDimages = glob.glob("/home/pi/ruff-wavs/Mercury_Loop/*.png")
for LEDimage in sorted(LEDimages):
pngToLED (strip, LEDimage)
if pygame.mixer.Channel(2).get_busy() == False:
channel2.play(shuffledSounds[2],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
elif IRcount == 3:
LEDimages = glob.glob("/home/pi/ruff-wavs/Pink_Lava/*.png")
for LEDimage in sorted(LEDimages):
pngToLED (strip, LEDimage)
if pygame.mixer.Channel(3).get_busy() == False:
channel3.play(shuffledSounds[3],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
elif IRcount == 4:
LEDimages = glob.glob("/home/pi/ruff-wavs/Horiz_Mosaic/*.png")
for LEDimage in sorted(LEDimages):
pngToLED (strip, LEDimage)
if pygame.mixer.Channel(4).get_busy() == False:
channel4.play(shuffledSounds[4],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
elif IRcount == 5:
plasmaLED()
plasmaTime = plasmaTime + plasmaSpeed # increment plasma time
if pygame.mixer.Channel(5).get_busy() == False:
channel5.play(shuffledSounds[5],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
elif IRcount == 6:
LEDimages = glob.glob("/home/pi/ruff-wavs/Radio_Loop/*.png")
for LEDimage in sorted(LEDimages):
pngToLED (strip, LEDimage)
if pygame.mixer.Channel(6).get_busy() == False:
channel6.play(shuffledSounds[6],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
elif IRcount == 7:
LEDimages = glob.glob("/home/pi/ruff-wavs/Star_Loop/*.png")
for LEDimage in sorted(LEDimages):
pngToLED (strip, LEDimage)
if pygame.mixer.Channel(7).get_busy() == False:
channel7.play(shuffledSounds[7],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
elif IRcount == 14:
plasmaLED()
plasmaTime = plasmaTime + plasmaSpeed # increment plasma time
if pygame.mixer.Channel(14).get_busy() == False:
channel14.play(shuffledSounds[14],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
print (thresh)
elif IRcount == 15:
plasmaLED()
plasmaTime = plasmaTime + plasmaSpeed # increment plasma time
if pygame.mixer.Channel(15).get_busy() == False:
channel15.play(shuffledSounds[15],loops = -1)
waitTime = random.randint(minTime, maxTime)
if CheckTime(InflateWait,waitTime):
InflateWait = int(round(time.time() * 1000))
IRcount += 1
print(IRcount)
elif IRcount == 16:
# random color theater chase increment random ms to speed up with sounds
theaterChase(strip, Color(random.randint(1,255), random.randint(1,255), random.randint(1,255)), random.randint(40,50))
pygame.mixer.fadeout(45000)
if pygame.mixer.Channel(22).get_busy() == False:
channel22.play(presatisfactionsweep)
IRcount = 17
print(IRcount)
print("sweep end start")
elif IRcount == 18:
# random color theater chase increment random ms to speed up with sounds
theaterChase(strip, Color(random.randint(1,255), random.randint(1,255), random.randint(1,255)), random.randint(30,40))
if pygame.mixer.Channel(22).get_busy() == False:
pygame.mixer.stop()
channel23.play(satisfaction)
IRcount = 19
print(IRcount)
print("Play Satisfaction Sount")
elif IRcount == 19:
rainbowCycle(strip, 5)
if pygame.mixer.Channel(23).get_busy() == False: IRcount = 0
except KeyboardInterrupt:
colorWipe(strip, Color(0,0,0), 1)
pygame.mixer.stop()
pygame.quit()
```
Update 1 - Suspected Function(s)
When I left the script run overnight and came to the exhibit in the morning it would be stuck in the 1st state IRcount = 0 The only things that happen in that state is the maxTemp() function to get the max temp, the LED color wipe function to cycle colors.
When I would come in in the morning it would be stuck, playing a single sound from pygame, as it should, but it would not be cycling colors. I removed the maxTemp() from my test Pi and it has been working fine.
def maxTemp():
mlx.setup(8) #set frame rate of MLX90640
f = mlx.get_frame()
mlx.cleanup()
# get max and min temps from sensor
# v_min = min(f)
v_max = int(max(f))
return v_max
Update # 2
I thought that the thread might be the problem so I commented out the thread start call. That is why I made the simpler maxTemp() function to see if that would work better than the thread. So when I was using the max temp then the thread wasn't being called.
I don't understand threads very well. Is it possible to have the max temp variable update continuously and have the simple OpenCV numPy manipulations running continuously? That would be ideal. When I originally added the thread it seemed to stop after a few cycles.
I do not have a join on the thread. I know threads don't "restart" but do I need to call it again as the state machine starts again?
# not currently starting the thread because program is locking up without it
# want to figure out initial problem first
#start thread
#task = TempTask()
#task.start()
Update #3
I Uploaded new code that eliminated the duplicate functions. Everything is handled in the thread temp.task now. That seems to work fine. I also put the github suggestion of polling the thermal sensor if the image is a duplicate but that has not happened.
I left the program run over night and when I came in in the morning it was locked up. The SD card is set to read only mode. I ssh'd into the pi. I have my auto start python script in /etc/profile
It seems to start the script each time I log into ssh. When I logged in this morning to see if the pi was still up it game an out of memory error.
```
Traceback (most recent call last):
File "/home/pi/ruff-wavs/shufflewavdemo.py", line 210, in <module>
altsatisfaction = pygame.mixer.Sound("/home/pi/ruff-wavs/sounds/alt_satisfaction_trimmed.ogg")
pygame.error: Unable to open file '/home/pi/ruff-wavs/sounds/alt_satisfaction_trimmed.ogg'
OSError: [Errno 28] No space left on device
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.5/runpy.py", line 193, in _run_module_as_main
"__main__", mod_spec)
File "/usr/lib/python3.5/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/usr/local/lib/python3.5/dist-packages/virtualenvwrapper/hook_loader.py", line 223, in <module>
main()
File "/usr/local/lib/python3.5/dist-packages/virtualenvwrapper/hook_loader.py", line 145, in main
output.close()
OSError: [Errno 28] No space left on device
-bash: cannot create temp file for here-document: No space left on device
Could that be because it is in read only mode?
I used this script to switch from writable to read only and back.
[https://github.com/JasperE84/root-ro][1]
[1]: https://github.com/JasperE84/root-ro
I suspect the issue is that you're accessing the mlx device both in the main thread via maxTemp() as well as in the irCounter() thread. The fact that it works when you take out the maxTemp call, and that that call happens in the if IRcount == 0: state supports this.
I would add the maxTemp functionality to the irCounter thread, so that accessing it from only a single thread; and update a global variable (protected by a lock) with the maxTemp results if you need to retain this functionality.

Categories