Skip to content

Commit

Permalink
Add ability to return Input/Output/Function object with module_functi…
Browse files Browse the repository at this point in the history
…on()
  • Loading branch information
kizniche committed Apr 29, 2023
1 parent 8854856 commit e6734e9
Show file tree
Hide file tree
Showing 8 changed files with 53 additions and 41 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Add I2C interface for K30 Input
- Add Day to unit conversion
- Add ability to disable any Input/Output/Function/Widget option (user can view but not change)
- Add ability to return Input/Output/Function object with module_function()


## 8.15.8 (2023-04-06)
Expand Down
20 changes: 12 additions & 8 deletions mycodo/controllers/controller_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,22 +147,26 @@ def initialize_variables(self):
function_listener.daemon = True
function_listener.start()

def call_module_function(self, button_id, args_dict, thread=True):
def call_module_function(self, button_id, args_dict, thread=True, return_from_function=False):
"""Execute function from custom action button press."""
try:
run_command = getattr(self.run_function, button_id)
if thread:
if not thread or return_from_function:
return_val = run_command(args_dict)
if return_from_function:
return 0, return_val
else:
return 0, f"Command sent to Function Controller. Returned: {return_val}"
else:
thread_run_command = threading.Thread(
target=run_command,
args=(args_dict,))
thread_run_command.start()
return 0, "Command sent to Function Controller and is running in the background."
else:
return_val = run_command(args_dict)
return 0, ["Command sent to Function Controller.", return_val]
except:
self.logger.exception(
f"Error executing button press function '{button_id}'")
except Exception as err:
msg = f"Error executing function '{button_id}': {err}"
self.logger.exception(msg)
return 1, msg

def function_action(self, action_string, args_dict=None, thread=True):
"""Execute function action."""
Expand Down
16 changes: 10 additions & 6 deletions mycodo/controllers/controller_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,21 +443,25 @@ def force_measurements(self):
self.next_measurement = time.time()
return 0, "Input instructed to begin acquiring measurements"

def call_module_function(self, button_id, args_dict, thread=True):
def call_module_function(self, button_id, args_dict, thread=True, return_from_function=False):
"""Execute function from custom action button press."""
try:
run_command = getattr(self.measure_input, button_id)
if thread:
if not thread or return_from_function:
return_val = run_command(args_dict)
if return_from_function:
return 0, return_val
else:
return 0, f"Command sent to Input Controller. Returned: {return_val}"
else:
thread_run_command = threading.Thread(
target=run_command,
args=(args_dict,))
thread_run_command.start()
return 0, "Command sent to Input Controller and is running in the background."
else:
return_val = run_command(args_dict)
return 0, f"Command sent to Input Controller. Returned: {return_val}"

except Exception as err:
msg = f"Error executing button press function '{button_id}': {err}"
msg = f"Error executing function '{button_id}': {err}"
self.logger.exception(msg)
return 1, msg

Expand Down
19 changes: 12 additions & 7 deletions mycodo/controllers/controller_output.py
Original file line number Diff line number Diff line change
Expand Up @@ -397,18 +397,23 @@ def is_setup(self, output_id):
except Exception:
self.logger.exception("is_setup() exception")

def call_module_function(self, button_id, args_dict, unique_id=None, thread=True):
def call_module_function(self, button_id, args_dict, unique_id=None, thread=True, return_from_function=False):
"""Execute function from custom action button press."""
try:
run_command = getattr(self.output[unique_id], button_id)
if thread:
if not thread or return_from_function:
return_val = run_command(args_dict)
if return_from_function:
return 0, return_val
else:
return 0, f"Command sent to Output Controller. Returned: {return_val}"
else:
thread_run_command = threading.Thread(
target=run_command,
args=(args_dict,))
thread_run_command.start()
return 0, "Command sent to Output Controller and is running in the background."
else:
return_val = run_command(args_dict)
return 0, f"Command sent to Output Controller. Returned: {return_val}"
except:
self.logger.exception(f"Error executing custom action '{button_id}'")
except Exception as err:
msg = f"Error executing function '{button_id}': {err}"
self.logger.exception(msg)
return 1, msg
4 changes: 2 additions & 2 deletions mycodo/mycodo_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,10 @@ def send_email(recipients, message, subject=''):
smtp.user, smtp.passw, smtp.email_from,
recipients, message, subject=subject)

def module_function(self, controller_type, unique_id, button_id, args_dict, thread=True):
def module_function(self, controller_type, unique_id, button_id, args_dict, thread=True, return_from_function=False):
try:
return self.proxy().module_function(
controller_type, unique_id, button_id, args_dict, thread)
controller_type, unique_id, button_id, args_dict, thread=thread, return_from_function=return_from_function)
except Exception:
return 0, traceback.format_exc()

Expand Down
14 changes: 8 additions & 6 deletions mycodo/mycodo_daemon.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ def check_daemon(self):
return f"Exception: {except_msg}"


def module_function(self, controller_type, unique_id, button_id, args_dict, thread=True):
def module_function(self, controller_type, unique_id, button_id, args_dict, thread=True, return_from_function=False):
"""
Call a module function
Expand All @@ -432,23 +432,25 @@ def module_function(self, controller_type, unique_id, button_id, args_dict, thre
:type args_dict: dict
:param thread: execute the function as a thread or wait to get a return value
:type thread: bool
:param return_from_function: return the object returned from the function, rather than merely a status string
:type return_from_function: bool
"""
message = None
try:
if controller_type == "Input":
if unique_id in self.controller["Input"]:
return self.controller["Input"][unique_id].call_module_function(
button_id, args_dict, thread=thread)
button_id, args_dict, thread=thread, return_from_function=return_from_function)
else:
message = f"Attempting to call {button_id}() in inactive Input Controller with ID {unique_id}. Only active Input Controllers can have functions called."
self.logger.error(message)
elif controller_type == "Output":
return self.controller["Output"].call_module_function(
button_id, args_dict, unique_id=unique_id, thread=thread)
button_id, args_dict, unique_id=unique_id, thread=thread, return_from_function=False)
elif controller_type in ["Function", "Function_Custom"]:
if unique_id in self.controller["Function"]:
return self.controller["Function"][unique_id].call_module_function(
button_id, args_dict, thread=thread)
button_id, args_dict, thread=thread, return_from_function=return_from_function)
else:
message = f"Attempting to call {button_id}() in inactive Function Controller with ID {unique_id}. Only active Function Controllers can have functions called."
self.logger.error(message)
Expand Down Expand Up @@ -1132,10 +1134,10 @@ def get_condition_measurement(self, condition_id):
def get_condition_measurement_dict(self, condition_id):
return self.mycodo.get_condition_measurement_dict(condition_id)

def module_function(self, controller_type, unique_id, button_id, args_dict, thread=True):
def module_function(self, controller_type, unique_id, button_id, args_dict, thread=True, return_from_function=False):
"""execute custom button function."""
return self.mycodo.module_function(
controller_type, unique_id, button_id, args_dict, thread)
controller_type, unique_id, button_id, args_dict, thread=thread, return_from_function=return_from_function)

def controller_activate(self, cont_id):
"""Activates a controller."""
Expand Down
9 changes: 3 additions & 6 deletions mycodo/mycodo_flask/utils/utils_general.py
Original file line number Diff line number Diff line change
Expand Up @@ -1800,15 +1800,12 @@ def custom_command(controller_type, dict_device, unique_id, form):
'wait_for_return' in options[button_id] and
options[button_id]['wait_for_return']):
use_thread = False
status = control.module_function(
status, msg = control.module_function(
controller_type, unique_id, button_id, args_dict, use_thread)
if status:
if status[0]:
messages["error"].append("Custom Button: {}".format(status[1]))
else:
messages["success"].append("Custom Button: {}".format(status[1]))
messages["error"].append("Custom Button: {}".format(msg))
else:
messages["error"].append("Custom Button didn't receive a return value")
messages["success"].append("Custom Button: {}".format(msg))

except Exception as except_msg:
logger.exception(1)
Expand Down
11 changes: 5 additions & 6 deletions mycodo/widgets/widget_camera.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,13 +70,12 @@ def camera_img_acquire(image_type, camera_unique_id, max_age):
args_dict = {
"tmp_filename": tmp_filename
}
status, response_list = control.module_function(
"Function", camera_unique_id, "capture_image", args_dict, thread=False)
status, response_dict = control.module_function(
"Function", camera_unique_id, "capture_image", args_dict, thread=False, return_from_function=True)
# find path/filename
for each in response_list:
if type(each) == dict and 'path' in each and 'filename' in each:
path = each['path']
filename = each['filename']
if type(response_dict) == dict and 'path' in response_dict and 'filename' in response_dict:
path = response_dict['path']
filename = response_dict['filename']

if not path and not filename:
msg = "Could not acquire image."
Expand Down

0 comments on commit e6734e9

Please sign in to comment.