Mycroft Community Forum

Stop ATTEMPTING TO RELOAD

I have a skill that needs a prompt using messagebus. When I receive this prompt I need my skill to read json contents from a file and asks the user a question. However it appears once the contents have been read, the skill reloads and I’m unable to capture the users response. Is there a way to pause reloading the skill or can I read contents from the file as soon as the skill reloads? My directory structure is as follows:

skills/my-skill
         |_/json-files
             |_json_file

My json file is read as follows:

class MySkill(MycroftSkill):
    def __init__(self):
        MySkill.__init__(self)
        self.json_data = {}
        self.json_file = join(self.root_dir, 'json_files/json_file')

    def initialize(self):
        self.add_event('json', self.json_data)

    def handler_json(self, message):
        self.get_data()
        self.ask_questions()

    def get_data(self):
        if os.stat(self.json_file ).st_size == 0:
            return False
        else:
            with open(self.questions_file) as f:
               json_data = json.load(f)
               self.json_data = json_data
               self.json_data = True

    def ask_questions(self):
        response = self.get_response("You have new questions")
        if response == "yes":
            #read self.json_data
        else:
            #pass

My skill recieves a prompt with:

python3 -m mycroft.messagebus.send ‘json’

All help is appreciated thank you!

Hi Santiago,

It looks like your event handler isn’t registered correctly.

self.add_event('json', self.json_data)

Here the second argument is the handler callback so presumably should be self.handler_json in this instance.

If you haven’t found them yet the Skill will be generating logs at /var/log/mycroft/skills.log which are also visible in the CLI. You can generate your own logs too. Find out more in our docs:
https://mycroft-ai.gitbook.io/docs/skill-development/introduction/logging

There are a few other little typo’s that might be tripping up the Skill, eg self.questions_file doesn’t exist and the if / else block needs something in it other than comments.

As a side note, I’d suggest using a more specific message type. Instead of json it would be better as skill.myskill.json. We do this to keep each Skills messages in their own namespace. You could easily see someone else doing something with JSON messages which have nothing to do with your Skill but they’d both be issuing json messages.

Here’s a working example with the above incorporated:

import json
import os
from os.path import join

from mycroft import MycroftSkill, intent_handler


class JsonSkill(MycroftSkill):
    def __init__(self):
        super().__init__(name="JsonSkill")
        self.json_data = {}
        self.json_file = join(self.root_dir, 'json_files/json_file')

    def initialize(self):
        self.add_event('skill.jsonskill.json', self.handler_json)

    def handler_json(self, message):
        self.get_data()
        self.ask_questions()

    def get_data(self):
        if os.stat(self.json_file ).st_size == 0:
            return False
        else:
            with open(self.json_file) as f:
               json_data = json.load(f)
               self.json_data = json_data
               self.json_data = True

    def ask_questions(self):
        response = self.get_response("new.questions")
        if response == "yes":
            self.log.info("YES")
        else:
            self.log.info("NO")

def create_skill():
    return JsonSkill()

Edit: small note, I moved the dialog for get_response into locale/en-us/new-questions.dialog

1 Like

Mycroft has an auto-reload feature reloading the skill if a file in it gets updated. It’s probably this that happens.

You can turn this off completely by setting the self.reload_skill flag to false in initialize, in your case:

    def initialize(self):
        self.reload_skill = False
        self.add_event('json', self.json_data)

But you should consider an alternative location for the json file.

1 Like

Hi!

Just realised I have those typos in my question which I apologise for.

  1. self.add_event('json', self.json_data) should most definitely be self.add_event('json', self.handler_json)

  2. self.questions_file should be self.json_file

  3. The comments in the if/else block are there to illustrate what’s supposed to happen not actually what I have in my code. However, I’ll keep in mind this is confusing when reading, appreciate the feedback and will definitely not repeat this again!

Moving dialogue into locale/en-us/ certainly looks a lot cleaner and I’ll also implement this as well as changing the prompt to use skill.myskill.json to keep it within the skill namespace!

I was wondering if there was a way to match utterances from a user to an intent file. For example using something like:

 def ask_questions(self):
        response = self.get_response("new.questions")
        if response in yes.intent: <-----------------SOMETHING LIKE THIS
            self.log.info("YES")
        else:
            self.log.info("NO")

Responding to intents with an intent handler seems easy enough but within a block like that, I’m not so sure. Thank you very much for your help and bearing with my typos!

In relation to switching of auto reload, this is what I’m looking for. Thank you very much!
As for moving the location of the json file, I’ve been trying to figure out where else to put it but its a little confusing as to where mycroft is picking up files. Can you suggest where else I can store this file?

A few things I should have mentioned for this:

  1. For Yes / No questions in particular we have a built-in method for this: ask_yesno(dialog)

  2. translate("yes") will return the phrase “yes” in the users set language if the translation exists. So better to use this than attempting to match against the string “yes” directly.

  3. voc_match(response, "yes") returns a boolean on whether “yes” (translated into the users language) is in the response string

As for file location:
self.file_system.path should be assigned to your Skills dedicated directory. By default this is ~/.mycroft/skills/YourSkillName

1 Like