def camera_record(record_type, unique_id, duration_sec=None, tmp_filename=None): """ Record still image from cameras :param record_type: :param unique_id: :param duration_sec: :param tmp_filename: :return: """ daemon_control = None settings = db_retrieve_table_daemon(Camera, unique_id=unique_id) timestamp = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') assure_path_exists(PATH_CAMERAS) camera_path = assure_path_exists( os.path.join(PATH_CAMERAS, '{uid}'.format(uid=settings.unique_id))) if record_type == 'photo': if settings.path_still != '': save_path = settings.path_still else: save_path = assure_path_exists(os.path.join(camera_path, 'still')) filename = 'Still-{cam_id}-{cam}-{ts}.jpg'.format( cam_id=settings.id, cam=settings.name, ts=timestamp).replace(" ", "_") elif record_type == 'timelapse': if settings.path_timelapse != '': save_path = settings.path_timelapse else: save_path = assure_path_exists( os.path.join(camera_path, 'timelapse')) start = datetime.datetime.fromtimestamp( settings.timelapse_start_time).strftime("%Y-%m-%d_%H-%M-%S") filename = 'Timelapse-{cam_id}-{cam}-{st}-img-{cn:05d}.jpg'.format( cam_id=settings.id, cam=settings.name, st=start, cn=settings.timelapse_capture_number).replace(" ", "_") elif record_type == 'video': if settings.path_video != '': save_path = settings.path_video else: save_path = assure_path_exists(os.path.join(camera_path, 'video')) filename = 'Video-{cam}-{ts}.h264'.format(cam=settings.name, ts=timestamp).replace( " ", "_") else: return assure_path_exists(save_path) if tmp_filename: filename = tmp_filename path_file = os.path.join(save_path, filename) # Turn on output, if configured if settings.output_id: daemon_control = DaemonControl() daemon_control.output_on(settings.output_id) # Pause while the output remains on for the specified duration. # Used for instance to allow fluorescent lights to fully turn on before # capturing an image. if settings.output_duration: time.sleep(settings.output_duration) if settings.library == 'picamera': # Try 5 times to access the pi camera (in case another process is accessing it) for _ in range(5): try: with picamera.PiCamera() as camera: camera.resolution = (settings.width, settings.height) camera.hflip = settings.hflip camera.vflip = settings.vflip camera.rotation = settings.rotation camera.brightness = int(settings.brightness) camera.contrast = int(settings.contrast) camera.exposure_compensation = int(settings.exposure) camera.saturation = int(settings.saturation) camera.start_preview() time.sleep(2) # Camera warm-up time if record_type in ['photo', 'timelapse']: camera.capture(path_file, use_video_port=False) elif record_type == 'video': camera.start_recording(path_file, format='h264', quality=20) camera.wait_recording(duration_sec) camera.stop_recording() else: return break except picamera.exc.PiCameraMMALError: logger.error( "The camera is already open by picamera. Retrying 4 times." ) time.sleep(1) elif settings.library == 'fswebcam': cmd = "/usr/bin/fswebcam --device {dev} --resolution {w}x{h} --set brightness={bt}% " \ "--no-banner --save {file}".format(dev=settings.device, w=settings.width, h=settings.height, bt=settings.brightness, file=path_file) if settings.hflip: cmd += " --flip h" if settings.vflip: cmd += " --flip h" if settings.rotation: cmd += " --rotate {angle}".format(angle=settings.rotation) if settings.custom_options: cmd += " " + settings.custom_options out, err, status = cmd_output(cmd, stdout_pipe=False) # logger.error("TEST01: {}; {}; {}; {}".format(cmd, out, err, status)) # Turn off output, if configured if settings.output_id and daemon_control: daemon_control.output_off(settings.output_id) try: set_user_grp(path_file, 'mycodo', 'mycodo') return save_path, filename except Exception as e: logger.exception( "Exception raised in 'camera_record' when setting user grp: " "{err}".format(err=e))
def camera_record(record_type, unique_id, duration_sec=None, tmp_filename=None): """ Record still image from cameras :param record_type: :param unique_id: :param duration_sec: :param tmp_filename: :return: """ daemon_control = None settings = db_retrieve_table_daemon(Camera, unique_id=unique_id) timestamp = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') assure_path_exists(PATH_CAMERAS) camera_path = assure_path_exists( os.path.join(PATH_CAMERAS, '{uid}'.format(uid=settings.unique_id))) if record_type == 'photo': if settings.path_still != '': save_path = settings.path_still else: save_path = assure_path_exists(os.path.join(camera_path, 'still')) filename = 'Still-{cam_id}-{cam}-{ts}.jpg'.format( cam_id=settings.id, cam=settings.name, ts=timestamp).replace(" ", "_") elif record_type == 'timelapse': if settings.path_timelapse != '': save_path = settings.path_timelapse else: save_path = assure_path_exists( os.path.join(camera_path, 'timelapse')) start = datetime.datetime.fromtimestamp( settings.timelapse_start_time).strftime("%Y-%m-%d_%H-%M-%S") filename = 'Timelapse-{cam_id}-{cam}-{st}-img-{cn:05d}.jpg'.format( cam_id=settings.id, cam=settings.name, st=start, cn=settings.timelapse_capture_number).replace(" ", "_") elif record_type == 'video': if settings.path_video != '': save_path = settings.path_video else: save_path = assure_path_exists(os.path.join(camera_path, 'video')) filename = 'Video-{cam}-{ts}.h264'.format(cam=settings.name, ts=timestamp).replace( " ", "_") else: return assure_path_exists(save_path) if tmp_filename: filename = tmp_filename path_file = os.path.join(save_path, filename) # Turn on output, if configured output_already_on = False output_id = None output_channel_id = None if settings.output_id and ',' in settings.output_id: output_id = settings.output_id.split(",")[0] output_channel_id = settings.output_id.split(",")[1] if output_id and output_channel_id: daemon_control = DaemonControl() if daemon_control.output_state( output_id, output_channel=output_channel_id) == "on": output_already_on = True else: daemon_control.output_on(output_id, output_channel=output_channel_id) # Pause while the output remains on for the specified duration. # Used for instance to allow fluorescent lights to fully turn on before # capturing an image. if settings.output_duration: time.sleep(settings.output_duration) if settings.library == 'picamera': import picamera # Try 5 times to access the pi camera (in case another process is accessing it) for _ in range(5): try: with picamera.PiCamera() as camera: camera.resolution = (settings.width, settings.height) camera.hflip = settings.hflip camera.vflip = settings.vflip camera.rotation = settings.rotation camera.brightness = int(settings.brightness) camera.contrast = int(settings.contrast) camera.exposure_compensation = int(settings.exposure) camera.saturation = int(settings.saturation) camera.shutter_speed = settings.picamera_shutter_speed camera.sharpness = settings.picamera_sharpness camera.iso = settings.picamera_iso camera.awb_mode = settings.picamera_awb if settings.picamera_awb == 'off': camera.awb_gains = (settings.picamera_awb_gain_red, settings.picamera_awb_gain_blue) camera.exposure_mode = settings.picamera_exposure_mode camera.meter_mode = settings.picamera_meter_mode camera.image_effect = settings.picamera_image_effect camera.start_preview() time.sleep(2) # Camera warm-up time if record_type in ['photo', 'timelapse']: camera.capture(path_file, use_video_port=False) elif record_type == 'video': camera.start_recording(path_file, format='h264', quality=20) camera.wait_recording(duration_sec) camera.stop_recording() else: return break except picamera.exc.PiCameraMMALError: logger.error( "The camera is already open by picamera. Retrying 4 times." ) time.sleep(1) elif settings.library == 'fswebcam': cmd = "/usr/bin/fswebcam --device {dev} --resolution {w}x{h} --set brightness={bt}% " \ "--no-banner --save {file}".format(dev=settings.device, w=settings.width, h=settings.height, bt=settings.brightness, file=path_file) if settings.hflip: cmd += " --flip h" if settings.vflip: cmd += " --flip h" if settings.rotation: cmd += " --rotate {angle}".format(angle=settings.rotation) if settings.custom_options: cmd += " {}".format(settings.custom_options) out, err, status = cmd_output(cmd, stdout_pipe=False, user='******') logger.debug("Camera debug message: " "cmd: {}; out: {}; error: {}; status: {}".format( cmd, out, err, status)) elif settings.library == 'opencv': import cv2 import imutils cap = cv2.VideoCapture(settings.opencv_device) cap.set(cv2.CAP_PROP_FRAME_WIDTH, settings.width) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, settings.height) cap.set(cv2.CAP_PROP_EXPOSURE, settings.exposure) cap.set(cv2.CAP_PROP_GAIN, settings.gain) cap.set(cv2.CAP_PROP_BRIGHTNESS, settings.brightness) cap.set(cv2.CAP_PROP_CONTRAST, settings.contrast) cap.set(cv2.CAP_PROP_HUE, settings.hue) cap.set(cv2.CAP_PROP_SATURATION, settings.saturation) # Check if image can be read status, _ = cap.read() if not status: logger.error("Cannot detect USB camera with device '{dev}'".format( dev=settings.opencv_device)) return # Discard a few frames to allow camera to adjust to settings for _ in range(2): cap.read() if record_type in ['photo', 'timelapse']: edited = False status, img_orig = cap.read() cap.release() if not status: logger.error("Could not acquire image") return img_edited = img_orig.copy() if any((settings.hflip, settings.vflip, settings.rotation)): edited = True if settings.hflip and settings.vflip: img_edited = cv2.flip(img_orig, -1) elif settings.hflip: img_edited = cv2.flip(img_orig, 1) elif settings.vflip: img_edited = cv2.flip(img_orig, 0) if settings.rotation: img_edited = imutils.rotate_bound(img_orig, settings.rotation) if edited: cv2.imwrite(path_file, img_edited) else: cv2.imwrite(path_file, img_orig) elif record_type == 'video': # TODO: opencv video recording is currently not working. No idea why. Try to fix later. try: cap = cv2.VideoCapture(settings.opencv_device) fourcc = cv2.CV_FOURCC('X', 'V', 'I', 'D') resolution = (settings.width, settings.height) out = cv2.VideoWriter(path_file, fourcc, 20.0, resolution) time_end = time.time() + duration_sec while cap.isOpened() and time.time() < time_end: ret, frame = cap.read() if ret: # write the frame out.write(frame) if cv2.waitKey(1) & 0xFF == ord('q'): break else: break cap.release() out.release() cv2.destroyAllWindows() except Exception as e: logger.exception("Exception raised while recording video: " "{err}".format(err=e)) else: return elif settings.library == 'http_address': import cv2 import imutils from urllib.error import HTTPError from urllib.parse import urlparse from urllib.request import urlretrieve if record_type in ['photo', 'timelapse']: path_tmp = "/tmp/tmpimg.jpg" # Get filename and extension, if available a = urlparse(settings.url_still) filename = os.path.basename(a.path) if filename: path_tmp = "/tmp/{}".format(filename) try: os.remove(path_tmp) except FileNotFoundError: pass try: urlretrieve(settings.url_still, path_tmp) except HTTPError as err: logger.error(err) except Exception as err: logger.exception(err) try: img_orig = cv2.imread(path_tmp) if img_orig is not None and img_orig.shape is not None: if any( (settings.hflip, settings.vflip, settings.rotation)): img_edited = None if settings.hflip and settings.vflip: img_edited = cv2.flip(img_orig, -1) elif settings.hflip: img_edited = cv2.flip(img_orig, 1) elif settings.vflip: img_edited = cv2.flip(img_orig, 0) if settings.rotation: img_edited = imutils.rotate_bound( img_orig, settings.rotation) if img_edited: cv2.imwrite(path_file, img_edited) else: cv2.imwrite(path_file, img_orig) else: os.rename(path_tmp, path_file) except Exception as err: logger.error( "Could not convert, rotate, or invert image: {}".format( err)) try: os.rename(path_tmp, path_file) except FileNotFoundError: logger.error("Camera image not found") elif record_type == 'video': pass # No video (yet) elif settings.library == 'http_address_requests': import cv2 import imutils import requests if record_type in ['photo', 'timelapse']: path_tmp = "/tmp/tmpimg.jpg" try: os.remove(path_tmp) except FileNotFoundError: pass try: r = requests.get(settings.url_still) if r.status_code == 200: open(path_tmp, 'wb').write(r.content) else: logger.error( "Could not download image. Status code: {}".format( r.status_code)) except requests.HTTPError as err: logger.error("HTTPError: {}".format(err)) except Exception as err: logger.exception(err) try: img_orig = cv2.imread(path_tmp) if img_orig is not None and img_orig.shape is not None: if any( (settings.hflip, settings.vflip, settings.rotation)): if settings.hflip and settings.vflip: img_edited = cv2.flip(img_orig, -1) elif settings.hflip: img_edited = cv2.flip(img_orig, 1) elif settings.vflip: img_edited = cv2.flip(img_orig, 0) if settings.rotation: img_edited = imutils.rotate_bound( img_orig, settings.rotation) cv2.imwrite(path_file, img_edited) else: cv2.imwrite(path_file, img_orig) else: os.rename(path_tmp, path_file) except Exception as err: logger.error( "Could not convert, rotate, or invert image: {}".format( err)) try: os.rename(path_tmp, path_file) except FileNotFoundError: logger.error("Camera image not found") elif record_type == 'video': pass # No video (yet) try: set_user_grp(path_file, 'mycodo', 'mycodo') except Exception as e: logger.exception( "Exception raised in 'camera_record' when setting user grp: " "{err}".format(err=e)) # Turn off output, if configured if output_id and output_channel_id and daemon_control and not output_already_on: daemon_control.output_off(output_id, output_channel=output_channel_id) try: set_user_grp(path_file, 'mycodo', 'mycodo') return save_path, filename except Exception as e: logger.exception( "Exception raised in 'camera_record' when setting user grp: " "{err}".format(err=e))
def generate_output_usage_report(): """ Generate output usage report in a csv file """ logger.debug("Generating output usage report...") try: assure_path_exists(USAGE_REPORTS_PATH) misc = db_retrieve_table_daemon(Misc, entry='first') output = db_retrieve_table_daemon(Output) output_usage = return_output_usage(misc, output.all()) timestamp = time.strftime("%Y-%m-%d_%H-%M") file_name = 'output_usage_report_{ts}.csv'.format(ts=timestamp) report_path_file = os.path.join(USAGE_REPORTS_PATH, file_name) with open(report_path_file, 'wb') as f: w = csv.writer(f) # Header row w.writerow([ 'Relay ID', 'Relay Unique ID', 'Relay Name', 'Type', 'Past Day', 'Past Week', 'Past Month', 'Past Month (from {})'.format(misc.output_usage_dayofmonth), 'Past Year' ]) for key, value in output_usage.items(): if key in ['total_duration', 'total_cost', 'total_kwh']: # Totals rows w.writerow([ '', '', '', key, value['1d'], value['1w'], value['1m'], value['1m_date'], value['1y'] ]) else: # Each output rows each_output = output.filter( Output.unique_id == key).first() w.writerow([ each_output.unique_id, each_output.unique_id, str(each_output.name).encode("utf-8"), 'hours_on', value['1d']['hours_on'], value['1w']['hours_on'], value['1m']['hours_on'], value['1m_date']['hours_on'], value['1y']['hours_on'] ]) w.writerow([ each_output.unique_id, each_output.unique_id, str(each_output.name).encode("utf-8"), 'kwh', value['1d']['kwh'], value['1w']['kwh'], value['1m']['kwh'], value['1m_date']['kwh'], value['1y']['kwh'] ]) w.writerow([ each_output.unique_id, each_output.unique_id, str(each_output.name).encode("utf-8"), 'cost', value['1d']['cost'], value['1w']['cost'], value['1m']['cost'], value['1m_date']['cost'], value['1y']['cost'] ]) set_user_grp(report_path_file, 'mycodo', 'mycodo') except Exception: logger.exception("Energy Usage Report Generation ERROR")
def camera_record(record_type, settings, duration_sec=None, start_time=None, capture_number=None): """ Record still/timelapse images, and video :param record_type: 'photo', 'timelapse', or 'video' :param settings: picamera settings object :param duration_sec: video duration :param start_time: timelapse start time (for filename) :param capture_number: timelapse capture number (for filename) :return: """ timestamp = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') root_path = assure_path_exists(os.path.join(INSTALL_DIRECTORY, 'cameras')) camera_path = assure_path_exists( os.path.join(root_path, '{id}-{uid}'.format(id=settings.id, uid=settings.unique_id))) if record_type == 'photo': save_path = assure_path_exists(os.path.join(camera_path, 'still')) filename = 'Still-{cam_id}-{cam}-{ts}.jpg'.format( cam_id=settings.id, cam=settings.name, ts=timestamp) elif record_type == 'timelapse': save_path = assure_path_exists(os.path.join(camera_path, 'timelapse')) start = datetime.datetime.fromtimestamp( settings.timelapse_start_time).strftime("%Y-%m-%d_%H-%M-%S") filename = 'Timelapse-{cam_id}-{cam}-{st}-img-{cn:05d}.jpg'.format( cam_id=settings.id, cam=settings.name, st=start, cn=settings.timelapse_capture_number) elif record_type == 'video': save_path = assure_path_exists(os.path.join(camera_path, 'video')) filename = 'Video-{cam}-{ts}.h264'.format( cam=settings.name, ts=timestamp) else: return path_file = os.path.join(save_path, filename) if settings.library == 'picamera': with picamera.PiCamera() as camera: camera.resolution = (settings.width, settings.height) camera.hflip = settings.hflip camera.vflip = settings.vflip camera.rotation = settings.rotation camera.start_preview() time.sleep(2) # Camera warm-up time if record_type in ['photo', 'timelapse']: camera.capture(path_file, use_video_port=True) elif record_type == 'video': camera.start_recording(path_file, format='h264', quality=20) camera.wait_recording(duration_sec) camera.stop_recording() else: return elif settings.library == 'opencv': cap = cv2.VideoCapture(settings.opencv_device) # Check if image can be read if not cap.read(): logger.error( "Cannot detect USB camera with device '{dev}'".format( dev=settings.opencv_device)) return cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, settings.width) cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, settings.height) cap.set(cv2.cv.CV_CAP_PROP_EXPOSURE, settings.exposure) cap.set(cv2.cv.CV_CAP_PROP_GAIN, settings.gain) cap.set(cv2.cv.CV_CAP_PROP_BRIGHTNESS, settings.brightness) cap.set(cv2.cv.CV_CAP_PROP_CONTRAST, settings.contrast) cap.set(cv2.cv.CV_CAP_PROP_HUE, settings.hue) cap.set(cv2.cv.CV_CAP_PROP_SATURATION, settings.saturation) if record_type in ['photo', 'timelapse']: edited = False _, img_orig = cap.read() img_edited = img_orig.copy() if any((settings.hflip, settings.vflip, settings.rotation)): edited = True if settings.hflip and settings.vflip: img_edited = cv2.flip(img_orig, -1) elif settings.hflip: img_edited = cv2.flip(img_orig, 1) elif settings.vflip: img_edited = cv2.flip(img_orig, 0) if settings.rotation: img_edited = imutils.rotate_bound(img_orig, settings.rotation) if edited: cv2.imwrite(path_file, img_edited) else: cv2.imwrite(path_file, img_orig) cap.release() else: return try: set_user_grp(path_file, 'mycodo', 'mycodo') except Exception as e: logger.error( "Exception raised in 'camera_record' when setting user grp: " "{err}".format(err=e))
def camera_record(record_type, settings, duration_sec=None): """ Record still/timelapse images, and video :param record_type: 'photo', 'timelapse', or 'video' :param settings: picamera settings object :param duration_sec: video duration :return: """ timestamp = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') root_path = os.path.abspath(os.path.join(INSTALL_DIRECTORY, 'cameras')) assure_path_exists(root_path) camera_path = assure_path_exists( os.path.join(root_path, '{id}-{uid}'.format(id=settings.id, uid=settings.unique_id))) if record_type == 'photo': save_path = assure_path_exists(os.path.join(camera_path, 'still')) filename = u'Still-{cam_id}-{cam}-{ts}.jpg'.format( cam_id=settings.id, cam=settings.name, ts=timestamp).replace(" ", "_") elif record_type == 'timelapse': save_path = assure_path_exists(os.path.join(camera_path, 'timelapse')) start = datetime.datetime.fromtimestamp( settings.timelapse_start_time).strftime("%Y-%m-%d_%H-%M-%S") filename = u'Timelapse-{cam_id}-{cam}-{st}-img-{cn:05d}.jpg'.format( cam_id=settings.id, cam=settings.name, st=start, cn=settings.timelapse_capture_number).replace(" ", "_") elif record_type == 'video': save_path = assure_path_exists(os.path.join(camera_path, 'video')) filename = u'Video-{cam}-{ts}.h264'.format( cam=settings.name, ts=timestamp).replace(" ", "_") else: return path_file = os.path.join(save_path, filename) if settings.library == 'picamera': with picamera.PiCamera() as camera: camera.resolution = (settings.width, settings.height) camera.hflip = settings.hflip camera.vflip = settings.vflip camera.rotation = settings.rotation camera.brightness = int(settings.brightness) camera.contrast = int(settings.contrast) camera.exposure_compensation = int(settings.exposure) camera.saturation = int(settings.saturation) camera.start_preview() time.sleep(2) # Camera warm-up time if record_type in ['photo', 'timelapse']: camera.capture(path_file, use_video_port=True) elif record_type == 'video': camera.start_recording(path_file, format='h264', quality=20) camera.wait_recording(duration_sec) camera.stop_recording() else: return elif settings.library == 'fswebcam': cmd = "/usr/bin/fswebcam --device {dev} --resolution {w}x{h} --set brightness={bt}% " \ "--no-banner --save {file}".format(dev=settings.device, w=settings.width, h=settings.height, bt=settings.brightness, file=path_file) if settings.hflip: cmd += " --flip h" if settings.vflip: cmd += " --flip h" if settings.rotation: cmd += " --rotate {angle}".format(angle=settings.rotation) logger.error(cmd) out, err, status = cmd_output(cmd, stdout_pipe=False, su_mycodo=False) logger.error("TEST01: {}; {}; {}".format(out, err, status)) elif settings.library == 'opencv': cap = cv2.VideoCapture(settings.opencv_device) # Check if image can be read if not cap.read(): logger.error( "Cannot detect USB camera with device '{dev}'".format( dev=settings.opencv_device)) return cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, settings.width) cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, settings.height) cap.set(cv2.cv.CV_CAP_PROP_EXPOSURE, settings.exposure) cap.set(cv2.cv.CV_CAP_PROP_GAIN, settings.gain) cap.set(cv2.cv.CV_CAP_PROP_BRIGHTNESS, settings.brightness) cap.set(cv2.cv.CV_CAP_PROP_CONTRAST, settings.contrast) cap.set(cv2.cv.CV_CAP_PROP_HUE, settings.hue) cap.set(cv2.cv.CV_CAP_PROP_SATURATION, settings.saturation) # # Discard a few frames to allow camera to adjust to settings # for _ in range(2): # cap.read() if record_type in ['photo', 'timelapse']: edited = False try: _, img_orig = cap.read() cap.release() except Exception: logger.exception(1) if not img_orig: logger.error("Could not access camera") return img_edited = img_orig.copy() if any((settings.hflip, settings.vflip, settings.rotation)): edited = True if settings.hflip and settings.vflip: img_edited = cv2.flip(img_orig, -1) elif settings.hflip: img_edited = cv2.flip(img_orig, 1) elif settings.vflip: img_edited = cv2.flip(img_orig, 0) if settings.rotation: img_edited = imutils.rotate_bound(img_orig, settings.rotation) if edited: cv2.imwrite(path_file, img_edited) else: cv2.imwrite(path_file, img_orig) elif record_type == 'video': # TODO: opencv video recording is currently not working. No idea why. try: cap = cv2.VideoCapture(settings.opencv_device) fourcc = cv2.cv.CV_FOURCC('X', 'V', 'I', 'D') resolution = (settings.width, settings.height) out = cv2.VideoWriter(path_file, fourcc, 20.0, resolution) time_end = time.time() + duration_sec while cap.isOpened() and time.time() < time_end: ret, frame = cap.read() if ret: # write the frame out.write(frame) if cv2.waitKey(1) & 0xFF == ord('q'): break else: break cap.release() out.release() cv2.destroyAllWindows() except Exception as e: logger.exception( "Exception raised while recording video: " "{err}".format(err=e)) else: return try: set_user_grp(path_file, 'mycodo', 'mycodo') except Exception as e: logger.exception( "Exception raised in 'camera_record' when setting user grp: " "{err}".format(err=e))
def generate_output_usage_report(): """ Generate output usage report in a csv file """ logger.debug("Generating output usage report...") try: assure_path_exists(USAGE_REPORTS_PATH) misc = db_retrieve_table_daemon(Misc, entry='first') output = db_retrieve_table_daemon(Output) output_usage = return_output_usage(misc, output.all()) timestamp = time.strftime("%Y-%m-%d_%H-%M") file_name = 'output_usage_report_{ts}.csv'.format(ts=timestamp) report_path_file = os.path.join(USAGE_REPORTS_PATH, file_name) with open(report_path_file, 'wb') as f: w = csv.writer(f) # Header row w.writerow([ 'Relay ID', 'Relay Unique ID', 'Relay Name', 'Type', 'Past Day', 'Past Week', 'Past Month', 'Past Month (from {})'.format(misc.output_usage_dayofmonth), 'Past Year' ]) for key, value in output_usage.items(): if key in ['total_duration', 'total_cost', 'total_kwh']: # Totals rows w.writerow(['', '', '', key, value['1d'], value['1w'], value['1m'], value['1m_date'], value['1y']]) else: # Each output rows each_output = output.filter(Output.unique_id == key).first() w.writerow([each_output.unique_id, each_output.unique_id, str(each_output.name).encode("utf-8"), 'hours_on', value['1d']['hours_on'], value['1w']['hours_on'], value['1m']['hours_on'], value['1m_date']['hours_on'], value['1y']['hours_on']]) w.writerow([each_output.unique_id, each_output.unique_id, str(each_output.name).encode("utf-8"), 'kwh', value['1d']['kwh'], value['1w']['kwh'], value['1m']['kwh'], value['1m_date']['kwh'], value['1y']['kwh']]) w.writerow([each_output.unique_id, each_output.unique_id, str(each_output.name).encode("utf-8"), 'cost', value['1d']['cost'], value['1w']['cost'], value['1m']['cost'], value['1m_date']['cost'], value['1y']['cost']]) set_user_grp(report_path_file, 'mycodo', 'mycodo') except Exception: logger.exception("Energy Usage Report Generation ERROR")
def generate_widget_html(): """ Generate all HTML files for all widgets """ dict_widgets = parse_widget_information() assure_path_exists(PATH_HTML_USER) for widget_name in dict_widgets: try: filename_head = "widget_template_{}_head.html".format(widget_name) path_head = os.path.join(PATH_HTML_USER, filename_head) with open(path_head, 'w') as fw: if 'widget_dashboard_head' in dict_widgets[widget_name]: html_head = dict_widgets[widget_name][ 'widget_dashboard_head'] else: html_head = "" fw.write(html_head) fw.close() set_user_grp(path_head, 'mycodo', 'mycodo') filename_title_bar = "widget_template_{}_title_bar.html".format( widget_name) path_title_bar = os.path.join(PATH_HTML_USER, filename_title_bar) with open(path_title_bar, 'w') as fw: if 'widget_dashboard_title_bar' in dict_widgets[widget_name]: html_title_bar = dict_widgets[widget_name][ 'widget_dashboard_title_bar'] else: html_title_bar = "" fw.write(html_title_bar) fw.close() set_user_grp(path_title_bar, 'mycodo', 'mycodo') filename_body = "widget_template_{}_body.html".format(widget_name) path_body = os.path.join(PATH_HTML_USER, filename_body) with open(path_body, 'w') as fw: if 'widget_dashboard_body' in dict_widgets[widget_name]: html_body = dict_widgets[widget_name][ 'widget_dashboard_body'] else: html_body = "" fw.write(html_body) fw.close() set_user_grp(path_body, 'mycodo', 'mycodo') filename_configure_options = "widget_template_{}_configure_options.html".format( widget_name) path_configure_options = os.path.join(PATH_HTML_USER, filename_configure_options) with open(path_configure_options, 'w') as fw: if 'widget_dashboard_configure_options' in dict_widgets[ widget_name]: html_configure_options = dict_widgets[widget_name][ 'widget_dashboard_configure_options'] else: html_configure_options = "" fw.write(html_configure_options) fw.close() set_user_grp(path_configure_options, 'mycodo', 'mycodo') filename_js = "widget_template_{}_js.html".format(widget_name) path_js = os.path.join(PATH_HTML_USER, filename_js) with open(path_js, 'w') as fw: if 'widget_dashboard_js' in dict_widgets[widget_name]: html_js = dict_widgets[widget_name]['widget_dashboard_js'] else: html_js = "" fw.write(html_js) fw.close() set_user_grp(path_js, 'mycodo', 'mycodo') filename_js_ready = "widget_template_{}_js_ready.html".format( widget_name) path_js_ready = os.path.join(PATH_HTML_USER, filename_js_ready) with open(path_js_ready, 'w') as fw: if 'widget_dashboard_js_ready' in dict_widgets[widget_name]: html_js_ready = dict_widgets[widget_name][ 'widget_dashboard_js_ready'] else: html_js_ready = "" fw.write(html_js_ready) fw.close() set_user_grp(path_js_ready, 'mycodo', 'mycodo') filename_js_ready_end = "widget_template_{}_js_ready_end.html".format( widget_name) path_js_ready_end = os.path.join(PATH_HTML_USER, filename_js_ready_end) with open(path_js_ready_end, 'w') as fw: if 'widget_dashboard_js_ready_end' in dict_widgets[ widget_name]: html_js_ready_end = dict_widgets[widget_name][ 'widget_dashboard_js_ready_end'] else: html_js_ready_end = "" fw.write(html_js_ready_end) fw.close() set_user_grp(path_js_ready_end, 'mycodo', 'mycodo') except Exception: logger.exception( "Generating widget HTML for widget: {}".format(widget_name))
def save_conditional_code(error, cond_statement, cond_status, unique_id, table_conditions_all, table_actions_all, timeout=30, test=False): lines_code = None cmd_status = None cmd_out = None try: pre_statement_run = """import os import sys sys.path.append(os.path.abspath('/var/mycodo-root')) from mycodo.controllers.base_conditional import AbstractConditional from mycodo.mycodo_client import DaemonControl control = DaemonControl(pyro_timeout={timeout}) class ConditionalRun(AbstractConditional): def __init__(self, logger, function_id, message): super().__init__(logger, function_id, message, timeout={timeout}) self.logger = logger self.function_id = function_id self.variables = {{}} self.message = message self.running = True def conditional_code_run(self): """.format(timeout=timeout) if cond_statement: indented_code = textwrap.indent(cond_statement, ' ' * 8) else: indented_code = textwrap.indent("pass", ' ' * 8) cond_statement_run = pre_statement_run + indented_code cond_statement_run = cond_statement_replace(cond_statement_run, table_conditions_all, table_actions_all) cond_statement_run += """ def function_status(self): """ if cond_status: cond_statement_run += textwrap.indent(cond_status, ' ' * 8) else: cond_statement_run += textwrap.indent("pass", ' ' * 8) assure_path_exists(PATH_PYTHON_CODE_USER) file_run = '{}/conditional_{}.py'.format(PATH_PYTHON_CODE_USER, unique_id) with open(file_run, 'w') as fw: fw.write('{}\n'.format(cond_statement_run)) fw.close() set_user_grp(file_run, 'mycodo', 'mycodo') if len(cond_statement_run.splitlines()) > 999: error.append( "Too many lines in code. Reduce code to less than 1000 lines.") if test: lines_code = '' for line_num, each_line in enumerate( cond_statement_run.splitlines(), 1): if len(str(line_num)) == 3: line_spacing = '' elif len(str(line_num)) == 2: line_spacing = ' ' else: line_spacing = ' ' lines_code += '{sp}{ln}: {line}\n'.format(sp=line_spacing, ln=line_num, line=each_line) cmd_test = 'mkdir -p /var/mycodo-root/.pylint.d && ' \ 'export PYTHONPATH=$PYTHONPATH:/var/mycodo-root && ' \ 'export PYLINTHOME=/var/mycodo-root/.pylint.d && ' \ '{dir}/env/bin/python -m pylint -d I,W0621,C0103,C0111,C0301,C0327,C0410,C0413,R0912,R0914,R0915 {path}'.format( dir=INSTALL_DIRECTORY, path=file_run) cmd_out, _, cmd_status = cmd_output(cmd_test) except Exception as err: error.append("Error saving/testing conditional code: {}".format(err)) return error, lines_code, cmd_status, cmd_out
def camera_record(record_type, unique_id, duration_sec=None, tmp_filename=None): """ Record still image from cameras :param record_type: :param unique_id: :param duration_sec: :param tmp_filename: :return: """ daemon_control = None settings = db_retrieve_table_daemon(Camera, unique_id=unique_id) timestamp = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') assure_path_exists(PATH_CAMERAS) camera_path = assure_path_exists( os.path.join(PATH_CAMERAS, '{uid}'.format(uid=settings.unique_id))) if record_type == 'photo': if settings.path_still != '': save_path = settings.path_still else: save_path = assure_path_exists(os.path.join(camera_path, 'still')) filename = 'Still-{cam_id}-{cam}-{ts}.jpg'.format( cam_id=settings.id, cam=settings.name, ts=timestamp).replace(" ", "_") elif record_type == 'timelapse': if settings.path_timelapse != '': save_path = settings.path_timelapse else: save_path = assure_path_exists(os.path.join(camera_path, 'timelapse')) start = datetime.datetime.fromtimestamp( settings.timelapse_start_time).strftime("%Y-%m-%d_%H-%M-%S") filename = 'Timelapse-{cam_id}-{cam}-{st}-img-{cn:05d}.jpg'.format( cam_id=settings.id, cam=settings.name, st=start, cn=settings.timelapse_capture_number).replace(" ", "_") elif record_type == 'video': if settings.path_video != '': save_path = settings.path_video else: save_path = assure_path_exists(os.path.join(camera_path, 'video')) filename = 'Video-{cam}-{ts}.h264'.format( cam=settings.name, ts=timestamp).replace(" ", "_") else: return assure_path_exists(save_path) if tmp_filename: filename = tmp_filename path_file = os.path.join(save_path, filename) # Turn on output, if configured if settings.output_id: daemon_control = DaemonControl() daemon_control.output_on(settings.output_id) # Pause while the output remains on for the specified duration. # Used for instance to allow fluorescent lights to fully turn on before # capturing an image. if settings.output_duration: time.sleep(settings.output_duration) if settings.library == 'picamera': # Try 5 times to access the pi camera (in case another process is accessing it) for _ in range(5): try: with picamera.PiCamera() as camera: camera.resolution = (settings.width, settings.height) camera.hflip = settings.hflip camera.vflip = settings.vflip camera.rotation = settings.rotation camera.brightness = int(settings.brightness) camera.contrast = int(settings.contrast) camera.exposure_compensation = int(settings.exposure) camera.saturation = int(settings.saturation) camera.start_preview() time.sleep(2) # Camera warm-up time if record_type in ['photo', 'timelapse']: camera.capture(path_file, use_video_port=False) elif record_type == 'video': camera.start_recording(path_file, format='h264', quality=20) camera.wait_recording(duration_sec) camera.stop_recording() else: return break except picamera.exc.PiCameraMMALError: logger.error("The camera is already open by picamera. Retrying 4 times.") time.sleep(1) elif settings.library == 'fswebcam': cmd = "/usr/bin/fswebcam --device {dev} --resolution {w}x{h} --set brightness={bt}% " \ "--no-banner --save {file}".format(dev=settings.device, w=settings.width, h=settings.height, bt=settings.brightness, file=path_file) if settings.hflip: cmd += " --flip h" if settings.vflip: cmd += " --flip h" if settings.rotation: cmd += " --rotate {angle}".format(angle=settings.rotation) if settings.custom_options: cmd += " " + settings.custom_options out, err, status = cmd_output(cmd, stdout_pipe=False) # logger.error("TEST01: {}; {}; {}; {}".format(cmd, out, err, status)) # Turn off output, if configured if settings.output_id and daemon_control: daemon_control.output_off(settings.output_id) try: set_user_grp(path_file, 'mycodo', 'mycodo') return save_path, filename except Exception as e: logger.exception( "Exception raised in 'camera_record' when setting user grp: " "{err}".format(err=e))
def camera_record(record_type, unique_id, duration_sec=None, tmp_filename=None): """ Record still/timelapse images, and video :param record_type: 'photo', 'timelapse', or 'video' :param settings: picamera settings object :param duration_sec: video duration :return: """ settings = db_retrieve_table_daemon(Camera, unique_id=unique_id) timestamp = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') root_path = os.path.abspath(os.path.join(INSTALL_DIRECTORY, 'cameras')) assure_path_exists(root_path) camera_path = assure_path_exists( os.path.join(root_path, '{uid}'.format(uid=settings.unique_id))) if record_type == 'photo': save_path = assure_path_exists(os.path.join(camera_path, 'still')) filename = 'Still-{cam_id}-{cam}-{ts}.jpg'.format( cam_id=settings.id, cam=settings.name, ts=timestamp).replace(" ", "_") elif record_type == 'timelapse': save_path = assure_path_exists(os.path.join(camera_path, 'timelapse')) start = datetime.datetime.fromtimestamp( settings.timelapse_start_time).strftime("%Y-%m-%d_%H-%M-%S") filename = 'Timelapse-{cam_id}-{cam}-{st}-img-{cn:05d}.jpg'.format( cam_id=settings.id, cam=settings.name, st=start, cn=settings.timelapse_capture_number).replace(" ", "_") elif record_type == 'video': save_path = assure_path_exists(os.path.join(camera_path, 'video')) filename = 'Video-{cam}-{ts}.h264'.format(cam=settings.name, ts=timestamp).replace( " ", "_") else: return if tmp_filename: filename = tmp_filename path_file = os.path.join(save_path, filename) if settings.library == 'picamera': # Try 5 times to access the pi camera (in case another process is accessing it) for _ in range(5): try: with picamera.PiCamera() as camera: camera.resolution = (settings.width, settings.height) camera.hflip = settings.hflip camera.vflip = settings.vflip camera.rotation = settings.rotation camera.brightness = int(settings.brightness) camera.contrast = int(settings.contrast) camera.exposure_compensation = int(settings.exposure) camera.saturation = int(settings.saturation) camera.start_preview() time.sleep(2) # Camera warm-up time if record_type in ['photo', 'timelapse']: camera.capture(path_file, use_video_port=True) elif record_type == 'video': camera.start_recording(path_file, format='h264', quality=20) camera.wait_recording(duration_sec) camera.stop_recording() else: return break except picamera.exc.PiCameraMMALError: # 'out of resources' error when the camera is already open by picamera pass time.sleep(1) elif settings.library == 'fswebcam': cmd = "/usr/bin/fswebcam --device {dev} --resolution {w}x{h} --set brightness={bt}% " \ "--no-banner --save {file}".format(dev=settings.device, w=settings.width, h=settings.height, bt=settings.brightness, file=path_file) if settings.hflip: cmd += " --flip h" if settings.vflip: cmd += " --flip h" if settings.rotation: cmd += " --rotate {angle}".format(angle=settings.rotation) out, err, status = cmd_output(cmd, stdout_pipe=False) # logger.error("TEST01: {}; {}; {}; {}".format(cmd, out, err, status)) try: set_user_grp(path_file, 'mycodo', 'mycodo') return save_path, filename except Exception as e: logger.exception( "Exception raised in 'camera_record' when setting user grp: " "{err}".format(err=e))