def device_online(self, transport, params): params = self.login_params_schema.validate(params) project_name = params['project'] login_code = params['login_code'] login_passwd = params['login_passwd'] device = self._dao.get_by_login_code(login_code) if not device: raise IVRError('Unknown device <{0}> try to login: {1}'.format( login_code, params)) if device.project_name != project_name: raise IVRError( 'Device <{0}> of project <{1}> attampts to login as project <{2}> device' .format(login_code, device.project_name, project_name)) if device.login_passwd != login_passwd: raise IVRError( 'Device login failed with wrong password: {0}'.format(params)) device_conn = DeviceConn(self, project_name, device.uuid, transport, self._device_ttl) old_device_conn = self._device_connections.pop(device.uuid, None) if old_device_conn: log.warning('There is old {0}, disconnect it first'.format( old_device_conn)) try: old_device_conn.force_shutdown() except Exception: log.exception( 'failed to force shutdown {0}'.format(old_device_conn)) self._device_connections[device.uuid] = device_conn log.info('{0} online'.format(device)) device.state = device.STATE_ONLINE device.ltime = datetime.datetime.now() self._dao.update(device) return device_conn
def change_password(self, username, old_password, new_password): with self._dao_context_mngr.context(): user = self._user_dao.get_by_username(username) if user is None: raise IVRError("User Not Found", 404) if user.password != hashlib.sha256(old_password).hexdigest(): raise IVRError("Old password mismatch", 404) user.password = STRING(hashlib.sha256(new_password.encode()).hexdigest()) user.utime = datetime.datetime.now() self._user_dao.update(user)
def leave_from_project(self, username, project_name): with self._dao_context_mngr.context(): user = self._user_dao.get_by_username(username) if user is None: raise IVRError("Username Not Found", 404) user_projects = self._user_dao.get_user_projects(user) for user_project in user_projects: if user_project.name == project_name: break else: raise IVRError("Not In Project", 400) self._user_dao.leave_from_project(user, user_project)
def join_to_project(self, username, project_name): with self._dao_context_mngr.context(): user = self._user_dao.get_by_username(username) if user is None: raise IVRError("Username Not Found", 404) user_projects = self._user_dao.get_user_projects(user) for user_project in user_projects: if user_project.name == project_name: raise IVRError("Already in Project", 400) project = self._project_dao.get_by_name(project_name) if project is None: raise IVRError("Project(%s) Not Found" % project_name, 404) self._user_dao.join_to_project(user, project)
def stop_rtmp_publish(self, project_name, camera_id, stream_id): camera = self.get_camera(project_name, camera_id) if not camera: raise IVRError('Unknown camera <{0}> or project <{1}>'.format( camera_id, project_name)) self._device_mngr.stop_rtmp_publish(project_name, camera.device_uuid, camera.channel_index, stream_id)
def stop_rtmp_publish(self, project_name, device_id, channel, stream_id): device_conn = self._device_connections.get(device_id) if not device_conn: raise IVRError( 'Device <{0}> of project <{1}> is not online'.format( device_id, project_name)) device_conn.stop_rtmp_publish(channel, stream_id)
def keepalive_session(self, project_name, camera_id, session_id): session = self._dao.get_by_id(project_name, session_id) if not session: raise IVRError('session <{0}> of project <{1}> not found'.format(session_id, project_name)) session.last_keepalive = datetime.datetime.now() self._dao.update(session) self._stream_mngr.keepalive(session.stream_id)
def _match_stream(self, quality, preferred_type=None): if not preferred_type: preferred_type = ('rtsp', 'rtmp') stream_type = None for _type in preferred_type: if _type in self.streams: stream_type = _type if stream_type is None: for stream_type in self.streams: break if not stream_type: raise IVRError('No possible stream for "{0}"'.format(self)) if quality not in self.streams[stream_type]: raise IVRError('No proper {0} stream for {1}'.format( quality, self)) return self.streams[stream_type][quality]
def update(self, session): for i, s in enumerate(self._sessions): if s.project_name == session.project_name and s.uuid == session.uuid: if session.end is None: self._sessions[i] = session else: self._sessions.pop(i) return raise IVRError("{0} not found".format(session))
def rtmp_publish_stream(self, project_name, device_id, channel, stream_id, quality, publish_url): device_conn = self._device_connections.get(device_id) if not device_conn: raise IVRError( 'Device <{0}> of project <{1}> is not online'.format( device_id, project_name)) device_conn.rtmp_publish_stream(channel, quality, publish_url, stream_id)
def rtmp_publish_stream(self, project_name, camera_id, stream_id, target_quality, publish_to): camera = self.get_camera(project_name, camera_id) if not camera: raise IVRError('Unknown camera <{0}> or project <{1}>'.format( camera_id, project_name)) self._device_mngr.rtmp_publish_stream(project_name, camera.device_uuid, camera.channel_index, stream_id, target_quality, publish_to)
def mod_access_key(self, key_id, **kwargs): with self._dao_context_mngr.context(): access_key = self._key_dao.get_by_key_id(key_id) if access_key is None: raise IVRError("access_key Not Found", 404) for (k, v) in kwargs.items(): if k in ("enabled", "desc"): setattr(access_key, k, v) self._key_dao.update(access_key) return access_key
def add_user(self, username, password, **kwargs): with self._dao_context_mngr.context(): user = self._user_dao.get_by_username(username) if user is not None: raise IVRError("Username Exist", 400) password = STRING(hashlib.sha256(password.encode()).hexdigest()) user = User(username=username, password=password, **kwargs) self._user_dao.add(user) user = self._user_dao.get_by_username(username) return user
def mod_user(self, username, **kwargs): with self._dao_context_mngr.context(): user = self._user_dao.get_by_username(username) if user is None: raise IVRError("User Not Found", 404) for (k, v) in kwargs.items(): if k in ("title", "desc", "long_desc", "cellphone", "email"): setattr(user, k, v) user.utime = datetime.datetime.now() self._user_dao.update(user) return user
def _wait_util_ready(self, stream_format, stream): if stream_format == 'hls': if stream.hls_ready: self._dao.set_keepalive(stream.id, datetime.datetime.now()) return stream elif wait_util_http_resource_ready(stream.hls_url, timeout=5, retry_wait=1, retry=30): self._dao.set_hls_ready(stream.id, keepalive=datetime.datetime.now()) return stream else: raise IVRError('Failed to create {0}'.format(stream)) self._dao.set_keepalive(stream.id, datetime.datetime.now()) return stream
def new_access_key(self, username, **kwargs): key_id = self._generate_base64_key(15) # 20 chars length secret = self._generate_base64_key(30) # 40 chars length access_key = AccessKey(key_id=key_id, secret=secret, username=username, **kwargs) with self._dao_context_mngr.context(): user = self._user_dao.get_by_username(username) if user is None: raise IVRError("User Not Found", 404) if access_key.key_type == AccessKey.KEY_TYPE_PRIVILEGE and \ user.user_type != user.USER_TYPE_ADMIN: raise IVRError( "only admin user can owns KEY_TYPE_PRIVILEGE key", 400) access_key_list = self._key_dao.get_list(username=username) if len(access_key_list) >= self.MAX_KEYS_PER_USER: raise IVRError( "%s access key is limited per user" % self.MAX_KEYS_PER_USER, 400) self._key_dao.add(access_key) access_key = self._key_dao.get_by_key_id(key_id) return access_key
def request_stream(self, project_name, camera_id, stream_format='hls', stream_quality=VideoQuality.LD, auto_delete=True, create=True): # TODO concurrent request for the same stream maybe harmful, need to handle this situation # find possible existing stream stream = self._dao.get_stream(project_name, camera_id, stream_quality) if stream: return self._wait_util_ready(stream_format, stream) camera = self._camera_mngr.get_camera(project_name, camera_id) if not camera: raise IVRError('No such camera <{0}> or project <{1}>'.format(camera_id, project_name)) if camera.is_online == camera.STATE_OFFLINE: raise IVRError('{0} is offline'.format(camera)) target_quality = camera.find_possible_quality(stream_quality) if target_quality != stream_quality: stream = self._dao.get_stream(project_name, camera_id, target_quality) if stream: return self._wait_util_ready(stream_format, stream) # target stream does not exist, create stream stream_id = STRING(uuid.uuid4()) publish_to = os.path.join(self._rtmp_publish_url_prefix, stream_id) stream = Stream( project_name=project_name, stream_id=stream_id, camera_id=camera_id, stream_quality=stream_quality, publish_to=publish_to, hls_url=self.calc_url('hls', stream_id), rtmp_url=self.calc_url('rtmp', stream_id), rtmp_ready=True, ) self._dao.add(stream) self._camera_mngr.rtmp_publish_stream(project_name, camera_id, stream_id, target_quality, publish_to) try: return self._wait_util_ready(stream_format, stream) except Exception: self._dao.delete(stream_id) self._camera_mngr.stop_rtmp_publish(stream_id) raise
def get_user_list_in_project(self, project_name, filter_name=None, filter_value="", start_index=0, max_number=65535): with self._dao_context_mngr.context(): project = self._project_dao.get_by_name(project_name) if project is None: raise IVRError("Project(%s) Not Found" % project_name, 404) user_list = self._user_dao.get_list_by_project( project_name=project_name, filter_name=filter_name, filter_value=filter_value, start_index=start_index, max_number=max_number) user_total_count = self._user_dao.get_count_by_project( project_name=project_name, filter_name=filter_name, filter_value=filter_value) return user_total_count, user_list
def device_keepalive(self, device_id, params): device_conn = self._device_connections.get(device_id) if not device_conn: log.error( 'BUG: device connection not found for keepalive device <{0}>'. format(device_id)) device = self._dao.get_by_uuid(device_id) if not device: self._device_connections.pop(device_id, None) try: device_conn.force_shutdown() except Exception: log.exception( 'Failed to force shutdown {0}'.format(device_conn)) raise IVRError('Unkonw device for {0}'.format(device_conn)) device.is_online = device.STATE_ONLINE device.ltime = datetime.datetime.now() self._dao.update(device) for channel in params: self._camera_mngr.set_camera_state_by_device_channel( device.project_name, device.uuid, channel, params[channel]['is_online'])
def delete_user_by_name(self, username): with self._dao_context_mngr.context(): user = self._user_dao.get_by_username(username) if user is None: raise IVRError("Username Not Found", 404) self._user_dao.delete_by_username(username)
def stop_session(self, project_name, camera_id, session_id): session = self._dao.get_by_id(project_name, session_id) if not session: raise IVRError('session <{0}> of project <{1}> not found'.format(session_id, project_name)) self._stop_session(session)
def update(self, device): for i, d in enumerate(self._devices): if d.project_name == device.project_name and d.uuid == device.uuid: self._devices[i] = device return raise IVRError('No device "{0}" found'.format(device.uuid))
def add(self, dev): for d in self._devices: if d.uuid == dev.uuid: raise IVRError('Duplicated device UUID <{0}>'.format(dev.uuid)) self._devices.append(dev)
def rtmp_stop_publish(self, channel, stream_id): camera = self._cameras.get(channel) if not camera: raise IVRError('Channel {0} not exists'.format(channel)) camera.rtmp_stop_publish(stream_id)
def stop_rtmp_publish(self, project_name, device_id, camera_id, stream_id): device = self.get_device(project_name, device_id) if not device: raise IVRError('Device "{0}" of project "{1}" not found'.format(device_id, project_name)) if not device.is_online: raise IVRError('{0} is offline'.format(device))
def stream_factory(stream_type, camera, url, quality, **kwargs): if stream_type not in stream_type_registry: raise IVRError('Unknown stream type {0}'.format(stream_type)) return stream_type_registry[stream_type](camera, url, quality, **kwargs)
def camera_factory(camera_type, *args, **kwargs): if camera_type not in camera_type_registry: raise IVRError('Unknown camera type {0}'.format(camera_type)) return camera_type_registry[camera_type](*args, **kwargs)
def del_access_key(self, key_id): with self._dao_context_mngr.context(): access_key = self._key_dao.get_by_key_id(key_id) if access_key is None: raise IVRError("access_key Not Found", 404) self._key_dao.delete_by_key_id(key_id)
def get_key_secret(self, key_id): with self._dao_context_mngr.context(): access_key = self._key_dao.get_by_key_id(key_id) if access_key is None: raise IVRError("access_key Not Found", 404) return access_key.secret
def get_user(self, username): with self._dao_context_mngr.context(): user = self._user_dao.get_by_username(username) if user is None: raise IVRError("User Not Found", 404) return user