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

how can I add custom actions to ambit? #4

Open
jafny opened this issue Jan 13, 2022 · 4 comments
Open

how can I add custom actions to ambit? #4

jafny opened this issue Jan 13, 2022 · 4 comments
Labels
documentation Improvements or additions to documentation question Further information is requested

Comments

@jafny
Copy link

jafny commented Jan 13, 2022

Let me start by saying thanks for this great repo, really excited to play around with it! One question I have is where can I register callbacks to execute when I get an Input? I see that I can use actionmaps for the executeCommand action when I receive input...but I was curious where I can define those callbacks.

Such as the below example: "rotation_left": { "action": "adjustTemperature", "behavior": "delta", "invert": true }

Where can I define what the adjustTemperature string argument maps to a callback function?

@khimaros khimaros added documentation Improvements or additions to documentation question Further information is requested labels Jan 13, 2022
@khimaros khimaros changed the title Probably Silly Question how can I add custom actions to ambit? Jan 13, 2022
@khimaros
Copy link
Owner

khimaros commented Jan 13, 2022

hello @jafny -- this is a completely reasonable question!

the callback system is not quite as extensible/modular as i'd like and requires modifying a few different parts of the core ambit code in order to add a new native action. this is suboptimal and will require you to maintain patches against ambit and possibly deal with merge conflicts as the core code evolves. however, for posterity, the places are:

in the meantime, your best bet might actually be to use executeCommand with an external program written in any language of your choice. there are some examples of this in the included layouts: https://github.com/khimaros/ambit/tree/master/ambit/resources/layouts/multifunction-buttons

the executeCommand action is documented at https://github.com/khimaros/ambit/blob/master/docs/CONFIG.md#executecommand and usage would look something like:

{ "action": "executeCommand", "argv": [ "./example/scripts/temperature.sh" ], "limits": [50, 80] }

with the accompanying external program at https://github.com/khimaros/ambit/blob/master/example/scripts/temperature.sh

if you are interested in writing native modules in python or executeCommand doesn't fit your needs, please let me know. i can prioritize adding a plugin based system for this, as it was already on the roadmap.

@khimaros khimaros pinned this issue Jan 13, 2022
@khimaros
Copy link
Owner

i can envision a few ways to support defining custom actions in ambit, i'm interested to hear your thoughts on these.

regardless, i'd like the end result to support using custom external actions in the layout like:

{ "action": "externalAction", "data": {"somekey": "somevalue"}, "limits": [50, 80] }

option 1: enable plugins in config file

this would allow loading of modules entirely from the config and would not require writing any python code except for the module. it would also make it easier to use community made modules. loading the plugin in the layout config would look like:

{
    "action_plugins": ["/path/to/external_action.py"],
    "module_mappings": {...}
}

and the module itself would look like:

class Behavior:
    items = [...]

class Actions:
    def externalAction(self, ctrl, value, data):
        ctrl.screen_string('E: %s %s' % (value, data['somekey']))

option 2: subclass ambit controller

this option would require creating a new main entrypoint like bin/ambit and executing that instead of the upstream bin. a downside is that this would require making your own copy of any such upstream you use such as bin/ambit_demoscene. it also means making more of the core ambit API stable across releases.

class CustomController(ambit.Controller):
    @ambit.Callback('externalAction')
    def external_action_callback(self, value, data):
        self.screen_string('E: %s %s' % (value, data['somekey']))

def main():
    config = ambit.StandardConfiguration()
    ctrl = CustomController(config)
    ...

option 3: register callbacks procedurally

same limitations as option 2.

def external_action_callback(ctrl, value, data):
   ctrl.screen_string('E: %s %s' % (value, data['somekey']))

def main():
    config = ambit.StandardConfiguration()
    ctrl = ambit.Controller(config)
    ctrl.register_external_action('externalAction', external_action_callback, items=[...])
    ...

arguably, we could have some combination of these, but curious which you'd prefer. in terms of ease of implementation for me, the order would be: option 3, 2, 1

@jafny
Copy link
Author

jafny commented Jan 18, 2022

Sorry for the delayed response! If I am picturing the easy option 3 I think it will work well for my use case. At it's most basic, I want to create a method of interfacing with a websocket API where an ambitt powered MonogramCC is my UI. If I can write all my websocket interactions as modules, and then use the proposed "register_external_action" callback to inject that into a button push or knob dial....that feels like it would work great.

@khimaros
Copy link
Owner

khimaros commented Feb 9, 2022

@jafny thank you for the feedback. i just want to confirm: does executeCommand fit your needs in the short term or is there something you'd like to do that isn't supported there?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants