added state api
This commit is contained in:
@@ -30,6 +30,7 @@ api_group = Namespace('group', description="Group management namespace", authori
|
||||
api_permissions = Namespace('permissions', description="Permissions management namespace", authorizations=api_authorizations)
|
||||
api_room = Namespace('room', description="Room management namespace", authorizations=api_authorizations)
|
||||
api_recorder = Namespace('recorder', description="Recorder management namespace", authorizations=api_authorizations)
|
||||
api_state = Namespace('state', description="Object state management namespace", authorizations=api_authorizations)
|
||||
api_virtual_command = Namespace('virtual_command', description="Virtual command namespace",
|
||||
authorizations=api_authorizations)
|
||||
api_cron_job = Namespace('cron_job', description="Cron job namespace",
|
||||
@@ -42,6 +43,7 @@ api_v1.add_namespace(api_group)
|
||||
api_v1.add_namespace(api_permissions)
|
||||
api_v1.add_namespace(api_room)
|
||||
api_v1.add_namespace(api_recorder)
|
||||
api_v1.add_namespace(api_state)
|
||||
api_v1.add_namespace(api_virtual_command)
|
||||
api_v1.add_namespace(api_cron_job)
|
||||
api_v1.add_namespace(api_control)
|
||||
@@ -64,6 +66,7 @@ from .permission_api import *
|
||||
from .group_api import *
|
||||
from .room_api import *
|
||||
from .recorder_api import *
|
||||
from .state_api import *
|
||||
from .control_api import *
|
||||
from .virtual_command_api import *
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
from flask_restx import fields
|
||||
from backend.api import api_user, api_recorder, api_v1
|
||||
from backend.api import api_user, api_recorder, api_v1, api_state
|
||||
|
||||
generic_id_parser = api_v1.parser()
|
||||
generic_id_parser.add_argument('id', type=str, required=True, store_missing=False)
|
||||
@@ -102,3 +102,6 @@ recorder_model_model = api_recorder.model('Recorder Model', {
|
||||
description='Model of the recorder.'),
|
||||
'commands': fields.List(fields.Nested(recorder_command_model), attribute="recorder_commands")
|
||||
})
|
||||
|
||||
state_model = api_state.model('Recorder', {
|
||||
})
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to authentication through the API.
|
||||
For example: listing of available auth providers or registration of users.
|
||||
|
||||
Login through API does not start a new session, but instead returns JWT.
|
||||
This module provides functions related to recorders through the API.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from pprint import pprint
|
||||
|
||||
48
backend/api/state_api.py
Normal file
48
backend/api/state_api.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# Copyright (c) 2019. Tobias Kurze
|
||||
"""
|
||||
This module provides functions related to object states through the API.
|
||||
"""
|
||||
from datetime import datetime
|
||||
from pprint import pprint
|
||||
|
||||
from flask_jwt_extended import jwt_required
|
||||
from flask_restx import fields, Resource, inputs
|
||||
|
||||
from backend import db, app
|
||||
from backend.api import api_state
|
||||
from backend.api.models import recorder_model, recorder_model_model, recorder_command_model, state_model
|
||||
from backend.models.recorder_model import Recorder, RecorderModel, RecorderCommand
|
||||
from backend.models.room_model import Room
|
||||
import backend.recorder_adapters as r_a
|
||||
|
||||
|
||||
# ==
|
||||
|
||||
@api_state.route('/<int:id>')
|
||||
@api_state.response(404, 'Recorder not found')
|
||||
@api_state.param('id', 'The recorder identifier')
|
||||
class RecorderStateResource(Resource):
|
||||
@jwt_required
|
||||
@api_state.doc('get_recorder_state')
|
||||
@api_state.marshal_with(state_model, skip_none=False)
|
||||
def get(self, id):
|
||||
"""Fetch a recorder given its identifier"""
|
||||
recorder = Recorder.query.get(id)
|
||||
if recorder is None:
|
||||
api_state.abort(404)
|
||||
return recorder
|
||||
|
||||
|
||||
|
||||
|
||||
@api_state.route('')
|
||||
class RecorderStateList(Resource):
|
||||
@jwt_required
|
||||
@api_state.doc('recorders')
|
||||
@api_state.marshal_list_with(recorder_model, skip_none=False)
|
||||
def get(self):
|
||||
"""
|
||||
List all recorders
|
||||
:return: recorders
|
||||
"""
|
||||
return Recorder.get_all()
|
||||
@@ -47,6 +47,9 @@ def add_default_jobs(sched=None, testing=False):
|
||||
check_recorder_state_job = sched.add_job(recorder_checker.check_object_state, 'interval', minutes=2,
|
||||
id="check_recorder_state_job")
|
||||
|
||||
"""
|
||||
Job regularly sending the state to "frontend recorders" through websocket
|
||||
"""
|
||||
send_update_state_to_recorder_job = sched.add_job(
|
||||
lambda: send_state_update_to_recorders(recorder_checker.get_current_state()), 'interval', minutes=1,
|
||||
id="send_update_state_to_recorder_job")
|
||||
|
||||
@@ -22,6 +22,11 @@ T = TypeVar('T')
|
||||
|
||||
|
||||
class StateChecker(Generic[T]):
|
||||
"""
|
||||
This class is designed generically to regularly check the state of objects with given function(s).
|
||||
The determined state is stored "locally" in the state checker object and NOT reflected back to the checked objects!
|
||||
It can be retrieved by calling get_current_state.
|
||||
"""
|
||||
def __init__(self, state_checker_func: Union[Callable, List[Callable]], type_to_check: T, type_name=None,
|
||||
threads=NUM_THREADS):
|
||||
self.num_threads = threads
|
||||
@@ -135,7 +140,6 @@ class StateChecker(Generic[T]):
|
||||
'previous': {'state_ok': self.state_results[o_s]['state_ok'],
|
||||
'msg': self.state_results[o_s].get('msg', None),
|
||||
'time_stamp': self.state_results[o_s].get('time_stamp', None)}}
|
||||
pass
|
||||
else:
|
||||
self.state_results[o_s] = object_states[o_s]
|
||||
|
||||
|
||||
@@ -38,8 +38,6 @@ rec_err_state_log_stream_handler.setLevel(logging.WARNING)
|
||||
logger.addHandler(rec_err_state_log_stream_handler)
|
||||
#logger.addHandler(mem_handler)
|
||||
|
||||
base_url = "https://opencast.bibliothek.kit.edu"
|
||||
|
||||
session = requests.session()
|
||||
session.auth = HTTPBasicAuth(Config.OPENCAST_USER, Config.OPENCAST_PW)
|
||||
|
||||
@@ -55,7 +53,7 @@ def get_service_url(service_type: str):
|
||||
if service_type in config['service_urls']:
|
||||
return config['service_urls'][service_type]
|
||||
params = {'serviceType': service_type}
|
||||
url = base_url + "/services/available.json"
|
||||
url = Config.OPENCAST_URL + "/services/available.json"
|
||||
res = session.get(url, params=params)
|
||||
if res.ok:
|
||||
service = res.json()["services"]["service"]
|
||||
@@ -135,6 +133,7 @@ def check_stream_sanity(recorder: Recorder, recorder_adapter: RecorderAdapter):
|
||||
|
||||
for i in range(0, Config.STREAM_SANITY_CHECK_RETRIES):
|
||||
do_checks = False
|
||||
|
||||
if do_checks:
|
||||
return True
|
||||
else:
|
||||
@@ -224,7 +223,6 @@ if __name__ == '__main__':
|
||||
for a in agents:
|
||||
agent_states[a.get('name')] = 'PROBLEMATIC - unknown'
|
||||
|
||||
|
||||
# pool = ThreadPool(5)
|
||||
# pool.map(check_capture_agent_state, agents)
|
||||
|
||||
@@ -239,7 +237,6 @@ if __name__ == '__main__':
|
||||
except TimeoutError as e:
|
||||
logger.error("Timeout while pinging capture agent! {}".format(e))
|
||||
|
||||
|
||||
with ThreadPool(NUM_THREADS) as pool:
|
||||
results = [pool.apply_async(check_capture_agent_state, (agent,)) for agent in agents]
|
||||
try:
|
||||
|
||||
@@ -9,29 +9,6 @@ from pydub import AudioSegment
|
||||
from pydub.playback import play
|
||||
|
||||
|
||||
def old_test():
|
||||
file_name = tempfile.gettempdir() + os.path.sep + "test.jpg"
|
||||
print(file_name)
|
||||
if os.path.exists(file_name):
|
||||
os.remove(file_name)
|
||||
process = (
|
||||
ffmpeg
|
||||
.input('rtsp://172.22.246.207/extron1')
|
||||
# .input('rtsp://172.22.246.207/extron3')
|
||||
.output(file_name, vframes=1)
|
||||
# .output('-', format='h264')
|
||||
.run(capture_stdout=True)
|
||||
)
|
||||
image = Image.open(file_name)
|
||||
r, g, b = image.split()
|
||||
print(r.histogram())
|
||||
print(g.histogram())
|
||||
print(b.histogram())
|
||||
image.show()
|
||||
|
||||
|
||||
# old_test()
|
||||
|
||||
def is_single_color_image(image):
|
||||
single_color_image = True
|
||||
color = {}
|
||||
@@ -97,7 +74,7 @@ def check_if_audio_is_valid(stream_url, sample_length_sec=3, lower_alert_limit_d
|
||||
|
||||
sound = AudioSegment.from_file(file_name, "aac")
|
||||
# print(sound.dBFS)
|
||||
play(sound)
|
||||
#play(sound)
|
||||
if sound.max_dBFS == -float('inf'):
|
||||
return False, "No active audio signal detected!"
|
||||
elif sound.max_dBFS < lower_alert_limit_dBFS:
|
||||
@@ -115,9 +92,14 @@ def check_if_audio_is_valid(stream_url, sample_length_sec=3, lower_alert_limit_d
|
||||
else:
|
||||
return False, msg
|
||||
|
||||
|
||||
print(check_if_audio_is_valid('rtsp://172.22.246.207/extron1'))
|
||||
|
||||
|
||||
"""
|
||||
Following code is not working correctly - ffmpeg parameters are wrong.
|
||||
"""
|
||||
"""
|
||||
def check_if_audio_is_valid_stream(stream_url, raise_errors=True):
|
||||
audio, _ = (
|
||||
ffmpeg
|
||||
@@ -130,3 +112,4 @@ def check_if_audio_is_valid_stream(stream_url, raise_errors=True):
|
||||
play(sound)
|
||||
|
||||
# check_if_audio_is_valid('rtsp://172.22.246.207/extron1')
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user