def update(self, config, force_cache=False): """Update camera info.""" self.name = config['name'] self.camera_id = str(config['camera_id']) self.network_id = str(config['network_id']) self.serial = config['serial'] self.motion_enabled = config['enabled'] self.battery_voltage = config['battery_voltage'] self.battery_state = config['battery_state'] self.temperature = config['temperature'] self.wifi_strength = config['wifi_strength'] # Check if thumbnail exists in config, if not try to # get it from the homescreen info in teh sync module # otherwise set it to None and log an error new_thumbnail = None if config['thumbnail']: thumb_addr = config['thumbnail'] else: thumb_addr = self.get_thumb_from_homescreen() if thumb_addr is not None: new_thumbnail = "{}{}.jpg".format(self.sync.urls.base_url, thumb_addr) # Check if a new motion clip has been recorded # check_for_motion_method sets motion_detected variable self.check_for_motion() clip_addr = None if self.last_record: clip_addr = self.sync.all_clips[self.name][self.last_record[0]] self.clip = "{}{}".format(self.sync.urls.base_url, clip_addr) # If the thumbnail or clip have changed, update the cache update_cached_image = False if new_thumbnail != self.thumbnail or self._cached_image is None: update_cached_image = True self.thumbnail = new_thumbnail update_cached_video = False if self._cached_video is None or self.motion_detected: update_cached_video = True if new_thumbnail is not None and (update_cached_image or force_cache): self._cached_image = api.http_get(self.sync.blink, url=self.thumbnail, stream=True, json=False) if clip_addr is not None and (update_cached_video or force_cache): self._cached_video = api.http_get(self.sync.blink, url=self.clip, stream=True, json=False)
def update_images(self, config, force_cache=False): """Update images for camera.""" new_thumbnail = None thumb_addr = None if config.get("thumbnail", False): thumb_addr = config["thumbnail"] else: _LOGGER.warning("Could not find thumbnail for camera %s", self.name) if thumb_addr is not None: new_thumbnail = f"{self.sync.urls.base_url}{thumb_addr}.jpg" try: self.motion_detected = self.sync.motion[self.name] except KeyError: self.motion_detected = False clip_addr = None try: clip_addr = self.sync.last_record[self.name]["clip"] self.last_record = self.sync.last_record[self.name]["time"] self.clip = f"{self.sync.urls.base_url}{clip_addr}" except KeyError: pass # If the thumbnail or clip have changed, update the cache update_cached_image = False if new_thumbnail != self.thumbnail or self._cached_image is None: update_cached_image = True self.thumbnail = new_thumbnail update_cached_video = False if self._cached_video is None or self.motion_detected: update_cached_video = True if new_thumbnail is not None and (update_cached_image or force_cache): self._cached_image = api.http_get( self.sync.blink, url=self.thumbnail, stream=True, json=False, timeout=TIMEOUT_MEDIA, ) if clip_addr is not None and (update_cached_video or force_cache): self._cached_video = api.http_get( self.sync.blink, url=self.clip, stream=True, json=False, timeout=TIMEOUT_MEDIA, )
def _parse_downloaded_items(self, result, camera, debug): """Parse downloaded videos.""" for item in result: try: created_at = item["created_at"] camera_name = item["device_name"] is_deleted = item["deleted"] address = item["media"] except KeyError: _LOGGER.info("Missing clip information, skipping...") continue if camera_name not in camera and "all" not in camera: _LOGGER.debug("Skipping videos for %s.", camera_name) continue if is_deleted: _LOGGER.debug("%s: %s is marked as deleted.", camera_name, address) continue clip_address = f"{self.urls.base_url}{address}" filename = f"{camera_name}-{created_at}" filename = f"{slugify(filename)}.mp4" #filename = os.path.join(path, filename) if not debug: bucket = client.get_bucket(self.bucket_name) blob = bucket.blob(filename) if blob.exists(): _LOGGER.info("%s already exists, skipping...", filename) continue ## Commenting the existing path ##if os.path.isfile(filename): ## _LOGGER.info("%s already exists, skipping...", filename) ## continue response = api.http_get( self, url=clip_address, stream=True, json=False, timeout=TIMEOUT_MEDIA, ) blob.upload_from_file( response.raw, content_type=response.headers.get('Content-Type')) ## Commented the code ##with open(filename, "wb") as vidfile: ## copyfileobj(response.raw, vidfile) _LOGGER.info("Downloaded video to %s", filename) else: print((f"Camera: {camera_name}, Timestamp: {created_at}, " "Address: {address}, Filename: {filename}"))
def test_http_req_connect_error(self, mock_auth): """Test http_get error condition.""" mock_auth.return_value = {'foo': 'bar'} firstlog = ("INFO:blinkpy.helpers.util:" "Cannot connect to server with url {}." ).format('http://notreal.fake') nextlog = ("INFO:blinkpy.helpers.util:" "Auth token expired, attempting reauthorization.") lastlog = ("ERROR:blinkpy.helpers.util:" "Endpoint {} failed. Possible issue with " "Blink servers.").format('http://notreal.fake') expected = [firstlog, nextlog, firstlog, lastlog] with self.assertLogs() as getlog: api.http_get(self.blink, 'http://notreal.fake') with self.assertLogs() as postlog: api.http_post(self.blink, 'http://notreal.fake') self.assertEqual(getlog.output, expected) self.assertEqual(postlog.output, expected)
def get_media(self, media_type="image"): """Download media (image or video).""" url = self.thumbnail if media_type.lower() == "video": url = self.clip return api.http_get( self.sync.blink, url=url, stream=True, json=False, timeout=TIMEOUT_MEDIA, )
def _parse_downloaded_items(self, result, camera, path, delay, debug): """Parse downloaded videos.""" for item in result: try: created_at = item["created_at"] camera_name = item["device_name"] is_deleted = item["deleted"] address = item["media"] except KeyError: _LOGGER.info("Missing clip information, skipping...") continue if camera_name not in camera and "all" not in camera: _LOGGER.debug("Skipping videos for %s.", camera_name) continue if is_deleted: _LOGGER.debug("%s: %s is marked as deleted.", camera_name, address) continue clip_address = f"{self.urls.base_url}{address}" filename = f"{camera_name}-{created_at}" filename = f"{slugify(filename)}.mp4" filename = os.path.join(path, filename) if not debug: if os.path.isfile(filename): _LOGGER.info("%s already exists, skipping...", filename) continue response = api.http_get( self, url=clip_address, stream=True, json=False, timeout=TIMEOUT_MEDIA, ) with open(filename, "wb") as vidfile: copyfileobj(response.raw, vidfile) _LOGGER.info("Downloaded video to %s", filename) else: print( ( f"Camera: {camera_name}, Timestamp: {created_at}, " "Address: {address}, Filename: {filename}" ) ) if delay > 0: time.sleep(delay)
def _parse_downloaded_items(self, result, camera, path, debug): """Parse downloaded videos.""" for item in result: try: created_at = item['created_at'] camera_name = item['device_name'] is_deleted = item['deleted'] address = item['media'] except KeyError: _LOGGER.info("Missing clip information, skipping...") continue if camera_name not in camera and 'all' not in camera: _LOGGER.debug("Skipping videos for %s.", camera_name) continue if is_deleted: _LOGGER.debug("%s: %s is marked as deleted.", camera_name, address) continue clip_address = "{}{}".format(self.urls.base_url, address) filename = "{}-{}".format(camera_name, created_at) filename = "{}.mp4".format(slugify(filename)) filename = os.path.join(path, filename) if not debug: if os.path.isfile(filename): _LOGGER.info("%s already exists, skipping...", filename) continue response = api.http_get(self, url=clip_address, stream=True, json=False) with open(filename, 'wb') as vidfile: copyfileobj(response.raw, vidfile) _LOGGER.info("Downloaded video to %s", filename) else: print(("Camera: {}, Timestamp: {}, " "Address: {}, Filename: {}").format( camera_name, created_at, address, filename))
def show_vid(): vid_id = request.args.get('vid_id') group_id = request.args.get('group_id') file_path = os.path.join(PKGDIR, "static", "videos", "%s.mp4" % vid_id) if not os.path.isfile(file_path): print("Fetching: %s" % vid_id) vid_url = "%s/api/v2/accounts/%s/media/clip/%s.mp4" % ( blink.urls.base_url, blink.account_id, vid_id) resp = blinkapi.http_get(blink, url=vid_url, stream=True, json=False) with open(file_path, "wb") as h: copyfileobj(resp.raw, h) return jsonify({ "ret": "ok", "vid_path": "/static/videos/%s.mp4" % vid_id, "group_id": group_id })
def update(self, config, force_cache=False, **kwargs): """Update camera info.""" # force = kwargs.pop('force', False) self.name = config['name'] self.camera_id = str(config['id']) self.network_id = str(config['network_id']) self.serial = config['serial'] self.motion_enabled = config['enabled'] self.battery_voltage = config['battery_voltage'] self.battery_state = config['battery_state'] self.temperature = config['temperature'] self.wifi_strength = config['wifi_strength'] # Retrieve calibrated temperature from special endpoint resp = api.request_camera_sensors(self.sync.blink, self.network_id, self.camera_id) try: self.temperature_calibrated = resp['temp'] except KeyError: self.temperature_calibrated = self.temperature _LOGGER.warning("Could not retrieve calibrated temperature.") # Check if thumbnail exists in config, if not try to # get it from the homescreen info in the sync module # otherwise set it to None and log an error new_thumbnail = None thumb_addr = None if config['thumbnail']: thumb_addr = config['thumbnail'] else: _LOGGER.warning("Could not find thumbnail for camera %s", self.name, exc_info=True) if thumb_addr is not None: new_thumbnail = "{}{}.jpg".format(self.sync.urls.base_url, thumb_addr) try: self.motion_detected = self.sync.motion[self.name] except KeyError: self.motion_detected = False clip_addr = None if self.name in self.sync.last_record: clip_addr = self.sync.last_record[self.name]['clip'] self.last_record = self.sync.last_record[self.name]['time'] self.clip = "{}{}".format(self.sync.urls.base_url, clip_addr) # If the thumbnail or clip have changed, update the cache update_cached_image = False if new_thumbnail != self.thumbnail or self._cached_image is None: update_cached_image = True self.thumbnail = new_thumbnail update_cached_video = False if self._cached_video is None or self.motion_detected: update_cached_video = True if new_thumbnail is not None and (update_cached_image or force_cache): self._cached_image = api.http_get(self.sync.blink, url=self.thumbnail, stream=True, json=False) if clip_addr is not None and (update_cached_video or force_cache): self._cached_video = api.http_get(self.sync.blink, url=self.clip, stream=True, json=False)
if datetime.today() >= (loop_start + timedelta(seconds=TIMEOUT_SECONDS)): break time.sleep(1) # Debug # with open("videos.json", "w") as f: # f.write(json.dumps(videos, indent=4)) # exit(0) if len(videos) >= 1: video = videos[0] # Use the first video in the list. video_address = "{}{}".format(blink.urls.base_url, video["media"]) response = api.http_get(blink, url=video_address, stream=True, json=False) with open(VIDEO_FILE, "wb") as video_file_content: video_file_content.write(response.content) # Extract a still image from the frame at 4s and save that to disk os.system( "ffmpeg -y -ss 00:00:04 -i {} -vf 'crop=720:720:280:0' -vframes 1 -vcodec png {}" .format( # noqa VIDEO_FILE, IMAGE_FILE)) # Build the notification data data = { "message": "Doorbell", "data": { "attachment": {