ESP8266 MQTT and the UART

I wonder… those of you who have used the excellent MQTT software (stand-alone – not the LUA version)… I need to do two things – one of them is giving me problems but is no doubt trivial – the other I’m hoping someone has already solved.

Ok, so I’m using the MQTT software and I’ve added my own drivers… and that’s fine.

There is a function call INFO which prints stuff to the serial – I want to optionally turn that off. Here’s the DEBUG.H file.

#ifndef USER_DEBUG_H_
#define USER_DEBUG_H_

#ifndef INFO
    #define INFO os_printf
#endif

#endif /* USER_DEBUG_H_ */

That’s simple enough – INFO function simply is the os_printf function. So I figured I’d put my own function in which I could control.

#ifndef USER_DEBUG_H_
#define USER_DEBUG_H_

#ifndef INFO
    #include <stdarg.h>
    void ICACHE_FLASH_ATTR petes_debug_print(char *fmt, … ){
     // if (debug==0) return;
      va_list args;
      va_start (args, fmt );
      os_printf(fmt, args);
      va_end (args);
    }

    #define INFO petes_debug_print
#endif

#endif /* USER_DEBUG_H_ */

Looks simple enough but this will NOT compile – stating that the function is being redefined… ie (petes_debug_print) –  this occurs NO-where else – I have of course tried a different name just in case I’m living in an alternative reality – no matter what I do it says it’s being redefined – and yet the IFNDEF should be stopping that.

Anyone know what I’m doing wrong?

Secondly – in the MQTT code – only UART out is used…. uart IN is not – and what I’d like to do is have an Arduino send a suggested MQTT subscription… for the life of me I can’t get my head around how to simple check for incoming characters…’

13 thoughts on “ESP8266 MQTT and the UART

  1. Peter

    Can I point you to the comments in your blog “ESP8266 Serial”.

  2. Still looking for any actual example of adding comms input to the MQTT library code… the output side I have handled now.. Simple really, the ESP8266 board handles incoming subscribes… when any incoming messages appear if they are not in the list of topics to be processed they are sent out of the serial, wrapped to look like simple JSON.

    So if a topic ArduinoWantsX comes in – and if the data is ABC… I send that out of the comms port as

    {“ArduinoWantsX”:”ABC”}

    With a carriage return on the end.

    So the bit I’m missing is to be able to send something like that from the Arduino to the ESP board by serial – the ESP would then SUBSCRIBE to that topic – so you’d send {“ArduinoWantsX”} to subscribe to a topic – or {“ArduinoWantsX”:”ABC”} (with enter on the end) to get the ESP to actually publish something… that way you have the best of both worlds – the ESP can run stand-alone – but where needed you can strap an Arduino on the end.,… and have that do some lifting work. For example – handling RGB LEDS or Servos or whatever.

    If anyone has added Comms in to the MQTT code, I would appreciate a code snippet to test.

  3. I don’t know WHAT I was thinking about – there’s a much simpler way – incidentally half the people out there seem to think you can pass variable arguments from one function to another – the other half say emphatically that you can’t – anyway, the solution was a lot simpler than that… in the debug header..

    #define INFO if (DEBUG==1) os_printf

    No need for a function… DEBUG is set to either 0 or 1 as a define. Job done.

  4. Right- thanks to all – but now I have another issue – same subject – you may recall I wanted my own optional os_printf.. so the idea was to simple pass the variable information to my own routine

    Brilliant idea – strings are getting through – but integers are displaying withMASSIVE numbers…

    Anyone know what I’m doing wrong here???

    #include
    void ICACHE_FLASH_ATTR ps_os_printf(char *fmt, …){
    if (DEBUG==1)
    {
    va_list args;
    va_start(args,fmt);
    os_printf(fmt,args);
    va_end(args);
    }
    }

  5. Such ifdefs will protect you from defining something twice in one compilation unit. Each such unit (i.e. any .c file) is compiled separately and they are then linked. Each of them that includes your user_debug.h will end up with it’s own copy of petes_debug_print() function that by default will be exported and you will have a conflict when linking.

    To avoid that, you should only _declare_ your petes_debug_print function inside of .h file but implement it inside of .c file that will be linked with others. That way each compilation unit will know that it should look for the function body in some other compilation unit at linking stage.

    Another solution is to declare this function static, this way it won’t be exported so there won’t be any conflict but the downside is that your output code will be larger as you will have separate copy of this function body for each compilation unit. In this case it’s quite small so you may decide you can afford that overhead.

    1. Yup, that was it. I simply moved the function into user_main.c and it’s working a treat. Thanks to all.

  6. The first issue is very simple. You have defined the function in the header file, so it is being defined in every c file wherever that header is included. What you can do is that define that function in some other c file and in the header file, just keep the macro mapping along with an extern declaration if needed.

    For the UART in stuff, you need to put a loop and wait for characters before proceeding. You can either do it in the user_init function or early on in the MQTT_Task function.

    1. Correct – the instant I saw your response Shantanu I realised I’d missed the point about the IFDEF… sorted. Thank you. On the second point I’m hoping someone can give a LITTLE more hand-holding on that.

  7. Two solutions:

    Tried making the function static? Otherwise the function is redefined with external linkage in each module where the header is included. Static gives internal linkage, so the function is not visible outside of the module. Thus, no more name collisions.

    But maybe a better solution would be to define the function in a separate module and just add a declaration in the header. This might save some code size.

    1. Thanks Sabastian – you all came to the same conclusion. I moved the function to user_main and it’s working.

Comments are closed.