ERROR - mycodo.actions - Condition ID not found

Hi,

I have defined a minimal example conditional controler with a dictionary for actions and measurements as an helper. I have a unexpected ERROR in the logs :

ERROR - mycodo.actions - Condition ID not found

What may happen since the IDs looks correct ?

Here is my code belonging to the Conditional Statement part (the Conditional Status one contains only return 0):

import time

io = {"mymes":"c4cc0971",
      "test output":"323d213a",
      }  

def action(nomAction, log=None):
    self.run_action("{" + io[nomAction] + "}", message=nomAction)
    if log is None:
        log = nomAction + " {" + io[nomAction] + "}"
    self.logger.info(log)

def mesure(nomMesure, log=None):
    ret = self.condition("{" + io[nomMesure] + "}")
    if log is None:
        log = nomMesure  + " {" + io[nomMesure] + "}"
    if ret is not None:
        self.logger.info(log + " = " + ret)
    else:
        self.logger.info(log + " = None")
    return ret

self.logger.info("Minimal Example")

if not hasattr(self, "state"):
    self.state = "init"
self.logger.info(f"State = {self.state}")

if self.state == "init":
    mymes = mesure("mymes")
    action("test output")
    time.sleep(1)
    self.state = "end"
    self.logger.info("State = end")

And the logs:

2022-06-22 12:50:42,509 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Activated in 97.2 ms
2022-06-22 12:50:42,538 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Minimal Example
2022-06-22 12:50:42,538 - INFO - mycodo.controllers.controller_conditional_087ea8ca - State = init
2022-06-22 12:50:42,575 - ERROR - mycodo.actions - Condition ID not found
2022-06-22 12:50:42,578 - INFO - mycodo.controllers.controller_conditional_087ea8ca - mymes {c4cc0971} = None
2022-06-22 12:50:42,620 - INFO - mycodo.controllers.controller_conditional_087ea8ca - test output {323d213a}
2022-06-22 12:50:43,622 - INFO - mycodo.controllers.controller_conditional_087ea8ca - State = end
2022-06-22 12:50:43,902 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Minimal Example
2022-06-22 12:50:43,902 - INFO - mycodo.controllers.controller_conditional_087ea8ca - State = end
2022-06-22 12:50:44,679 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Minimal Example
2022-06-22 12:50:44,708 - INFO - mycodo.controllers.controller_conditional_087ea8ca - State = end
2022-06-22 12:50:45,735 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Minimal Example
2022-06-22 12:50:45,736 - INFO - mycodo.controllers.controller_conditional_087ea8ca - State = end
2022-06-22 12:50:46,762 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Minimal Example
2022-06-22 12:50:46,762 - INFO - mycodo.controllers.controller_conditional_087ea8ca - State = end
2022-06-22 12:50:47,542 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Minimal Example
2022-06-22 12:50:47,543 - INFO - mycodo.controllers.controller_conditional_087ea8ca - State = end
2022-06-22 12:50:48,562 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Minimal Example
2022-06-22 12:50:48,563 - INFO - mycodo.controllers.controller_conditional_087ea8ca - State = end
2022-06-22 12:50:49,566 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Deactivated in 238.3 ms

Here are the I/O in the enclosed file. Sorry, no way to enclose the file nor copy/past a snapshot, but the ids are the right ones: c4cc0971 for the measurement and 323d213a for the action.

I had a python error: I did not generate ". Here is the correction, but I have still the same error.

def action(nomAction, log=None):
    self.run_action('"{' + io[nomAction] + '}"', message=nomAction)
    if log is None:
        log = nomAction + ' "{' + io[nomAction] + '}"'
    self.logger.info(log)

def mesure(nomMesure, log=None):
    ret = self.condition('"{' + io[nomMesure] + '}"')
    if log is None:
        log = nomMesure  + ' "{' + io[nomMesure] + '}"'
    if ret is not None:
        self.logger.info(log + " = " + ret)
    else:
        self.logger.info(log + " is None")
    return ret

Conditional Functions replace strings in the format {1234asdf} with the full UUID of the condition or action. If you save the Conditional using the proper formatting provided you will see the resulting pylint output that shows you the entire generated Class, and any short ID strings have been replaced with the entire UUID strings (if they exist). Since you are not providing this string anywhere in the code, it cannot be properly replaced.

I have modified the Conditional abstract base Class to accept literal strings of the format {1234asdf} to be sent to the condition/action function and parse it at the function level to find if the UUID exists for a condition/action.

1 Like

Thank you Kyle.

Could you please tag a version so I can upgrade ?
Alternatively, if I replace my Mycodo folder by the one of your last commit, is it safe (my setup was built from curl -L https://kizniche.github.io/Mycodo/install | bash) ?

1 Like

Use this method if you want to test code on the master branch:

You can also now leave off the curly brackets and just pass the short ID.

Done, but it looks broken now: Error 502: Bad Gateway Error:

pi@raspberrypi:~ $ sudo service mycodoflask status
\u25cf mycodoflask.service - Mycodo web user interface
   Loaded: loaded (/home/pi/Mycodo/install/mycodoflask.service; enabled; vendor preset: enabled)
   Active: failed (Result: exit-code) since Sat 2022-06-25 12:07:33 CEST; 5min ago
  Process: 604 ExecStart=/var/mycodo-root/env/bin/python -m gunicorn --workers 1 --worker-class gthread --threads 2 --timeout 300 --pid /var/run/mycodoflask.pid --b
 Main PID: 604 (code=exited, status=3)

juin 25 12:07:32 raspberrypi python[604]: sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: misc.measurement_db_name
juin 25 12:07:32 raspberrypi python[604]: [SQL: SELECT count(*) AS count_1
juin 25 12:07:32 raspberrypi python[604]: FROM (SELECT misc.id AS misc_id, misc.dismiss_notification AS misc_dismiss_notification, misc.force_https AS misc_force_ht
juin 25 12:07:32 raspberrypi python[604]: FROM misc) AS anon_1]
juin 25 12:07:32 raspberrypi python[604]: (Background on this error at: https://sqlalche.me/e/14/e3q8)
juin 25 12:07:32 raspberrypi python[604]: [2022-06-25 12:07:32 +0200] [741] [INFO] Worker exiting (pid: 741)
juin 25 12:07:33 raspberrypi python[604]: [2022-06-25 12:07:33 +0200] [604] [INFO] Shutting down: Master
juin 25 12:07:33 raspberrypi python[604]: [2022-06-25 12:07:33 +0200] [604] [INFO] Reason: Worker failed to boot.
juin 25 12:07:33 raspberrypi systemd[1]: mycodoflask.service: Main process exited, code=exited, status=3/NOTIMPLEMENTED
juin 25 12:07:33 raspberrypi systemd[1]: mycodoflask.service: Failed with result 'exit-code'.

It looks like the database is not in line with the new code.

I have a backup of my database from the Mycodo backup feature, but not of Mycodo. What do you suggest, is it correct?

  • I suppress the database /var/lib/influxdb/data/mycodo_db and /var/lib/influxdb/wal/mycodo_db
  • I suppress Mycodo
  • I reinstall
  • I import my backup

Here are also the upgrade logs : Mycodo upgrade v8.13.10 Master - b6dc0a6e

Hi Kyle, how can I revert please? I have only a backup from the Mycodo backup feature?
I stay very concise since all my messages with details have been filtered by the antispam.

There is a restore command:

The backup directory is /var/Mycodo-backups

1 Like

Thank you very much Kyle, for your kindness, availability, and your amazing piece of software. All what you have included is smart and great. I have managed software dev with many teams, and I can measure how much you are awsome.

1 Like

Hi Kyle,

Do you have an idea of the problem that occured when I upgraded to the last commit Add ability to use non-standard condition/action ID strings in Conditional Functions ?

raspberrypi python[604]: sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such column: misc.measurement_db_name

Did I make something wrong or something is missing to update the database?

As a turnover, I am going to modify my code to use long UUIDs. That would be nice to show them along with the short ones in the Conditional Controller.

Here is my final working code with the workaround. It enables me to write state machines in Conditional Controllers in a more readible way and less prone to errors with UUIDs.

import time

#io = {"mymes":"{c4cc0971}",
#      "test output":"{323d213a}"
#      }  
io = {"mymes":"c4cc0971-75f6-42e7-ba3f-0c23a09bf169",
      "test output":"323d213a-af09-469a-b687-c9a4760f741e"
      }  

def action(name, log=None, io=io):
    if name in io:
        self.run_action(io[name], message=name)
        if log is None:
            log = name + ' "' + io[name] + '"'
    else:
        log  = "ERROR : " + name + " is undefined"
    self.logger.info(log)

def measure(name, log=None, io=io):
    if name in io:
        ret = self.condition(io[name])
        if log is None:
            log = name  + ' "' + io[name] + '"'
    else:
        log  = "ERROR : " + name + " is undefined"
    if ret is not None:
        self.logger.info(log + " = " + str(ret))
    else:
        self.logger.info(log + " is None")
    return ret

def change_state(init, target):
    if self.state != init:
        log  = "ERROR : the current state is not " + init + " but " + self.state
    else:
        self.state = target
        log = "State change : " + init + " --> " + target
    self.logger.info(log)


if not hasattr(self, "state"):
    self.state = "init"

if self.state != "end":
    self.logger.info(f"Minimal Example - State = {self.state}")

if self.state == "init":
    mymes = measure("mymes")
    action("test output")
    time.sleep(1)
    change_state("init", "end")

if False:
    m = self.condition("{c4cc0971}")
    self.run_action("{323d213a}")

The last part with if False is to get the long UUIDs from pylint.

and the logs:

2022-06-26 11:07:37,568 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Activated in 39.1 ms
2022-06-26 11:07:37,581 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Minimal Example - State = init
2022-06-26 11:07:37,645 - INFO - mycodo.controllers.controller_conditional_087ea8ca - mymes "c4cc0971-75f6-42e7-ba3f-0c23a09bf169" = 0.0
2022-06-26 11:07:37,922 - INFO - mycodo.controllers.controller_conditional_087ea8ca - test output "323d213a-af09-469a-b687-c9a4760f741e"
2022-06-26 11:07:38,924 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Changement d'état : init --> fin
2022-06-26 11:07:40,735 - INFO - mycodo.controllers.controller_conditional_087ea8ca - Deactivated in 67.8 ms

Your database schema didn’t update during the upgrade. Why it didn’t, I have no idea. Try the upgrade to master again.

Ok, thanks, I will next week.

Hi Kyle, I lost this piece of code above I did make work. I have difficulties to make it work again, as if your modification were not anymore in mycodo v8.15.8. Could you please confirm it is still there?

I haven’t removed any of the above code.