The message returned is a dict of all available audio backends as keys
containing 'supported_uris' listing supported uri types (file:// http://
etc.), 'remote' (bool) True if remote), 'default' (bool) true if the
default audio backend.
Revert "Fix a couple of minor issues intruduced by skill_gid (#2079)"
This reverts commit e046377ce1.
Revert "Merge pull request #2075 from forslund/bugfix/msm_wrapper-license"
This reverts commit 18cfbce0ca, reversing
changes made to 82fa314ce9.
Revert "Feature/skillsmeta gid (#2074)"
This reverts commit 82fa314ce9.
* Fix skill_gid for modified skills
Used the old '_' after device uuid
* Identify skill using gid
When receiving data from server the "identifier" entry is now removed and in it's stead the skill_gid should be used.
This also removes the "fetch other settings" functionallity since that is no longer relevant.
* Add global id basics to settings meta
- All skills will upload a blank settingsmeta
- a skill_gid will be appended to all settingsmeta upload-data
- Added basic function for generating skill_gid
* Use new skill_gid field.
Populate skill_gid directly from metadata
* Separate travis tmp-dirs
- Update travis script to use tempdir for each python version
- Update test script to handle nonstandard tempdirs
- Generate msm folder using tempdir when running create_msm test
* Add title field with pretty name
* Collect and expand "title" as needed
For title use market-place title or name in settings meta or skillname
* Switch skill_manager create_msm test to 19.02
* Remove leading / trailing Skill in display name
Also rename title displayname to match new mycroft-skills-data
* Lock msm_create and mock the name info test_settings
If no match was found for the non-normalized utterance it would jump to
the exception handler for StopIteration skipping the normalized step
altogether
This changes the next/StopIteration system for list comprehensions
Previously Padatious intent matches were performed on non-normalized text, meaning that things like "what's the weather" wouldn't match a Padatious intent but
"what is the weather" would.
The "utterance" in Adapt intent data will still be non-normalized even if the intent match occurred on a normalized utterance. Retaining the existing behavior.
The "intent_failure" data. In there, "utterance" is always the raw version, "norm_utt" is the normalized one.
Also added better debugging info for intent matching to the log.
Also addresses a rare issue with the old code where the Adapt context could
have been updated even if the Adapt intent wasn't actually invoked due to
a higher Padatious intent match.
* Add the SkillGUI method send_event()
Sends raw mycroft.events.triggered messages to the gui for the skills namespace.
Example usage:
self.gui.send_event('event_name' {'param1': 12, 'param2': 'abc'})
The loose (conf > 0.5) Padatious match was previously occurring as Fallback
priority 99. The AIML fallback at priority 90 would consume lots of
utterances, interferring with many skills. Now Padatious runs at priority
89.
Additionally, added documentation of the intent and fallback system, including
guidelines for priorities.
Much of the code used "en-us" as the default value when not specified.
This limited the internationalization potential. Changing the default
to None and adds the ability to define the default lang code from other
locations in code. E.g.
```python
from mycroft.util.lang import set_default_lang
set_default_lang("en-us")
print("English date: "+nice_date(dt))
set_default_lang("de-de")
print("German date: "+nice_date(dt))
```
This allows easier localization of Skills by having the framework set the default without any changes necessary by the Skill writers.
Other minor changes:
* Changed the default return value of get_gender*() to None instead of False
* Split ADJUST into ADJUST and SET
* Use enum names instead of values.
* Add properties to CommonIoTSkill
* property -> attribute to avoid conflict with builtin
* Add increase and decrease actions
* Fix copy/paste error
Padatious was accepting fairly low confidence matches (0.5). This
would match a phrase such as "Where is the Empire State Building?" to the
intent "Where were you born?" (Which is a 0.54 match)
Now there are two passes mad on the Padatious fallback. The first is
looking for high confidence matches (> 0.8). Then other fallbacks -- such
as the CommonQuery fallbacks -- have an opportunity to consume the
utterance. If they don't consume it, Padatious is invoked again with
looser confidence before finally invoking the Unknown fallback.
Now the eyes go to a khaki color and "< < < LOADING < < <" displays
during the skill startup. When Padatious finishes the first training
we now emit a "mycroft.ready" on the messagebus.
A change to the skill_mark_1 to look for "mycroft.ready" instead of
"mycroft.skills.initialized" provides a good visual change to show that
it is ready for use.
The deprecation warning was firing off at the load of every skill when
the decorators are being iterated through by internal code (which
includes the self.config with an @property). Add check for these
special cases to not show a warning.
The scoring for CommonPlay would favor skills that responded with overly long
matches. E.g. "Huey Lewis and the News" would be considered a better fit than
just "News" for the request "Play the News"
* Deprecate self.config in skills
Skills should contain their own settings, the self.config concept is being
deprecated.
Also removed the defaults set for several old MycroftAI skills. The 19.02
version of these Skills initializes the default values using:
```python
self.settings["key"] = default
```
* Update padatious config to work with the config property.
* Add base common_iot_skill
* can_run takes IoTRequest
* Minor cleanup + documentation
* Fix pep8 issues
* Adjust scene and entity registration.
The controller skill is not guaranteed to be alive before
CommonIoTSkills, so we must call for values when it is alive, in
addition to accepting them at any time from other skills.
* Safer parsing
* Address PR feedback
* Add skill_id to register message
* Minor docstring edits
* Add remove page methods
* Implement SkillGUI.clear()
The method will now remove the namespace entirely from the gui.
This adds the message gui.clear.namespace
* Remove debug prints from SkillGUI
* Correcting docstring
* More docstring changes
* Remove whitespace added by Github webUI
* Attempt to create skill directory if not existing
* Handle missing priority skills
* Minor update of comments
* Handle skill load exception
Make sure an exception while trying to load/reload skill doesn't shutdown thread.
* Handle MsmException during SkillManager creation
If SkillManager can't be created due to an MsmException wait for network connection and retry.
* Update immediately if skill install file is missing
Missing skill install file indicates that this is a new venv and the requirements of the skills will need to be reinstalled.
* Add basic test for skill_manager
Basically only creating the skill_manager but it ensures that msm can be used on all supported python versions
* Update to pyee 5.0.0
- Update requirement
- Make the SkillSettings class hashable
* Update adapt to 0.3.2
* Upgrade websocket-client
* Remove special threading for common query
This sends a new system.update.check message when the device is booted and not paired
It is not sent every boot because the command could upgrade across major versions which the user could not want.
- Create a read_vocab_file() function that normal vocab loading and voc_match both uses. This function handles blank lines and comments
- Use a simpler regex instead of word logic to match
- Add a couple of test cases for the method
Previously the voc_match() method had several problems:
* Blank lines in the .voc file would cause it to match all strings
* Comments weren't ignored
* Substrings matched so "book" would match "ok", for instance
In the case where a network call during the initialization of the
settings poll fails the first time, it would never be tried again.
Now it will retry initialization once a minute.
The settings code worked, but was noisy and generally messy about
a few exceptional but common situations:
* When the .mycroft/skills/<SkillName> folder didn't already exist
* When network timeouts and such occcurred
I also slipped in a couple trivial code cleanups for an unused variable
and a log message.
To simplify the process of adding an idle page to a skill the decorator "resting_screen_handler" was added. In a skill class the decorator can be applied to a method to register it to handle idle.
@resting_page_handler("My Idle Page")
def handler(self, message):
...
The decorator will Register the method with the Mark-2 skill and perform all communications needed to make it work smoothly.
The wrong method was registered, instead of the wrapped function call
the original method was registered. This led to not being able to
unregister fallbacks.
* Add communication from GUI to skills
- "set" events from Qt will set/update a variable in the skills .gui member
- It's possible to add general event handlers using self.gui.register_handler()
- Moved registration of skill_id to just after skill init
* Ensure that simultaneously writes doesn't occur
Wrap WebSocketHandler.write_message() with a lock in an attempt to handle "buffererror: existing exports of data: object cannot be re-sized."
* Add better logging to help debug disconnect issue
* Allow overriding the idle page
SkillGUI.show_page() and SkillGUI.show_pages() now takes an optional
override_idle parameter. This is used as a hint by the mark-2 skill
and if possible the idle screen will not be shown.
* Improve debugging using Logger
* Raise exception when sending a non-existing gui page
* Restore running state to new connections
When a GUI is connected data and running namespaces are synchronised and
shown.
This refactors the code quite a bit moving the GUI state from the GUIConnection
object to the Enclosure.
The GUIConnection object does the handles the sync in the on_connection_open()
method.
* Add gui.page_interaction message
Currently triggered on page change on the display.
* Handle message when gui changes sessionData
* Check if socket exists on gui before sending data
* Increase port on each failure and retry
The audioservice can now jump forward and backward in the audio stream/file
The functionality is accessed via the audioservice class's seek_forward(),
seek_backward() and seek() methods
Several additions to the GUI protocol support
These changes allow switching between pages successfully with the current
mycroft-gui widget:
* Optimized commands to handle the active skill list
* MycroftSkill.gui.show_pages(list, idx) allows multiple-pages to be displayed
at a time starting with the given index visible.
* Merge SkillGUI.show_page with show_pages
This limits code duplication and makes things a bit more maintainable.
* Do not reload on changed .qmlc files
* Make EnclosureGeneric derive from Enclosure
* Update show function to match mycroft-gui-app
- adds internal representation of all loaded skills
- uses new commands to switch between pages and namespaces
* Add Extra debug output in enclosure
- Log if starting websocket fails
- Log the sending of page info in more detail
* Update GUI Debug client in CLI
- The CLI GUI now handles the new messages for switching pages
- Handle different data types better by using format instead of string concatenation
* Disable syncing code.
The sync code at startup outdated and needs to be reworked. Disabling it for now
to allow better interaction.
* Minor cleanups
- do not inherit from object
- use format instead of string concatenations
- remove duplicated self.loaded
- correct private member access
* Refactor GUIConnection.show()
Move the actions into separate methods for better overview of the logic
* Flipped "valid_file" to become "ignored_file"
Several small changes based on the code review feedback:
* Drop '_' from classes like Enclosure_Mark1
* Adopt Python 3 style for class definitions and don't explicitly list '(object)'
* Slightly better documentation
* Moved MycroftSkill.show_html() to SkillGUI, resulting in code like self.gui.show_page('Weather.qml')
* Renamed SkillGUI.__dict to SkillGUI.__session_data. This better reflects the
how values are accessed in the QML.
Adds support for negotiating best answer for a questions
Currently three levels of confidence are defined
EXACT: If the query could be identified exactly and a response is returned.
Example: The cockail skill could find a cocktail in the query that exists in
it's database.
CATEGORY: A category of questions the skill handles could be identified.
Example: The wiki-data skill can identify that the question is regarding
A date of birth and finds an answer.
GENERAL: A general question and answer service could parse the question.
Example: The wolfram alpha skill got a match for "How tall is Abraham
Lincoln".
The QML files are typically not translated like other Mycroft resources,
they have internal translation tools. And at times there are other
resources that don't need to be translated all the time, for example
color strings like "AliceBlue" which might be used by non-English
speakers.
So now the translation mechanism looks for resource file X as follows:
1) Look for <res_dir>/<lang>/X
2) Look for <res_dir>/X
3) Look for anywhere under locale/<lang>/.../X
And now the show_page() method starts looking for resources under the skill/ui folder.
Make sure the older version of the install skill will still work. The SettingsManager.load/write_skills_data() will return the version 0 format of the skills_data and the write_skills_data() will convert to the version 1 format before doing the write.
- Lock msm when doing an update
- Add device enpoint for uploading skills.json
- Add configuration value for skill store updates
- Upload skills manifest after update
Further fleshing out of the GUI mechanisms
* Support for data and page from Mycroft -> GUIConnection
* Add a 'reconnecting' event for the messagebus
* Add MycroftSkill.show_url()
* Plumb MycroftSkill.gui into the messagebus
* Implement MycroftSkill.gui dictionary
CLI extensions for the GUI:
* Can now act as a simple GUIConnection
* Minor revamp of messagebus connection, provides kinder handling when
messagebus isn't found or ready.
* BUGFIX: An empty filter would filter ALL messages
* BUGFIX: Input wider than the screen would cause a crash
* BUGFIX: "filter" or "find" with no param would filer "filter" or find "find"
Still very much a work in progress.
For understand and testing, here is the sequence:
STEP 1: GUI announces itself
* Connect to the main Mycroft messagebus
* Send: "mycroft.gui.connected" with data { "gui_id": XXX } where XXX is a uniq ID (uuid)
STEP 2: Mycroft creates GUI socket
* Mycroft extracts the gui_id
* Mycroft prepares a socket and announces its availability on the Mycroft messagebus with:
self.bus.emit(Message("mycroft.gui.port",
{"port": self.GUIs[gui_id].port,
"gui_id": gui_id}))
STEP 3: GUI connects
In python, a very minimal test socket handler on the GUI side would look like this
from websocket import create_connection
port = 18181 (from the message above)
ws = create_connection("ws://0.0.0.0:"+port+"/gui")
ws.send("Hello, World")
print("Sent")
print("Receiving...")
result = ws.recv()
print("Received '%s'" % result)
ws.close()
Enclosures
* Create a mechanism to instantiate unique Enclosure classes, depending on the platform found in the SYSTEM mycroft.conf
* Implement a generic Enclosure, which support the new GUI protocol
* Implement a Mark 1 Enclosure (expects the serial connection to an Arduino)
* Implement the start of a Mark II enclosure
* Implement a generic enclosure (no screen)
* Implement the GUI announcement and protocol basics
MycroftSkill
* Implement the basis of the GUI-controlling interfaces. Namely:
- MycroftSkill.show_text()
- MycroftSkill.show_image()
- MycroftSkill.show_html()
- MycroftSkill.show_page()
- MycroftSkill.gui to set values for page displays.
Configuration
* Add "gui_websocket" to the mycroft.config.py
The registered intents are now stored in a list. When a detach_skill message is received the list is checked for matching intents and the intents are removed
The CommonPlaySkill base class provides an easy base class for any
skill wishing to use the "Common Play" framework. This allows multiple
skills to jointly handle requests such as "play Janet Joplin",
"play my Sled Zepplin playlist", "play NPS news" or "play Strump's
speech to the UN". Previously the "wildcard" intents needed to handle
this were basically impossible -- only one skill got a shot at handling
the request. Now several skills to search their service to see if they
have anything that can service the request. The service with which
reports the highest confidence gets invoked.
The CommonPlaySkill makes it easy to implement this. Simply derive a
skill from CommonPlaySkill (instead of MycroftSkill) and override
the two required methods CPS__match_query_phrase() and CPS__start().
The skill can then use self.CPS__play(url) to begin playback, or invoke
a unique player to interact with a custom service.
This makes a cross context call be treated as one level when calculating the probability. this makes previous contexes not be completely invalidated when a cross context call is sent.
* Add protection for naive skill authors
It is fairly common for new skill authors to attempt actions in the __init__()
method which are not legal yet, as the Skill has not been fully connected to
the Mycroft system. This adds an @property protection layer for the two most common
issues:
* Accessing MycroftSkill.bus
* Accessing MycroftSkill.enclosure
Now those are properties instead of variables and provide appropriate warnings
when used before they exist.
Also enhancing the handling of error logs in the CLI to highlight problems such
as this:
* Color "- ERROR -" log messages in red
* Retaining leading characters from log messages, improving readability in formatted messages
This eliminates a lot of the noise in the log files. Later I'll add features in the CLI to
assist watching the messagebus messages rather than writing them all to logs.
Also corrected some language and formatting in settings.py docstrings.
* Add "wait" option to MycroftSkill.speak() and speak_dialog()
The new "wait" option will cause the speak function to block until all
of the given dialog has been spoken by Mycroft. This means:
self.speak("Hello world", wait=True)
is now equivalent to:
self.speak("Hello world")
wait_while_speaking()
* Add ability to schedule event in seconds
The MycroftSkill.schedule_event() method now accepts an integer in addition to
a datetime for the 'when' parameter. The integer represents the number of
seconds in the future to fire off the event. E.g.
```python
self.schedule_event(some_handler, 7)
```
Will invoke some_handler() seven seconds from now.
Also unified language used in event docstrings.
Switch to an OrderedDict() for translate_namedvalues(), maintaining the
sequence of values defined in the original "list.value" file. This is
useful in circumstances where there are multiple values, but the order
of listing indicates some sort of preference.
This is used in the Alarm skill to allow synonyms like "weekdays"/"weekday",
"Mondays/Monday", but the first value is used when building the status string.
For example "You have an alarm for 8am on Mondays". Generically, this lets
translators consistently provide preferred names for values by adjusting the
order.
Adapt doesn't populate the entry from the one_of correctly from context. To work around the issue intent structure is scanned for empty keys and tries to populate them from entities in __tags__
* Add repeat option to audioservice
The audioservice.play() method now accepts a repeat parameter. If this
parameter is True the playlist passed to the audio service will be
repeated.
* Add repeat support to vlc
* Add the repeat parameter to all services
Not functional but playback will work at least. Hacktoberfest?
* Add cleanup if the skill loading fails
If a skill throws an exception in initialize the registered handlers
need to be removed. To cleanup this the skill shutdown procedure is
run.
* Don't try converse method on non-loaded skills
Checks if a valid skill instance is present before calling the converse method
to filter out skills that wasn't loaded.
* Mark unloaded skills as inactive in CLI
The recent changes to support the 'locale' directory were incorrectly
joining the os.walk() path and filename, resulting in double-directories,
like "./vocab/en-us/./vocab/en-us/Something.voc"
This is a step towards abstracting the idea of an Enclosure which ties Mycroft to the hardware that is running Mycroft.
- Move the enclosure API to mycroft.enclosure.api (previously was mycroft.client.enclosure.api)
- Move display_manager out of enclosure client to mycroft.enclosure.display_manager
- Merge EnclosureWeather into EnclosureMouth
- Wrap display manager in a class
* Add MycroftSkill.find_resource() that locates a localization resource file
from either under the old vocab/regex/dialog folder, or under any folder in
the new 'locale' folder. The locale folder unifies the three different
folders and allows arbitrary subfolders underneath it.
* MycroftSkill.speak_dialog() will now speak the entry name if no dialog file
is found. Periods are replaced with spaces, so
```self.speak_dialog("this.is.a.test.")``` would return "this is a test" if
no file named this.is.a.test.dialog is found.
* Remove MycroftSkills.vocab_dir value
* Minor edits to several docstrings
The method first tries to use the skill vocab directory and then tries
the mycroft/res/text... directory.
After the vocab is loaded from file once it's stored in a cache
dictionary and further uses of the method won't hit the disk.
Example:
if self.voc_match(utt, "Yes):
...
The initial implementation of web settings returned values as
strings all the time, even Boolean and numeric values. This
required unnecessarily complicated code, such as:
```python
if setting["show_time"] == "true":
# do whatever...
```
Now a value defined in metadata as a "checkbox" gets cast to a boolean,
and values defined in metadata as a "number" is typecast to int or
float, as appropriate. This allows cleaner code such as:
```python
if setting["show_time"]:
# do whatever...
```
NOTE: This can be a breaking change, verify you skill which uses 'checkbox'
webUI types handles this correctly for 18.08.
The list holding the names of scheduled events was being populated with decorated names,
but other code assumed it held the "friendly" name. Corrected this assumption.
Several locations also removed list entries while iterating on the same list, resulting
in entries being skipped and left un-deleted. This left behind phantom scheduled events
when skills were reloaded, goofing up many schedules after the reload.
Allow a Padatious intent to override Adapt when it is VERY
certain that the utterance is directed at it. (95% confidence
or greater.) Right now that only occurs if the intent match
for the given phrase is perfect.
This solves this kind of issue:
* Adapt: Matching on "Set" and "Alarm"
* Padatious: Handling "is an alarm set"
* Fix logic error for when no Padatious intent
While working on the Alarm skill I discovered several issues with the
event scheduler. This PR cleans up those findings and resolves several
other potential issues:
1) To avoid thread synchronization issues, the EventScheduler had several
queues which independently held objects to be added/deleted/updated. However, the order of the events was undefined and got mixed since they were all batched together. So, for instance, if skill code performed:
self.add_event("foo", self.handle_foo)
if SomeReason:
self.cancel_event("foo")
The actual order of queue handling would perform Remove first, then Add which resulted in "foo" not being found for delete, but then added and left as an active event.
Now the EventScheduler protects the list using a Lock and the queues have been removed. Modifications to the list happen immediately after obtaining the lock and are not batched up.
2) One-time events were triggered while the event was still in the EventScheduler list. Now the entry is removed before invoking the handler.
3) Within the MycroftSkill.add_event(name, handler) is a local 'wrapper' method that actually makes the callback. The MycroftSkill.remove_event(name) method attempted to find entries in the events list and the associated handler entries in the self.emitter to remove. However, the emitter actually held the wrapper(handler), not the handler itself. So the emitter handlers were left behind.
This was a quiet bug until the next time you scheduled an event of the same name. When that second event finally triggered, it would fire off both the new and the old handler -- which snowballed in the 'skill-alarm:Beep' case, doubling and redoubling with every beep.
Now this cancels all the emitter listeners by name. There is a very slim chance that someone has registered a listener with the same name, but since it is namespaced to "skill-name:Event" I think this is pretty safe.
Not technically related, but a failure that has been lurking for
some time and is a French unit test that doesn't work depending
on the time of day when the test is run.
At startup, Padatious was blocking in the fallback while the
training occurred. As a result, any attempts to use Mycroft
during that period would queue up rather than giving the
user feedback. Now it immediately returns False, allowing
user notification to occur elsewhere.
* Fix cases where the unmunge misses keywords
The unmunge would invariably miss keys due to the fact that the dict is modified while being iterated. This breaks out the keys into a list before iterating through them to ensure that all original keys are checked.
* Clean up the unmunge function slightly
This makes the dialog parameter dual-purpose. It can be used as a
literal spoken string, or a dialog resource. In the future the
announcement parameter can be retired.
New function allows simple yes/no queries to be asked, capturing common
affirmations (e.g. "yes", "yeah", "yep", "sure", ...) and rejections
("no", "nope", ...) that are consistent across all skills.
The method will return a normalized 'yes', 'no' or whatever else is spoken
for further parsing. None is also possible.
This also adds the MycroftSkill.is_match() method to assist in matching
translated synonyms within an utterance.
- Remove setup scripts for mycroft-skills-sdk since it's not used anymore
- Rename mycroft-base-setup.in/MANIFEST.in to setup.py and MANIFEST.in
- Remove skill-container, since it hasn't been used or kept up to date since 17.08 and the cli commands to remove and activate skills is easier to work with
==== Environment Notes ====
Small update of the packaging script is needed due to this change