4 from std_msgs.msg
import String, Bool
5 from mycroft_ros.msg import Mycroft, IntentResponse, IntentResponseEntity
as Entity, GetResponseAction, GetResponseResult
6 from mycroft_ros.srv import MycroftSkill
as MycroftService, MycroftSkillResponse, MycroftSkillRequest
10 from threading
import Timer
13 from os.path
import basename
14 from mycroft
import dialog
21 connected, wait_while_speaking, reset_sigint_handler,
22 create_echo_function, create_daemon, wait_for_exit_signal
31 from adapt.intent
import Intent, IntentBuilder
34 event_scheduler =
None 36 topic_name =
"checking" 37 connect_to_mycroft_backend =
True 38 get_response_server =
None 39 ask_yesno_server =
None 42 start_ticks = time.monotonic()
43 start_clock = time.time()
48 result = GetResponseResult()
57 skill_path = goal.skill_path
59 skill = self.manager.loaded_skills.get(skill_path, {})
60 self.result.response = skill[
"instance"].
get_response(dialog=goal.dialog)
61 self.server.set_succeeded(self.
result)
66 result = GetResponseResult()
74 skill_path = goal.skill_path
75 skill = self.manager.loaded_skills.get(skill_path, {})
76 self.result.response = skill[
"instance"].
ask_yesno(prompt=goal.dialog)
77 self.server.set_succeeded(self.
result)
80 global bus, skill_manager
81 skill_path = data.skill_path
82 skill = skill_manager.loaded_skills.get(skill_path, {})
84 if skill[
"instance"]
is not None:
85 text = skill[
"instance"].
get_response(dialog=data.dialog)
99 - SkillManager to load/reloading of skills when needed 100 - a timer to check for internet connection 101 - adapt intent service 102 - padatious intent service 104 global bus, skill_manager, event_scheduler, connect_to_mycroft_backend
106 bus.on(
'intent_failure', FallbackSkill.make_intent_failure_handler(bus))
113 except Exception
as e:
114 LOG.exception(
'Failed to create padatious handlers ' 115 '({})'.format(repr(e)))
124 LOG.info(
'Msm is uninitialized and requires network connection',
125 'to fetch skill information\n' 126 'Waiting for network connection...')
131 skill_manager.daemon =
True 135 skill_manager.load_priority()
136 skill_manager.start()
137 bus.emit(
Message(
'skill.manager.initialised'))
138 if connect_to_mycroft_backend:
145 event_scheduler.shutdown()
153 bus.emit(
Message(
'system.update'))
154 msg =
Message(
'system.update', {
158 resp = bus.wait_for_response(msg,
'system.update.processing')
160 if resp
and (resp.data
or {}).
get(
'processing',
True):
161 bus.wait_for_response(
Message(
'system.update.waiting'),
162 'system.update.complete', 1000)
166 bus.emit(
Message(
'mycroft.internet.connected'))
170 bus.emit(
Message(
"recognizer_loop:utterance", {
'utterances': [data.data],
'lang':
"en-us"}))
172 def register_intents(instance, skill_topic, intent_files=None, entities=None, intents=None):
173 pub = rospy.Publisher(skill_topic, IntentResponse, queue_size=10)
175 for intent_file
in intent_files:
176 instance.register_intent_file(intent_file,
lambda m : pub.publish(IntentResponse(m.type, m.data[
'utterance'], [Entity(entity, value)
for entity, value
in m.data.items()
if entity !=
'utterance'])))
178 for intent
in intents:
179 instance.register_intent(Intent(name=intent.name, requires=[(req.entity, req.attribute_name)
if req.attribute_name !=
'' else (req.entity, req.entity)
for req
in intent.requires], at_least_one=intent.at_least_one, optional=[(opt.entity, opt.attribute_name)
if opt.attribute_name !=
'' else (opt.entity, opt.entity)
for opt
in intent.optional]),
lambda m : pub.publish(IntentResponse(m.data[
'intent_type'], m.data[
'utterance'], [Entity(entity, value)
for entity, value
in m.data.items()
if entity
not in (
'intent_type',
'target',
'confidence',
'__tags__',
'utterance')])))
181 for entity
in entities:
182 instance.register_entity_file(entity)
186 Removes the skill using its path. 188 data (String): Skill directory path 190 global bus, skill_manager
191 skill_path = data.data
192 skill = skill_manager.loaded_skills.get(skill_path, {})
194 skill[
"is_ros_node"] =
False 197 """ Create new MycroftSkill for ROS node and load into SkillManager 200 data: mycroft/register_skill service payload containing MycroftSkill srv 203 global bus, skill_manager
204 mycroft_skill = data.skill
205 skill_path = mycroft_skill.path.rstrip(
'/')
206 skill_id = basename(skill_path)
207 skill = skill_manager.loaded_skills.setdefault(skill_path, {})
208 skill.update({
"id": skill_id,
"path": skill_path})
209 skill[
"loaded"] =
True 210 skill[
"is_ros_node"] =
True 212 instance.skill_id = skill_id
215 instance.load_data_files(skill_path)
216 skill_topic =
'mycroft/' + skill_id
217 register_intents(instance=instance, intents=mycroft_skill.intents, skill_topic=skill_topic, intent_files=mycroft_skill.intent_files, entities=mycroft_skill.entities)
218 instance.initialize()
219 except Exception
as e:
220 instance.default_shutdown()
222 skill[
"instance"] = instance
224 if skill[
'instance']
is not None:
225 bus.emit(
Message(
'mycroft.skills.loaded', {
'path': skill_path,
'id': skill[
'id'],
'name': skill[
'instance'].name,
'modified': modified}))
226 return MycroftSkillResponse(
True)
228 bus.emit(
Message(
'mycroft.skills.loading_failure', {
'path': skill_path,
'id': skill[
'id']}))
229 return MycroftSkillResponse(
False)
233 Check for network connection. If not paired trigger pairing. 234 Runs as a Timer every second until connection is detected. 242 enclosure.mouth_text(dialog.get(
"message_synching.clock"))
245 config = Configuration.get()
246 platform = config[
'enclosure'].
get(
"platform",
"unknown")
247 if platform
in [
'mycroft_mark_1',
'picroft']:
248 bus.wait_for_response(
Message(
'system.ntp.sync'),
249 'system.ntp.sync.complete', 15)
255 skew = abs((time.monotonic() - start_ticks) -
256 (time.time() - start_clock))
261 data = {
'utterance': dialog.get(
"time.changed.reboot")}
262 bus.emit(
Message(
"speak", data))
266 enclosure.mouth_text(dialog.get(
"message_rebooting"))
267 enclosure.eyes_color(70, 65, 69)
268 enclosure.eyes_spin()
274 bus.emit(
Message(
"system.reboot"))
277 bus.emit(
Message(
"enclosure.mouth.reset"))
280 enclosure.eyes_color(189, 183, 107)
281 enclosure.mouth_text(dialog.get(
"message_loading.skills"))
283 bus.emit(
Message(
'mycroft.internet.connected'))
288 'utterances': [
"pair my device"],
291 bus.emit(
Message(
"recognizer_loop:utterance", payload))
297 data = {
'utterance': dialog.get(
"backend.down")}
298 bus.emit(
Message(
"speak", data))
299 bus.emit(
Message(
"backend.down"))
302 thread = Timer(1, check_connection)
307 if message
is not None:
308 print(
'do somethingggg')
311 print(
'do something else')
319 rospy.init_node(
'mycroft_skills')
320 rospy.loginfo(rospy.get_caller_id() +
" started")
321 rospy.Subscriber(
"mycroft/utterance", String, handle_utterance)
322 rospy.Subscriber(
"mycroft/remove_skill", String, handle_remove_skill)
323 s = rospy.Service(
'mycroft/register_skill', MycroftService, handle_register_skill)
331 Configuration.init(bus)
332 config = Configuration.get()
336 bus.on(
'skill.manager.initialised', initialise_response_server)
339 bus.once(
'open', _starting_up)
340 bus.on(
'skill.converse.request', check_working)
348 if __name__ ==
'__main__':
def create_daemon(target, args=(), kwargs=None)
def register_intents(instance, skill_topic, intent_files=None, entities=None, intents=None)
def check_working(message)
def wait_for_exit_signal()
def wait_while_speaking()
def is_paired(ignore_errors=True)
def set_active_lang(lang_code)
def handle_register_skill(data)
def handle_utterance(data)
def create_echo_function(name, whitelist=None)
def check_connection_without_backend()
def try_update_system(platform)
def reset_sigint_handler()
def handle_remove_skill(data)
def __init__(self, manager)
def initialise_response_server(message)
def get_response(skill_path, dialog, client=None)
def __init__(self, manager)
def get(phrase, lang=None, context=None)
def ask_yesno(skill_path, dialog, client=None)
def handle_get_response(data)