Raspberry Pi Flask Server Not Accessible After Shutdown

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

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

Answers (2)

dave.tdv
dave.tdv

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.

  1. Add a new function to check connection status.
  2. Create a shell script to execute main.py
  3. Make the shell script executable.
  4. Create a cron job to execute the script after reboot.

Check Connection Status

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)

Create Shell Script

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.

Make Shell Script Executable

Assuming we are still in the current directory, type the following command on terminal.

chmod 755 runner.sh

Create a Cron Job

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.

Final Test

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

Papop Lekhapanyaporn
Papop Lekhapanyaporn

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

Related Questions