Skip to content

Commit

Permalink
added save video service
Browse files Browse the repository at this point in the history
  • Loading branch information
twrecked committed Sep 10, 2019
1 parent 5245714 commit 5f2f948
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 4 deletions.
77 changes: 74 additions & 3 deletions custom_components/aarlo/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@

SERVICE_REQUEST_SNAPSHOT = 'aarlo_request_snapshot'
SERVICE_REQUEST_SNAPSHOT_TO_FILE = 'aarlo_request_snapshot_to_file'
SERVICE_REQUEST_VIDEO_TO_FILE = 'aarlo_request_video_to_file'
SERVICE_STOP_ACTIVITY = 'aarlo_stop_activity'

WS_TYPE_VIDEO_URL = 'aarlo_video_url'
Expand All @@ -85,6 +86,11 @@
vol.Required('type'): WS_TYPE_SNAPSHOT_IMAGE,
vol.Required('entity_id'): cv.entity_id
})
WS_TYPE_VIDEO_DATA = 'aarlo_video_data'
SCHEMA_WS_VIDEO_DATA = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
vol.Required('type'): WS_TYPE_VIDEO_DATA,
vol.Required('entity_id'): cv.entity_id
})
WS_TYPE_STOP_ACTIVITY = 'aarlo_stop_activity'
SCHEMA_WS_STOP_ACTIVITY = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
vol.Required('type'): WS_TYPE_STOP_ACTIVITY,
Expand All @@ -111,7 +117,11 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
aarlo_snapshot_to_file_service_handler
)
component.async_register_entity_service(
SERVICE_STOP_ACTIVITY,CAMERA_SERVICE_SCHEMA,
SERVICE_REQUEST_VIDEO_TO_FILE, CAMERA_SERVICE_SNAPSHOT,
aarlo_video_to_file_service_handler
)
component.async_register_entity_service(
SERVICE_STOP_ACTIVITY, CAMERA_SERVICE_SCHEMA,
aarlo_stop_activity_handler
)
hass.components.websocket_api.async_register_command(
Expand All @@ -130,6 +140,10 @@ async def async_setup_platform(hass, config, async_add_entities, discovery_info=
WS_TYPE_SNAPSHOT_IMAGE, websocket_snapshot_image,
SCHEMA_WS_SNAPSHOT_IMAGE
)
hass.components.websocket_api.async_register_command(
WS_TYPE_VIDEO_DATA, websocket_video_data,
SCHEMA_WS_VIDEO_DATA
)
hass.components.websocket_api.async_register_command(
WS_TYPE_STOP_ACTIVITY, websocket_stop_activity,
SCHEMA_WS_STOP_ACTIVITY
Expand Down Expand Up @@ -317,6 +331,12 @@ def get_snapshot(self):
def async_get_snapshot(self):
return self.hass.async_add_job(self.get_snapshot)

def get_video(self):
return self._camera.get_video()

def async_get_video(self):
return self.hass.async_add_job(self.get_video)

def stop_activity( self ):
return self._camera.stop_activity()

Expand Down Expand Up @@ -408,6 +428,25 @@ async def websocket_snapshot_image(hass, connection, msg):
connection.send_message(websocket_api.error_message(
msg['id'], 'image_fetch_failed', 'Unable to fetch image'))

@websocket_api.async_response
async def websocket_video_data(hass, connection, msg):
camera = _get_camera_from_entity_id(hass, msg['entity_id'])
_LOGGER.debug('video_data for ' + str(camera.unique_id))

try:
video = await camera.async_get_video()
connection.send_message(websocket_api.result_message(
msg['id'], {
'content_type': 'video/mp4',
'content': base64.b64encode(video).decode('utf-8')
}
))

except HomeAssistantError:
connection.send_message(websocket_api.error_message(
msg['id'], 'video_fetch_failed', 'Unable to fetch video'))


@websocket_api.async_response
async def websocket_stop_activity(hass, connection, msg):
camera = _get_camera_from_entity_id( hass,msg['entity_id'] )
Expand Down Expand Up @@ -458,7 +497,39 @@ def _write_image(to_file, image_data):
except OSError as err:
_LOGGER.error("Can't write image to file: %s", err)

async def aarlo_stop_activity_handler( camera,service ):
_LOGGER.info( "{0} stop activity".format( camera.unique_id ) )

async def aarlo_video_to_file_service_handler(camera, service):
_LOGGER.info("{0} video to file".format(camera.unique_id))

hass = camera.hass
filename = service.data[ATTR_FILENAME]
filename.hass = hass

video_file = filename.async_render(variables={ATTR_ENTITY_ID: camera})

# check if we allow to access to that file
if not hass.config.is_allowed_path(video_file):
_LOGGER.error("Can't write %s, no access to path!", video_file)
return

image = await camera.async_get_video()

def _write_image(to_file, image_data):
with open(to_file, 'wb') as img_file:
img_file.write(image_data)

try:
await hass.async_add_executor_job(_write_image, video_file, image)
hass.bus.fire('aarlo_video_ready', {
'entity_id': 'aarlo.' + camera.unique_id,
'file': video_file
})
except OSError as err:
_LOGGER.error("Can't write image to file: %s", err)

_LOGGER.debug("{0} video to file finished".format(camera.unique_id))

async def aarlo_stop_activity_handler(camera, _service):
_LOGGER.info("{0} stop activity".format(camera.unique_id))
camera.stop_activity()

2 changes: 1 addition & 1 deletion custom_components/aarlo/pyaarlo/background.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def _run_next( self ):
try:
job['callback'](**job['args'])
except Exception as e:
self.log.debug('job-error={}'.format(type(e).__name__))
self.arlo.debug('job-error={}'.format(type(e).__name__))

# reschedule?
self._lock.acquire()
Expand Down
6 changes: 6 additions & 0 deletions custom_components/aarlo/pyaarlo/camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,12 @@ def get_stream( self ):
self._arlo.debug( 'url={}'.format(url) )
return url

def get_video(self):
video = self.last_video
if video is not None:
return http_get(video.video_url)
return None

def stop_activity( self ):
self._arlo._bg.run( self._arlo._be.notify,
base=self.base_station,
Expand Down

0 comments on commit 5f2f948

Please sign in to comment.