Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor/homescreen #182

Merged
merged 2 commits into from
Jan 30, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 26 additions & 67 deletions ovos_workshop/skills/idle_display_skill.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,17 @@
# 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 ovos_utils.log import LOG, log_deprecation
import abc
from ovos_bus_client.message import Message

from ovos_workshop.skills.base import BaseSkill
from ovos_utils.log import LOG
from ovos_workshop.skills.ovos import OVOSSkill


class IdleDisplaySkill(BaseSkill):
class IdleDisplaySkill(OVOSSkill):
"""
Base class for skills that define an idle display.
equivalent to using @resting_handler decorator in a regular OVOSSkill

Helper class for skills that define an idle display.

An idle display is what shows on a device's screen when it is not in use
by other skills. i.e. a Home Screen skill.
Expand All @@ -35,100 +36,58 @@ class IdleDisplaySkill(BaseSkill):
This base class is meant to be agnostic to the type of display.
"""

def __init__(self, *args, **kwargs):
BaseSkill.__init__(self, *args, **kwargs)
self._homescreen_entry = None

@abc.abstractmethod
def handle_idle(self):
"""
Override this method to display the idle screen.
"""
raise NotImplementedError(
"Subclass must override the handle_idle method")
raise NotImplementedError("Subclass must override the handle_idle method")

def _register_system_event_handlers(self):
"""
Defines the bus events handled in this skill and their handlers.
"""
BaseSkill._register_system_event_handlers(self)
self.add_event("mycroft.ready", self._handle_mycroft_ready)
self.add_event("homescreen.manager.activate.display",
self._display_homescreen_requested)
self.add_event("homescreen.manager.reload.list",
self._reload_homescreen_entry)
self.add_event("mycroft.skills.shutdown",
self._remove_homescreen_on_shutdown)
self._build_homescreen_entry()
super()._register_system_event_handlers()
self.add_event("homescreen.manager.activate.display", self.handle_homescreen_request)
self.add_event("homescreen.manager.reload.list", self.register_homescreen)
self.add_event("mycroft.skills.shutdown", self._remove_homescreen_on_shutdown)
self.register_homescreen()

def _handle_mycroft_ready(self, message):
"""
Shows idle screen when device is ready for use.
"""
self._show_idle_screen()
self.bus.emit(message.reply("skill.idle.displayed"))
LOG.debug("Homescreen ready")

def _show_idle_screen(self):
"""
Backwards-compat method for pre-Dinkum Mycroft Mark2 skills
"""
log_deprecation("Call `self.handle_idle()` directly", "0.1.0")
self.handle_idle()

def _build_homescreen_entry(self, message: Message = None):
def register_homescreen(self, message: Message = None):
"""
Update the internal _homescreen_entry object
for this skill and send it to the Home Screen Manager.
@param message: optional Message associated with request
"""
# get the super class this inherits from
super_class_name = "IdleDisplaySkill"
super_class_object = self.__class__.__name__
self._homescreen_entry = {"class": super_class_name,
"name": super_class_object,
"id": self.skill_id}
self._add_available_homescreen(message)

def _add_available_homescreen(self, message: Message = None):
"""
Add this skill's homescreen_entry to the Home Screen Manager.
@param message: optional Message associated with request
"""
message = message or Message("homescreen.manager.reload.list")
LOG.debug(f"Registering Homescreen {self._homescreen_entry}")
msg = message.forward("homescreen.manager.add", self._homescreen_entry)
LOG.debug(f"Registering Homescreen {self.skill_id}")
msg = message.forward("homescreen.manager.add",
{"class": "IdleDisplaySkill", # TODO - rm in ovos-gui, only for compat
"id": self.skill_id})
self.bus.emit(msg)

def _remove_homescreen(self, message: Message):
def remove_homescreen(self, message: Message):
"""
Remove this skill's homescreen_entry from the Home Screen Manager
@param message: `mycroft.skills.shutdown` message
"""
LOG.debug(f"Requesting removal of {self._homescreen_entry}")
msg = message.forward("homescreen.manager.remove", self._homescreen_entry)
LOG.debug(f"Requesting homescreen removal of {self.skill_id}")
msg = message.forward("homescreen.manager.remove",
{"id": self.skill_id})
self.bus.emit(msg)

def _reload_homescreen_entry(self, message: Message):
"""
Reload this skill's homescreen_entry and send it to the
Home Screen Manager.
@param message: `homescreen.manager.reload.list` message
"""
self._build_homescreen_entry(message)

def _remove_homescreen_on_shutdown(self, message: Message):
"""
Remove this homescreen from the Home Screen Manager if requested
@param message: `mycroft.skills.shutdown` message
"""
if message.data["id"] == self.skill_id:
self._remove_homescreen(message)
self.remove_homescreen(message)

def _display_homescreen_requested(self, message: Message):
def handle_homescreen_request(self, message: Message):
"""
Display this home screen if requested by the Home Screen Manager
@param message: `homescreen.manager.activate.display` message
"""
if message.data["homescreen_id"] == self.skill_id:
self._show_idle_screen()
self.handle_idle()
self.bus.emit(message.reply("skill.idle.displayed"))
69 changes: 38 additions & 31 deletions ovos_workshop/skills/ovos.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,6 @@ def __init__(self, name: Optional[str] = None,
self._enable_settings_manager = enable_settings_manager
self._init_event = Event()
self.name = name or self.__class__.__name__
self.resting_name = None
self.skill_id = skill_id # set by SkillLoader, guaranteed unique
self._settings_meta = None # DEPRECATED - backwards compat only
self.settings_manager = None
Expand Down Expand Up @@ -782,22 +781,45 @@ def register_resting_screen(self):
This only allows one screen and if two is registered only one
will be used.
"""
resting_name = None
for attr_name in get_non_properties(self):
method = getattr(self, attr_name)
if hasattr(method, 'resting_handler'):
self.resting_name = method.resting_handler
self.log.info(f'Registering resting screen {method} for {self.resting_name}.')

# Register for handling resting screen
self.add_event(f'{self.skill_id}.idle', method, speak_errors=False)
# Register handler for resting screen collect message
self.add_event('mycroft.mark2.collect_idle',
self._handle_collect_resting, speak_errors=False)

# Do a send at load to make sure the skill is registered
# if reloaded
self._handle_collect_resting()
break
handler = getattr(self, attr_name)
if hasattr(handler, 'resting_handler'):
resting_name = handler.resting_handler

def register(message=None):
self.log.info(f'Registering resting screen {resting_name} for {self.skill_id}.')
self.bus.emit(Message("homescreen.manager.add",
{"class": "IdleDisplaySkill", # TODO - rm in ovos-gui, only for compat
"name": resting_name,
"id": self.skill_id}))

register() # initial registering

self.add_event("homescreen.manager.reload.list", register,
speak_errors=False)

def wrapper(message):
if message.data["homescreen_id"] == self.skill_id:
handler(message)

self.add_event("homescreen.manager.activate.display", wrapper,
speak_errors=False)

def shutdown_handler(message):
if message.data["id"] == self.skill_id:
msg = message.forward("homescreen.manager.remove",
{"id": self.skill_id})
self.bus.emit(msg)

self.add_event("mycroft.skills.shutdown", shutdown_handler,
speak_errors=False)

# backwards compat listener
self.add_event(f'{self.skill_id}.idle', handler,
speak_errors=False)

return

def _start_filewatcher(self):
"""
Expand Down Expand Up @@ -1104,21 +1126,6 @@ def _handle_converse_request(self, message: Message):
{"skill_id": self.skill_id,
"result": False}))

def _handle_collect_resting(self, message: Optional[Message] = None):
"""
Handler for collect resting screen messages.

Sends info on how to trigger this skill's resting page.
"""
self.log.info('Registering resting screen')
msg = message or Message("")
message = msg.reply(
'mycroft.mark2.register_idle',
data={'name': self.resting_name, 'id': self.skill_id},
context={"skill_id": self.skill_id}
)
self.bus.emit(message)

def _handle_stop_ack(self, message: Message):
"""
Inform skills service if we want to handle stop. Individual skills
Expand Down
Loading