Python Forum
Picamera2 commands between modules
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Picamera2 commands between modules
#1
Hi all, please be patience, I'm a newbie
I started to write a simple program to allow comunication and control between App Inventor and Python on RPi4 with Camera, via Bluetooth.
Comunication seems to work just fine. Now, I'm facing with variables implementation issues. Basically, I have a glvars.py file:
from picamera2 import Picamera2, Preview

# Camera init
cam = Picamera2()
camera_config = cam.create_preview_configuration()
cam.configure(camera_config)
cam.start_preview(Preview.DRM, x=0, y=0, width=1024, height=600)
cam.start()
cam.stop_preview()
for 'global' variables (I'm not sure this is a good or bad idea) and a myModules.py file with:
import glvars

def camExec(*args): # Camera commands
    clientSock = args[0]
    cmd = args[1]
    # line with Picamera2 commands follows
my App Inventor app send strings to RPi via bluetooth and the running python scripts should interpret these strings as Picamera2 commands. For example, if I send the string 'start_preview(True)' (cmd = args[1] variable above), the resulting command for Picamera2 should be:
    glvars.cam.start_preview(True)
that works just fine, but
glvars.cam.cmd
doesn't.
EDIT:
def camExec(*args): # Camera commands
    clientSock = args[0]
    cmd = args[1]
    # glvars.cam.start_preview(True) # works
    return getattr(glvars.cam, cmd)
give me the error:
AttributeError: 'Picamera2' object has no attribute 'start_preview(True)'
I tried several string formatting methods but no success. How should I format the final command line in Python?
Thanks
Reply
#2
It looks like you have something you made using app inventor sending a string to a python program. The python program executes the command represented by that string. The most important detail here is that app inventor is sending a string, not a command.

You could use eval() to execute the command.
eval("glvars.cam.start_preview(True)")
That is easy, but potentially dangerous. eval will execute any string it is passed, including commands to delete all files on your computer or install malware from a website. Unless you know for sure that there is no way malicious commands can be sent to your program, you should pass on eval.

getattr is on the right track. getattr(glvars.cam, "start_preview") returns the Picamera2.start_preview method. You call the method like this:
method = getattr(glvars, cam, "start_preview")  # get the method
method() # call the method
That doesn't call the method with arguments. You need to write additional code to accept the arguments and convert them from strings to whatever objects they are supposed to be. "True" is not the same as True. Well, that's not completely correct, but "False" is definitely not the same as False.

You could put the commands and argument processing code in a dictionary. When the python program receives a command string it splits the string into command name and arguments. The command is used to look up information about how to process the command, including converting the arguments from strings to whatever they need to be. Below is how I envision the dictionary looking. Dictionary keys are the names of commands you want to execute. The value has information about where to get the function or method, and how to convert argument strings to argument values. This dictionary "exports" two commands: glcvars.cmd.start_preview which takes one bool argument, and glvars.cmd.stop which takes no arguments.
commands = {
    "start_preview": {"receiver": glvars.cmd.start_preview, "converters": [bool]},
    "stop": {"receiver": glvars.cmd.stop, "converters": []},
}
On the inventor side, sending the command cmd.start_preview(True) could be done with a string like this: "start_preview,True". There is no reason for inventor to write the command in a python format. Write the command as something that is easy to parse. On the Python side the command string would be processed like this:
cmd_str = "start_preview,True"  # command str app inventor sends.
cmd_name, *arg_strings = cmd_str.split(",")  # Split into the command and arguments.
command = commands[cmd_name]  # Lookup information for the command.
args = [converter(arg) for converter, arg in zip(command["converters"], arg_strings)  # Call converters to change "True" to True.
command["receiver"](*args)  # Call the method with arguments.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  how to get PID's of linux commands executed through python modules? Manikandan_PS 4 4,354 Mar-12-2020, 07:16 AM
Last Post: Manikandan_PS
  Modules issue, pip3 download modules only to pyhton3.5.2 not the latest 3.6.1 bmohanraj91 6 10,027 May-25-2017, 08:15 AM
Last Post: wavic
  import commands modules not working in python 3.6.0 bmohanraj91 2 19,585 May-01-2017, 10:59 AM
Last Post: bmohanraj91

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020