Getting Unknown controller: Function_Custom error in a Custom Function

Ok!! Thanks for enlighting my doubts. I’ve runned some more tests… (i’m trying to help)

With the following code i got some weird behavior as you can see in the debug log at he end.

It’s basically the same, but i added 2 more ‘custom_options’, ‘integer_2’ (defined at init()) and ‘integer_3’ (defined in the button_one() command)

import time

from mycodo.databases.models import CustomController
from mycodo.functions.base_function import AbstractFunction
from mycodo.mycodo_client import DaemonControl
from mycodo.utils.constraints_pass import constraints_pass_positive_value
from mycodo.utils.database import db_retrieve_table_daemon


FUNCTION_INFORMATION = {
    'function_name_unique': 'custom_var_test3',
    'function_name': 'Var Test3',

    'message': 'This is a test of the Function options. ',

    'options_enabled': [
        'custom_options'
    ],

    
    # These options will appear in the settings of the Function,
    # which the user can use to set different values and options for the Function.
    # These settings can only be changed when the Function is inactive.
    'custom_options': [
        {
            'id': 'period',
            'type': 'integer',
            'default_value': 10,
            'required': True,
            'name': 'Function Period (seconds)',
            'phrase': 'The duration (seconds) to run the Function'
        },
        {
            'id': 'text_1',
            'type': 'text',
            'default_value': 'Text_1',
            'required': True,
            'name': 'Text 1',
            'phrase': 'Text 1 Description'
        },
        {
            'id': 'integer_1',
            'type': 'integer',
            'default_value': 100,
            'required': True,
            'constraints_pass': constraints_pass_positive_value,
            'name': 'Integer 1',
            'phrase': 'Integer 1 Description'
        }
        
    ],

    # Custom Actions give the user the ability to interact with the running Function Controller.
    # Each button will execute a different function within the Function Controller and pass any
    # input (text, numbers, selections, etc.) the user entered. This is useful for such things as
    # calibration.
    'custom_commands_message': 'This is a message for custom actions.',
    'custom_commands': [
        {
            'id': 'button_one_value',
            'type': 'integer',
            'default_value': 650,
            'required': True,
            'name': 'Button One Value',
            'phrase': 'Value for button one.'
        },
        {
            'id': 'button_one',  # Do a search for the function "button_one(self, args_dict)"
            'type': 'button',
            'wait_for_return': True,  # The UI will wait until the function has returned the UI with a value to display
            'name': 'Button One',
            'phrase': "This is button one"
        }
    ]
}


class CustomModule(AbstractFunction):
    """
    Class to operate custom controller
    """
    def __init__(self, function, testing=False):
        super().__init__(function, testing=testing, name=__name__)

        self.control = DaemonControl()
        self.timer_loop = time.time()
        #
        # Initialize what you defined in custom_options, above
        #
        # Standard custom options inherit the name you defined in the "id" key
        self.text_1 = None
        self.integer_1 = None
        self.period = None
        self.set_custom_option("integer_2", 2222) ##### WORKS!!!
        
       
        #
        # Set custom options
        #
        custom_function = db_retrieve_table_daemon(
            CustomController, unique_id=self.unique_id)
        self.setup_custom_options(
            FUNCTION_INFORMATION['custom_options'], custom_function)
        
        if not testing:
            self.try_initialize()

    def initialize(self):
        
        self.timer_loop = time.time()
        self.integer_2 = self.get_custom_option("integer_2")
        
        

    
    def loop(self):
        if self.timer_loop > time.time():
            return
        while self.timer_loop < time.time():
            self.timer_loop += self.period
            
       
        # sets new variable to monitor 'integer_1' custom option value  
        self.integer_1_update = self.get_custom_option("integer_1")
        self.button_one_value = self.get_custom_option("button_one_value")
        self.integer_2 = self.get_custom_option("integer_2")
        self.integer_3 = self.get_custom_option("integer_3")
        
        
        
        self.logger.debug(f'--------------------- Loop timer-------------------------')
        self.logger.debug(f'time.time(): {time.time()}')
        self.logger.debug(f'self.timer_loop: {self.timer_loop}')
        self.logger.debug(f'self.period: {self.period}')
        self.logger.debug(f'--------------------- Var -----------------------------')
        self.logger.debug(f'self.text_1: {self.text_1}')
        self.logger.debug(f'self.integer_1: {self.integer_1}')
        self.logger.debug(f'self.integer_1_update: {self.integer_1_update}')
        self.logger.debug(f'self.button_one_value: {self.button_one_value}')
        self.logger.debug(f'self.integer_2: {self.integer_2}')
        self.logger.debug(f'self.integer_3: {self.integer_3}')
        
        
        
        
        
    #Updates or create self.set_custom_option('button_one_value',) with button_one_value
    #updates integer_1 with button_one_value-1
    def button_one(self, args_dict):
        self.logger.error("Button One Pressed!: {}".format(int(args_dict['button_one_value'])))
        self.logger.debug("Button One Pressed!: {}".format(int(args_dict['button_one_value'])))
        try: 
            self.set_custom_option('button_one_value', int(args_dict['button_one_value']))
            self.set_custom_option('integer_1', int(args_dict['button_one_value']) - 1)
            self.set_custom_option("integer_3", 3333)
        except: self.logger.debug(f'Cannot set new button one value')
        
        return "Button One Pressed!"

The log is result of the operations:

1- Activate the functions with its default values.
2- Change to 10 the ‘button_one_value’ and press ‘button_one’ .
3- Deactivated the function and refresh browser. (screenshot)

2022-10-17 10:50:05,510 - INFO - mycodo.controllers.controller_function_dc18a35c - Activated in 1867.9 ms
2022-10-17 10:50:05,511 - DEBUG - mycodo.daemon - Function controller with ID dc18a35c-def0-4259-9578-0e22422e9261 activated.
2022-10-17 10:50:05,700 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - --------------------- Loop timer-------------------------
2022-10-17 10:50:05,702 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - time.time(): 1666014605.7024288
2022-10-17 10:50:05,703 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.timer_loop: 1666014615.4626243
2022-10-17 10:50:05,703 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.period: 10
2022-10-17 10:50:05,704 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - --------------------- Var -----------------------------
2022-10-17 10:50:05,704 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.text_1: Text_1
2022-10-17 10:50:05,710 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_1: 100
2022-10-17 10:50:05,715 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_1_update: 100
2022-10-17 10:50:05,721 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.button_one_value: None
2022-10-17 10:50:05,722 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_2: 2222
2022-10-17 10:50:05,723 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_3: None
2022-10-17 10:50:12,784 - ERROR - mycodo.function.custom_var_test3_dc18a35c - Button One Pressed!: 10
2022-10-17 10:50:12,785 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - Button One Pressed!: 10
2022-10-17 10:50:15,617 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - --------------------- Loop timer-------------------------
2022-10-17 10:50:15,617 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - time.time(): 1666014615.6176841
2022-10-17 10:50:15,618 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.timer_loop: 1666014625.4626243
2022-10-17 10:50:15,618 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.period: 10
2022-10-17 10:50:15,618 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - --------------------- Var -----------------------------
2022-10-17 10:50:15,618 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.text_1: Text_1
2022-10-17 10:50:15,618 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_1: 100
2022-10-17 10:50:15,618 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_1_update: 9
2022-10-17 10:50:15,619 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.button_one_value: 10
2022-10-17 10:50:15,619 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_2: 2222
2022-10-17 10:50:15,619 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_3: 3333
2022-10-17 10:50:19,148 - INFO - mycodo.controllers.controller_function_dc18a35c - Deactivated in 193.6 ms
2022-10-17 10:50:19,150 - DEBUG - mycodo.daemon - Function controller with ID dc18a35c-def0-4259-9578-0e22422e9261 deactivated.

4- Reactivated the function.
5- Deactivate the function and refresh browser. (screenshot)

2022-10-17 10:50:50,523 - INFO - mycodo.controllers.controller_function_dc18a35c - Activated in 558.1 ms
2022-10-17 10:50:50,523 - DEBUG - mycodo.daemon - Function controller with ID dc18a35c-def0-4259-9578-0e22422e9261 activated.
2022-10-17 10:50:50,751 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - --------------------- Loop timer-------------------------
2022-10-17 10:50:50,757 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - time.time(): 1666014650.7571816
2022-10-17 10:50:50,762 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.timer_loop: 1666014660.4774222
2022-10-17 10:50:50,768 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.period: 10
2022-10-17 10:50:50,770 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - --------------------- Var -----------------------------
2022-10-17 10:50:50,770 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.text_1: Text_1
2022-10-17 10:50:50,771 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_1: 9
2022-10-17 10:50:50,771 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_1_update: 9
2022-10-17 10:50:50,771 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.button_one_value: 10
2022-10-17 10:50:50,772 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_2: 2222
2022-10-17 10:50:50,772 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_3: 3333
2022-10-17 10:50:54,298 - INFO - mycodo.controllers.controller_function_dc18a35c - Deactivated in 108.2 ms
2022-10-17 10:50:54,304 - DEBUG - mycodo.daemon - Function controller with ID dc18a35c-def0-4259-9578-0e22422e9261 deactivated.

6- Change ‘integer_1’ from 9 to 100 and Save.
7- Activate the Function again.
8- Deactivate the function and refresh browser. (screenshot)

2022-10-17 10:51:45,356 - INFO - mycodo.controllers.controller_function_dc18a35c - Activated in 1032.6 ms
2022-10-17 10:51:45,356 - DEBUG - mycodo.daemon - Function controller with ID dc18a35c-def0-4259-9578-0e22422e9261 activated.
2022-10-17 10:51:45,547 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - --------------------- Loop timer-------------------------
2022-10-17 10:51:45,553 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - time.time(): 1666014705.5538113
2022-10-17 10:51:45,556 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.timer_loop: 1666014715.3125362
2022-10-17 10:51:45,557 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.period: 10
2022-10-17 10:51:45,557 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - --------------------- Var -----------------------------
2022-10-17 10:51:45,558 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.text_1: Text_1
2022-10-17 10:51:45,558 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_1: 100
2022-10-17 10:51:45,559 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_1_update: 100
2022-10-17 10:51:45,560 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.button_one_value: None
2022-10-17 10:51:45,560 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_2: 2222
2022-10-17 10:51:45,560 - DEBUG - mycodo.function.custom_var_test3_dc18a35c - self.integer_3: None

Am i doing something wrong again? ‘integer_3’ and ‘button_one_value’ disappeared from the ‘custom_options’ after i saved a new ‘integer_1’ value.

I’am running these tests because i’ve saw one post here in the forum saying that was possible to store “static variables” between reboots, but i’m not getting it.

Just to clarify: What I’m trying to do is like a Feed Schedule Function for a Drain-To-Waste hydroponics setup, where the user inputs the Start time, Span, Nº of feeds, Volume to feed, Reservoir volume, etc, and it do everything else for you, controlling Feed and recirculation pump and notificating the volume left in the reservoir with the help pf a Hall Flow meter. And my intention is to share the code here.



Post edited for clarification.

1 Like