initial migration
This commit is contained in:
parent
31d8fdd3b1
commit
805cf3baf9
12 changed files with 370 additions and 525 deletions
|
@ -1,7 +1,7 @@
|
|||
import os
|
||||
import random
|
||||
|
||||
from ovos_local_backend.configuration import CONFIGURATION
|
||||
from ovos_backend_manager.configuration import CONFIGURATION
|
||||
from ovos_local_backend.database.metrics import JsonMetricDatabase, Metric
|
||||
from ovos_local_backend.database.wakewords import JsonWakeWordDatabase, WakeWordRecording
|
||||
from os.path import dirname
|
||||
|
|
|
@ -3,7 +3,7 @@ import os
|
|||
import requests
|
||||
from flask import Flask, request
|
||||
from oauthlib.oauth2 import WebApplicationClient
|
||||
from ovos_local_backend.database.oauth import OAuthTokenDatabase, OAuthApplicationDatabase
|
||||
from ovos_backend_manager.configuration import DB
|
||||
from pywebio.platform.flask import webio_view
|
||||
|
||||
from ovos_backend_manager.menu import start
|
||||
|
@ -23,7 +23,7 @@ def oauth_callback(oauth_id):
|
|||
params = dict(request.args)
|
||||
code = params["code"]
|
||||
|
||||
data = OAuthApplicationDatabase()[oauth_id]
|
||||
data = DB.get_oauth_app(oauth_id)
|
||||
client_id = data["client_id"]
|
||||
client_secret = data["client_secret"]
|
||||
token_endpoint = data["token_endpoint"]
|
||||
|
@ -43,8 +43,7 @@ def oauth_callback(oauth_id):
|
|||
auth=(client_id, client_secret),
|
||||
).json()
|
||||
|
||||
with OAuthTokenDatabase() as db:
|
||||
db.add_token(oauth_id, token_response)
|
||||
DB.add_oauth_token(oauth_id, token_response)
|
||||
|
||||
return params
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
from ovos_local_backend.configuration import CONFIGURATION
|
||||
from ovos_local_backend.utils.geolocate import get_location_config
|
||||
from ovos_backend_manager.configuration import CONFIGURATION
|
||||
from ovos_backend_client.api import GeolocationApi
|
||||
from pywebio.input import textarea, select, actions
|
||||
from pywebio.output import put_table, put_markdown, popup, put_code, put_image, use_scope
|
||||
|
||||
|
@ -18,7 +18,6 @@ def backend_menu(back_handler=None):
|
|||
['Device Authentication enabled', not CONFIGURATION["skip_auth"]],
|
||||
['Location override enabled', CONFIGURATION["override_location"]],
|
||||
['IP Geolocation enabled', CONFIGURATION["geolocate"]],
|
||||
['Selene Proxy enabled', CONFIGURATION["selene"]["enabled"]],
|
||||
['Default TTS', CONFIGURATION["default_tts"]],
|
||||
['Default Wake Word', CONFIGURATION["default_ww"]],
|
||||
['Default date format', CONFIGURATION["date_format"]],
|
||||
|
@ -76,7 +75,7 @@ def backend_menu(back_handler=None):
|
|||
loc = textarea("Enter an address",
|
||||
placeholder="Anywhere street Any city Nº234",
|
||||
required=True)
|
||||
data = get_location_config(loc)
|
||||
data = GeolocationApi().get_geolocation(loc)
|
||||
CONFIGURATION["default_location"] = data
|
||||
with popup(f"Default location set to: {loc}"):
|
||||
put_code(json.dumps(data, ensure_ascii=True, indent=2), "json")
|
||||
|
|
215
ovos_backend_manager/configuration.py
Normal file
215
ovos_backend_manager/configuration.py
Normal file
|
@ -0,0 +1,215 @@
|
|||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
from os.path import exists, expanduser
|
||||
|
||||
from json_database import JsonConfigXDG
|
||||
from ovos_utils.log import LOG
|
||||
from ovos_backend_client.api import DatabaseApi
|
||||
|
||||
|
||||
DEFAULT_CONFIG = {
|
||||
"lang": "en-us", # default language
|
||||
"database": "sqlite:///ovos_backend.db",
|
||||
"stt": {
|
||||
"module": "ovos-stt-plugin-server",
|
||||
"ovos-stt-plugin-server": {
|
||||
"url": "https://stt.openvoiceos.com/stt"
|
||||
}
|
||||
},
|
||||
"backend_port": 6712,
|
||||
"admin_key": "", # To enable simply set this string to something
|
||||
"skip_auth": False, # you almost certainly do not want this, only for atypical use cases such as ovos-qubes
|
||||
"default_location": {
|
||||
"city": {
|
||||
"code": "Lawrence",
|
||||
"name": "Lawrence",
|
||||
"state": {
|
||||
"code": "KS",
|
||||
"name": "Kansas",
|
||||
"country": {
|
||||
"code": "US",
|
||||
"name": "United States"
|
||||
}
|
||||
}
|
||||
},
|
||||
"coordinate": {
|
||||
"latitude": 38.971669,
|
||||
"longitude": -95.23525
|
||||
},
|
||||
"timezone": {
|
||||
"code": "America/Chicago",
|
||||
"name": "Central Standard Time",
|
||||
"dstOffset": 3600000,
|
||||
"offset": -21600000
|
||||
}
|
||||
},
|
||||
"default_ww": "hey_mycroft", # needs to be present below
|
||||
"ww_configs": { # these can be exposed in a web UI for selection
|
||||
"android": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/android.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"computer": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/computer.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"hey_chatterbox": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/hey_chatterbox.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"hey_firefox": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/hey_firefox.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"hey_k9": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/hey_k9.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"hey_kit": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/hey_kit.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"hey_moxie": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/hey_moxie.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"hey_mycroft": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/hey_mycroft.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"hey_scout": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/hey_scout.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"marvin": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/marvin.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"o_sauro": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/o_sauro.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"sheila": {"module": "ovos-ww-plugin-precise-lite",
|
||||
"model": "https://github.com/OpenVoiceOS/precise-lite-models/raw/master/wakewords/en/sheila.tflite",
|
||||
"expected_duration": 3,
|
||||
"trigger_level": 3,
|
||||
"sensitivity": 0.5
|
||||
},
|
||||
"hey_jarvis": {"module": "ovos-ww-plugin-vosk",
|
||||
"rule": "fuzzy",
|
||||
"samples": [
|
||||
"hay jarvis",
|
||||
"hey jarvis",
|
||||
"hay jarbis",
|
||||
"hey jarbis"
|
||||
]
|
||||
},
|
||||
"christopher": {"module": "ovos-ww-plugin-vosk",
|
||||
"rule": "fuzzy",
|
||||
"samples": [
|
||||
"christopher"
|
||||
]
|
||||
},
|
||||
"hey_ezra": {"module": "ovos-ww-plugin-vosk",
|
||||
"rule": "fuzzy",
|
||||
"samples": [
|
||||
"hay ezra",
|
||||
"hey ezra"
|
||||
]
|
||||
},
|
||||
"hey_ziggy": {"module": "ovos-ww-plugin-vosk",
|
||||
"rule": "fuzzy",
|
||||
"samples": [
|
||||
"hey ziggy",
|
||||
"hay ziggy"
|
||||
]
|
||||
},
|
||||
"hey_neon": {"module": "ovos-ww-plugin-vosk",
|
||||
"rule": "fuzzy",
|
||||
"samples": [
|
||||
"hey neon",
|
||||
"hay neon"
|
||||
]
|
||||
}
|
||||
},
|
||||
"default_tts": "American Male", # needs to be present below
|
||||
"tts_configs": { # these can be exposed in a web UI for selection
|
||||
"American Male": {"module": "ovos-tts-plugin-mimic2", "voice": "kusal"},
|
||||
"British Male": {"module": "ovos-tts-plugin-mimic", "voice": "ap"}
|
||||
},
|
||||
"date_format": "DMY",
|
||||
"system_unit": "metric",
|
||||
"time_format": "full",
|
||||
"geolocate": True,
|
||||
"override_location": False,
|
||||
"api_version": "v1",
|
||||
"data_path": expanduser("~"),
|
||||
"record_utterances": False,
|
||||
"record_wakewords": False,
|
||||
"microservices": {
|
||||
# if query fail, attempt to use free ovos services
|
||||
"ovos_fallback": True,
|
||||
# backend can be auto/local/ovos
|
||||
# auto == attempt local -> ovos
|
||||
"wolfram_provider": "auto",
|
||||
"weather_provider": "auto",
|
||||
# auto == OpenStreetMap default
|
||||
# valid - osm/arcgis/geocode_farm
|
||||
"geolocation_provider": "auto",
|
||||
# secret keys
|
||||
"wolfram_key": "",
|
||||
"owm_key": ""
|
||||
},
|
||||
"email": {
|
||||
"username": None,
|
||||
"password": None
|
||||
}
|
||||
}
|
||||
|
||||
CONFIGURATION = JsonConfigXDG("ovos_backend")
|
||||
if not exists(CONFIGURATION.path):
|
||||
CONFIGURATION.merge(DEFAULT_CONFIG, skip_empty=False)
|
||||
CONFIGURATION.store()
|
||||
LOG.info(f"Saved default configuration: {CONFIGURATION.path}")
|
||||
else:
|
||||
# set any new default values since file creation
|
||||
for k, v in DEFAULT_CONFIG.items():
|
||||
if k not in CONFIGURATION:
|
||||
CONFIGURATION[k] = v
|
||||
LOG.info(f"Loaded configuration: {CONFIGURATION.path}")
|
||||
|
||||
|
||||
DB = DatabaseApi(CONFIGURATION["admin_key"])
|
||||
|
|
@ -3,28 +3,25 @@ import os
|
|||
import time
|
||||
from base64 import b64encode
|
||||
|
||||
from ovos_local_backend.configuration import CONFIGURATION
|
||||
from ovos_local_backend.database.settings import DeviceDatabase
|
||||
from ovos_local_backend.database.utterances import JsonUtteranceDatabase
|
||||
from ovos_local_backend.database.wakewords import JsonWakeWordDatabase
|
||||
from pywebio.input import actions, file_upload, input_group, textarea, select
|
||||
from pywebio.output import put_text, put_code, use_scope, put_markdown, popup, put_image, put_file, put_html, \
|
||||
put_buttons, put_table
|
||||
|
||||
from ovos_backend_manager.configuration import CONFIGURATION, DB
|
||||
|
||||
def _render_ww(idx, db=None):
|
||||
db = db or JsonWakeWordDatabase()
|
||||
|
||||
def _render_ww(rec_id):
|
||||
|
||||
def on_tag(bt):
|
||||
data["tag"] = bt
|
||||
db[idx]["tag"] = bt
|
||||
db.commit()
|
||||
_render_ww(idx, db)
|
||||
DB.update_ww_recording(rec_id, tag=bt)
|
||||
_render_ww(rec_id)
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
data = db[idx] # id == db_position + 1
|
||||
data = DB.get_ww_recording(rec_id)
|
||||
data["tag"] = data.get("tag") or "untagged"
|
||||
|
||||
# TODO - get binary_data directly
|
||||
if os.path.isfile(data["path"]):
|
||||
content = open(data["path"], 'rb').read()
|
||||
html = f"""
|
||||
|
@ -50,72 +47,73 @@ def _render_ww(idx, db=None):
|
|||
|
||||
def ww_select(back_handler=None, uuid=None, ww=None):
|
||||
buttons = []
|
||||
db = JsonWakeWordDatabase()
|
||||
if not len(db):
|
||||
if not len(DB.list_ww_recordings()):
|
||||
with use_scope("main_view", clear=True):
|
||||
put_text("No wake words uploaded yet!")
|
||||
datasets_menu(back_handler=back_handler)
|
||||
return
|
||||
|
||||
for m in db:
|
||||
for m in DB.list_ww_recordings():
|
||||
if uuid is not None and m["uuid"] != uuid:
|
||||
continue
|
||||
if ww is not None and m["transcription"] != ww:
|
||||
continue
|
||||
name = f"{m['wakeword_id']}-{m['transcription']}"
|
||||
buttons.append({'label': name, 'value': m['wakeword_id']})
|
||||
name = f"{m['recording_id']}-{m['transcription']}"
|
||||
buttons.append({'label': name, 'value': m['recording_id']})
|
||||
|
||||
if len(buttons) == 0:
|
||||
with use_scope("main_view", clear=True):
|
||||
put_text("No wake words uploaded from this device yet!")
|
||||
opt = "main"
|
||||
else:
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
opt = actions(label="Select a WakeWord recording",
|
||||
buttons=buttons)
|
||||
if opt == "main":
|
||||
ww_menu(back_handler=back_handler)
|
||||
return
|
||||
|
||||
_render_ww(opt - 1, db)
|
||||
elif back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
|
||||
ww_select(back_handler=back_handler, ww=ww, uuid=uuid)
|
||||
rec_id = actions(label="Select a WakeWord recording", buttons=buttons)
|
||||
|
||||
if rec_id == "main": # go back
|
||||
ww_menu(back_handler=back_handler)
|
||||
else:
|
||||
_render_ww(rec_id)
|
||||
ww_select(back_handler=back_handler, ww=ww, uuid=uuid)
|
||||
|
||||
|
||||
def utt_select(back_handler=None, uuid=None, utt=None):
|
||||
buttons = []
|
||||
db = JsonUtteranceDatabase()
|
||||
if not len(db):
|
||||
if not len(DB.list_stt_recordings()):
|
||||
with use_scope("main_view", clear=True):
|
||||
put_text("No utterances uploaded yet!")
|
||||
datasets_menu(back_handler=back_handler)
|
||||
return
|
||||
|
||||
for m in db:
|
||||
for m in DB.list_stt_recordings():
|
||||
if uuid is not None and m["uuid"] != uuid:
|
||||
continue
|
||||
if utt is not None and m["transcription"] != utt:
|
||||
continue
|
||||
name = f"{m['utterance_id']}-{m['transcription']}"
|
||||
buttons.append({'label': name, 'value': m['utterance_id']})
|
||||
name = f"{m['recording_id']}-{m['transcription']}"
|
||||
buttons.append({'label': name, 'value': m['recording_id']})
|
||||
|
||||
if len(buttons) == 0:
|
||||
with use_scope("main_view", clear=True):
|
||||
put_text("No utterances uploaded from this device yet!")
|
||||
opt = "main"
|
||||
utt_menu(back_handler=back_handler)
|
||||
return
|
||||
else:
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
opt = actions(label="Select a Utterance recording",
|
||||
buttons=buttons)
|
||||
if opt == "main":
|
||||
utt_menu(back_handler=back_handler)
|
||||
return
|
||||
rec_id = actions(label="Select a Utterance recording",
|
||||
buttons=buttons)
|
||||
if rec_id == "main":
|
||||
utt_menu(back_handler=back_handler)
|
||||
return
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
data = db[opt - 1] # id == db_position + 1
|
||||
# opt is recording_id
|
||||
data = DB.get_stt_recording(rec_id)
|
||||
put_code(json.dumps(data, indent=4), "json")
|
||||
# TODO - get binary data from api
|
||||
if os.path.isfile(data["path"]):
|
||||
content = open(data["path"], 'rb').read()
|
||||
html = f"""<audio controls src="data:audio/x-wav;base64,{b64encode(content).decode('ascii')}" />"""
|
||||
|
@ -128,8 +126,8 @@ def utt_select(back_handler=None, uuid=None, utt=None):
|
|||
|
||||
|
||||
def device_select(back_handler=None, ww=True):
|
||||
devices = {uuid: f"{device['name']}@{device['device_location']}"
|
||||
for uuid, device in DeviceDatabase().items()}
|
||||
devices = {device["uuid"]: f"{device['name']}@{device['device_location']}"
|
||||
for device in DB.list_devices()}
|
||||
buttons = [{'label': "All Devices", 'value': "all"},
|
||||
{'label': "Unknown Devices", 'value': "AnonDevice"}] + \
|
||||
[{'label': d, 'value': uuid} for uuid, d in devices.items()]
|
||||
|
@ -159,7 +157,7 @@ def device_select(back_handler=None, ww=True):
|
|||
|
||||
|
||||
def ww_opts(back_handler=None, uuid=None):
|
||||
wws = list(set([ww["transcription"] for ww in JsonWakeWordDatabase()]))
|
||||
wws = list(set([ww["transcription"] for ww in DB.list_ww_recordings()]))
|
||||
buttons = [{'label': "All Wake Words", 'value': "all"}] + \
|
||||
[{'label': ww, 'value': ww} for ww in wws]
|
||||
if back_handler:
|
||||
|
@ -180,7 +178,7 @@ def ww_opts(back_handler=None, uuid=None):
|
|||
|
||||
|
||||
def utt_opts(back_handler=None, uuid=None):
|
||||
utts = list(set([ww["transcription"] for ww in JsonUtteranceDatabase()]))
|
||||
utts = list(set([ww["transcription"] for ww in DB.list_stt_recordings()]))
|
||||
buttons = [{'label': "All Utterances", 'value': "all"}] + \
|
||||
[{'label': ww, 'value': ww} for ww in utts]
|
||||
if back_handler:
|
||||
|
@ -200,9 +198,7 @@ def utt_opts(back_handler=None, uuid=None):
|
|||
utt_menu(back_handler=back_handler)
|
||||
|
||||
|
||||
def _render_ww_tagger(selected_idx, selected_wws, db=None, untagged_only=False):
|
||||
db = db or JsonWakeWordDatabase()
|
||||
|
||||
def _render_ww_tagger(selected_idx, selected_wws, untagged_only=False):
|
||||
def on_tag(tag):
|
||||
nonlocal selected_idx, selected_wws
|
||||
|
||||
|
@ -219,21 +215,19 @@ def _render_ww_tagger(selected_idx, selected_wws, db=None, untagged_only=False):
|
|||
return on_tag(tag) # recurse
|
||||
|
||||
elif selected_idx is not None:
|
||||
db_id = selected_wws[selected_idx]["wakeword_id"]
|
||||
db[db_id]["tag"] = selected_wws[selected_idx]["tag"] = tag
|
||||
db.commit()
|
||||
db_id = selected_wws[selected_idx]["recording_id"]
|
||||
DB.update_ww_recording(db_id, tag=tag)
|
||||
|
||||
_render_ww_tagger(selected_idx, selected_wws, db, untagged_only=untagged_only)
|
||||
_render_ww_tagger(selected_idx, selected_wws, untagged_only=untagged_only)
|
||||
|
||||
def on_gender(tag):
|
||||
nonlocal selected_idx, selected_wws
|
||||
|
||||
if selected_idx is not None:
|
||||
db_id = selected_wws[selected_idx]["wakeword_id"]
|
||||
db[db_id]["speaker_type"] = selected_wws[selected_idx]["speaker_type"] = tag
|
||||
db.commit()
|
||||
db_id = selected_wws[selected_idx]["recording_id"]
|
||||
DB.update_ww_recording(db_id, speaker_type=tag)
|
||||
|
||||
_render_ww_tagger(selected_idx, selected_wws, db, untagged_only=untagged_only)
|
||||
_render_ww_tagger(selected_idx, selected_wws, untagged_only=untagged_only)
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
content = open(selected_wws[selected_idx]["path"], 'rb').read()
|
||||
|
@ -258,8 +252,6 @@ def ww_tagger(back_handler=None, selected_wws=None, selected_idx=None, untagged_
|
|||
img = open(f'{os.path.dirname(__file__)}/res/wakewords.png', 'rb').read()
|
||||
put_image(img)
|
||||
|
||||
db = JsonWakeWordDatabase()
|
||||
|
||||
def get_next_untagged():
|
||||
nonlocal selected_idx
|
||||
if untagged_only:
|
||||
|
@ -271,7 +263,7 @@ def ww_tagger(back_handler=None, selected_wws=None, selected_idx=None, untagged_
|
|||
selected_idx = 0
|
||||
|
||||
if not selected_wws:
|
||||
wws = set([w["transcription"] for w in db
|
||||
wws = set([w["transcription"] for w in DB.list_ww_recordings()
|
||||
if os.path.isfile(w["path"])])
|
||||
if not len(wws):
|
||||
with use_scope("main_view", clear=True):
|
||||
|
@ -279,7 +271,7 @@ def ww_tagger(back_handler=None, selected_wws=None, selected_idx=None, untagged_
|
|||
datasets_menu(back_handler=back_handler)
|
||||
return
|
||||
current_ww = select("Target WW", wws)
|
||||
selected_wws = [w for w in db
|
||||
selected_wws = [w for w in DB.list_ww_recordings()
|
||||
if w["transcription"] == current_ww
|
||||
and os.path.isfile(w["path"])]
|
||||
selected_idx = 0
|
||||
|
@ -296,7 +288,7 @@ def ww_tagger(back_handler=None, selected_wws=None, selected_idx=None, untagged_
|
|||
if "speaker_type" not in ww:
|
||||
selected_wws[idx]["speaker_type"] = "untagged"
|
||||
|
||||
_render_ww_tagger(selected_idx, selected_wws, db, untagged_only)
|
||||
_render_ww_tagger(selected_idx, selected_wws, untagged_only)
|
||||
|
||||
buttons = [
|
||||
{'label': "Show all recordings" if untagged_only else 'Show untagged only', 'value': "toggle"},
|
||||
|
@ -326,10 +318,9 @@ def ww_tagger(back_handler=None, selected_wws=None, selected_idx=None, untagged_
|
|||
for ww in selected_wws:
|
||||
if os.path.isfile(ww["path"]):
|
||||
os.remove(ww["path"])
|
||||
dbid = db.get_item_id(ww)
|
||||
if dbid >= 0:
|
||||
db.remove_item(dbid)
|
||||
db.commit()
|
||||
|
||||
rec_id = current_ww # TODO - rec_id
|
||||
DB.delete_ww_recording(rec_id)
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_text(f"{current_ww} database deleted!")
|
||||
|
@ -382,11 +373,9 @@ def ww_menu(back_handler=None):
|
|||
os.makedirs(f"{CONFIGURATION['data_path']}/wakewords", exist_ok=True)
|
||||
|
||||
uuid = "AnonDevice" # TODO - allow tagging to a device
|
||||
wav_path = f"{CONFIGURATION['data_path']}/wakewords/{name}.{filename}"
|
||||
meta_path = f"{CONFIGURATION['data_path']}/wakewords/{name}.{filename}.meta"
|
||||
|
||||
meta = {
|
||||
"transcription": name,
|
||||
"path": wav_path,
|
||||
"meta": {
|
||||
"name": name,
|
||||
"time": time.time(),
|
||||
|
@ -397,12 +386,8 @@ def ww_menu(back_handler=None):
|
|||
},
|
||||
"uuid": uuid
|
||||
}
|
||||
with JsonWakeWordDatabase() as db:
|
||||
db.add_wakeword(name, wav_path, meta, uuid)
|
||||
with open(wav_path, "wb") as f:
|
||||
f.write(content)
|
||||
with open(meta_path, "w") as f:
|
||||
json.dump(meta, f)
|
||||
rec = DB.add_ww_recording(byte_data=content, transcription=name, metadata=meta)
|
||||
|
||||
with popup("wake word uploaded!"):
|
||||
put_code(json.dumps(meta, indent=4), "json")
|
||||
|
||||
|
@ -415,15 +400,13 @@ def ww_menu(back_handler=None):
|
|||
buttons=[{'label': "yes", 'value': True},
|
||||
{'label': "no", 'value': False}])
|
||||
if opt:
|
||||
# remove ww files from path
|
||||
db = JsonWakeWordDatabase()
|
||||
for ww in db:
|
||||
if os.path.isfile(ww["path"]):
|
||||
os.remove(ww["path"])
|
||||
# remove db itself
|
||||
os.remove(db.db.path)
|
||||
|
||||
for rec in DB.list_ww_recordings():
|
||||
DB.delete_ww_recording(rec_id=rec["recording_id"])
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_text("wake word database deleted!")
|
||||
|
||||
datasets_menu(back_handler=back_handler)
|
||||
return
|
||||
if opt == "main":
|
||||
|
@ -469,18 +452,12 @@ def utt_menu(back_handler=None):
|
|||
os.makedirs(f"{CONFIGURATION['data_path']}/utterances", exist_ok=True)
|
||||
|
||||
uuid = "AnonDevice" # TODO - allow tagging to a device
|
||||
path = f"{CONFIGURATION['data_path']}/utterances/{utterance}.{filename}"
|
||||
|
||||
meta = {
|
||||
"transcription": utterance,
|
||||
"path": path,
|
||||
"uuid": uuid
|
||||
}
|
||||
with JsonUtteranceDatabase() as db:
|
||||
db.add_utterance(utterance, path, uuid)
|
||||
|
||||
with open(path, "wb") as f:
|
||||
f.write(content)
|
||||
DB.add_stt_recording(content, utterance, meta)
|
||||
|
||||
with popup("utterance recording uploaded!"):
|
||||
put_code(json.dumps(meta, indent=4), "json")
|
||||
|
@ -494,8 +471,10 @@ def utt_menu(back_handler=None):
|
|||
buttons=[{'label': "yes", 'value': True},
|
||||
{'label': "no", 'value': False}])
|
||||
if opt:
|
||||
# TODO - also remove files from path
|
||||
os.remove(JsonUtteranceDatabase().db.path)
|
||||
|
||||
for rec in DB.list_stt_recordings():
|
||||
DB.delete_stt_recording(rec["recording_id"])
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_text("utterance database deleted!")
|
||||
datasets_menu(back_handler=back_handler)
|
||||
|
|
|
@ -3,10 +3,9 @@ import os
|
|||
import time
|
||||
from uuid import uuid4
|
||||
|
||||
from ovos_local_backend.configuration import CONFIGURATION
|
||||
from ovos_local_backend.database.settings import DeviceDatabase
|
||||
from ovos_local_backend.utils import generate_code
|
||||
from ovos_local_backend.utils.geolocate import get_location_config
|
||||
from ovos_backend_manager.configuration import CONFIGURATION, DB
|
||||
import random
|
||||
from ovos_backend_client.api import GeolocationApi
|
||||
from pywebio.input import textarea, select, actions, checkbox
|
||||
from pywebio.output import put_text, put_table, put_markdown, popup, put_code, use_scope, put_image
|
||||
|
||||
|
@ -52,14 +51,12 @@ def device_menu(uuid, back_handler=None):
|
|||
['Time Format', d.time_format],
|
||||
['System Unit', d.system_unit],
|
||||
['Opt In', d.opt_in],
|
||||
['Selene Blocked', uuid in CONFIGURATION["selene"]["opt_in_blacklist"]],
|
||||
['Lang', d.lang],
|
||||
['Default Wake Word', d.default_ww],
|
||||
['Default Voice', d.default_tts]
|
||||
])
|
||||
|
||||
db = DeviceDatabase()
|
||||
device = db.get_device(uuid)
|
||||
device = DB.get_device(uuid)
|
||||
if device:
|
||||
y = False
|
||||
opt = actions(label="What would you like to do?",
|
||||
|
@ -77,74 +74,63 @@ def device_menu(uuid, back_handler=None):
|
|||
buttons=[{'label': "yes", 'value': True},
|
||||
{'label': "no", 'value': False}])
|
||||
if y:
|
||||
db.delete_device(uuid)
|
||||
db.store()
|
||||
DB.delete_device(uuid)
|
||||
elif opt == "opt-in":
|
||||
opt_in = checkbox("Open Dataset - device metrics and speech recordings",
|
||||
[{'label': 'Store metrics and recordings',
|
||||
'selected': device.opt_in,
|
||||
'value': "opt_in"},
|
||||
{'label': 'Block Selene sharing',
|
||||
'selected': uuid in CONFIGURATION["selene"]["opt_in_blacklist"],
|
||||
'value': "blacklist"}])
|
||||
'value': "opt_in"}])
|
||||
|
||||
device["opt_in"] = "opt_in" in opt_in
|
||||
|
||||
device.opt_in = "opt_in" in opt_in
|
||||
if "blacklist" in opt_in:
|
||||
if uuid not in CONFIGURATION["selene"]["opt_in_blacklist"]:
|
||||
CONFIGURATION["selene"]["opt_in_blacklist"].append(uuid)
|
||||
CONFIGURATION.store()
|
||||
else:
|
||||
if uuid in CONFIGURATION["selene"]["opt_in_blacklist"]:
|
||||
CONFIGURATION["selene"]["opt_in_blacklist"].remove(uuid)
|
||||
CONFIGURATION.store()
|
||||
elif opt == "tts":
|
||||
tts = select("Choose a voice",
|
||||
list(CONFIGURATION["tts_configs"].keys()))
|
||||
device.default_tts = CONFIGURATION["tts_configs"][tts]["module"]
|
||||
device.default_tts_cfg = CONFIGURATION["tts_configs"][tts]
|
||||
device["default_tts"] = CONFIGURATION["tts_configs"][tts]["module"]
|
||||
device["default_tts_cfg"] = CONFIGURATION["tts_configs"][tts]
|
||||
elif opt == "ww":
|
||||
ww = select("Choose a wake word",
|
||||
list(CONFIGURATION["ww_configs"].keys()))
|
||||
device.default_ww = ww
|
||||
device.default_ww_cfg = CONFIGURATION["ww_configs"][ww]
|
||||
device["default_ww"] = ww
|
||||
device["default_ww_cfg"] = CONFIGURATION["ww_configs"][ww]
|
||||
elif opt == "date":
|
||||
date = select("Change date format",
|
||||
['DMY', 'MDY'])
|
||||
device.date_format = date
|
||||
device["date_format"] = date
|
||||
elif opt == "time":
|
||||
tim = select("Change time format",
|
||||
['full', 'short'])
|
||||
device.time_format = tim
|
||||
device["time_format"] = tim
|
||||
elif opt == "unit":
|
||||
unit = select("Change system units",
|
||||
['metric', 'imperial'])
|
||||
device.system_unit = unit
|
||||
device["system_unit"] = unit
|
||||
elif opt == "email":
|
||||
email = textarea("Enter your device email",
|
||||
placeholder="notify@me.com",
|
||||
required=True)
|
||||
device.email = email
|
||||
device["email"] = email
|
||||
elif opt == "name":
|
||||
name = textarea("Enter your device name",
|
||||
placeholder="OVOS Mark2",
|
||||
required=True)
|
||||
device.name = name
|
||||
device["name"] = name
|
||||
elif opt == "location":
|
||||
loc = textarea("Enter your device placement",
|
||||
placeholder="kitchen",
|
||||
required=True)
|
||||
device.device_location = loc
|
||||
device["device_location"] = loc
|
||||
elif opt == "geo":
|
||||
loc = textarea("Enter an address",
|
||||
placeholder="Anywhere street Any city Nº234",
|
||||
required=True)
|
||||
data = get_location_config(loc)
|
||||
device.location = data
|
||||
data = GeolocationApi().get_geolocation(loc)
|
||||
device["location"] = data
|
||||
elif opt == "identity":
|
||||
identity = {"uuid": device.uuid,
|
||||
identity = {"uuid": device["uuid"],
|
||||
"expires_at": time.time() + 99999999999999,
|
||||
"accessToken": device.token,
|
||||
"refreshToken": device.token}
|
||||
"accessToken": device["token"],
|
||||
"refreshToken": device["token"]}
|
||||
with use_scope("main_view", clear=True):
|
||||
put_markdown(f'### identity2.json')
|
||||
put_code(json.dumps(identity, indent=4), "json")
|
||||
|
@ -154,8 +140,7 @@ def device_menu(uuid, back_handler=None):
|
|||
update_info(device, False)
|
||||
|
||||
if opt not in ["identity", "delete", "view_loc"]:
|
||||
db.update_device(device)
|
||||
db.store()
|
||||
DB.update_device(**device)
|
||||
popup("Device updated!")
|
||||
elif opt == "delete" and y:
|
||||
uuid = None
|
||||
|
@ -172,8 +157,8 @@ def device_select(back_handler=None):
|
|||
img = open(f'{os.path.dirname(__file__)}/res/devices.png', 'rb').read()
|
||||
put_image(img)
|
||||
|
||||
devices = {uuid: f"{device['name']}@{device['device_location']}"
|
||||
for uuid, device in DeviceDatabase().items()}
|
||||
devices = {device["uuid"]: f"{device['name']}@{device['device_location']}"
|
||||
for device in DB.list_devices()}
|
||||
buttons = [{'label': d, 'value': uuid} for uuid, d in devices.items()] + \
|
||||
[{'label': 'Delete device database', 'value': "delete_devices"}]
|
||||
if back_handler:
|
||||
|
@ -195,7 +180,9 @@ def device_select(back_handler=None):
|
|||
buttons=[{'label': "yes", 'value': True},
|
||||
{'label': "no", 'value': False}])
|
||||
if opt:
|
||||
os.remove(DeviceDatabase().path)
|
||||
for dev in DB.list_devices():
|
||||
DB.delete_device(dev["uuid"])
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
if back_handler:
|
||||
back_handler()
|
||||
|
@ -218,11 +205,11 @@ def instant_pair(back_handler=None):
|
|||
put_image(img)
|
||||
|
||||
uuid = str(uuid4())
|
||||
code = generate_code()
|
||||
code = f"{random.randint(100, 999)}ABC"
|
||||
token = f"{code}:{uuid}"
|
||||
|
||||
# add device to db
|
||||
with DeviceDatabase() as db:
|
||||
db.add_device(uuid, token)
|
||||
DB.add_device(uuid, token)
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_markdown("# Device paired!")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from ovos_local_backend.configuration import CONFIGURATION
|
||||
from ovos_backend_manager.configuration import CONFIGURATION
|
||||
from pywebio.input import textarea, actions
|
||||
from pywebio.output import put_text, popup, use_scope, put_image
|
||||
|
||||
|
@ -8,7 +8,6 @@ from ovos_backend_manager.devices import device_select, instant_pair
|
|||
from ovos_backend_manager.metrics import metrics_menu
|
||||
from ovos_backend_manager.microservices import microservices_menu
|
||||
from ovos_backend_manager.oauth import oauth_menu
|
||||
from ovos_backend_manager.selene import selene_menu
|
||||
|
||||
|
||||
def main_menu():
|
||||
|
@ -24,8 +23,7 @@ def main_menu():
|
|||
{'label': 'Manage Datasets', 'value': "db"},
|
||||
{'label': 'OAuth Applications', 'value': "oauth"},
|
||||
{'label': 'Configure Backend', 'value': "backend"},
|
||||
{'label': 'Configure Microservices', 'value': "services"},
|
||||
{'label': 'Configure Selene Proxy', 'value': "selene"}])
|
||||
{'label': 'Configure Microservices', 'value': "services"}])
|
||||
if opt == "pair":
|
||||
instant_pair(back_handler=main_menu)
|
||||
elif opt == "services":
|
||||
|
@ -36,8 +34,6 @@ def main_menu():
|
|||
datasets_menu(back_handler=main_menu)
|
||||
elif opt == "backend":
|
||||
backend_menu(back_handler=main_menu)
|
||||
elif opt == "selene":
|
||||
selene_menu(back_handler=main_menu)
|
||||
elif opt == "device":
|
||||
device_select(back_handler=main_menu)
|
||||
elif opt == "metrics":
|
||||
|
|
|
@ -3,10 +3,8 @@ import os
|
|||
import time
|
||||
|
||||
from cutecharts.charts import Pie, Bar, Scatter
|
||||
from ovos_local_backend.database.metrics import JsonMetricDatabase
|
||||
from ovos_local_backend.database.settings import DeviceDatabase
|
||||
from ovos_local_backend.database.utterances import JsonUtteranceDatabase
|
||||
from ovos_local_backend.database.wakewords import JsonWakeWordDatabase
|
||||
|
||||
from ovos_backend_manager.configuration import CONFIGURATION, DB
|
||||
from pywebio.input import actions
|
||||
from pywebio.output import put_text, popup, put_code, put_markdown, put_html, use_scope, put_image
|
||||
|
||||
|
@ -14,8 +12,8 @@ chart_type = Pie
|
|||
|
||||
|
||||
def device_select(back_handler=None):
|
||||
devices = {uuid: f"{device['name']}@{device['device_location']}"
|
||||
for uuid, device in DeviceDatabase().items()}
|
||||
devices = {device["uuid"]: f"{device['name']}@{device['device_location']}"
|
||||
for device in DB.list_devices()}
|
||||
buttons = [{'label': "All Devices", 'value': "all"}] + \
|
||||
[{'label': d, 'value': uuid} for uuid, d in devices.items()]
|
||||
if back_handler:
|
||||
|
@ -41,29 +39,29 @@ def device_select(back_handler=None):
|
|||
|
||||
def metrics_select(back_handler=None, uuid=None):
|
||||
buttons = []
|
||||
db = JsonMetricDatabase()
|
||||
if not len(db):
|
||||
metrics = DB.list_metrics()
|
||||
if not len(metrics):
|
||||
with use_scope("main_view", clear=True):
|
||||
put_text("No metrics uploaded yet!")
|
||||
metrics_menu(back_handler=back_handler, uuid=uuid)
|
||||
return
|
||||
|
||||
for m in db:
|
||||
for m in metrics:
|
||||
name = f"{m['metric_id']}-{m['metric_type']}"
|
||||
if uuid is not None and m["uuid"] != uuid:
|
||||
continue
|
||||
buttons.append({'label': name, 'value': m['metric_id']})
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
opt = actions(label="Select a metric to inspect",
|
||||
metric_id = actions(label="Select a metric to inspect",
|
||||
buttons=buttons)
|
||||
if opt == "main":
|
||||
if metric_id == "main":
|
||||
device_select(back_handler=back_handler)
|
||||
return
|
||||
# id == db_position + 1
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_markdown("# Metadata")
|
||||
put_code(json.dumps(db[opt - 1], indent=4), "json")
|
||||
put_code(json.dumps(metric_id, indent=4), "json")
|
||||
metrics_select(back_handler=back_handler, uuid=uuid)
|
||||
|
||||
|
||||
|
@ -167,8 +165,8 @@ def _plot_metrics(uuid, selected_metric="types"):
|
|||
md = ""
|
||||
if uuid is None:
|
||||
md = f"""# Open Dataset Report
|
||||
Total Registered Devices: {len(DeviceDatabase())}
|
||||
Currently Opted-in: {len([d for d in DeviceDatabase() if d.opt_in])}
|
||||
Total Registered Devices: {len(DB.list_devices())}
|
||||
Currently Opted-in: {len([d for d in DB.list_devices() if d["opt_in"]])}
|
||||
Unique Devices seen: {m.total_devices}"""
|
||||
|
||||
# Open Dataset Report"""
|
||||
|
@ -239,7 +237,9 @@ def metrics_menu(back_handler=None, uuid=None, selected_metric="types"):
|
|||
buttons=[{'label': "yes", 'value': True},
|
||||
{'label': "no", 'value': False}])
|
||||
if opt:
|
||||
os.remove(JsonMetricDatabase().db.path)
|
||||
for m in DB.list_metrics():
|
||||
DB.delete_metric(m["metric_id"])
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
if back_handler:
|
||||
back_handler()
|
||||
|
@ -264,10 +264,10 @@ class MetricsReportGenerator:
|
|||
self.total_fallbacks = 0
|
||||
self.total_stt = 0
|
||||
self.total_tts = 0
|
||||
self.total_ww = len(JsonWakeWordDatabase())
|
||||
self.total_utt = len(JsonUtteranceDatabase())
|
||||
self.total_devices = len(DeviceDatabase())
|
||||
self.total_metrics = len(JsonMetricDatabase())
|
||||
self.total_ww = len(DB.list_ww_recordings())
|
||||
self.total_utt = len(DB.list_stt_recordings())
|
||||
self.total_devices = len(DB.list_devices())
|
||||
self.total_metrics = len(DB.list_metrics())
|
||||
|
||||
self.intents = {}
|
||||
self.fallbacks = {}
|
||||
|
@ -289,10 +289,10 @@ class MetricsReportGenerator:
|
|||
self.total_fallbacks = 0
|
||||
self.total_stt = 0
|
||||
self.total_tts = 0
|
||||
self.total_ww = len(JsonWakeWordDatabase())
|
||||
self.total_metrics = len(JsonMetricDatabase())
|
||||
self.total_utt = len(JsonUtteranceDatabase())
|
||||
self.total_ww = len(DB.list_ww_recordings())
|
||||
self.total_utt = len(DB.list_stt_recordings())
|
||||
self.total_devices = 0
|
||||
self.total_metrics = len(DB.list_metrics())
|
||||
|
||||
self.intents = {}
|
||||
self.devices = {}
|
||||
|
@ -309,11 +309,11 @@ class MetricsReportGenerator:
|
|||
|
||||
def load_metrics(self):
|
||||
self.reset_metrics()
|
||||
for m in JsonMetricDatabase():
|
||||
for m in DB.list_metrics():
|
||||
if m["uuid"] not in self.devices:
|
||||
self.total_devices += 1
|
||||
self._process_metric(m)
|
||||
for ww in JsonWakeWordDatabase():
|
||||
for ww in DB.list_ww_recordings():
|
||||
if ww["meta"]["name"] not in self.ww:
|
||||
self.ww[ww["meta"]["name"]] = 0
|
||||
else:
|
||||
|
@ -333,7 +333,7 @@ class MetricsReportGenerator:
|
|||
|
||||
@property
|
||||
def untracked_devices(self):
|
||||
return [dev.uuid for dev in DeviceDatabase() if not dev.opt_in]
|
||||
return [dev["uuid"] for dev in DB.list_devices() if not dev["opt_in"]]
|
||||
|
||||
# cute charts
|
||||
def timings_chart(self):
|
||||
|
@ -577,18 +577,18 @@ class DeviceMetricsReportGenerator(MetricsReportGenerator):
|
|||
def load_metrics(self):
|
||||
self.reset_metrics()
|
||||
|
||||
self.total_ww = len([ww for ww in JsonWakeWordDatabase()
|
||||
self.total_ww = len([ww for ww in DB.list_ww_recordings()
|
||||
if ww["uuid"] == self.uuid])
|
||||
self.total_metrics = 0
|
||||
self.total_utt = len([utt for utt in JsonUtteranceDatabase()
|
||||
self.total_utt = len([utt for utt in DB.list_stt_recordings()
|
||||
if utt["uuid"] == self.uuid])
|
||||
|
||||
for m in JsonMetricDatabase():
|
||||
for m in DB.list_metrics():
|
||||
if m["uuid"] != self.uuid:
|
||||
continue
|
||||
self._process_metric(m)
|
||||
self.total_metrics += 1
|
||||
for ww in JsonWakeWordDatabase():
|
||||
for ww in DB.list_ww_recordings():
|
||||
if ww["uuid"] != self.uuid:
|
||||
continue
|
||||
if ww["meta"]["name"] not in self.ww:
|
||||
|
@ -598,5 +598,5 @@ class DeviceMetricsReportGenerator(MetricsReportGenerator):
|
|||
|
||||
|
||||
if __name__ == "__main__":
|
||||
for ww in JsonWakeWordDatabase():
|
||||
for ww in DB.list_ww_recordings():
|
||||
print(ww)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
from ovos_local_backend.configuration import CONFIGURATION
|
||||
from ovos_backend_manager.configuration import CONFIGURATION
|
||||
from ovos_plugin_manager.stt import get_stt_configs, get_stt_supported_langs, get_stt_lang_configs
|
||||
from pywebio.input import select, actions, input_group, input, TEXT, NUMBER
|
||||
from pywebio.output import put_text, put_table, popup, put_code, put_image, use_scope
|
||||
|
@ -11,8 +11,7 @@ def _get_stt_opts(lang=None):
|
|||
STT_CONFIGS = {}
|
||||
if lang is not None:
|
||||
for p, data in get_stt_lang_configs(lang, include_dialects=True).items():
|
||||
if p == "ovos-stt-plugin-selene" and \
|
||||
not CONFIGURATION["selene"].get("enabled"):
|
||||
if p == "ovos-stt-plugin-selene":
|
||||
continue
|
||||
if not data:
|
||||
continue
|
||||
|
@ -22,8 +21,7 @@ def _get_stt_opts(lang=None):
|
|||
STT_CONFIGS[cfg["display_name"]] = cfg
|
||||
else:
|
||||
for p, data in get_stt_configs().items():
|
||||
if p == "ovos-stt-plugin-selene" and \
|
||||
not CONFIGURATION["selene"].get("enabled"):
|
||||
if p == "ovos-stt-plugin-selene":
|
||||
continue
|
||||
if not data:
|
||||
continue
|
||||
|
@ -40,8 +38,6 @@ def microservices_menu(back_handler=None):
|
|||
img = open(f'{os.path.dirname(__file__)}/res/microservices_config.png', 'rb').read()
|
||||
put_image(img)
|
||||
|
||||
selene = CONFIGURATION["selene"]["enabled"]
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_table([
|
||||
['STT module', CONFIGURATION["stt"]["module"]],
|
||||
|
@ -49,12 +45,7 @@ def microservices_menu(back_handler=None):
|
|||
|
||||
['WolframAlpha provider', CONFIGURATION["microservices"]["wolfram_provider"]],
|
||||
['Weather provider', CONFIGURATION["microservices"]["weather_provider"]],
|
||||
['Geolocation provider', CONFIGURATION["microservices"]["geolocation_provider"]],
|
||||
|
||||
['Selene WolframAlpha proxy enabled', selene and CONFIGURATION["selene"]["proxy_wolfram"]],
|
||||
['Selene OpenWeatherMap proxy enabled', selene and CONFIGURATION["selene"]["proxy_weather"]],
|
||||
['Selene Geolocation proxy enabled', selene and CONFIGURATION["selene"]["proxy_geolocation"]],
|
||||
['Selene Email proxy enabled', selene and CONFIGURATION["selene"]["proxy_email"]]
|
||||
['Geolocation provider', CONFIGURATION["microservices"]["geolocation_provider"]]
|
||||
])
|
||||
|
||||
buttons = [{'label': 'Configure STT', 'value': "stt"},
|
||||
|
@ -79,8 +70,6 @@ def microservices_menu(back_handler=None):
|
|||
return
|
||||
elif opt == "geo":
|
||||
opts = ["OpenStreetMap", "ArcGIS", "Geocode Farm"] # TODO - ovos endpoint
|
||||
if selene and CONFIGURATION["selene"]["proxy_geolocation"]:
|
||||
opts.append("Selene")
|
||||
provider = select("Choose a weather provider", opts)
|
||||
if provider == "OpenStreetMap":
|
||||
provider = "osm"
|
||||
|
@ -89,16 +78,12 @@ def microservices_menu(back_handler=None):
|
|||
opts = ["ovos"]
|
||||
if CONFIGURATION["microservices"]["owm_key"]:
|
||||
opts.append("local")
|
||||
if selene and CONFIGURATION["selene"]["proxy_weather"]:
|
||||
opts.append("selene")
|
||||
provider = select("Choose a weather provider", opts)
|
||||
CONFIGURATION["microservices"]["weather_provider"] = provider
|
||||
elif opt == "wolfram":
|
||||
opts = ["ovos"]
|
||||
if CONFIGURATION["microservices"]["wolfram_key"]:
|
||||
opts.append("local")
|
||||
if selene and CONFIGURATION["selene"]["proxy_wolfram"]:
|
||||
opts.append("selene")
|
||||
provider = select("Choose a WolframAlpha provider", opts)
|
||||
CONFIGURATION["microservices"]["wolfram_provider"] = provider
|
||||
elif opt == "ovos":
|
||||
|
@ -133,7 +118,6 @@ def microservices_menu(back_handler=None):
|
|||
CONFIGURATION["microservices"]["owm_key"] = data["owm"]
|
||||
popup("Secrets updated!")
|
||||
elif opt == "smtp":
|
||||
# TODO - checkbox for selene proxy
|
||||
# TODO - ovos endpoint
|
||||
|
||||
if "smtp" not in CONFIGURATION["email"]:
|
||||
|
|
|
@ -2,8 +2,7 @@ import json
|
|||
import os
|
||||
|
||||
from oauthlib.oauth2 import WebApplicationClient
|
||||
from ovos_local_backend.configuration import CONFIGURATION
|
||||
from ovos_local_backend.database.oauth import OAuthApplicationDatabase, OAuthTokenDatabase
|
||||
from ovos_backend_manager.configuration import CONFIGURATION, DB
|
||||
from pywebio.input import actions, input_group, input, TEXT
|
||||
from pywebio.output import use_scope, popup, put_image, put_link, put_code, put_text, put_table, put_markdown
|
||||
|
||||
|
@ -11,7 +10,7 @@ from pywebio.output import use_scope, popup, put_image, put_link, put_code, put_
|
|||
def get_oauth_data(app_id=None):
|
||||
data = {}
|
||||
if app_id:
|
||||
data = OAuthApplicationDatabase().get(app_id)
|
||||
data = DB.get_oauth_app(app_id)
|
||||
data = data or {'auth_endpoint': "https://",
|
||||
'token_endpoint': "https://",
|
||||
'refresh_endpoint': "https://"}
|
||||
|
@ -56,7 +55,7 @@ def authorize_app(data):
|
|||
|
||||
def _render_app(app_id):
|
||||
with use_scope("main_view", clear=True):
|
||||
data = OAuthApplicationDatabase()[app_id]
|
||||
data = DB.get_oauth_app(app_id)
|
||||
|
||||
put_markdown(f'# {app_id.title()}')
|
||||
put_table([
|
||||
|
@ -83,7 +82,7 @@ def app_menu(app_id, back_handler=None):
|
|||
buttons = [
|
||||
{'label': "Configure", 'value': "oauth"},
|
||||
]
|
||||
tok = OAuthTokenDatabase().get(app_id)
|
||||
tok = DB.get_oauth_token(app_id)
|
||||
if tok:
|
||||
buttons.append({'label': "View Token", 'value': "token"})
|
||||
buttons.append({'label': "Refresh Token", 'value': "refresh"})
|
||||
|
@ -103,22 +102,17 @@ def app_menu(app_id, back_handler=None):
|
|||
with popup("OAuth Token"):
|
||||
put_code(json.dumps(tok, indent=4), language="json")
|
||||
elif opt == "auth" or opt == "refresh": # TODO special refresh handling (?)
|
||||
data = OAuthApplicationDatabase()[app_id]
|
||||
data = DB.get_oauth_app(app_id)
|
||||
authorize_app(data)
|
||||
elif opt == "oauth":
|
||||
data = get_oauth_data(app_id)
|
||||
|
||||
with OAuthApplicationDatabase() as db:
|
||||
db[data["oauth_service"]] = data
|
||||
|
||||
app_id = data.pop("oauth_service")
|
||||
DB.update_oauth_app(app_id, **data)
|
||||
with popup(app_id):
|
||||
put_text(f"{app_id} oauth settings updated!")
|
||||
|
||||
elif opt == "delete":
|
||||
db = OAuthApplicationDatabase()
|
||||
if app_id in db:
|
||||
db.pop(app_id)
|
||||
db.store()
|
||||
DB.delete_oauth_app(app_id)
|
||||
with popup(app_id):
|
||||
put_text(f"{app_id} oauth settings deleted!")
|
||||
oauth_menu(back_handler=back_handler)
|
||||
|
@ -138,8 +132,10 @@ def oauth_menu(back_handler=None):
|
|||
pass
|
||||
|
||||
buttons = [{'label': 'New App', 'value': "new"}]
|
||||
for app, data in OAuthApplicationDatabase().items():
|
||||
buttons.append({'label': app, 'value': app})
|
||||
for app in DB.list_oauth_apps():
|
||||
app_id = app.pop("token_id")
|
||||
data = app
|
||||
buttons.append({'label': app_id, 'value': data})
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
|
||||
|
@ -147,15 +143,8 @@ def oauth_menu(back_handler=None):
|
|||
buttons=buttons)
|
||||
if opt == "new":
|
||||
data = get_oauth_data()
|
||||
|
||||
with OAuthApplicationDatabase() as db:
|
||||
db.add_application(data["oauth_service"],
|
||||
data["client_id"],
|
||||
data["client_secret"],
|
||||
data["auth_endpoint"],
|
||||
data["token_endpoint"],
|
||||
data["refresh_endpoint"],
|
||||
data["scope"])
|
||||
app_id = data.pop("oauth_service")
|
||||
DB.add_oauth_app(app_id, **data)
|
||||
|
||||
authorize_app(data)
|
||||
|
||||
|
|
|
@ -1,303 +0,0 @@
|
|||
import json
|
||||
import os
|
||||
|
||||
from ovos_local_backend.configuration import CONFIGURATION
|
||||
from pywebio.input import actions, file_upload, input_group, textarea
|
||||
from pywebio.output import put_table, popup, use_scope, put_image, put_markdown, put_code
|
||||
|
||||
|
||||
def pairing_menu(back_handler=None):
|
||||
version = CONFIGURATION["selene"]["version"]
|
||||
host = CONFIGURATION["selene"]["url"]
|
||||
ident = CONFIGURATION["selene"]["identity_file"]
|
||||
paired = os.path.exists(ident)
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_markdown("# Status")
|
||||
put_table([
|
||||
['Enabled', CONFIGURATION["selene"]["enabled"]],
|
||||
['Host', host],
|
||||
['Version', version],
|
||||
['Identity', ident],
|
||||
['Paired', paired],
|
||||
['Proxy Pairing Enabled', CONFIGURATION["selene"]["proxy_pairing"]]
|
||||
])
|
||||
if os.path.isfile(ident):
|
||||
with open(ident) as f:
|
||||
content = f.read()
|
||||
|
||||
put_markdown("# Identity")
|
||||
put_code(content, "json")
|
||||
|
||||
buttons = [{'label': 'Upload identity2.json', 'value': "upload"},
|
||||
{'label': 'Paste identity2.json', 'value': "paste"}]
|
||||
if os.path.isfile(ident):
|
||||
buttons.append({'label': 'Delete identity2.json', 'value': "delete"})
|
||||
|
||||
label = "Enable Proxy Pairing" if not CONFIGURATION["selene"]["proxy_pairing"] else "Disable Proxy Pairing"
|
||||
buttons.append({'label': label, 'value': "proxy"})
|
||||
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
|
||||
opt = actions(label="What would you like to do?", buttons=buttons)
|
||||
if opt == "main":
|
||||
selene_menu(back_handler=back_handler)
|
||||
return
|
||||
elif opt == "delete":
|
||||
with use_scope("main_view", clear=True):
|
||||
if os.path.isfile(ident):
|
||||
os.remove(ident)
|
||||
popup("Identity deleted!")
|
||||
else:
|
||||
popup("Identity does not exist!")
|
||||
elif opt == "upload":
|
||||
with use_scope("main_view", clear=True):
|
||||
data = input_group("Upload identity", [
|
||||
file_upload("identity file", name="file")
|
||||
])
|
||||
mime = data["file"]["mime_type"]
|
||||
content = data["file"]["content"]
|
||||
if mime != "application/json":
|
||||
popup("invalid format!")
|
||||
else:
|
||||
os.makedirs(os.path.dirname(ident), exist_ok=True)
|
||||
with open(ident, "wb") as f:
|
||||
f.write(content)
|
||||
with popup("Identity uploaded!"):
|
||||
put_code(content.decode("utf-8"), "json")
|
||||
elif opt == "paste":
|
||||
with use_scope("main_view", clear=True):
|
||||
dummy = """{
|
||||
"uuid": "31628fa1-dbfd-4626-aaa2-1464dd204715",
|
||||
"expires_at": 100001663862051.53,
|
||||
"accessToken": "8YI3NQ:31628fa1-dbfd-4626-aaa2-1464dd204715",
|
||||
"refreshToken": "8YI3NQ:31628fa1-dbfd-4626-aaa2-1464dd204715"
|
||||
}
|
||||
"""
|
||||
data = textarea("identity2.json", placeholder=dummy, required=True)
|
||||
with open(ident, "w") as f:
|
||||
f.write(data)
|
||||
with popup("Identity updated!"):
|
||||
put_code(data, "json")
|
||||
elif opt == "proxy":
|
||||
CONFIGURATION["selene"]["proxy_pairing"] = not CONFIGURATION["selene"]["proxy_pairing"]
|
||||
CONFIGURATION.store()
|
||||
pairing_menu(back_handler=back_handler)
|
||||
|
||||
|
||||
def account_menu(back_handler=None):
|
||||
version = CONFIGURATION["selene"]["version"]
|
||||
host = CONFIGURATION["selene"]["url"]
|
||||
ident = CONFIGURATION["selene"]["identity_file"]
|
||||
paired = os.path.exists(ident)
|
||||
uuid = None
|
||||
if paired:
|
||||
with open(ident) as f:
|
||||
uuid = json.load(f)["uuid"]
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_markdown("# Account")
|
||||
put_table([
|
||||
['Selene UUID', uuid],
|
||||
['Download Location', CONFIGURATION["selene"]["download_location"]],
|
||||
['Download Preferences', CONFIGURATION["selene"]["download_prefs"]],
|
||||
['Download Skill Settings', CONFIGURATION["selene"]["download_settings"]],
|
||||
['Upload Skill Settings', CONFIGURATION["selene"]["upload_settings"]],
|
||||
['Force 2 way Skill Settings sync', CONFIGURATION["selene"]["force2way"]]
|
||||
])
|
||||
|
||||
buttons = []
|
||||
label = "Enable Location Download" if not CONFIGURATION["selene"][
|
||||
"download_location"] else "Disable Location Download"
|
||||
buttons.append({'label': label, 'value': "location"})
|
||||
label = "Enable Preferences Download" if not CONFIGURATION["selene"][
|
||||
"download_prefs"] else "Disable Preferences Download"
|
||||
buttons.append({'label': label, 'value': "prefs"})
|
||||
label = "Enable SkillSettings Download" if not CONFIGURATION["selene"][
|
||||
"download_settings"] else "Disable SkillSettings Download"
|
||||
buttons.append({'label': label, 'value': "download_settings"})
|
||||
label = "Enable SkillSettings Upload" if not CONFIGURATION["selene"][
|
||||
"upload_settings"] else "Disable SkillSettings Upload"
|
||||
buttons.append({'label': label, 'value': "upload_settings"})
|
||||
label = "Enable forced 2way sync" if not CONFIGURATION["selene"]["force2way"] else "Disable forced 2way sync"
|
||||
buttons.append({'label': label, 'value': "2way"})
|
||||
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
|
||||
opt = actions(label="What would you like to do?", buttons=buttons)
|
||||
|
||||
if opt == "main":
|
||||
selene_menu(back_handler=back_handler)
|
||||
return
|
||||
elif opt == "location":
|
||||
CONFIGURATION["selene"]["download_location"] = not CONFIGURATION["selene"]["download_location"]
|
||||
elif opt == "prefs":
|
||||
CONFIGURATION["selene"]["download_prefs"] = not CONFIGURATION["selene"]["download_prefs"]
|
||||
elif opt == "download_settings":
|
||||
CONFIGURATION["selene"]["download_settings"] = not CONFIGURATION["selene"]["download_settings"]
|
||||
elif opt == "upload_settings":
|
||||
CONFIGURATION["selene"]["upload_settings"] = not CONFIGURATION["selene"]["upload_settings"]
|
||||
elif opt == "2way":
|
||||
CONFIGURATION["selene"]["force2way"] = not CONFIGURATION["selene"]["force2way"]
|
||||
|
||||
CONFIGURATION.store()
|
||||
account_menu(back_handler=back_handler)
|
||||
|
||||
|
||||
def integrations_menu(back_handler=None):
|
||||
version = CONFIGURATION["selene"]["version"]
|
||||
host = CONFIGURATION["selene"]["url"]
|
||||
ident = CONFIGURATION["selene"]["identity_file"]
|
||||
paired = os.path.exists(ident)
|
||||
uuid = None
|
||||
if paired:
|
||||
with open(ident) as f:
|
||||
uuid = json.load(f)["uuid"]
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_markdown("# Integrations")
|
||||
put_table([
|
||||
['Selene UUID', uuid],
|
||||
['Weather Enabled', CONFIGURATION["selene"]["proxy_weather"]],
|
||||
['WolframAlpha Enabled', CONFIGURATION["selene"]["proxy_wolfram"]],
|
||||
['Geolocation Enabled', CONFIGURATION["selene"]["proxy_geolocation"]],
|
||||
['Email Enabled', CONFIGURATION["selene"]["proxy_email"]]
|
||||
])
|
||||
|
||||
buttons = []
|
||||
label = "Enable Weather Proxy" if not CONFIGURATION["selene"]["proxy_weather"] else "Disable Weather Proxy"
|
||||
buttons.append({'label': label, 'value': "weather"})
|
||||
label = "Enable WolframAlpha Proxy" if not CONFIGURATION["selene"][
|
||||
"proxy_wolfram"] else "Disable WolframAlpha Proxy"
|
||||
buttons.append({'label': label, 'value': "wolfram"})
|
||||
label = "Enable Geolocation Proxy" if not CONFIGURATION["selene"][
|
||||
"proxy_geolocation"] else "Disable Geolocation Proxy"
|
||||
buttons.append({'label': label, 'value': "geolocation"})
|
||||
label = "Enable Email Proxy" if not CONFIGURATION["selene"]["proxy_email"] else "Disable Email Proxy"
|
||||
buttons.append({'label': label, 'value': "email"})
|
||||
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
|
||||
opt = actions(label="What would you like to do?", buttons=buttons)
|
||||
|
||||
if opt == "main":
|
||||
selene_menu(back_handler=back_handler)
|
||||
return
|
||||
elif opt == "geolocation":
|
||||
CONFIGURATION["selene"]["proxy_geolocation"] = not CONFIGURATION["selene"]["proxy_geolocation"]
|
||||
elif opt == "weather":
|
||||
CONFIGURATION["selene"]["proxy_weather"] = not CONFIGURATION["selene"]["proxy_weather"]
|
||||
elif opt == "wolfram":
|
||||
CONFIGURATION["selene"]["proxy_wolfram"] = not CONFIGURATION["selene"]["proxy_wolfram"]
|
||||
elif opt == "email":
|
||||
CONFIGURATION["selene"]["proxy_email"] = not CONFIGURATION["selene"]["proxy_email"]
|
||||
|
||||
CONFIGURATION.store()
|
||||
integrations_menu(back_handler=back_handler)
|
||||
|
||||
|
||||
def dataset_menu(back_handler=None):
|
||||
version = CONFIGURATION["selene"]["version"]
|
||||
host = CONFIGURATION["selene"]["url"]
|
||||
ident = CONFIGURATION["selene"]["identity_file"]
|
||||
paired = os.path.exists(ident)
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_markdown("# Open Dataset")
|
||||
put_table([
|
||||
['Opt In', CONFIGURATION["selene"]["opt_in"]],
|
||||
['Upload Metrics', CONFIGURATION["selene"]["upload_metrics"]],
|
||||
['Upload Wake Words', CONFIGURATION["selene"]["upload_wakewords"]],
|
||||
['Upload Utterances', CONFIGURATION["selene"]["upload_utterances"]]
|
||||
])
|
||||
|
||||
buttons = []
|
||||
label = "Enable Open Dataset Opt In" if not CONFIGURATION["selene"]["opt_in"] else "Disable Open Dataset Opt In"
|
||||
buttons.append({'label': label, 'value': "opt_in"})
|
||||
label = "Enable Metrics Upload" if not CONFIGURATION["selene"]["upload_metrics"] else "Disable Metrics Upload"
|
||||
buttons.append({'label': label, 'value': "metrics"})
|
||||
label = "Enable Wake Words Upload" if not CONFIGURATION["selene"][
|
||||
"upload_wakewords"] else "Disable Wake Words Upload"
|
||||
buttons.append({'label': label, 'value': "ww"})
|
||||
label = "Enable Utterances Upload" if not CONFIGURATION["selene"][
|
||||
"upload_utterances"] else "Disable Utterances Upload"
|
||||
buttons.append({'label': label, 'value': "stt"})
|
||||
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
|
||||
opt = actions(label="What would you like to do?", buttons=buttons)
|
||||
|
||||
if opt == "main":
|
||||
selene_menu(back_handler=back_handler)
|
||||
return
|
||||
elif opt == "opt_in":
|
||||
CONFIGURATION["selene"]["opt_in"] = not CONFIGURATION["selene"]["opt_in"]
|
||||
elif opt == "selene":
|
||||
CONFIGURATION["selene"]["enabled"] = not CONFIGURATION["selene"]["enabled"]
|
||||
elif opt == "stt":
|
||||
CONFIGURATION["selene"]["upload_utterances"] = not CONFIGURATION["selene"]["upload_utterances"]
|
||||
elif opt == "ww":
|
||||
CONFIGURATION["selene"]["upload_wakewords"] = not CONFIGURATION["selene"]["upload_wakewords"]
|
||||
elif opt == "metrics":
|
||||
CONFIGURATION["selene"]["upload_metrics"] = not CONFIGURATION["selene"]["upload_metrics"]
|
||||
|
||||
CONFIGURATION.store()
|
||||
dataset_menu(back_handler=back_handler)
|
||||
|
||||
|
||||
def selene_menu(back_handler=None):
|
||||
version = CONFIGURATION["selene"]["version"]
|
||||
host = CONFIGURATION["selene"]["url"]
|
||||
ident = CONFIGURATION["selene"]["identity_file"]
|
||||
paired = os.path.exists(ident)
|
||||
|
||||
with use_scope("logo", clear=True):
|
||||
img = open(f'{os.path.dirname(__file__)}/res/selene_proxy.png', 'rb').read()
|
||||
put_image(img)
|
||||
|
||||
with use_scope("main_view", clear=True):
|
||||
put_markdown("# Status")
|
||||
put_table([
|
||||
['Enabled', CONFIGURATION["selene"]["enabled"]],
|
||||
['Host', host]
|
||||
])
|
||||
|
||||
buttons = [{'label': 'Manage Identity', 'value': "pair"},
|
||||
{'label': 'Manage Account', 'value': "account"},
|
||||
{'label': 'Manage Integrations', 'value': "integrations"},
|
||||
{'label': 'Manage Open Dataset', 'value': "dataset"}]
|
||||
|
||||
if CONFIGURATION["selene"]["enabled"]:
|
||||
buttons.insert(0, {'label': "Disable Selene", 'value': "selene"})
|
||||
else:
|
||||
buttons.insert(0, {'label': "Enable Selene", 'value': "selene"})
|
||||
if back_handler:
|
||||
buttons.insert(0, {'label': '<- Go Back', 'value': "main"})
|
||||
|
||||
opt = actions(label="What would you like to do?", buttons=buttons)
|
||||
if opt == "main":
|
||||
with use_scope("main_view", clear=True):
|
||||
if back_handler:
|
||||
back_handler()
|
||||
return
|
||||
elif opt == "pair":
|
||||
pairing_menu(back_handler=back_handler)
|
||||
return
|
||||
elif opt == "account":
|
||||
account_menu(back_handler=back_handler)
|
||||
return
|
||||
elif opt == "integrations":
|
||||
integrations_menu(back_handler=back_handler)
|
||||
return
|
||||
elif opt == "dataset":
|
||||
dataset_menu(back_handler=back_handler)
|
||||
return
|
||||
elif opt == "selene":
|
||||
CONFIGURATION["selene"]["enabled"] = not CONFIGURATION["selene"]["enabled"]
|
||||
CONFIGURATION.store()
|
||||
|
||||
selene_menu(back_handler=back_handler)
|
|
@ -1,3 +1,3 @@
|
|||
pywebio
|
||||
ovos-local-backend>=0.1.5a2
|
||||
ovos-backend-client
|
||||
cutecharts
|
Loading…
Add table
Reference in a new issue