Adding config options to custom input

I have created my first custom input for an HX711 Load Cell, which imported fine and is in the inputs dropdown. My problem is adding the config options like GPIO pin, etc.. Can someone look at my code and maybe point me in the right direction?

Thank you in advance.

from mycodo.inputs.base_input import Input
#from mycodo.mycodo_client.measurements import convert_units
from hx711 import HX711  # Ensure this library is installed

INPUT_INFORMATION = {
    'input_name_unique': 'HX711',
    'input_name': 'HX711 Load Cell',
    'input_manufacturer': 'Generic',
    'input_library': 'hx711',
    'measurements_name': 'Weight',
    'measurements_dict': {
        0: {'measurement': 'weight', 'unit': 'Grams'}
    },
    'url_manufacturer': 'https://github.com/robert-hh/hx711'
}

OPTIONS = {
    'dt_pin': {
        'type': 'int',
        'default': 5,
        'description': 'GPIO pin for DT (data)'
    },
    'sck_pin': {
        'type': 'int',
        'default': 6,
        'description': 'GPIO pin for SCK (clock)'
    },
    'scale': {
        'type': 'float',
        'default': 1.0,
        'description': 'Calibration scale factor'
    },
    'tare_offset': {
        'type': 'float',
        'default': 0.0,
        'description': 'Tare offset in grams'
    }
}

class InputModule(Input):
    def __init__(self, input_config, testing=False):
        super(InputModule, self).__init__(input_config, testing)
        self.dt_pin = int(self.get_setting('dt_pin', OPTIONS['dt_pin']['default']))
        self.sck_pin = int(self.get_setting('sck_pin', OPTIONS['sck_pin']['default'])) # Default GPIO 6
        self.scale = float(self.get_setting('scale', OPTIONS['scale']['default'])) # Calibration factor
        self.tare_offset = float(self.get_setting('tare_offset', OPTIONS['tare_offset']['default'])) # Optional tare

        try:
            self.hx = HX711(dout=self.dt_pin, pd_sck=self.sck_pin)
            self.hx.set_scale_ratio(self.scale)
            self.logger.info(f"HX711 initialized on DT={self.dt_pin}, SCK={self.sck_pin}")
        except Exception as e:
            self.logger.error(f"Failed to initialize HX711: {e}")
            self.hx = None
            
    def get_input_options(self):
        return OPTIONS            

    def get_measurement(self):
        if not self.hx:
            self.logger.error("HX711 not initialized")
            return None

        try:
            raw_weight = self.hx.get_weight_mean(5)  # Average of 5 readings
            weight = raw_weight - self.tare_offset
            self.logger.debug(f"Raw: {raw_weight}, Tared: {weight}")
            return {0: weight}
        except Exception as e:
            self.logger.error(f"Error reading HX711: {e}")
            return None

my apologies, I did something wrong posting that code… I hope you can understand it.

There are several issues with the module. See the wiki for building an Input module:

But just a brief list:

  1. The import of the core library should occur in initialize().
  2. dependencies should be defined in dependencies_module so the dependencies can be installed when the Input is created.
  3. setting the variables defined in the web UI settings should not be done in this way: self.dt_pin = int(self.get_setting('dt_pin', OPTIONS['dt_pin']['default'])), they need to be set to None, then calling self.setup_custom_options(INPUT_INFORMATION['custom_options'], input_dev) will set the variables.
  4. I’m not sure what get_input_options() is, this is not defined anywhere in Mycodo.
  5. OPTIONS is not used.
  6. custom_options is not defined, which is required to create settings fields in the web UI config for the Input.
  7. The object returned from get_measurement() should be a copy of the measurement dictionary that has the value added to it.

There are several other peculiarities that are not similar to the standard conventions used by any Input modules. It looks like you used a LLM to write this code. If so, I would highly advise not doing this and follow the guide I created, which explains each part of an input module and how to write your own.

So I started this process by editing mcp9808.py, which again worked somewhat, but somewhere along the line i made some errors which caused me issues and the config options failed to function. I decided to give Copilot a whirl to see if it was something simple that I missed, which led me down a rabbit hole, and now here I am. I am still learning python, so I appreciate your input. Thank you.

If you are going to use a LLM, you should feed in several existing input modules first, before having it help develop one. If you don’t, it has no idea what to base what it does and you’ll get something like the code in the OP.