Exemple #1
0
    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)
Exemple #2
0
    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}"))
Exemple #4
0
 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)
Exemple #5
0
 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,
     )
Exemple #6
0
    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)
Exemple #7
0
    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))
Exemple #8
0
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
    })
Exemple #9
0
    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)
Exemple #10
0
    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": {