Call server side method from button click

I'm an old dog and just so used to jQuery I always just go that route.

foosel, I think the link you posted is for client side libraries. My library is on the server side, or do I need the client library as well?

Well, I will do some studying and then try to solv my little project.

The javascript of your plugin runs client side - that OctoPrint client lib is what you can use (it is completely optional :slightly_smiling_face:) to communicate from JS client to the python (server) side of your plugin.

My recommendation above is still relevant - wrap your python functions under SimpleApi commands, then call them from the client (on button click) using the JS client OctoPrint.SimpleAPICommand to trigger those commands server side.

2 Likes

Yes, my client is ready. If I understand correctly, I only need to complete my "on click functions" using the SimpleAPICommands. Then I will create the server side wrapper to recieve the commands and call my library functions. I will check this out tomorrow.

Thank you all for the great help.

2 Likes

Stuck again.

I do not quit understand what to call in my button onClick function. Here is what I have come up with so far, reading the posts here and the documentation I have found so far.

I added this to my plugin init.py file

# SimpleApiPlugin

def get_api_commands(self):
    return dict(
        whitLight=["on"],
        irLight=["on"]
    )

def on_api_command(self, command, data):
    import flask # (shall this be used here ?)
    if command == "whitLight":
        # TODO: Implement whiteLight control here.
        self._logger.info("whitLight called, parameter is {on}".format(**data))
    elif command == "irLight":
        # TODO: Implement irLight control here.
        self._logger.info("irLight called, some_parameter is {on}".format(**data))

and the following to my ViewModel

image

Above shows one of my botton functions with two alternatives. One according to Charlie_Powell and the second from the SimpleApiPlugin documentation.

Neither is complete. The first do not pass any parameters and I cannot find the command in the OctoPrint documentation.

I'm not sure if the second alternative is ment for a button click function and I don't know what to put in for the Host and X-Api-Key parameters.

Some further help would be much appreciated.

OK so you're most of the way there :slightly_smiling_face:.

The Python side bit looks good, there is just one part I would change:

self._logger.info("whitLight called, parameter is {on}".format(data.get('on')))

Since data is a dictionary, you can get the parameters using data.get(). You probably would have figured that out once the log would have shown the full response data.

Onto the JS side:
Here is a link to the simpleAPICommand client documentation. It does all the work for you making sure the command is valid, and tying up the host, apikey etc. from OctoPrint's internals.

The section you posted:

POST /api/plugin/brightpi HTTP/1.1
Host: example.com
Content-Type: application/json
[...]

is the raw HTTP request. That is what a request looks like behind the scenes - provided so you know how to call the command from any system, it is the 'standard protocol'. This is not required in your plugin.

I didn't realise that you wanted a parameter on your command, but that is easily added - now you have the link, you can see how this works too. Change it to this:

OctoPrint.simpleApiCommand("brightpi", "whitlight", {"on": true})

Hopefully that should now work.

Yes I was going to ask about the format function. I did't look right, so now I know. Thanks.

I did suspect that the code from the documentation was just information and not ment for the button function.

Thanks a lot for the information. I will try it.

1 Like

What we didn't see is your jinja file and how you are binding to the click event.

Here is two of the buttons:

image

The binidng works and the message is sent to, and recived by the server.

I have almost finnished the coding also on the server side. The problem is that the compiler cannot find the smbus2 module imported by my library module brightpilib.

I have installed smbus2 in my venv, but for some reason it will not load it. Maybe it's a version problem. I'm not so experienced so it's a bit hard for me to find out what is the real problem.

Here is the install script
sudo apt-get install git python3-smbus python3-distutils -y

Unfortunately I'm not a big fan of CLI so I don't exacly know what this means.

Since I am using PyCharm I need to know what URL to add to my Manage Repositories dialog to find it on the web. Currently I have https://pypi.python.org/simple
but this only give me access to smbus2 and that obviously is not the correct one.

where is this module?

If you can provide a link to your full source code on github or something I could take a look. From what I can tell it seems smbus2 is compatible with both python 2 and 3. The best approach is including smbus2 in the setup_requires list in setup.py and requirements.txt and that way it gets installed when you install the plugin.

Here is the link on github:

"https://github.com/PiSupply/Bright-Pi"

I have run the install script on my Raspberry Pi and it works fine on my Raspberry Pi, but now I also need it in my development environment. The problem is that I don't understand where git gets it from.

A requirements.txt was created for me so that exsists.
Do you mean the plugin_requires list like this?

Any additional requirements besides OctoPrint should be listed here
plugin_requires = ["smbus2"]

yes, plugin_requires, sorry that reply was early this monring and was going by memory.

the problem with gpio and smbus those only exist on devices with gpio like the pi. You can do remote debugging from a pi while you are developing from something like PyCharm or Visual Code, but @Charlie_Powell would have to speak up on that, because I know he has done it and I haven't.

l am aware that I cannot have it fully functioning on my desktop.

The plan was to build it without errors on the desktop, create a plugin package and install it on my Raspberry Pi for testing.

I have now stepped through the debugger to find out why it can't load the smbus2 module.

If I understand this correctly it seams to only look in the directories listed in below picture.

and the smbus2.py file is located in

C:\Users\Lars\PycharmProjects\OctoPrint-Brightpi\venv\Lib\site-packages\smbus2

The builder only checks the OctoPrint venv3 and not my plugin venv where the smbus2 module resides.

Shall I not define a separate virtual evironment for my plugin or what is wrong with my setup?

This is exactly it. Your plugin has to be fully installed into OctoPrint's virtualenv. Not standalone. It will be executed within OctoPrint, so anything it needs needs to be available in OctoPrint's venv.

Thanks!

Now I am pointing my venv for my plugin to the same venv3 as in my OctoPrint project but it still doesn't work.

Now it is complaining about this line
from fcntl import ioctl
in the smbus2 file.

I tried to install this but could only find two modules in the list:
micropython-fcnt and pycopy-fcntl.
Neither could be installed. I got the following eror message:
DEPRECATION: The -b/--build/--build-dir/--build-directory option is deprecated. pip 20.3 will remove support for this functionality. A possible replacement is use the TMPDIR/TEMP/TMP environment variable, possibly combined with --no-clean. You can find discussion regarding this at https://github.com/pypa/pip/issues/8333.

In the document reffered to it says something about "looking for setup.py. The Bright-Pi setup.py file starts with the following lines of code
from distutils.core import setup
from brightpi import brightpilib

The Bright-Pi install.sh file includes the line
sudo apt-get install git python3-smbus python3-distutils -y
so I thought maybe it would help to install the package python3-distutils.

This package is not included in the list of available packages but there are a bunch of others:
Distutils, Distutils2, Distutils2-py3

I tried to install one of them but the only one that could be installed was Distutils2-py3. The other ones are also depricated. Unfortuanteley it didn't help. micropython-fcnt and pycopy-fcntl still refuse to install.

I have now found the library installed by the install.sh script


but when I try to install it I will get the same depricated error message as for the pycopy-fcntl (see above). (It works fine when installed on the Raspberry Pi.)

Maybe I should take a step back and ask:
How can I integrate the https://github.com/PiSupply/Bright-Pi application with my OctoPrint plugin?
My biggest concern is to make my plugin do the necessary parts of the install.sh script.

This is part of the standard library of Python, however only on UNIX so if you are using Windows it will not load.

Since it is not hosted on PyPi, if I were doing it I would include the single file it contains brightpilib.py vendored alongside your plugin. So this means that you download the file, and add it to your own plugin project.

From the looks of it, the only other step would be enabling i2c. Until you get super confident using Python and the plugin system and can connect up buttons to do things for you, I would just document the fact that i2c must be enabled clearly.

By doing the method mentioned above, you skip the extra step of installing and just vendor the file. Doesn't work for complex dependencies, but in this case with a single file is more worth it.

The python3-smbus package is currently installed on my Raspberry Pi.
It is installed allong with a testprogram so I can see that it works. The i2c is also enabled by the Install.sh script.
Can I skip including it in my plugin?
Will my plugin find it on Raspberry Pi after installing the plugin with OctoPrint PluginManager?

No, since your plugin will run in OctoPrint's virtual environment, but your system wide python3-smbus package is installed globally and thus in a different environment.