Reputation: 610
I followed a YouTube video to create a remote viewable camera with a Raspberry Pi, source code for tutorial available here. Basically it creates a Flask server to stream a live feed of a Pi Camera, which is available via browser on other devices. The problem I am having is I cannot get a feed after shutting down and starting the Pi. If I reboot the Pi, debug the app or manually start the service, everything works just fine, however if I actually shut down the Pi, unplug it, plug it back in and let it boot, the server seems to fail to start and the video fee cannot be accessed from any device including the Pi itself, although the service status says it is running. I need this server to start whenever I plug in the Pi, the OS starts and I connect to a predefined network.
The final portion of the tutorial states to add sudo python3 /home/pi/pi-camera-stream-flask/main.py
at the end of the /etc/profile file is supposed to start the main.py file which starts the flask server. This did not work so I created a service to start the app after there's a network connection, which looks like:
[Unit]
Description=Start Camera Flask
After=systemd-networkd-wait-online.service
Wants=systemd-networkd-wait-online.service
[Service]
User=pi
WorkingDirectory=/home/pi/pi-camera-stream-flask/
ExecStart=sudo python3 /home/pi/pi-camera-stream-flask/main.py
Restart=always
[Install]
WantedBy=multi-user.target
After=Network.target
and After=Network-online.target
NetworkManager-wait-online.service
and systemd-networkd-wait-online.service
My Python app looks like:
#Modified by smartbuilds.io
#Date: 27.09.20
#Desc: This web application serves a motion JPEG stream
# main.py
# import the necessary packages
from flask import Flask, render_template, Response, request
from camera import VideoCamera
import time
import threading
import os
pi_camera = VideoCamera(flip=False) # flip pi camera if upside down.
# App Globals (do not edit)
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html') #you can customze index.html here
def gen(camera):
#get camera frame
while True:
frame = camera.get_frame()
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
@app.route('/video_feed')
def video_feed():
return Response(gen(pi_camera),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == '__main__':
app.run(host='192.168.0.14', port=5000, debug=False) # have also tried app.run(host='0.0.0.0', debug=False)
Upvotes: 0
Views: 735
Reputation: 395
This problem usually occurs when the Flask server is started before the Raspberry Pi is connected to the network. There are a few ways to solve the problem, but here's my approach.
main.py
We will create a function that checks network connection using subprocess
module.
The function will check network connection periodically until it is properly connected to the network and return True
. (assume that the Raspberry Pi ever connected to the network and network adapter is always enabled)
Add the following code snippet in your code and execute it before initializing Flask Server.
from subprocess import check_output
from time import sleep
def initializing_network():
while True:
try:
result = check_output(['hostname', '-I']).decode('utf-8').strip()
# The conditional below may not be the cleanest solution.
# Feel free to come up with better solution
# It will check if the shortest IP length exists,
# i.e. "x.x.x.x" = 7 characters
# or check '192' in the result string if you are sure your private network
# always begins with '192'
if (len(result) > 6) or ('192' in result):
return True
except:
pass
# If it fails, wait for 10 seconds then recheck the connection again.
sleep(10)
Considering the only possible return value of initializing_network()
function is True
or loop indefinitely, the function can be called without additional condition in main function = blocking function. You may want to log the exception or terminate the Python script to prevent infinite loop.
if __name__ == '__main__':
initializing_network()
app.run(host='192.168.0.14', port=5000, debug=False)
Assuming that you are in main directory, create a shell script in the directory, let say runner.sh
.
Type the following in terminal
nano runner.sh
Then add the following code snippet.
#!/bin/sh
cd /
sudo python3 /home/pi/pi-camera-stream-flask/main.py
cd /
When you're done, press Ctrl + X
and select Yes
to save the change.
Assuming we are still in the current directory, type the following command on terminal.
chmod 755 runner.sh
Next, let's add a new cron job for the Flask Server. Back to terminal and execute the following.
sudo crontab -e
Next, select nano
as the text editor, but feel free to use any text editor that you like.
At the very bottom of the content, insert new line and add this line.
@reboot sh /home/pi/runner.sh
Similarly, press Ctrl + X
and Yes
to save the change.
To ensure the shell script runs properly, execute it and check if everything works.
./runner.sh
If it works, then it is time to test the cron job.
Type sudo reboot
in the terminal. After reboot, wait for a while then check the designated IP address whether the server has been started. It may take some time, so check it periodically. Ideally, it will work without any problem. Otherwise, repeat the steps and make sure you don't miss anything.
Upvotes: 0
Reputation: 587
you can try to autoboot your code everytime its connected to power by set it up in your .bashrc
sudo nano /home/pi/.bashrc
scroll down to the bottom. Add these two line
echo running flask
sudo python3 /home/pi/pi-camera-stream-flask/main.py
try to remove your editing in /etc/profile first
and make sure you have some cooldown at the start maybe 5 secound
time.sleep(5)
Upvotes: 1