Skip to content

Commit

Permalink
Fix Actions not executing for MQTT, TTN, and Python Code Inputs (#1336)…
Browse files Browse the repository at this point in the history
…, Fix Python Code Inputs running pylint
  • Loading branch information
kizniche committed Nov 21, 2023
1 parent 4e7ba6e commit 72c1dde
Show file tree
Hide file tree
Showing 15 changed files with 81 additions and 67 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

- Add Input Action: Execute Python 3 Code ([#1334](https://github.com/kizniche/Mycodo/issues/1334))

### Bugfixes

- Fix Actions not executing for MQTT, TTN, and Python Code Inputs ([#1336](https://github.com/kizniche/Mycodo/issues/1336))
- Fix Python Code Inputs running pylint


## 8.15.12 (2023.10.28)

Expand Down
2 changes: 1 addition & 1 deletion mycodo/actions/input_action_equation.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def run_action(self, dict_vars):

if original_value is None:
msg = f" Error: No measurement found in dictionary passed to Action for channel {channel}."
self.logger.error(msg)
self.logger.debug(msg)
dict_vars['message'] += msg
return dict_vars

Expand Down
2 changes: 1 addition & 1 deletion mycodo/actions/input_action_mqtt_publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ def run_action(self, dict_vars):
self.logger.debug(f"Input channel: {channel}, payload: {payload}")

if payload is None:
msg = f" Error: No measurement found in dictionary passed to Action for channel {channel}."
msg = f" Error: No measurement found in payload for {channel}."
self.logger.error(msg)
dict_vars["message"] += msg
return dict_vars
Expand Down
21 changes: 4 additions & 17 deletions mycodo/controllers/controller_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,12 @@
import time

from mycodo.controllers.base_controller import AbstractController
from mycodo.databases.models import (SMTP, Actions, Conversion,
from mycodo.databases.models import (SMTP, Conversion,
DeviceMeasurements, Input, Misc, Output,
OutputChannel)
from mycodo.inputs.base_input import AbstractInput
from mycodo.mycodo_client import DaemonControl
from mycodo.utils.actions import run_input_actions
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import add_measurements_influxdb
from mycodo.utils.inputs import parse_input_information, parse_measurement
Expand Down Expand Up @@ -218,23 +219,9 @@ def loop(self):
if self.measurement_success:
measurements_dict = self.create_measurements_dict()

# Run any actions
# Run actions
message = "Executing actions of Input."
actions = db_retrieve_table_daemon(Actions).filter(
Actions.function_id == self.unique_id).all()
for each_action in actions:
return_dict = self.control.trigger_action(
each_action.unique_id,
value={"message": message, "measurements_dict": measurements_dict},
debug=self.log_level_debug)

# if message is returned, set message
if return_dict and 'message' in return_dict and return_dict['message']:
message = return_dict['message']

# if measurements_dict is returned, use that to store measurements
if return_dict and 'measurements_dict' in return_dict and return_dict['measurements_dict']:
measurements_dict = return_dict['measurements_dict']
message, measurements_dict = run_input_actions(self.unique_id, message, measurements_dict, self.log_level_debug)

# Add measurement(s) to influxdb
use_same_timestamp = True
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from mycodo.databases.models import Conversion
from mycodo.databases.models import InputChannel
from mycodo.inputs.base_input import AbstractInput
from mycodo.utils.actions import run_input_actions
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import add_measurements_influxdb
from mycodo.utils.inputs import parse_measurement
Expand Down Expand Up @@ -333,9 +334,10 @@ def __init__(self, input_dev, testing=False):

self.random = None
self.interface = None
self.resolution = None
self.i2c_address = None
self.i2c_bus = None
self.resolution = None
self.log_level_debug = None

#
# Set variables to custom options
Expand Down Expand Up @@ -374,6 +376,7 @@ def initialize(self):
#

self.resolution = self.input_dev.resolution
self.log_level_debug = self.input_dev.log_level_debug

#
# Initialize the sensor class
Expand Down Expand Up @@ -441,6 +444,9 @@ def get_measurement(self):
measurements[channel]['value'] = meas[channel]['value']

if measurements:
# Run Actions for Input before saving measurements to database
message, measurements = run_input_actions(self.unique_id, "", measurements, self.log_level_debug)

self.logger.debug("Adding measurements to influxdb: {}".format(measurements))
add_measurements_influxdb(
self.unique_id, measurements,
Expand Down
6 changes: 6 additions & 0 deletions mycodo/inputs/mqtt_paho.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from mycodo.databases.models import Conversion
from mycodo.databases.models import InputChannel
from mycodo.inputs.base_input import AbstractInput
from mycodo.utils.actions import run_input_actions
from mycodo.utils.constraints_pass import constraints_pass_positive_value
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import add_measurements_influxdb
Expand Down Expand Up @@ -154,6 +155,7 @@ class InputModule(AbstractInput):
def __init__(self, input_dev, testing=False):
super().__init__(input_dev, testing=testing, name=__name__)

self.log_level_debug = None
self.client = None

self.mqtt_hostname = None
Expand All @@ -175,6 +177,8 @@ def __init__(self, input_dev, testing=False):
def initialize(self):
import paho.mqtt.client as mqtt

self.log_level_debug = self.input_dev.log_level_debug

input_channels = db_retrieve_table_daemon(
InputChannel).filter(InputChannel.input_id == self.input_dev.unique_id).all()
self.options_channels = self.setup_custom_channel_options_json(
Expand Down Expand Up @@ -276,6 +280,8 @@ def on_message(self, client, userdata, msg):
measurement = self.check_conversion(channel, measurement)

if measurement:
message, measurement = run_input_actions(self.unique_id, "", measurement, self.log_level_debug)

self.logger.debug(f"Adding measurement to influxdb: {measurement}")
add_measurements_influxdb(
self.unique_id,
Expand Down
8 changes: 6 additions & 2 deletions mycodo/inputs/mqtt_paho_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import json

from flask_babel import lazy_gettext

from mycodo.utils.actions import run_input_actions
from mycodo.config_translations import TRANSLATIONS
from mycodo.databases.models import Conversion
from mycodo.databases.models import InputChannel
Expand Down Expand Up @@ -170,6 +170,7 @@ class InputModule(AbstractInput):
def __init__(self, input_dev, testing=False):
super().__init__(input_dev, testing=testing, name=__name__)

self.log_level_debug = None
self.client = None
self.jmespath = None
self.options_channels = None
Expand All @@ -195,6 +196,7 @@ def initialize(self):
import jmespath

self.jmespath = jmespath
self.log_level_debug = self.input_dev.log_level_debug

input_channels = db_retrieve_table_daemon(
InputChannel).filter(InputChannel.input_id == self.input_dev.unique_id).all()
Expand Down Expand Up @@ -307,7 +309,9 @@ def on_message(self, client, userdata, msg):
self.logger.error(
"Error in JSON '{}' finding '{}': {}".format(
json_values, json_name, err))


message, measurement = run_input_actions(self.unique_id, "", measurement, self.log_level_debug)

self.logger.debug(f"Adding measurement to influxdb: {measurement}")
add_measurements_influxdb(
self.unique_id,
Expand Down
5 changes: 4 additions & 1 deletion mycodo/inputs/python_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ def generate_code(new_input):
sys.path.append(os.path.abspath('/var/mycodo-root'))
from mycodo.databases.models import Conversion
from mycodo.mycodo_client import DaemonControl
from mycodo.utils.actions import run_input_actions
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import add_measurements_influxdb
from mycodo.utils.inputs import parse_measurement
Expand Down Expand Up @@ -68,6 +69,8 @@ def store_measurement(self, channel=None, measurement=None, timestamp=None):
measure[channel]['unit'] = meas_conv[channel]['unit']
measure[channel]['value'] = meas_conv[channel]['value']
message, measure = run_input_actions(self.input_id, "", measure)
add_measurements_influxdb(self.input_id, measure)
def python_code_run(self):
Expand Down Expand Up @@ -150,7 +153,7 @@ def execute_at_modification(
'export PYLINTHOME=/var/mycodo-root/.pylint.d && ' \
'{dir}/env/bin/python -m pylint -d I,W0621,C0103,C0111,C0301,C0327,C0410,C0413 {path}'.format(
dir=INSTALL_DIRECTORY, path=file_run)
cmd_out, cmd_error, cmd_status = cmd_output(cmd_test)
cmd_out, cmd_error, cmd_status = cmd_output(cmd_test, user='root')
pylint_message = Markup(
'<pre>\n\n'
'Full Python Code Input code:\n\n{code}\n\n'
Expand Down
42 changes: 4 additions & 38 deletions mycodo/inputs/python_code_v_2_0.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,7 @@ def generate_code(input_id, python_code):
pre_statement_run = """import os
import sys
sys.path.append(os.path.abspath('/var/mycodo-root'))
from mycodo.databases.models import Conversion
from mycodo.mycodo_client import DaemonControl
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import add_measurements_influxdb
from mycodo.utils.inputs import parse_measurement
control = DaemonControl()
class PythonInputRun:
Expand All @@ -39,38 +35,6 @@ def __init__(self, logger, input_id, measurement_info, channels_conversion, chan
self.channels_conversion = channels_conversion
self.channels_measurement = channels_measurement
def store_measurement(self, channel=None, measurement=None, timestamp=None):
if None in [channel, measurement]:
return
measure = {
channel: {
'measurement': self.measurement_info[channel]['measurement'],
'unit': self.measurement_info[channel]['unit'],
'value': measurement,
'timestamp_utc': None
}
}
if timestamp:
measure[channel]['timestamp_utc'] = timestamp
if channel in self.channels_conversion and self.channels_conversion[channel]:
conversion = db_retrieve_table_daemon(
Conversion,
unique_id=self.channels_measurement[channel].conversion_id)
if conversion: # Convert value/unit is conversion_id present and valid
meas_conv = parse_measurement(
self.channels_conversion[channel],
self.channels_measurement[channel],
measure,
channel,
measure[channel],
timestamp=measure[channel]['timestamp_utc'])
measure[channel]['measurement'] = meas_conv[channel]['measurement']
measure[channel]['unit'] = meas_conv[channel]['unit']
measure[channel]['value'] = meas_conv[channel]['value']
add_measurements_influxdb(self.input_id, measure)
def python_code_run(self):
"""

Expand Down Expand Up @@ -164,7 +128,7 @@ def execute_at_modification(
'export PYLINTHOME=/var/mycodo-root/.pylint.d && ' \
'{dir}/env/bin/python -m pylint -d I,W0621,C0103,C0111,C0301,C0327,C0410,C0413 {path}'.format(
dir=INSTALL_DIRECTORY, path=file_run)
cmd_out, cmd_error, cmd_status = cmd_output(cmd_test)
cmd_out, cmd_error, cmd_status = cmd_output(cmd_test, user='root')
pylint_message = Markup(
'<pre>\n\n'
'Full Python Code Input code:\n\n{code}\n\n'
Expand All @@ -173,6 +137,7 @@ def execute_at_modification(
code=lines_code, report=cmd_out.decode("utf-8")))
except Exception as err:
cmd_status = None
cmd_error = None
messages["error"].append("Error running pylint: {}".format(err))

if cmd_status:
Expand Down Expand Up @@ -206,7 +171,8 @@ def execute_at_modification(

'message': 'This is an alternate Python 3 Code Input that uses a different method for storing values to the '
'database. This was created because the Python 3 Code v1.0 Input does not allow the use of Input '
'Actions. This method does allow the use of Input Actions. '
'Actions. This method does allow the use of Input Actions. (11/21/2023 Update: The Python 3 Code '
'(v1.0) Input now allows the execution of Actions). '
'All channels require a Measurement Unit to be selected and saved in order to store values to the '
'database. Your code is executed from the same Python virtual environment that Mycodo runs from. '
'Therefore, you must install Python libraries to this environment if you want them to be available to '
Expand Down
5 changes: 5 additions & 0 deletions mycodo/inputs/ttn_data_storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from mycodo.databases.models import InputChannel
from mycodo.databases.utils import session_scope
from mycodo.inputs.base_input import AbstractInput
from mycodo.utils.actions import run_input_actions
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import add_measurements_influxdb
from mycodo.utils.inputs import parse_measurement
Expand Down Expand Up @@ -124,6 +125,7 @@ class InputModule(AbstractInput):
def __init__(self, input_dev, testing=False):
super().__init__(input_dev, testing=testing, name=__name__)

self.log_level_debug = None
self.first_run = True

self.application_id = None
Expand All @@ -136,6 +138,7 @@ def __init__(self, input_dev, testing=False):
self.try_initialize()

def initialize(self):
self.log_level_debug = self.input_dev.log_level_debug
self.interface = self.input_dev.interface
self.period = self.input_dev.period
self.latest_datetime = self.input_dev.datetime
Expand Down Expand Up @@ -211,6 +214,8 @@ def get_new_data(self, past_seconds):
measurements[channel]['value'] = meas[channel]['value']

if measurements:
message, measurements = run_input_actions(self.unique_id, "", measurements, self.log_level_debug)

self.logger.debug("Adding measurements to influxdb: {}".format(measurements))
add_measurements_influxdb(
self.unique_id, measurements,
Expand Down
5 changes: 5 additions & 0 deletions mycodo/inputs/ttn_data_storage_ttn_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from mycodo.databases.models import InputChannel
from mycodo.databases.utils import session_scope
from mycodo.inputs.base_input import AbstractInput
from mycodo.utils.actions import run_input_actions
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import add_measurements_influxdb
from mycodo.utils.inputs import parse_measurement
Expand Down Expand Up @@ -127,6 +128,7 @@ class InputModule(AbstractInput):
def __init__(self, input_dev, testing=False):
super().__init__(input_dev, testing=testing, name=__name__)

self.log_level_debug = None
self.first_run = True

self.application_id = None
Expand All @@ -146,6 +148,7 @@ def __init__(self, input_dev, testing=False):
self.try_initialize()

def initialize(self):
self.log_level_debug = self.input_dev.log_level_debug
self.interface = self.input_dev.interface
self.period = self.input_dev.period
self.latest_datetime = self.input_dev.datetime
Expand Down Expand Up @@ -260,6 +263,8 @@ def get_new_data(self, past_seconds):
measurements[channel]['value'] = meas[channel]['value']

if measurements:
message, measurements = run_input_actions(self.unique_id, "", measurements, self.log_level_debug)

self.logger.debug("Adding measurements to influxdb: {}".format(measurements))
add_measurements_influxdb(
self.unique_id, measurements,
Expand Down
5 changes: 5 additions & 0 deletions mycodo/inputs/ttn_data_storage_ttn_v3_jmespath.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from mycodo.databases.models import InputChannel
from mycodo.databases.utils import session_scope
from mycodo.inputs.base_input import AbstractInput
from mycodo.utils.actions import run_input_actions
from mycodo.utils.database import db_retrieve_table_daemon
from mycodo.utils.influx import add_measurements_influxdb
from mycodo.utils.inputs import parse_measurement
Expand Down Expand Up @@ -135,6 +136,7 @@ class InputModule(AbstractInput):
def __init__(self, input_dev, testing=False):
super().__init__(input_dev, testing=testing, name=__name__)

self.log_level_debug = None
self.jmespath = None
self.first_run = True

Expand All @@ -159,6 +161,7 @@ def initialize(self):

self.jmespath = jmespath

self.log_level_debug = self.input_dev.log_level_debug
self.interface = self.input_dev.interface
self.period = self.input_dev.period
self.latest_datetime = self.input_dev.datetime
Expand Down Expand Up @@ -286,6 +289,8 @@ def get_new_data(self, past_seconds):
measurements[channel]['value'] = meas[channel]['value']

if measurements:
message, measurements = run_input_actions(self.unique_id, "", measurements, self.log_level_debug)

self.logger.debug("Adding measurements to influxdb: {}".format(measurements))
add_measurements_influxdb(
self.unique_id, measurements,
Expand Down
2 changes: 1 addition & 1 deletion mycodo/mycodo_flask/templates/pages/input.html
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ <h4>{{dict_translation['input']['title']}} <a href="{{help_page[0]}}" target="_b
popup_response(data);
},
error: function() {
toastr['error']('Error: Could not get Function Actions');
toastr['error']('Error: Could not get Input Actions');
}
});
}
Expand Down
1 change: 1 addition & 0 deletions mycodo/scripts/upgrade_commands.sh
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,7 @@ case "${1:-''}" in
chown -LR mycodo:mycodo "${MYCODO_PATH}"
chown -R mycodo:mycodo /var/log/mycodo
chown -R mycodo:mycodo /var/Mycodo-backups
chown -R mycodo:mycodo /var/mycodo-root

find "${MYCODO_PATH}" -type d -exec chmod u+wx,g+wx {} +
find "${MYCODO_PATH}" -type f -exec chmod u+w,g+w,o+r {} +
Expand Down
Loading

0 comments on commit 72c1dde

Please sign in to comment.