PubSubClient (ESP8266) - How to get the right type (Float/String)

Hi every one, first i’m not an english-born so may be my language will not be fully undestandable…
Here is my probleme :

  • i’m trying to add some wireless sensor by using ESP8266 and MQTT protocol. The library “¨PubSubClient” seems to only support char type value for sending message to a topic. But Mycodo is waiting for Float value. I’ve seen some topics about this issues, one recommand to use a custom input, the others to use JSON. I’m not such a good developers so i was wondering if anybody had already made this type of custom input, or if there is some JSON exemple for using this particular set-up with PubSubClient and ESP8266 … Thanks a lot for taking time to read and respond to this question, i’ve passed my 5 last days searching a solutions but none of them seems convinient to do …
1 Like

Hi Malory. So you’re right that the General MQTT Input can only accept a float or a string representing a float. However, it is relatively easy to take this module and, with slight editing, create a new module that will work for your needs. Here are the steps I would take:

  1. Copy Mycodo/mycodo/inputs/mqtt_paho.py to another file on your computer, such as mqtt_paho_char.py
  2. Open mqtt_paho_char.py for editing
  3. Create a unique name for the input by changing Line 25 from:
    'input_name_unique': 'MQTT_PAHO',

to:

    'input_name_unique': 'MQTT_PAHO_CHAR',
  1. Change the name so you can distinguish this from the original by changing Line 27 from:
    'input_name': 'MQTT Subscribe (Value payload)',

to:

    'input_name': 'MQTT Subscribe (Char payload)',
  1. Next, we need to check what char the payload is, and return a value based on the char. To do that, we change Line 261 from:
            value = float(payload)
            self.logger.debug("Payload represents a float: {}".format(value))

to:

            if payload == "a":
                value = 1
            elif payload == "b":
                value = 2
            elif payload == "c":
                value = 3
            elif payload == "d":
                value = 4
            else:
                self.logger.debug("payload not expected: {}".format(payload))
                return
  1. Save the file, then go to the Configure → Custom Inputs page and import the file.
  2. Go to the Setup → Input page, find your new “MQTT Subscribe (Char payload)” Input in the dropdown, then add, configure, and activate it.
  3. Now, if the payload for your subscribed topic is a, b, c, or d, the value stored in the database will be 1, 2, 3, or 4, respectively. You can edit the values to whatever works for you.

Thank you very much for this clear help, i’ll try this as soon as i can ! But is it possible to simply get the value pass in the payload (for exemple : “540”, “Hello World”, “Etc…”) and display it directly without a range of a specific input form as you have made in this exemple ? In other world, how can i do to not have to use if and elif, and just get the message and print it ^^. Thank you !

You don’t want to store what’s measured in a database?

well, if it’ possible to store directly what’s the sensor mesure it’s better. For instance my moisture sensor send me value between 250 and 500 that i will convert to a soil humidity indicator after making some test to trigger what value correspond to what amount of humidity. In order to do that i need to send the ADC value by MQTT using PubSub, and save the value in the dataBase without associating it to a quantify value as you do in the exemple you made for me. Is it understandable ? May be i’m not clear enough ^^

more simply i need to store directly the message receive by MQTT in the database
is it possible ?

Although the influxdb timeseries database can store strings, I did not design Mycodo to do so. So, I would suggest figuring out how publish values via MQTT.

Are you suggesting here that your payload can be strings and not just chars?

Yes, i’ve said “char” because is the variable type use in ESP8266 but it’s work as a string (multiple characters can be put in it), thus i made something like this :
try:
if isinstance(payload, str) == True :
value = payload
else:
self.logger.debug(“payload not expected {}”.format(payload))
return

For now that work perfectly :wink: Thx for helping me looking at the right location to complet this code ^^. In the other side (ESP8266) i send an char but it’s understand by mycodo as a string. Well for me it’s ok :slight_smile:

Then there doesn’t need to be any modification at all to the module because it already accepts strings that represent values. The payload can be 100 or “100”.