Hello & Thanks for any insights. I have a python 3.11.2 script running on a Pi Zero 2 W (Raspberry Pi OS 64 bit Lite) that starts upon power on (power supply is solid) from rc.local, runs for hours, then executes a shutdown using: os.system("sudo shutdown -h now"). The problem is that upon the next power on, the system immediately shuts down with the message: Broadcast message from root@raspberrypi (Wed…): The system will power off now! At this point the only way to recover is to re-image the SD card (64G).
I have written a short Python script (including imports) that executes the same shutdown command from rc.local after a 60 second delay (so I can regain control). This script runs as expected and does not cause the system to immediately shut down after power on. Neither this script, nor my larger script causes the problem when executed from a terminal over SSH.
I have installed the following packages using the following commands:
sudo apt update
sudo apt full-upgrade
sudo apt install -y python3-pip
sudo apt install -y python3-pillow
sudo apt install -y python3-picamera2 --no-install-recommends
and edited rc.local thus: python /home/pi/web.py (added before “exit 0”). Entire python script is attached. I am not an accomplished Python programmer and I know nothing about Linux, so if you say “look in the log file”, please add where & how. Thanks to all!
(AC power is switched off at midnight and back on 30 minutes later)
The suspect code is about 3/4 of the way down "if(hours == '22')"
I have written a short Python script (including imports) that executes the same shutdown command from rc.local after a 60 second delay (so I can regain control). This script runs as expected and does not cause the system to immediately shut down after power on. Neither this script, nor my larger script causes the problem when executed from a terminal over SSH.
I have installed the following packages using the following commands:
sudo apt update
sudo apt full-upgrade
sudo apt install -y python3-pip
sudo apt install -y python3-pillow
sudo apt install -y python3-picamera2 --no-install-recommends
and edited rc.local thus: python /home/pi/web.py (added before “exit 0”). Entire python script is attached. I am not an accomplished Python programmer and I know nothing about Linux, so if you say “look in the log file”, please add where & how. Thanks to all!
(AC power is switched off at midnight and back on 30 minutes later)
The suspect code is about 3/4 of the way down "if(hours == '22')"
Code:
from PIL import Imagefrom PIL import ImageDrawfrom PIL import ImageFontfrom picamera2 import Picamera2import requestsimport datetimeimport timeimport ftplibimport os def resolveWind(dir): # transform heading in degrees to "N" etc wdir = ["N", "NE", "E", "SE", "S", "SW", "W", "NW","N"] boundry = -22.5 index = 0 while(dir>(boundry+45)): index = index + 1 boundry = boundry + 45 return wdir[index] def ftpToWebsite(file): # ftp try: host = "stevensarns.com" # website port = 21 ftp.connect(host, port) ftp.login("xxx", "xxx") # login, pw ftp.cwd('/public_html/Colorado') # change work dir, '/public_html/ExperimentalPics' ftp.storbinary('STOR '+file, open(file, 'rb')) print(file, "sent") # debug except: print("ftp failure") # ftp error has occurred finally: return True # ftp has been started, needs ftp(close)def writeText(text, color, size, org, image): color = color # noon forecast textSize = size font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",textSize)# font font path, size image = image draw = ImageDraw.Draw(image) text = text org = org draw.text((org), text, font=font, fill=(color)) return imagedef snap(): # snap, timestamp filename = "pic.png" # name of file to create now = datetime.datetime.now() # get time now now = now.strftime("%A %I:%M") # format string print("Snap", filename, now) # show filename and timestamp picam2.start() # start camera time.sleep(2) # wait for camera to initialize picam2.capture_file(filename) # capture file (pic.jpg) do not picam2.close() png! img = Image.open(filename) # open file (pic.jpg) draw = ImageDraw.Draw(img) # Call draw Method to add 2D graphics in an image font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",20)# font size & loc draw.text((28, 5), now, font=font, fill=(0, 0, 0)) # location -x,-y, font color img.save(filename) # Save, all images stored in same file as code return filename # return pic.png# ------------------------ Main --------------------------------------------snapInterval = 15 # minutes between webcam snapsforecastInterval = 15 # minutes between forecastslastHour = 0 # used to create 8 hourly pictureslastSnap = 0 # used to create hourly view w/ overlaylastForecast = 0 # save for next testfilename = "pic.png" # primary file to send to website picam2 = Picamera2()ftp = ftplib.FTP()os.environ['TZ'] = 'America/Denver' # Set the timezonetime.tzset() # Apply the timezone changeconfig = picam2.create_still_configuration(main={"size": (640,480)}, lores={"size": (640, 480)}, display="lores")picam2.configure(config)picam2.still_configuration.size = (640,480) # image sizeftpActive = True # set ftp addprint("Start main loop") # end of setupwhile True: # main loop # wait for snap interval=>snap, overlay & ftp to website now = int((time.time())/60) # integer minutes (from forever) hours = datetime.datetime.now() # time data type hours = hours.strftime("%H") # hours in 24 hour format, zero padded e.g. 08 = 8AM if(((now%snapInterval)==0) and (now!=lastSnap)): # interval passed? lastSnap = now # fail test until 1 minute interval passes print("Snap interval ", snapInterval) filename = snap() # snap & stamp ftpActive = ftpToWebsite(filename) # ftp => website print(filename, "=> website") # debug # if this is an even hour change, save 1 of 8 pictures with hour as part of filename # images are stored at 6AM, 8AM, 10AM, 12AM, 2PM, 4PM, 6PM & 8PM # browser will display sequence, files are stored overwriting older files if(((now%snapInterval)==0) and (hours != lastHour)): # has hour changed and pic snapped? lastHour = hours # fail test until next hour print("Hour =", hours) if(hours=='06' or hours=='08' or hours=='10' or hours=='12' or hours=='14' or hours=='16' or hours=='18' or hours=='20'): # is it time to store image? title = "pic" + hours + ".png" # construct filename with hour attached e.g. "pic08" img = Image.open("pic.png") # open snapped image with overlay img.save(title) # save image & change to .png ftpActive = ftpToWebsite(title) # set flag, send file to website print(title, "=> website") # show file sent # overwrite timed images from yesterday with blank images if(hours=='04'): # print("Blank images => website") # send 8 blanks image = Image.new('RGB',(640,480),"rgb(0,0,0)") # black image.save("pic06.png") # create blank image ftpActive = ftpToWebsite("pic06.png") # old file will be overwritten with pic.png image.save("pic08.png") # this causes blanks to display at website ftpActive = ftpToWebsite("pic08.png") # image.save("pic10.png") ftpActive = ftpToWebsite("pic10.png") image.save("pic12.png") ftpActive = ftpToWebsite("pic12.png") image.save("pic14.png") ftpActive = ftpToWebsite("pic14.png") image.save("pic16.png") ftpActive = ftpToWebsite("pic16.png") image.save("pic18.png") ftpActive = ftpToWebsite("pic18.png") image.save("pic20.png") ftpActive = ftpToWebsite("pic20.png") if(hours=='22'): # shut down at 10pm MDT (=11PM MST) print("Shutting down now") # (mechanical AC timer switch does not know MDT/MST) time.sleep(5) # time for message to transmit os.system("sudo shutdown -h now") # shutdown while(True): time.sleep(100) # get 24 hour forecast and create 4 images in same directory as this code # Virutal Crossing 1000 requests / day free api if(((now%forecastInterval)==0) and (now!=lastForecast)): # interval passed? lastForecast = now # don't call again until this minute passes print("Request forecast") # this url will elicit 24 hours of hourly forecast for 4 data elements: temperature, windspeed, wind direction and cloud cover url = "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/Salida,CO/today?key=xxx&include=hours&elements=temp,windspeed,winddir,precipprob,cloudcover" response = requests.get(url) # send api to virtual Crossing & get reply data = response.json() # do something json hourly_data = data['days'][0]['hours'] # create python dictionary=>parameter:value index = -1 # hours start at 0 for midnight temp = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4] precipProb = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4] wspeed = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4] cloudCover = [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4] wdir = ["x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x","x",] tof = -1 # Time Of Forecast, hours start at 0 for midnight for hour in hourly_data: # transform json data into lists tof += 1 # index indicates the hour of the forecast temp[tof]= int(hour['temp']) precipProb[tof] = int(hour['precipprob']) wspeed[tof] = int(hour['windspeed']) cloudCover[tof] = int(hour['cloudcover']) wdir[tof] = resolveWind(int(hour['winddir'])) tof = 10 # first Time Of Forecast to create image for website while(tof<17): print("Forecast", tof) # create images of 10AM, 12AM, 2PM, 4PM forecasts image = Image.new('RGB',(240,240),"rgb(200, 200, 200)") #size, color=grey image.save("blankForecast.png") # start with blank, then add text if(tof == 10): text = "10 AM Forecast" if(tof == 12): text = "Noon Forecast" if(tof == 14): text = "2 PM Forecast" if(tof == 16): text = "4 PM Forecast" writeText(text, (0,0,255), 25, (0,30), image) image = writeText(("Temp " + str(int(temp[tof])) + " F"), (255,0,0), 20, (0,80), image) image = writeText(("Precip: " + str(int(precipProb[tof])) + " %"), (255,0,0), 20, (0,110), image) image = writeText(("Wind: " + str(int(wspeed[tof])) + " mph"), (255,0,0), 20, (0,140), image) image = writeText(("Dir: " + (wdir[tof])), (255,0,0), 20, (0,170), image) image = writeText(("Cloud: " + str(int(cloudCover[tof])) + " %"), (255,0,0), 20, (0,200), image) image.save('forecast'+ str(tof)+'.png') tof = tof + 2 print("Forecasts => website") ftpActive = ftpToWebsite("forecast10.png") ftpActive = ftpToWebsite("forecast12.png") ftpActive = ftpToWebsite("forecast14.png") ftpActive = ftpToWebsite("forecast16.png") if(ftpActive): # has ftp been started? ftpActive = False # reset flag try: ftp.quit() # quit if active except: print("ftp never started") # ftp.quit without start->error finally: print("ftp off") time.sleep(2) # ^C keyboard int caught here (keep trying)
Statistics: Posted by stevensarns — Wed Jul 31, 2024 7:55 pm