Hi, ich mal wieder.
Ich möchte bei meinem Script per Pillow ein Bild verkleinern, bevor ich es hochlade, und bekomme folgende Fehlermeldung:
Code: Alles auswählen
Traceback (most recent call last):
File "kestrelcam2.py", line 287, in <module>
main()
File "kestrelcam2.py", line 73, in main
foto = image_buffer.pop().verkleinern()
File "kestrelcam2.py", line 175, in verkleinern
im=Image.open(self.inhalt)
File "/usr/local/lib/python2.7/dist-packages/PIL/Image.py", line 2274, in open
% (filename if filename else fp))
IOError: cannot identify image file <_io.BytesIO object at 0xd43720>
Weiß allerdings nicht was ich falsch mache.
Unten der aktuelle Code dazu...
edit:
Nachdem ich probehalber einen seek(0) eingebaut hatte, bekam ich die Fehlermeldung: "IOError: decoder jpeg not available"
jpeglib-dev nachinstalliert, und es läuft
Trotzdem nehme ich gern Anregungen entgegen, wie ich das ganze betriebssicher bekomm.
Ich denke ich muss mich mal in Sachen "exceptions abfangen" einlesen
Außerdem bin ich für TIpps dankbar, wie ich wvdial (für die Surfstick-Verbindung) am besten aufrufen sollte.
Im Moment mach ich die Verbindung nach Bedarf über Popen auf, und beende per terminate. Bsp. siehe Zeile 183
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, os, cPickle as pickle
import gdata.service
import atom
from io import BytesIO
from collections import deque
import shutil
import time
from PIL import Image
import picamera
import RPi.GPIO as GPIO
from getpass import getpass
import threading
import logging
from subprocess import Popen, PIPE
CHECK_LIGHT = 60 # Zeitabstand zwischen Helligkeitschecks
DARK_THRESHOLD = 200
SNAPSHOT_INTERVAL = 5 # Zeitabstand zwischen Fotos in Sek.
UPLOAD_INTERVAL = 60 # minimaler Zeitabstand zwischen Uploads in Sek.
VIDEO_INTERVAL = 1200 # minimaler Zeitabstand zwischen Videos in Sek.
BUFFER_SIZE = 3 # maximale Anzahl der Bilder im Pufferspeicher
FOTO_PATH ='/media/PICAM/FOTOS/'
VIDEO_PATH ='/media/PICAM/VIDEO/'
VIDEO_LENGTH = 20 # Videolänge in Sek.
FEED_URL = 'http://picasaweb.google.com/data/feed/api/user/xxx/albumid/xxx'
PIR_PIN = 14
STOP_PIN = 19
PR_A_PIN = 20
PR_B_PIN = 21
def main():
logging.basicConfig(filename="/media/PICAM/kestrelcam.log", level=logging.DEBUG, format='%(asctime)s - %(message)s', datefmt='%d.%m.%Y %H:%M:%S')
logging.info("Programm gestartet")
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIR_PIN, GPIO.IN)
GPIO.setup(STOP_PIN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(PIR_PIN, GPIO.RISING)
GPIO.add_event_detect(STOP_PIN, GPIO.FALLING)
last_upload_time = 0
last_video_time = 0
image_buffer = deque(maxlen=BUFFER_SIZE)
username, password = auth()
gds = login(username, password)
red = Led(6)
yellow = Led(12)
green = Led(13)
green.led_on()
darkcheck=Dark()
darkcheck.start()
while not GPIO.event_detected(STOP_PIN):
now_in_s = time.time()
now = time.strftime("%Y-%m-%d um %H-%M-%S", time.localtime(now_in_s))
foto = Foto(now)
foto.aufnehmen(yellow)
image_buffer.append(foto)
if GPIO.event_detected(PIR_PIN):
for foto in image_buffer:
foto.speichern(red)
if (now_in_s - last_video_time) > VIDEO_INTERVAL:
last_video_time = now_in_s
#video(now, red)
if (now_in_s - last_upload_time) > UPLOAD_INTERVAL:
last_upload_time = now_in_s
foto = image_buffer.pop().verkleinern()
# foto.hochladen(gds)
image_buffer.clear()
while not darkcheck.light:
time.sleep(1)
sleepytime = round((SNAPSHOT_INTERVAL + now_in_s - time.time()), 1)
if sleepytime>0.1:
yellow.led_blink(0.1, sleepytime*10)
darkcheck.stop()
GPIO.cleanup()
sys.exit()
class Dark(threading.Thread):
"""
Helligkeitscheck im Hintergrund
"""
def __init__(self):
self._stopevent = threading.Event()
threading.Thread.__init__(self, name="dark")
self.light = True
def run(self):
"""
Kondensator an Fotowiderstand laden / entladen
"""
while not self._stopevent.isSet():
# entladen
GPIO.setup(PR_A_PIN, GPIO.IN)
GPIO.setup(PR_B_PIN, GPIO.OUT)
GPIO.output(PR_B_PIN, False)
time.sleep(CHECK_LIGHT)
# laden
GPIO.setup(PR_B_PIN, GPIO.IN)
GPIO.setup(PR_A_PIN, GPIO.OUT)
count = 0
GPIO.output(PR_A_PIN, True)
while not GPIO.input(PR_B_PIN):
count = count + 1
logging.info("Helligkeit: %s", count)
if count > DARK_THRESHOLD:
self.light=False
else:
self.light=True
def stop(self):
self._stopevent.set()
self.join()
class Led:
"""
LEDs steuern
"""
def __init__(self, pin):
self.pin = pin
GPIO.setup(pin, GPIO.OUT)
def led_on(self):
GPIO.output(self.pin,GPIO.HIGH)
def led_off(self):
GPIO.output(self.pin,GPIO.LOW)
def led_blink(self, dauer, repeat):
for _ in range(0, int(repeat)):
self.led_on()
time.sleep(dauer/2)
self.led_off()
time.sleep(dauer/2)
class Foto:
def __init__(self, datum):
self.inhalt = BytesIO()
self.datum = datum
self.name = datum+".jpg"
def aufnehmen(self, led):
led.led_on()
with picamera.PiCamera(resolution=(2592, 1944)) as camera:
camera.meter_mode = 'matrix'
camera.exposure_mode = 'antishake'
camera.hflip = True
camera.vflip = True
time.sleep(2)
camera.capture(self.inhalt, 'jpeg', quality=20, thumbnail=(64, 48, 10))
led.led_off()
logging.info("Foto aufgenommen")
def speichern(self, led):
with open(FOTO_PATH+self.name, 'wb') as new_img:
new_img.write(self.inhalt.getvalue())
led.led_blink(0.1, 1)
logging.info("Foto '%s' abgespeichert", self.name)
def verkleinern(self):
print self.inhalt
im=Image.open(self.inhalt)
im.resize((640,480))
klein = Foto(self.datum)
klein.name = "k"+klein.name
im.save(klein.inhalt, 'jpeg')
return klein
def hochladen(self, gds):
wvdial = Popen(["wvdial", "umts"])
time.sleep(4)
self.inhalt.seek(0, 2)
fil_len = self.inhalt.tell()
self.inhalt.seek(0)
media = gdata.MediaSource(file_handle=self.inhalt, content_type='image/jpeg', content_length=fil_len, file_name=self.name) # object for storing file's binary data
try:
posted_photo = gds.Post(
None, # used for metadata ?
FEED_URL, # album feed url
media_source = media, # object with file's data
)
except gdata.service.RequestError:
logging.debug('Error sending file')
except:
logging.debug('Unexpected error: %s', sys.exc_info())
else:
logging.info("Foto '%s' hochgeladen!", self.name)
finally:
wvdial.terminate()
def video(datum, led):
led.led_on()
dateiname = VIDEO_PATH+datum+'.h264'
with picamera.PiCamera() as camera:
camera.resolution = (640, 480)
camera.hflip = True
camera.vflip = True
camera.start_recording(dateiname)
camera.wait_recording(VIDEO_LENGTH)
camera.stop_recording()
led.led_off()
logging.info("Video '%s' aufgenommen", dateiname)
def auth():
"""Read authentication data from user input and store it to file.
Read authentication data from user and store it to file;
if file exists and user auth is not forced, read data from
file and return them.
"""
authfile = '~/.google_auth'
def getsaved():
try:
return open (os.path.expanduser(authfile), 'r')
except:
raise # pass exception to the top call
return None
def askandwrite():
username = str(raw_input('Login (without suffix @gmail.com): '))
password = getpass('Password (would not be displayed): ')
try:
authdata = open (os.path.expanduser(authfile), 'w')
pickle.dump((username, password), authdata)
authdata.close()
except IOError, (errno, strerror):
print "I/O error(%s): %s" % (errno, strerror)
return (username, password)
try:
authdata = getsaved()
username, password = pickle.load(authdata)
authdata.close()
except IOError, (errno, strerror):
print "I/O error(%s): %s" % (errno, strerror)
username, password = askandwrite()
except:
print "Unexpected error:", sys.exc_info()[0]
username, password = askandwrite()
return (username, password)
def login(username, password):
"""Perform login procedure to picasaweb.google.com.
"""
wvdial = Popen(["wvdial", "umts"])
time.sleep(5)
gds = gdata.service.GDataService()
gds.email = username
gds.password = password
gds.service = 'lh2' # where to get the list of all possible values?
try:
gds.ProgrammaticLogin()
except gdata.service.CaptchaRequired:
sys.exit('Required Captcha')
except gdata.service.BadAuthentication:
sys.exit('Bad Authentication')
except gdata_client.Error:
sys.exit('Login Error')
else:
logging.info("bei Google eingeloggt")
finally:
wvdial.terminate()
return gds
if __name__ == "__main__":
main()