I have a streaming server / motion detection script that works on my laptop, but when I move it to my PI it gives the following error when i try and access the stream:
my laptop ip address - - [23/Jun/2015 13:04:34] "GET / HTTP/1.1" 200 -
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner
self.run()
File "/usr/lib/python2.7/threading.py", line 505, in run
self.__target(*self.__args, **self.__kwargs)
File "/usr/src/scripts/areadetect_movie__33.py", line 300, in server
server = HTTPServer(('',port),CamHandler)
File "/usr/lib/python2.7/SocketServer.py", line 419, in __init__
self.server_bind()
File "/usr/lib/python2.7/BaseHTTPServer.py", line 108, in server_bind
SocketServer.TCPServer.server_bind(self)
File "/usr/lib/python2.7/SocketServer.py", line 430, in server_bind
self.socket.bind(self.server_address)
File "/usr/lib/python2.7/socket.py", line 224, in meth
return getattr(self._sock,name)(*args)
error: [Errno 98] Address already in use
a) The motion side of the script works, but the server doesn't.
b) I can serve a simple webpage using the same IP address and port, using a different script, so I don't think something else is using that port.
c) Both PI and laptop are on the same local network.
1) Are there any other tests I can do, that could point to what is wrong?
2) What do these errors suggest?
Edit:
ps aux | grep streaming_server_variation_16.py
gives:
root 2508 79.7 11.9 111392 45560 ? Sl 13:19 1:53 /usr/bin/python ./streaming_server_variation_16.py
root 2560 0.0 0.8 5380 3200 pts/0 S+ 13:21 0:00 grep streaming_server_variation_16.py
I'm starting two threads like this:
if runtime_frame_count == 0:
Thread(target = main).start()
time.sleep(10)
Thread(target = server).start()
note 'runtime_frame_count' increments, so this should only run once.
The "main" thread gathers the frames from the camera and performs the motion detection, and the "server" tries to serve the frames gathered.
Could this be why I'm having the same script trying to access the port, but in different threads?
edit 2 to explain exactly what i'm doing:
a) I'm accessing the headless PI, via two open SSH putty connections, from my laptop which has a local IP address of 192.168.1.4 and the PI has a local IP address of 192.168.1.61.
b) I run the script using one SSH connection and watch the script increment the runtime_frame_count which prints out on each new frame gathered; i'll call this SSH window run-ssh-window, then I use the other SSH connection to send the commands, i'll call this command-ssh-window.
c) When thread 2 starts (server) the script outputs from the run-ssh-window
server started on:
127.0.1.1
because of the following code inside that thread:
print ("server started on: ")
print(socket.gethostbyname(socket.gethostname()))
d) Then I try and access the stream from my laptop's browser by placing the text http://192.168.1.61:1991/
in the browser, when I get the same errors as listed above from the running incrementing script (in the run-ssh-window).
e) following the error, the script continues to increment (in the run-ssh-window), so in the command-ssh-window i sudo netstat -atpen
which gives:
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State User Inode PID/Program name
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN 0 6188 1962/uv4l
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 0 6509 2306/sshd
tcp 0 0 127.0.0.1:6010 0.0.0.0:* LISTEN 0 35991 11960/0
tcp 0 0 127.0.0.1:6011 0.0.0.0:* LISTEN 0 36885 12135/1
tcp 0 352 192.168.1.61:22 192.168.1.4:50175 ESTABLISHED 0 36843 12135/1
tcp 0 0 192.168.1.61:22 192.168.1.4:49853 ESTABLISHED 0 36031 11984/sshd: root@no
tcp 1 0 192.168.1.61:49540 editexternaladdress:443 CLOSE_WAIT 108 7075 2284/mount.davfs
tcp 0 0 192.168.1.61:22 192.168.1.4:49812 ESTABLISHED 0 35928 11960/0
tcp 0 0 192.168.1.61:22 192.168.1.4:50355 ESTABLISHED 0 37350 12214/sshd: root@no
where I cannot see two processes trying to access the port 1991 on 192.168.1.61.
Am I doing anything incorrectly?
I'm still confused what could be happening with the "address already in use" error listed above.
Another edit resulting from comments
I start the socket using the command: server = HTTPServer(('',port),CamHandler)
which calls the CamHandler class to deal with constructing the stream.
the CamHandler class looks like this:
class CamHandler(BaseHTTPRequestHandler):
def do_GET(self):
print (self.path)
if self.path.endswith('.mjpg'):
self.send_response(200)
self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
self.end_headers()
while(True):
global imgRGB #imgRGB is gathered from the camera in the main thread, which starts 10 seconds prior to the server thread (this one)
r, buf = cv2.imencode(".jpg",imgRGB) # imencode Encodes an image into a memory buffer.
# the following 7 lines output the contents of buf to the webpage
self.wfile.write("--jpgboundary\r\n")
self.send_header('Content-type','image/jpeg')
self.send_header('Content-length',str(len(buf)))
self.end_headers()
self.wfile.write(bytearray(buf))
self.wfile.write('\r\n')
time.sleep(0.01)
k = cv2.waitKey(20)
if k == 27:
break
cv2.destroyAllWindows()
capture.release()
if self.path.endswith('.html') or self.path=="/":# jumps into this block of code at start of request to set up the html page but doesn't come back
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write('<html><head></head><body>')
self.wfile.write('<img src="http://'+socket.gethostbyname(socket.gethostname())+':'+ str(port) +'/cam.mjpg"/>')
self.wfile.write('</body></html>')
return
I too thought there was an issue with the script outputting 127.0.1.1 to I tried:self.wfile.write('<img src="http://'+'192.168.1.61'+':'+ str(port) +'/cam.mjpg"/>')
but still I got the same error.
I'm using windows 7 too.
Yet another edit with a simplified version of the whole script.
#====================================================================
# a function to get the image from the camera (this is the only place the camera is accessed)
#====================================================================
def get_cv_frame():
global img
while(1):
rc,img = capture.read()
if not rc:
continue
return (img)
def cv_frame(frame):
#all the cv2 movement magic happens and it returns a modified image (numpy array)
return background
# the server function
def server():
global runtime_frame_count, runtime_frame
while(1):
#======================================= server started here
#=======================================
server = HTTPServer(('',port),CamHandler)
#=======================================
#=======================================
print ("server started on: ")
print(socket.gethostbyname(socket.gethostname()))
print("server started")
q1 = cv2.waitKey(20)
if (q1 == ord('q')) or (runtime_frame_count >= runtime_frame):
capture.release()
server.socket.close()
print("server stopped")
cv2.destroyAllWindows()
cv2.waitKey(10)
time.sleep(0.1)
cv2.waitKey(10)
cv2.waitKey(10)
break
server.handle_request()
return
class CamHandler(BaseHTTPRequestHandler):
def do_GET(self):
print (self.path)
if self.path.endswith('.mjpg'):
self.send_response(200)
self.send_header('Content-type','multipart/x-mixed-replace; boundary=--jpgboundary')
self.end_headers()
while(True):
global imgRGB
r, buf = cv2.imencode(".jpg",imgRGB) # imencode Encodes an image into a memory buffer.
self.wfile.write("--jpgboundary\r\n")
self.send_header('Content-type','image/jpeg')
self.send_header('Content-length',str(len(buf)))
self.end_headers()
self.wfile.write(bytearray(buf))
self.wfile.write('\r\n')
time.sleep(0.01)
k = cv2.waitKey(20)
if k == 27:
break
cv2.destroyAllWindows()
capture.release()
return
if self.path.endswith('.html') or self.path=="/":# jumps into this block of code at start of request to set up the html page but doesn't come back
self.send_response(200)
self.send_header('Content-type','text/html')
self.end_headers()
self.wfile.write('<html><head></head><body>')
self.wfile.write('<img src="http://'+socket.gethostbyname(socket.gethostname())+':'+ str(port) +'/cam.mjpg"/>')
self.wfile.write('</body></html>')
return
# the main function
def main():
global capture, average, img, imgRGB, runtime_frame_count, runtime_frame
capture = cv2.VideoCapture(0)
capture.set(3,REDUCED_SIZE[0])
capture.set(4,REDUCED_SIZE[1])
while(1):
img = get_cv_frame() # gets a frame from the camera
imgRGB = cv_frame(img) #all the cv2 movement magic happens and it returns a modified image (numpy array)
time.sleep(0.1)
print (runtime_frame_count)
runtime_frame_count = runtime_frame_count+1
q2 = cv2.waitKey(20)
if (q2 == ord('q')) or (runtime_frame_count >= runtime_frame):
capture.release()
server.socket.close()
print("main stopped")
cv2.destroyAllWindows()
cv2.waitKey(10)
time.sleep(0.1)
cv2.waitKey(10)
cv2.waitKey(10)
break
return
# this is where the threads are started.
if runtime_frame_count == 0:
Thread(target = main).start()# starts the main() function as a thread
time.sleep(1)
Thread(target = server).start()# starts the server() function as a new thread a time delay after the first thread was started
server started on: 127.0.1.1
I think this is your problem, you should be expecting the LAN IP not local hostserver = HTTPServer(('',port),CamHandler)
? Without seeing your complete code, it is rather difficult to help you.