The "MQTT: Publish" action fails when using it to publish values obtained from the "Python 3 Code" input:
[...] - DEBUG - mycodo.action.input_action_mqtt_publish_7252774f - Input channel: 0, payload: None
[...] - ERROR - mycodo.action.input_action_mqtt_publish_7252774f - Error: No measurement found in dictionary passed to Action for channel 0.
[...] - DEBUG - mycodo.trigger_action_7252774f - Message: Executing actions of Input. Error: No measurement found in dictionary passed to Action for channel 0.
Versions:
Mycodo Version: 8.15.8, 8.15.7
Raspberry Pi Version: 1B+
Raspbian OS Version: Bullseye Light
Debian Version: Bullseye
Tested on Raspberry Pi and on Debian server.
Reproducibility
Add MQTT-Value input
Add Python 3 Code input, Debug mode activated
Add Publish to MQTT action in Python code
Configure MQTT input and action to subscribe/publish to 127.0.0.1:1883, topic test_send, login:no
Activate both inputs
Observe Daemon log
Expected behavior
The measurement saved by the Python Code should be passed to the MQTT-publish action and subsequently published.
Screenshots
The Live Measurements should display the same values for the Python Code input and the MQTT input.
Additional context
Possibly related to #1297.
Full log output
```
2023-04-10 12:39:29,837 - DEBUG - mycodo.inputs.python_code_30d13119 - Python Code:
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:
def __init__(self, logger, input_id, measurement_info, channels_conversion, channels_measurement):
self.logger = logger
self.input_id = input_id
self.measurement_info = measurement_info
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):
import random # Import any external libraries
# Get measurements/values (for example, these are randomly-generated numbers)
random_value_channel_0 = random.uniform(10.0, 100.0)
# Store measurements in database (must specify the channel and measurement)
self.store_measurement(channel=0, measurement=random_value_channel_0)
2023-04-10 12:39:29,872 - DEBUG - mycodo.controllers.controller_input_30d13119 - Adding measurements to InfluxDB with ID 30d13119-069a-4dc1-aa03-7b87f7eebab4: {}
2023-04-10 12:39:30,579 - DEBUG - mycodo.action.input_action_mqtt_publish_7252774f - Input channel: 0, payload: None
2023-04-10 12:39:30,580 - ERROR - mycodo.action.input_action_mqtt_publish_7252774f - Error: No measurement found in dictionary passed to Action for channel 0.
2023-04-10 12:39:30,580 - DEBUG - mycodo.trigger_action_7252774f - Message: Executing actions of Input. Error: No measurement found in dictionary passed to Action for channel 0.
```
Describe the problem/bug
The "MQTT: Publish" action fails when using it to publish values obtained from the "Python 3 Code" input:
Versions:
Tested on Raspberry Pi and on Debian server.
Reproducibility
Expected behavior
The measurement saved by the Python Code should be passed to the MQTT-publish action and subsequently published.
Screenshots
The Live Measurements should display the same values for the Python Code input and the MQTT input.
Additional context
Possibly related to #1297.
Full log output
``` 2023-04-10 12:39:29,837 - DEBUG - mycodo.inputs.python_code_30d13119 - Python Code: 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: def __init__(self, logger, input_id, measurement_info, channels_conversion, channels_measurement): self.logger = logger self.input_id = input_id self.measurement_info = measurement_info 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): import random # Import any external libraries # Get measurements/values (for example, these are randomly-generated numbers) random_value_channel_0 = random.uniform(10.0, 100.0) # Store measurements in database (must specify the channel and measurement) self.store_measurement(channel=0, measurement=random_value_channel_0) 2023-04-10 12:39:29,872 - DEBUG - mycodo.controllers.controller_input_30d13119 - Adding measurements to InfluxDB with ID 30d13119-069a-4dc1-aa03-7b87f7eebab4: {} 2023-04-10 12:39:30,579 - DEBUG - mycodo.action.input_action_mqtt_publish_7252774f - Input channel: 0, payload: None 2023-04-10 12:39:30,580 - ERROR - mycodo.action.input_action_mqtt_publish_7252774f - Error: No measurement found in dictionary passed to Action for channel 0. 2023-04-10 12:39:30,580 - DEBUG - mycodo.trigger_action_7252774f - Message: Executing actions of Input. Error: No measurement found in dictionary passed to Action for channel 0. ```