Skip to content

Commit

Permalink
Few fixes and others... (#21)
Browse files Browse the repository at this point in the history
Add a setting to mute the audio when going to sleep
  • Loading branch information
goldyfruit authored Apr 13, 2024
1 parent ee2b825 commit 6084b61
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 90 deletions.
38 changes: 27 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,30 +1,46 @@
# <img src='https://raw.githack.com/FortAwesome/Font-Awesome/master/svgs/solid/bed.svg' card_color='#22a7f0' width='50' height='50' style='vertical-align:bottom'/> Naptime
Put the assistant to sleep when you don't want to be disturbed

## About
Put the assistant to sleep when you don't want to be disturbed.

## About

Tell the assistant to sleep when you don't want to be disturbed in any way.
This stops all calls to Speech to Text system, guaranteeing your voice won't
be sent anywhere on an accidental activation.
This stops all calls to Speech to Text system, guaranteeing your voice won't be sent anywhere on an accidental activation.

When sleeping, the assistant will only listen locally for the wake word `Hey Mycroft, wake up`. Otherwise the system will be totally silent and won't bother you.

On a Mark 1 device this also dims the eyes.

Skill can mute the audio as well when entering into sleep mode if required.

When sleeping, the assistant will only listen locally for the wake word "Hey Mycroft,
wake up". Otherwise the system will be totally silent and won't bother you.
## Configuration

On a Mark 1 this also dims the eyes.
The skill utilizes the `~/.config/mycroft/skills/skill-ovos-naptime.openvoiceos/settings.json` file which allows you to configure this skill.

## Examples
* "Go to sleep"
* "Nap time"
* "Wake up"
```json
{
"mute": false
}
```

## Examples

- "Go to sleep"
- "Nap time"
- "Wake up"

## Credits

OpenVoiceOS (@OpenVoiceOS)
Mycroft AI (@MycroftAI)

## Category

**Daily**
Configuration

## Tags

#nap
#naptime
#sleep
Expand Down
107 changes: 60 additions & 47 deletions __init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,38 +27,45 @@ class NapTimeSkill(OVOSSkill):

@classproperty
def runtime_requirements(self):
return RuntimeRequirements(internet_before_load=False,
network_before_load=False,
gui_before_load=False,
requires_internet=False,
requires_network=False,
requires_gui=False,
no_internet_fallback=True,
no_network_fallback=True,
no_gui_fallback=True)
return RuntimeRequirements(
internet_before_load=False,
network_before_load=False,
gui_before_load=False,
requires_internet=False,
requires_network=False,
requires_gui=False,
no_internet_fallback=True,
no_network_fallback=True,
no_gui_fallback=True,
)

def initialize(self):
self.started_by_skill = False
self.sleeping = False
self.old_brightness = 30
self.add_event('mycroft.awoken', self.handle_awoken)
self.add_event('mycroft.awoken', self.mark1_wake_up_animation)
self.add_event('recognizer_loop:sleep', self.mark1_sleep_animation)
self.add_event('mycroft.awoken', self.display_waking_face)
self.add_event('recognizer_loop:sleep', self.display_sleep_face)
self.add_event("mycroft.awoken", self.handle_awoken)
self.add_event("mycroft.awoken", self.mark1_wake_up_animation)
self.add_event("recognizer_loop:sleep", self.mark1_sleep_animation)
self.add_event("mycroft.awoken", self.display_waking_face)
self.add_event("recognizer_loop:sleep", self.display_sleep_face)
self.disabled_confirm_listening = False

@property
def mute(self):
return self.settings.get("mute", False)

@property
def wake_word(self):
default = Configuration().get('listener', {}).get('wake_word')
default = Configuration().get("listener", {}).get("wake_word")
# with multiple wakewords we can't be 100% sure what the correct name is
# a device might have multiple names
# - if the wake_word is set in listener consider that the main wakeword
# - if the wake_word in listener config does not have a ww config ignore it
# - else use the first hotword that listens and is set to self.lang, assume config is ordered by priority
# - else use the first hotword that listens and is set to self.lang, assume config is
# ordered by priority
# - else use the first hotword that listens, assume config is ordered by priority

hotwords = Configuration().get('hotwords', {})
hotwords = Configuration().get("hotwords", {})
if default in hotwords:
return default

Expand All @@ -78,7 +85,7 @@ def wake_word(self):
return default

# TODO move mark1 handlers to PHAL mk1 plugin
def mark1_sleep_animation(self, message=None):
def mark1_sleep_animation(self, message: Message):
time.sleep(0.5)
# Dim and look downward to 'go to sleep'
# TODO: Get current brightness from somewhere
Expand All @@ -88,14 +95,14 @@ def mark1_sleep_animation(self, message=None):
time.sleep(0.15)
self.enclosure.eyes_look("d")

def mark1_wake_up_animation(self, message=None):
def mark1_wake_up_animation(self, message: Message):
"""Mild animation to come out of sleep from voice command.
Pop open eyes and wait a sec.
"""
self.enclosure.eyes_reset()
time.sleep(1)
self.enclosure.eyes_blink('b')
self.enclosure.eyes_blink("b")
time.sleep(1)
# brighten the rest of the way
self.enclosure.eyes_brightness(self.old_brightness)
Expand Down Expand Up @@ -128,40 +135,46 @@ def show_notification(self, content, action=None, noticetype="transient"):
transient: 'Default' displays a notification with a timeout.
sticky: displays a notification that sticks to the screen.
"""
self.bus.emit(Message("homescreen.notification.set",
data={
"sender": self.skill_id,
"text": content,
"action": action,
"type": noticetype
}))

def handle_speak(self, message):
self.bus.emit(
Message(
"homescreen.notification.set",
data={
"sender": self.skill_id,
"text": content,
"action": action,
"type": noticetype,
},
)
)

def handle_speak(self, message: Message):
if self.sleeping:
utt = message.data["utterance"]
self.show_notification(utt)

@intent_handler("naptime.intent")
def handle_go_to_sleep(self, message):
def handle_go_to_sleep(self, message: Message):
"""Sends a message to the speech client putting the listener to sleep.
If the user has been told about the waking up process five times
already, it sends a shorter message.
"""
if self.wake_word:
self.speak_dialog('going.to.sleep', {'wake_word': self.wake_word}, wait=True)
self.speak_dialog(
"going.to.sleep", {"wake_word": self.wake_word}, wait=True
)
else:
self.speak_dialog('going.to.sleep.short', wait=True)
self.speak_dialog("going.to.sleep.short", wait=True)

self.bus.emit(Message('recognizer_loop:sleep'))
self.bus.emit(Message("recognizer_loop:sleep"))
self.sleeping = True
self.started_by_skill = True
self.bus.emit(Message('mycroft.volume.mute',
data={"speak_message": False}))
if self.config_core['confirm_listening']:
if self.mute:
self.bus.emit(Message("mycroft.volume.mute"))
if self.config_core["confirm_listening"]:
self.disable_confirm_listening()

def handle_awoken(self, message):
def handle_awoken(self, message: Message):
"""Handler for the mycroft.awoken message
The message is sent when the listener hears 'Hey Mycroft, Wake Up',
Expand All @@ -174,25 +187,25 @@ def handle_awoken(self, message):
self.speak_dialog("i.am.awake", wait=True)

def awaken(self):
self.bus.emit(Message('mycroft.volume.unmute',
data={"speak_message": False}))
if self.mute:
self.bus.emit(Message("mycroft.volume.unmute"))
if self.disabled_confirm_listening:
self.enable_confirm_listening()
self.sleeping = False
self.started_by_skill = False

def disable_confirm_listening(self):
msg = Message('configuration.patch',
data={'config': {'confirm_listening': False}}
)
msg = Message(
"configuration.patch", data={"config": {"confirm_listening": False}}
)
self.bus.emit(msg)
self.disabled_confirm_listening = True
self.log.info('Disabled listen sound')
self.log.info("Disabled listen sound")

def enable_confirm_listening(self):
msg = Message('configuration.patch',
data={'config': {'confirm_listening': True}}
)
msg = Message(
"configuration.patch", data={"config": {"confirm_listening": True}}
)
self.bus.emit(msg)
self.disabled_confirm_listening = False
self.log.info('Enabled listen sound')
self.log.info("Enabled listen sound")
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
ovos-utils~=0.0, >=0.0.38
ovos_workshop~=0.0, >=0.0.15
ovos-bus-client~=0.0, >=0.0.8
ovos-bus-client~=0.0, >=0.0.8
66 changes: 35 additions & 31 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,25 @@

# below derived from github url to ensure standard skill_id
SKILL_AUTHOR, SKILL_NAME = URL.split(".com/")[-1].split("/")
SKILL_PKG = SKILL_NAME.lower().replace('-', '_')
PLUGIN_ENTRY_POINT = f'{SKILL_NAME.lower()}.{SKILL_AUTHOR.lower()}={SKILL_PKG}:{SKILL_CLAZZ}'
SKILL_PKG = SKILL_NAME.lower().replace("-", "_")
PLUGIN_ENTRY_POINT = (
f"{SKILL_NAME.lower()}.{SKILL_AUTHOR.lower()}={SKILL_PKG}:{SKILL_CLAZZ}"
)
# skill_id=package_name:SkillClass


def get_requirements(requirements_filename: str):
requirements_file = path.join(path.abspath(path.dirname(__file__)),
requirements_filename)
with open(requirements_file, 'r', encoding='utf-8') as r:
requirements_file = path.join(
path.abspath(path.dirname(__file__)), requirements_filename
)
with open(requirements_file, "r", encoding="utf-8") as r:
requirements = r.readlines()
requirements = [r.strip() for r in requirements if r.strip()
and not r.strip().startswith("#")]
if 'MYCROFT_LOOSE_REQUIREMENTS' in os.environ:
print('USING LOOSE REQUIREMENTS!')
requirements = [r.replace('==', '>=').replace('~=', '>=') for r in requirements]
requirements = [
r.strip() for r in requirements if r.strip() and not r.strip().startswith("#")
]
if "MYCROFT_LOOSE_REQUIREMENTS" in os.environ:
print("USING LOOSE REQUIREMENTS!")
requirements = [r.replace("==", ">=").replace("~=", ">=") for r in requirements]
return requirements


Expand All @@ -34,34 +38,34 @@ def find_resource_files():
package_data = ["*.json"]
for res in resource_base_dirs:
if path.isdir(path.join(base_dir, res)):
for (directory, _, files) in walk(path.join(base_dir, res)):
for directory, _, files in walk(path.join(base_dir, res)):
if files:
package_data.append(
path.join(directory.replace(base_dir, "").lstrip('/'),
'*'))
path.join(directory.replace(base_dir, "").lstrip("/"), "*")
)
return package_data


with open("README.md", "r") as f:
long_description = f.read()


def get_version():
""" Find the version of this skill"""
version_file = os.path.join(os.path.dirname(__file__), 'version.py')
"""Find the version of this skill"""
version_file = os.path.join(os.path.dirname(__file__), "version.py")
major, minor, build, alpha = (None, None, None, None)
with open(version_file) as f:
for line in f:
if 'VERSION_MAJOR' in line:
major = line.split('=')[1].strip()
elif 'VERSION_MINOR' in line:
minor = line.split('=')[1].strip()
elif 'VERSION_BUILD' in line:
build = line.split('=')[1].strip()
elif 'VERSION_ALPHA' in line:
alpha = line.split('=')[1].strip()
if "VERSION_MAJOR" in line:
major = line.split("=")[1].strip()
elif "VERSION_MINOR" in line:
minor = line.split("=")[1].strip()
elif "VERSION_BUILD" in line:
build = line.split("=")[1].strip()
elif "VERSION_ALPHA" in line:
alpha = line.split("=")[1].strip()

if ((major and minor and build and alpha) or
'# END_VERSION_BLOCK' in line):
if (major and minor and build and alpha) or "# END_VERSION_BLOCK" in line:
break
version = f"{major}.{minor}.{build}"
if int(alpha):
Expand All @@ -72,18 +76,18 @@ def get_version():
setup(
name=PYPI_NAME,
version=get_version(),
description='ovos skill plugin',
description="ovos skill plugin",
long_description=long_description,
long_description_content_type="text/markdown",
url=URL,
author='JarbasAi',
author_email='jarbasai@mailfence.com',
license='Apache-2.0',
author="JarbasAi",
author_email="jarbasai@mailfence.com",
license="Apache-2.0",
package_dir={SKILL_PKG: ""},
package_data={SKILL_PKG: find_resource_files()},
packages=[SKILL_PKG],
include_package_data=True,
install_requires=get_requirements("requirements.txt"),
keywords='ovos skill plugin',
entry_points={'ovos.plugin.skill': PLUGIN_ENTRY_POINT}
keywords="ovos skill plugin",
entry_points={"ovos.plugin.skill": PLUGIN_ENTRY_POINT},
)

0 comments on commit 6084b61

Please sign in to comment.