Execute script addon via favourites
#1
Hi, I hope this is the right place - I am struggling with a problem meanwhile since weeks and apparently cannot solve it without help:

Long story short: I have a setup with beamer using a Windows based Kodi 21, recent version. As there is no point in firing up the beamer, let the canvas screen down, etc when listening to music, the system is often used headless, without screen output or menu interaction. This is where IOS Remote comes into the picture.

For controlling the different devices or the whole environment, I have implemented an addon script.home that needs two arguments, the device and the command to be executed - the rest goes over many different ways, partly HTTP requests to services, partly COM Serial, or IR or even radio remotes. I have also a feature "scenes" which are kind of macros setting up several devices with one command. The whole thing works fine and I managed to integrate in different ways into my modified skin:

Addon.py (in shortened form):
Code:
from lib import automation
from lib import xbmchelper
ADDON = xbmcaddon.Addon()
CWD = ADDON.getAddonInfo('path') # for kodi 19 and up..
if (__name__ == '__main__'):
   device = str(sys.argv[1])
   command = str(sys.argv[2])
   if device == 'this_or_that':
        #do this or do that
        pass
   elif device == 'scene':
       if command == 'listen':
           automation.execute('audio', 'aux')
        elif command == 'somethingelse'
            #further "scenes" = environment macros
            pass
       else:
           xbmcgui.Dialog().notification('script.home', 'Unknown ' + device + ' command ' + command)
   else:
       automation.execute(device, command)
# the end!
Calling from the skin works flawlessly, e.g. when music is played, the window MusicOSD.xml  triggers switching on the amplifier and the speakers:
Code:
    <onload>RunAddon(script.home,scene,listen)</onload>
    <onload>Skin.SetBool(Audio_State,true)</onload>
Also calling from menu controls works fine:
Code:
<control type="radiobutton" id="11144">
    <label>Stereoanlage</label>
    <include>DefaultSettingButton</include>
    <onclick>Skin.ToggleSetting(Audio_State)</onclick>
    <selected>Skin.HasSetting(Audio_State)</selected>
    <onclick condition="!Skin.HasSetting(Audio_State)">RunAddon(script.home,audio,aux)</onclick>
    <onclick condition="Skin.HasSetting(Audio_State)">RunAddon(script.home,audio,power)</onclick>
</control>
Switching off the computer via the remote simply shuts down, so I cannot catch the OnUnload event of any skin window or similar and obviously it is senseless in a headless mode to fire up the beamer and let the canvas down, just to go to a menu and switch off the amp before shutting down. So I would like to call my addon in certain situations from the remote: as I have no access to custom menus or screens, the favourites appear to be the right place for this?

Now to my problem: whatever I try, I simply do not manage to call the addon from favourites via the IOS remote:
Code:
<favourite name="Stereoanlage" thumb="DefaultAudio.png">RunScript(script.home,scene,listen)</favourite>
or
Code:
<favourite name="Stereoanlage" thumb="DefaultAudio.png">RunScript("script.home","audio","power")</favourite>
results in Python exception:
Code:
2024-10-18 09:30:44.721 T:7812 error <general>: EXCEPTION Thrown (PythonToCppException) : -->Python callback/script returned the following error<--
Traceback (most recent call last):
File "C:\Users\Richard\AppData\Roaming\Kodi\addons\script.home\addon.py", line 17, in <module>
device = str(sys.argv[1])
IndexError: list index out of range
...which means the call is handed over to Kodi properly, the Addon is found and started, but no arguments are exposed and sys.argv remains empty. Without args the addon is useless, not knowing what to do.

I tried to work around by calling an extra py script that handles this without parameters:

toggle.audio.py (extra script in root of the addon):
Code:
from lib import automation
from lib import xbmchelper
if xbmchelper.getsetting('audio_state') == 'true':
   automation.execute('audio','power')
else:
   automation.execute('audio','aux')
and call this from favourites.xml:
Code:
<favourite name="Stereoanlage" thumb="DefaultAudio.png">RunScript("special://home/addons/script.home/toggle.audio.py")</favourite>
IOS Remote refuses with: "Execution of the action is not possible", apparently cannot parse and the call does not reach Kodi at all?

All other workaround attempts failed as well, like calling a batch file via System.Exec, RunAddon instead of RunScript, with or without spaces, using single quotes, double quotes, no quotes, escaped quotes... also tried full path, C:\Users\... windows style, C:\\Users\\... python style, relative paths from special: or addon: protocols, etc, all in vain.

What would be the proper syntax to call a script addon via favourites in the remote? Or is this possibly some limitation of the remote with current Kodi releases?

Thank you in advance for any pointers or hints and greetings from Vienna, Austria.
Reply
#2
Maybe to add here:

It is only my gut feeling that tells me this could be related to the Official IOS remote, this is why I placed my questions here. If you mean this would be rather a question in some other subforum addons/python/whatever, please let me know, but as the scripts and the addon work well in "direct" Kodi calls, I assume the issue is not related to my limited Python coding capabilities.

Most likely it is simply a syntax issue - different areas seem to use different call conventions in Kodi and generally up-to-date documentation is not easy to find, forum solutions go back 10-15 years and very often are obsolete.

I hope someone may help me here though, cheers!
Reply
#3
First, the good news: As you see the message "Unable to execute the action" (= in German "Ausführung der Aktion nicht möglich"), this shows the App already recognizes the Favourites item as a script. Now the bad news: The app only calls a JSON command to run this script, and it receives an error from the API. The App does not interpret the script itself.

To narrow down the problem you could try to place the exact same JSON command to Kodi and try to debug from there.

Read the script path from Favourites:
Code:
{"jsonrpc":"2.0","method":"Favourites.GetFavourites","params":{"properties":"path"}, "id":2}

In the result look up the path to your script and fill this into next JSON command which calls this:
Code:
{"jsonrpc":"2.0","method":"Addons.ExecuteAddon","params":{"addonid":path_to_script}, "id":2}
Reply
#4
In case someone is hit by the same problem - I have finally managed to find a (really dirty) workaround:

The issue is quite apparently in the IOS Remote (edit: learnt below that the limitation is somewhere else, the rest is still valid), it has no impementation of RunAddon that would expose arguments, it can execute only RunScript with a limitation: only properly registered script addons can be called, but not any other path or py file.

The workaround consists of additional one-liner-mini-addons that can be called with no arguments and then make the proper call to the addon:

favourites.xml
Code:
<favourite name="Stereoanlage" thumb="DefaultAudio.png">RunScript(script.remote.audio)</favourite>
script.remote.audio
Code:
import xbmc
if (__name__ == '__main__'):
   xbmc.executebuiltin('RunScript("special://home/addons/script.home/toggle.audio.py")')
toggle.audio.py
Code:
from lib import automation
automation.execute('audio','toggle')
(finally, in automation.py I have the full logic of my addon that I wanted to call)

Extremely confusing and really dirty, but for the moment this seems to be a solution.

Cheers from Vienna.
Reply
#5
Thank you buschel,

indeed this seems to be a limitation somewhere along the line... I have already a rather steep learning curve behind me - coming from Windows and .net I needed to get grip of quite some things already in the Kodi/Python world.

For this reason I'd prefer not to dig into the JSON API also, I just accept your bad news as bad news :-D

Found a possible workaround as posted above - dirty but it should suffice until I have the time (and the burning urge) to get involved with yet another layer...

Thanks for your support, cheerio from Vienna
Reply
#6
I am not clear yet if this is a limitation of the remote or of Kodi's JSON API. If the JSON API allows this, can you share an example?

Edit: Ok, thanks. Your 2nd post is clear.
Reply
#7
Cannot tell you where the issue is along the chain. Maybe it helps if I share what did not work and what works at the end:

When executing an item from favourites.xml via IOS Remote, these approaches do not work:
  • RunAddon(script.home, audio, toggle) - looks like not available
  • RunScript(script.home, audio, toggle) - calls script.home without parameters - empty sys.argv
  • RunScript("special://home/addons/script.home/toggle.audio.py") - no log entry, does not reach Kodi, just the red "cannot execute"

The only thing that worked is calling another, new addon without parameters:
  • RunScript(script.remote.audio)

This one-liner addon can call the script xbmc.executebuiltin('RunScript("special://home/addons/script.home/toggle.audio.py")'), which again in turn makes the proper call with parameters to the originally intended addon.
Reply
#8
Hmm, so the main problem seems to me that the remote does not process the parameters when addressing RunScript(script.home, audio, toggle) via the JSON API. The remote definitely does not process any parameters.

I am personally not using any such scripts in my setup. If you can provide me a very basic example which has 2 parameters, and which allows me to see the success on a console, I can try to look into this.

Edit: I just added an add-on and also a related RunScript to favorites. But I see currently no obvious way to read the parameters via JSON API. Need to ask some expert, if this is possible. Until this is resolved, the remote app cannot implement what you initially were looking for.
Reply
#9
Thank you, Mr. Buschel,

I have prepared a quick example to illustrate - all code or platform specific references removed, the addons just make Kodi notifications when called. It should run in any environment, although I use Windows 10 currently. As I find no upload or attach option here, I share via Onedrive, hope you can access...?

https://1drv.ms/f/s!Ajz9MK4x8Dehgvly3Eaw...w?e=9APDHc

The standard "Kodi internal" call would be RunAddon(addonname,param1,param2) - this works all over the skin files fine, I did not try anything with JSON API yet.

It is quite possible, that I have tried to reinvent the wheel here and have built something overly complicated, but handing over params to addons seemed to me as a natural and easy way to build a common library fo different automation tasks. If you look into the file automation.py, you will get a clear picture what I tried to achieve - a single call of the addon for a "scene" or macro should switch many different devices using different ways to control: for "listen" I need just the amplifier and the subwoofer powered on and Kodi remains "headless", but if I want to "watch" something I'll need the projector running, the audio system powered and the screen going down, in the evening I also switch off the lights in the room, etc...

I have added also a favourites.xml file including the failed attempts/syntaxes and also the final workaround that seems to work.

If any questions (or findings) just scream at me, whish you a nice week, R.
Reply
#10
Thanks for sharing the details and the archive which I could access and download.

But for now, it looks like this is stuck until an updated API provides the script parameters.
Reply

Logout Mark Read Team Forum Stats Members Help
Execute script addon via favourites0