# (c)2019 Hendrik Schutter # Fotobox V01 from picamera import PiCamera, Color from time import sleep from ftplib import FTP from fractions import Fraction from datetime import datetime import ftplib import time import os import http.client as httplib from collections import namedtuple import logging import configparser import subprocess from spidev import SpiDev import RPi.GPIO as GPIO import re import fcntl import itertools configParser = configparser.RawConfigParser() configFilePath = r'/home/pi/config.txt' configParser.read(configFilePath) # ioBoard piezo = 25 bootSwitch = 17 switch12V = 23 flashPin = 18 version = '01' print('Copyright CopterSicht - info@coptersicht.de 2015-' + str(datetime.now().year)) print('starting camera version: ' + version) print('reading config...') ftp_url = configParser.get('config', 'ftp_url') ftp_picture_directory = configParser.get('config', 'ftp_picture_directory') ftp_log_directory = configParser.get('config', 'ftp_log_directory') ftp_user = configParser.get('config', 'ftp_user') ftp_pw = configParser.get('config', 'ftp_pw') picture_directory = configParser.get('config', 'picture_directory') log_directory = configParser.get('config', 'log_directory') camera_number = configParser.get('config', 'camera_number') enable_modem = configParser.get('config', 'enable_modem') picture_size = int(configParser.get('config', 'picture_size')) internet = configParser.get('config', 'internet') modem_apn = configParser.get('config', 'modem_apn') upload_only = int(configParser.get('config', 'upload_only')) interval = int(configParser.get('config', 'interval')) ioBoard = configParser.get('config', 'I/O_Board') mute = configParser.get('config', 'mute') wakeup_Time = str(configParser.get('config', 'wakeup_Time')).split(',') bed_Time = str(configParser.get('config', 'bed_Time')).split(',') tvOut = configParser.get('config', 'TV_Output') width = configParser.get('config', 'Width') height = configParser.get('config', 'Height') rebootCMD = configParser.get('config', 'Reboot') flash = configParser.get('config', 'Flash') print('done!') rebootFlag = 'false' picture_name = ' ' picture_path = ' ' print('initializing logger...') log_name = camera_number + '_' + str(datetime.now().strftime("%A %d. %B %Y")) + '.log' log_name = log_name.replace(" ", "-") logging.getLogger('').handlers = [] try: logging.basicConfig(filename=log_directory + log_name, format='%(asctime)s [%(levelname)s] %(message)s', level=logging.DEBUG, datefmt='%d/%m/%Y %H:%M:%S') except Exception as er: print('[Logger] Could not create .log' + str(er)) print('[USB] Could not find USB storage!') while 1: checkConnectionToFTPServer() if internet == 'true' and internetTmp == 'false': if internetTmp == 'false': rebootFlag = 'true' print('[Timelapse Core] Reboot Flag set') if rebootFlag == 'true': rebootSystem() print('[Timlapse Core] Waiting for maintenance!') sleep(3600) logging.info('starting camera version: ' + version) print('done') print('reading picture number...') try: f = open("/home/pi/picture_Number.txt", 'r') picture_number = int(f.read()) f.close() except Exception as ea: print('No picture_Number.txt found. Creating new .. ') f = open("/home/pi/picture_Number.txt", 'w') f.write(str(0)) f.close() f = open("/home/pi/picture_Number.txt", 'r') picture_number = int(f.read()) f.close() logging.info('Maybe a fatal error occourd! New picture_Number was created. Risk of redundancy!') print('Maybe a fatal error occourd! New picture_Number was created. Risk of redundancy!') print('done, picture number is:', str(picture_number)) camera = PiCamera() upload_every = upload_only internetTmp = internet if ioBoard == "true": print('Running with the nice IO board!') spi = SpiDev() spi.open(0, 0) spi.max_speed_hz = 5000 GPIO.setmode(GPIO.BCM) GPIO.setwarnings(False) GPIO.setup(piezo, GPIO.OUT) GPIO.setup(flashPin, GPIO.OUT) GPIO.setup(bootSwitch, GPIO.IN) GPIO.setup(switch12V, GPIO.IN) GPIO.output(piezo, GPIO.LOW) GPIO.output(flashPin, GPIO.LOW) if GPIO.input(bootSwitch) == 0: #camera = PiCamera() camera.resolution = (3280, 2464) # aufloesung der bilder maximal 3280,2464s camera.awb_mode = 'auto' camera.start_preview() # camera.start_preview(fullscreen=False, window = (100, 20, 960, 720)) print('---starting sharpness tool---') print('--------normal output--------') sleep(1000) camera.stop_preview() camera.close() if mute == "false": GPIO.output(piezo, GPIO.HIGH) sleep(1) GPIO.output(piezo, GPIO.LOW) else: print('Running without the nice IO board!') if rebootCMD == 'true': print('Automatic reboot is allowed while wake up!') logging.info('Automatic reboot is allowed while wakeup!') if tvOut == 'false': stdoutdata = subprocess.getoutput('sudo /usr/bin/tvservice -o ') print('[TV Out] Status: ' + stdoutdata) logging.info('[TV Out] Status: ' + stdoutdata) if internetTmp == 'true': print('Running in Online mode, internet connection is required') if enable_modem == 'true': reconnectToInternet() try: ftp = FTP(ftp_url, ftp_user, ftp_pw, timeout=20) ftp.cwd(ftp_picture_directory) print('New ftp connection successful! current dicertory is: ' + ftp.pwd()) logging.info('New ftp connection successful! current dicertory is: ' + ftp.pwd()) except Exception as ea: print('no internet or ftp connection on startup trying to reconnect later!') logging.error('no internet or ftp connection on startup trying to reconnect later!') internetTmp = 'false' else: print('Running in Offline mode, no internet connection is required') print('[Camera] Resolution: ' + width + 'x' + height) logging.info('[Camera] Resolution: ' + width + 'x' + height) subprocess.getoutput('sudo sh -c "TERM=linux setterm -foreground black -clear all >/dev/tty0"') # get cpu temperature def getCpuTemperature(): tempFile = open("/sys/class/thermal/thermal_zone0/temp") cpu_temp = tempFile.read() tempFile.close() return float(cpu_temp) / 1000 # uploading picture to ftp and make chmod 754 when done sleep until sleeping time is over def uploadToFTP(): global picture_name global picture_path print('trying to upload file ...') logging.info('trying to upload file ...') try: ftp.storbinary('STOR ' + picture_name, open(picture_path, 'rb'), 1024) ftp.sendcmd('SITE CHMOD 754 ' + picture_name) os.remove(picture_path) print('upload successful!') logging.info('[Upload] successful!') except Exception as e: print('upload failed!') print(e) logging.error('[Upload] failed!') logging.error(str(e)) try: print('[FTP] trying to reconnect ...') logging.info('[FTP] trying to reconnect ...') ftp.connect(ftp_url) ftp.login(ftp_user, ftp_pw) ftp.cwd(ftp_picture_directory) print('[FTP] re-connecting successful!') logging.info('[FTP] re-connecting successful!') ftp.storbinary('STOR ' + picture_name, open(picture_path, 'rb'), 1024) ftp.sendcmd('SITE CHMOD 754 ' + picture_name) os.remove(picture_path) print('[FTP] upload successful!') logging.info('[FTP]upload successful!') except Exception as e9: print('[FTP] re-connecting failed!') print(e9) logging.error('[FTP] re-connecting failed!') logging.error(str(e9)) if reconnectToInternet() == 'true': print('Reconnect successful') logging.info('[Internet] Reconnect successful!') else: print('Reconnect failed') logging.error('[Internet] Reconnect failed!') return def checkDiskSpace(): st = os.statvfs(picture_directory) free = st.f_bavail * st.f_frsize total = st.f_blocks * st.f_frsize freePercentaged = int(((st.f_bavail * st.f_frsize) / (st.f_blocks * st.f_frsize)) * 100) logging.info('[Disk] Free space: ' + str(freePercentaged) + ' %') print('Free disk space ', str(freePercentaged), ' %') if freePercentaged < 20 and freePercentaged > 10: logging.warning('[Disk] Storage Drive nearly full!') if freePercentaged < 10: logging.critical('[Disk] Storage Drive full, Backup Space in use!') return def checkCpu(): try: if getCpuTemperature() <= -5.0: logging.critical('[CPU] Coold: ' + str(getCpuTemperature()) + ' C') elif getCpuTemperature() <= 7.0: logging.warning('[CPU] Coold: ' + str(getCpuTemperature()) + ' C') elif getCpuTemperature() >= 45.0: logging.warning('[CPU] Hot: ' + str(getCpuTemperature()) + ' C') elif getCpuTemperature() >= 50.0: logging.critical('[CPU] Hot: ' + str(getCpuTemperature()) + ' C') else: logging.info('[CPU] Temperature: ' + str(getCpuTemperature()) + ' C') return except Exception as e2: print('[CPU] ' + str(e2)) logging.warning('[CPU] ' + str(e2)) def readMPC(channel): adc = spi.xfer2([1, (8 + channel) << 4, 0]) data = ((adc[1] & 3) << 8) + adc[2] return data def checkSystemVoltage(): systemVoltage = (((readMPC(0) / 1023.0 * 3.3) * 6.62) * 0.95) print("System Input Voltage: %.2f" % systemVoltage, "Volt") logging.info('[Voltage] ' + str("%.2f" % systemVoltage) + ' Volt') if systemVoltage < 11.2 and systemVoltage > 9: logging.warning('[Voltage] Low System Input Voltage! Maybe bad power supply or no sun.') if tvOut == 'auto': stdoutdata = subprocess.getoutput('sudo /usr/bin/tvservice -o ') print('[TV Out] Status: ' + stdoutdata) logging.info('[TV Out] Status: ' + stdoutdata) if systemVoltage < 9: logging.critical('[Voltage] Very low System Input Voltage! Bad power supply or no sun.') return def reconnectToInternet(): try: conn = httplib.HTTPConnection("www.coptersicht.de", timeout=5) conn.request("HEAD", "/") conn.close() print('Internet connection established') print('Server is maybe not online!') logging.info('Internet connection established') logging.error('Server maybe is not online!') global interntTmp interntTmp = 'true' #checkConnectionToFTPServer() return 'true' except Exception as e2: conn.close() print('no Internet connection') print('trying to reconnect to internet') logging.error('no Internet connection!') logging.info('trying to reconnect to internet') if enable_modem == 'true': print('[MODEM] no UMTS connection') logging.error('[MODEM] no UMTS connection') try: stdoutdata = subprocess.getoutput('sudo /usr/bin/modem3g/sakis3g status') print('[MODEM] Network Status: ' + stdoutdata) logging.info('[MODEM] Network Status: ' + stdoutdata) stdoutdata = subprocess.getoutput( "sudo /usr/bin/modem3g/sakis3g disconnect --console APN='" + modem_apn + "' USBINTERFACE='0' USBMODEM='12d1:1436'") print(stdoutdata) logging.info(stdoutdata) logging.info('[MODEM] disconnected') sleep(20) resetModem() stdoutdata = subprocess.getoutput( "sudo /usr/bin/modem3g/sakis3g connect --console APN='" + modem_apn + "' USBINTERFACE='0' USBMODEM='12d1:1436'") print(stdoutdata) print('[MODEM] reconnection successful attempt') logging.info('[MODEM] reconnection successful attempt') logging.info(stdoutdata) sleep(10) try: conn = httplib.HTTPConnection("www.google.de", timeout=5) conn.request("HEAD", "/") conn.close() print('Internet connection established') logging.info('Internet connection established') return 'true' except Exception as e5: conn.close() print('[MODEM] UMTS connection failed') logging.error('[MODEM] UMTS connection failed') print(str(e5)) logging.error(str(e5)) return 'false' except Exception as e4: print('[MODEM] UMTS connection failed') logging.error('[MODEM] UMTS connection failed') print(str(e4)) logging.error(str(e4)) return 'false' else: print('LAN or WLAN not connected!') logging.error('LAN or WLAN not connected!') return 'false' def checkConnectionToFTPServer(): try: # ping ftp url instead something else conn = httplib.HTTPConnection("www.coptersicht.de", timeout=5) conn.request("HEAD", "/") conn.close() try: global ftp ftp = FTP(ftp_url, ftp_user, ftp_pw, timeout=20) ftp.cwd(ftp_picture_directory) print('[FTP] New ftp connection successful! current dicertory is: ' + ftp.pwd()) logging.info('[FTP] New ftp connection successful! current dicertory is: ' + ftp.pwd()) global internetTmp internetTmp = 'true' global upload_every upload_every = upload_only print('[FTP] Server connection established') logging.info('[FTP] Server connection established') except Exception as ea: internetTmp = 'false' print('[FTP] no internet or ftp connection trying to reconnect later!') logging.error('[FTP] no internet or ftp connection trying to reconnect later!') except Exception as e5: conn.close() print('[FTP] Server connection not established') logging.info('[FTP] Server connection not established') reconnectToInternet() return def resetModem(): try: lsusb_cmd = 'lsusb | grep {}'.format('Huawei') lsusb_out = subprocess.check_output(lsusb_cmd, shell=True) parts = re.search(r'Bus (?P\d+) Device (?P\d+): ID [:\d\w]+ (?P.*)$', str(lsusb_out)) bus = parts.group('bus') dev = parts.group('dev') desc = parts.group('desc').strip() print('[Modem] Found device {} on bus {} for "{}"'.format(bus, dev, desc)) f = open('/dev/bus/usb/{}/{}'.format(bus, dev), 'w', os.O_WRONLY) fcntl.ioctl(f, 21780, 0) sleep(15) print('[Modem] Reset successfully attempt') except Exception as ea: print('[Modem] Reset Error: ' + str(ea)) def rebootSystem(): rebootFlag = 'false' os.system('sudo shutdown -r now') print('[Timelapse Core] Reboot') logging.info('[Timelapse Core] Reboot') if mute == "false": GPIO.output(piezo, GPIO.HIGH) sleep(0.5) GPIO.output(piezo, GPIO.LOW) sleep(0.5) GPIO.output(piezo, GPIO.HIGH) sleep(1) GPIO.output(piezo, GPIO.LOW) sleep(1) GPIO.output(piezo, GPIO.HIGH) sleep(2) GPIO.output(piezo, GPIO.LOW) sleep(2) sleep(70) def takePic(): global picture_number global picture_name global picture_path time_next_unix = time.time() + interval # time for next picture time_name = time.asctime(time.localtime(time.time())) # get time for picture_name time_name = time_name.replace(" ", "_") time_name = time_name.replace(":", "-") picture_name = camera_number + '_' + str(picture_number).zfill(6) + '_' + time_name + '.jpg' picture_path = picture_directory + picture_name print("Time:", time_name) #camera = PiCamera() camera.resolution = (int(width), int(height)) # aufloesung der bilder maximal 3280,2464s camera.exposure_mode = 'auto' camera.awb_mode = 'auto' camera.crop = (0, 0, 0, 0) try: camera.exif_tags['IFD0.Make'] = 'CopterSicht' camera.exif_tags['IFD0.Model'] = 'PhotoBox Camera' camera.exif_tags['IFD0.ShutterSpeedValue '] = '' camera.exif_tags['IFD0.ISOSpeedRatings '] = '' camera.exif_tags['IFD0.WhiteBalance '] = '' camera.exif_tags['IFD0.Copyright'] = 'Copyright (c) ' + str(datetime.now().year) + ' CopterSicht' camera.exif_tags['IFD0.ImageDescription'] = 'user triggered photo' if mute == "false":GPIO.output(piezo, GPIO.HIGH) if flash == "true":GPIO.output(flashPin, GPIO.HIGH) print('Capturing image') logging.info('[Camera] Capturing image') camera.annotate_text = " " camera.capture(picture_path) # capture image and save to picture_path (picture_directory + picture_name) print('[Camera] image captured') if flash == "true":GPIO.output(flashPin, GPIO.LOW) if mute == "false": GPIO.output(piezo, GPIO.LOW) picture_number += 1 # increase picture_number print('picture_number:', str(picture_number)) f = open("/home/pi/picture_Number.txt", 'w') f.write(str(picture_number)) # save picture_number to a text file f.close() except Exception as e2: logging.error(str(e2)) print(str(e2)) print('Picture size:', os.path.getsize(picture_path), "Byte") logging.info('[Camera] Picture size: ' + str(os.path.getsize(picture_path)) + ' Byte') def sleepToCapture(): if mute == "false":GPIO.output(piezo, GPIO.HIGH) camera.annotate_text = " 3 " sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.LOW) sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.HIGH) sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.LOW) sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.HIGH) camera.annotate_text = " 2 " sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.LOW) sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.HIGH) sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.LOW) sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.HIGH) camera.annotate_text = " 1 " sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.LOW) sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.HIGH) sleep(.25) if mute == "false":GPIO.output(piezo, GPIO.LOW) sleep(.25) print('ready') sleep(1) camera.resolution = (3280, 2464) camera.awb_mode = 'auto' camera.start_preview(fullscreen=True) camera.annotate_text_size = 160 camera.annotate_foreground = Color('white') while 1: camera.annotate_text = ' Bereit ' if GPIO.input(switch12V) == 0: print('Btn pressed') sleepToCapture() takePic() if (internetTmp == 'true') and (upload_every == 1): uploadToFTP() if ioBoard == "true": checkSystemVoltage() if internet == 'true' and internetTmp == 'false': checkConnectionToFTPServer() checkCpu() else: print(' ')