Error after upgrade to master

Hi,

Had a working system just with an i2c temp sensor issue, upgraded to master in case this was addressed. But now find my conditional controller is throwing errors:

# Desired range for electrical conductivity

range_ec_high = 1500    # 2.5 During Fruiting
range_ec_low = 1200     # 1.8 During Fruiting

# Desired range for pH
range_ph_high = 6.3
range_ph_low = 5.8

# pH range that will immediately cause a pH correction
range_ph_high_danger = 7.0
range_ph_low_danger = 5.0

### Edit below to set the IDs for Conditions and Actions ###
condition_id_measurement_ph_id = "{862e818d}"  # Condition: measurement, last, pH Input
condition_id_measurement_ec_id = "{268cc649}"  # Condition: measurement, last, EC Input
action_id_pump_1_acid = "{99c85210}"  # Action: Pump 1 (Acid)
action_id_pump_2_base = "{b204ce29}"  # Action: Pump 2 (Base)
action_id_pump_2_nutrient_a = "{0e20dfa7}"  # Action: Pump 3 (Nutrient A)
###action_id_pump_3_nutrient_b = "{14260317}"  # Action: Pump 3 (Nutrient B)
action_id_email_notification = "{e4ca2133}"  # Action: Email Notification
### DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING ###
import time
if 'notify_ec' not in self.variables:  # Initiate EC notification timer
    self.variables['notify_ec'] = 0
if 'notify_ph' not in self.variables:  # Initiate pH notification timer
    self.variables['notify_ph'] = 0
if 'notify_none' not in self.variables:  # Initiate None measurement notification timer
    self.variables['notify_none'] = 0
measure_ec = self.condition(condition_id_measurement_ec_id)
measure_ph = self.condition(condition_id_measurement_ph_id)
self.logger.debug("Conditional check. EC: {}, pH: {}".format(measure_ec, measure_ph))
if None in [measure_ec, measure_ph]:
    if measure_ec is None:
        self.message += "\nWarning: No EC Measurement! Check sensor!"
    if measure_ph is None:
        self.message += "\nWarning: No pH Measurement! Check sensor!"
    if self.variables['notify_none'] < time.time():  # Only notify every 12 hours
        self.variables['notify_none'] = time.time() + 43200  # 12 hours
        self.run_action(action_id_email_notification, message=self.message)  # Email alert
    return
# First check if pH is dangerously low or high, and adjust if it is
if measure_ph < range_ph_low_danger:  # pH dangerously low, add base (pH up)
    msg = "pH is dangerously low: {}. Should be > {}. Dispensing 1 ml base".format(measure_ph, range_ph_low_danger)
    self.logger.debug(msg)
    self.message += msg
    self.run_action(action_id_pump_2_base)  # Dispense 1 ml base (pH up)
    if self.variables['notify_ph'] < time.time():  # Only notify every 12 hours
        self.variables['notify_ph'] = time.time() + 43200  # 12 hours
        self.run_action(action_id_email_notification, message=self.message)  # Email alert
elif measure_ph > range_ph_high_danger:  # pH dangerously high, add acid (pH down)
    msg = "pH is dangerously high: {}. Should be < {}. Dispensing 1 ml acid".format(measure_ph, range_ph_high_danger)
    self.logger.debug(msg)
    self.message += msg
    self.run_action(action_id_pump_1_acid)  # Dispense 1 ml acid (pH down)
    if self.variables['notify_ph'] < time.time():  # Only notify every 12 hours
        self.variables['notify_ph'] = time.time() + 43200  # 12 hours
        self.run_action(action_id_email_notification, message=self.message)  # Email alert
# If pH isn't dangerously low or high, check if EC is within range
elif measure_ec < range_ec_low:  # EC too low, add nutrient
    self.logger.debug("EC: {}. Should be > {}. Dosing 3 ml Nut A, 3 ml Nut B".format(measure_ec, range_ec_low))
    self.run_action(action_id_pump_3_nutrient_a)  # Dispense 3 ml nutrient A
    self.run_action(action_id_pump_4_nutrient_b)  # Dispense 3 ml nutrient B
elif measure_ec > range_ec_high:  # EC too high, add nutrient
    msg = "EC: {}. Should be < {}. Need to add water to dilute!".format(measure_ec, range_ec_high)
    self.logger.debug(msg)
    if self.variables['notify_ec'] < time.time():  # Only notify every 12 hours
        self.variables['notify_ec'] = time.time() + 43200  # 12 hours
        self.message += msg
        self.run_action(action_id_email_notification, message=self.message)  # Email alert
# If EC is in range, make sure pH is within range
elif measure_ph < range_ph_low:  # pH too low, add base (pH up)
    self.logger.debug("pH is {}. Should be > {}. Dispensing 1 ml base".format(measure_ph, range_ph_low))
    self.run_action(action_id_pump_2_base)  # Dispense 1 ml base (pH up)
elif measure_ph > range_ph_high:  # pH too high, add acid (pH down)
    self.logger.debug("pH is {}. Should be < {}. Dispensing 1 ml acid".format(measure_ph, range_ph_high))
    self.run_action(action_id_pump_1_acid)  # Dispense 1 ml acid (pH down)
************* Module mycodo.user_python_code.conditional_432bdfe1-99e2-4212-a3af-4b283c82f836
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:41:8: C0415: Import outside toplevel (time) (import-outside-toplevel)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:50:26: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:62:18: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:70:18: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:79:30: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:80:28: E0602: Undefined variable 'action_id_pump_3_nutrient_a' (undefined-variable)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:81:28: E0602: Undefined variable 'action_id_pump_4_nutrient_b' (undefined-variable)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:83:18: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:91:30: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:94:30: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:37:8: W0612: Unused variable 'action_id_pump_2_nutrient_a' (unused-variable)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:101:58: E1101: Instance of 'ConditionalRun' has no 'loop_count' member (no-member)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:102:26: E1101: Instance of 'ConditionalRun' has no 'loop_count' member (no-member)

-----------------------------------
Your code has been rated at 6.46/10

Any thoughts what has changed. Thanks

Hi,

What I have tried so far;
Deleted all inputs, outputs and functions as per another post.
Reentered everything from start, inputs, outputs and enter new device numbers into controller code.

Thanks

You need to paste the code output that goes with the pylint output. You can’t associate any of the warnings/errors and line numbers without the actual output that has the line numbers.

Hi Kyle,

Yes of course.

  1: import os
  2: import sys
  3: sys.path.append(os.path.abspath('/var/mycodo-root'))
  4: from mycodo.controllers.base_conditional import AbstractConditional
  5: from mycodo.mycodo_client import DaemonControl
  6: control = DaemonControl(pyro_timeout=30.0)
  7: 
  8: class ConditionalRun(AbstractConditional):
  9:     def __init__(self, logger, function_id, message):
 10:         super().__init__(logger, function_id, message, timeout=30.0)
 11: 
 12:         self.logger = logger
 13:         self.function_id = function_id
 14:         self.variables = {}
 15:         self.message = message
 16:         self.running = True
 17: 
 18:     def conditional_code_run(self):
 19:         # Desired range for electrical conductivity
 20: 
 21:         range_ec_high = 1500    # 2.5 During Fruiting
 22:         range_ec_low = 1200     # 1.8 During Fruiting
 23: 
 24:         # Desired range for pH
 25:         range_ph_high = 6.3
 26:         range_ph_low = 5.8
 27: 
 28:         # pH range that will immediately cause a pH correction
 29:         range_ph_high_danger = 7.0
 30:         range_ph_low_danger = 5.0
 31: 
 32:         ### Edit below to set the IDs for Conditions and Actions ###
 33:         condition_id_measurement_ph_id = "1ff1299e-9d0c-4f41-aa67-b68a5af0a772"  # Condition: measurement, last, pH Input
 34:         condition_id_measurement_ec_id = "1c2208e0-7eeb-44eb-a986-9a3ecab69a8b"  # Condition: measurement, last, EC Input
 35:         action_id_pump_1_acid = "4f48e70f-b453-403c-8655-c974d4e2ca44"  # Action: Pump 2 (Acid)
 36:         action_id_pump_2_base = "abc4502d-eee9-42f9-bce8-7eb34e2440c7"  # Action: Pump 3 (Base)
 37:         action_id_pump_3_nutrient_a = "bbaf8ec6-f1fd-46f2-bcc6-2a4d27588faa"  # Action: Pump 3 (Nutrient A)
 38:         ###action_id_pump_4_nutrient_b = "{0e20dfa7}"  # Action: Pump 4 (Nutrient A)
 39:         action_id_email_notification = "fa67eab5-d06e-403d-9029-1c47618974a3"  # Action: Email Notification
 40:         ### DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING ###
 41:         import time
 42:         if 'notify_ec' not in self.variables:  # Initiate EC notification timer
 43:             self.variables['notify_ec'] = 0
 44:         if 'notify_ph' not in self.variables:  # Initiate pH notification timer
 45:             self.variables['notify_ph'] = 0
 46:         if 'notify_none' not in self.variables:  # Initiate None measurement notification timer
 47:             self.variables['notify_none'] = 0
 48:         measure_ec = self.condition(condition_id_measurement_ec_id)
 49:         measure_ph = self.condition(condition_id_measurement_ph_id)
 50:         self.logger.debug("Conditional check. EC: {}, pH: {}".format(measure_ec, measure_ph))
 51:         if None in [measure_ec, measure_ph]:
 52:             if measure_ec is None:
 53:                 self.message += "\nWarning: No EC Measurement! Check sensor!"
 54:             if measure_ph is None:
 55:                 self.message += "\nWarning: No pH Measurement! Check sensor!"
 56:             if self.variables['notify_none'] < time.time():  # Only notify every 12 hours
 57:                 self.variables['notify_none'] = time.time() + 43200  # 12 hours
 58:                 self.run_action(action_id_email_notification, message=self.message)  # Email alert
 59:             return
 60:         # First check if pH is dangerously low or high, and adjust if it is
 61:         if measure_ph < range_ph_low_danger:  # pH dangerously low, add base (pH up)
 62:             msg = "pH is dangerously low: {}. Should be > {}. Dispensing 1 ml base".format(measure_ph, range_ph_low_danger)
 63:             self.logger.debug(msg)
 64:             self.message += msg
 65:             self.run_action(action_id_pump_2_base)  # Dispense 1 ml base (pH up)
 66:             if self.variables['notify_ph'] < time.time():  # Only notify every 12 hours
 67:                 self.variables['notify_ph'] = time.time() + 43200  # 12 hours
 68:                 self.run_action(action_id_email_notification, message=self.message)  # Email alert
 69:         elif measure_ph > range_ph_high_danger:  # pH dangerously high, add acid (pH down)
 70:             msg = "pH is dangerously high: {}. Should be < {}. Dispensing 1 ml acid".format(measure_ph, range_ph_high_danger)
 71:             self.logger.debug(msg)
 72:             self.message += msg
 73:             self.run_action(action_id_pump_1_acid)  # Dispense 1 ml acid (pH down)
 74:             if self.variables['notify_ph'] < time.time():  # Only notify every 12 hours
 75:                 self.variables['notify_ph'] = time.time() + 43200  # 12 hours
 76:                 self.run_action(action_id_email_notification, message=self.message)  # Email alert
 77:         # If pH isn't dangerously low or high, check if EC is within range
 78:         elif measure_ec < range_ec_low:  # EC too low, add nutrient
 79:             self.logger.debug("EC: {}. Should be > {}. Dosing 3 ml Nut A, 3 ml Nut B".format(measure_ec, range_ec_low))
 80:             self.run_action(action_id_pump_3_nutrient_a)  # Dispense 3 ml nutrient A
 81:         elif measure_ec > range_ec_high:  # EC too high, add nutrient
 82:             msg = "EC: {}. Should be < {}. Need to add water to dilute!".format(measure_ec, range_ec_high)
 83:             self.logger.debug(msg)
 84:             if self.variables['notify_ec'] < time.time():  # Only notify every 12 hours
 85:                 self.variables['notify_ec'] = time.time() + 43200  # 12 hours
 86:                 self.message += msg
 87:                 self.run_action(action_id_email_notification, message=self.message)  # Email alert
 88:         # If EC is in range, make sure pH is within range
 89:         elif measure_ph < range_ph_low:  # pH too low, add base (pH up)
 90:             self.logger.debug("pH is {}. Should be > {}. Dispensing 1 ml base".format(measure_ph, range_ph_low))
 91:             self.run_action(action_id_pump_2_base)  # Dispense 1 ml base (pH up)
 92:         elif measure_ph > range_ph_high:  # pH too high, add acid (pH down)
 93:             self.logger.debug("pH is {}. Should be < {}. Dispensing 1 ml acid".format(measure_ph, range_ph_high))
 94:             self.run_action(action_id_pump_1_acid)  # Dispense 1 ml acid (pH down)
 95: 
 96:     def function_status(self):
 97:         # Example code to provide a return status for other controllers and widgets.
 98:         status_dict = {
 99:             'string_status': f"This is the demo status of the conditional controller. "
100:                              f"The controller has looped {self.loop_count} times",
101:             'loop_count': self.loop_count,
102:             'error': []
103:         }
104:         return status_dict

Conditional Statement code analysis:

************* Module mycodo.user_python_code.conditional_432bdfe1-99e2-4212-a3af-4b283c82f836
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:41:8: C0415: Import outside toplevel (time) (import-outside-toplevel)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:50:26: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:62:18: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:70:18: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:79:30: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:82:18: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:90:30: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:93:30: C0209: Formatting a regular string which could be a f-string (consider-using-f-string)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:100:58: E1101: Instance of 'ConditionalRun' has no 'loop_count' member (no-member)
craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py:101:26: E1101: Instance of 'ConditionalRun' has no 'loop_count' member (no-member)

------------------------------------------------------------------
Your code has been rated at 7.78/10 (previous run: 7.78/10, +0.00)

and from the Mycodo log.

2022-08-03 14:48:31,772 - DEBUG - mycodo.controllers.controller_conditional_432bdfe1 - Conditional check. EC: 1200.0, pH: 5.381
2022-08-03 14:48:31,772 - DEBUG - mycodo.controllers.controller_conditional_432bdfe1 - pH is 5.381. Should be > 5.8. Dispensing 1 ml base
2022-08-03 14:48:31,772 - ERROR - mycodo.controllers.controller_conditional_432bdfe1 - Exception executing Conditional Statement code
Traceback (most recent call last):
  File "/var/mycodo-root/mycodo/controllers/controller_conditional.py", line 175, in check_conditionals
    self.conditional_run.conditional_code_run()
  File "/home/craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py", line 91, in conditional_code_run
    self.run_action(action_id_pump_2_base)  # Dispense 1 ml base (pH up)
  File "/var/mycodo-root/mycodo/controllers/base_conditional.py", line 48, in run_action
    if action:
UnboundLocalError: local variable 'action' referenced before assignment
2022-08-03 14:49:18,982 - INFO - mycodo.controllers.controller_conditional_2813b927 - This INFO log entry will appear in the Daemon Log
2022-08-03 14:49:18,983 - ERROR - mycodo.controllers.controller_conditional_2813b927 - This ERROR log entry will appear in the Daemon Log
2022-08-03 14:49:19,137 - INFO - mycodo.controllers.controller_conditional_2813b927 - Check this measurement in the Daemon Log. The value is 19.5
2022-08-03 14:49:32,064 - DEBUG - mycodo.controllers.controller_conditional_432bdfe1 - Conditional check. EC: 1200.0, pH: 5.383
2022-08-03 14:49:32,065 - DEBUG - mycodo.controllers.controller_conditional_432bdfe1 - pH is 5.383. Should be > 5.8. Dispensing 1 ml base
2022-08-03 14:49:32,065 - ERROR - mycodo.controllers.controller_conditional_432bdfe1 - Exception executing Conditional Statement code
Traceback (most recent call last):
  File "/var/mycodo-root/mycodo/controllers/controller_conditional.py", line 175, in check_conditionals
    self.conditional_run.conditional_code_run()
  File "/home/craig/Mycodo/mycodo/user_python_code/conditional_432bdfe1-99e2-4212-a3af-4b283c82f836.py", line 91, in conditional_code_run
    self.run_action(action_id_pump_2_base)  # Dispense 1 ml base (pH up)
  File "/var/mycodo-root/mycodo/controllers/base_conditional.py", line 48, in run_action
    if action:
UnboundLocalError: local variable 'action' referenced before assignment

Thanks
Craig

1 Like

Thanks. The Daemon log was the biggest help. I think I figured out the issue. I just made a potential fix:

If you would like to test the new code, upgrade to master.

Beautiful that got it. Thanks