Data type conversion

Hi all,

newbie question: ::slight_smile:

I’m using an ESP8266 with Arduino core, I get from the Serial monitor “0FF022333232FF”, do a publish but this is what I receive on the broker "00FF 0002 0233 0302 32FF ".

I have to remove the ‘0’ before the byte I need,so remove this "00FF 0002 0233 0302 32FF ".

#include <PubSubClient.h>    
PubSubClient client(client);

uint8_t charIndex = 0;
uint8_t numChars = 39;
uint32_t lastCharMillis = 0;
uint8_t waitSerial = 25;
bool okPrint;
uint8_t manageIndex;
unsigned char msg[40];
byte bufferCounter = 0;
void setup()
{
  // put your setup code here, to run once:
  Serial.begin(115200);
//  Serial1.begin(115200);
}

void loop()
{
  // put your main code here, to run repeatedly:
  while (Serial.available())
  {
    byte incomingByte = Serial.read();
    char inChar = (char)incomingByte;
    Serial.print("I received: ");
    Serial.println(inChar, HEX);
    msg[charIndex] = inChar;     
    charIndex++;
    bufferCounter++;
    lastCharMillis = millis();
    okPrint = true;
    if (charIndex >= numChars) charIndex = numChars - 1;
  }
  if (millis() - lastCharMillis >= waitSerial && okPrint == true)
  {
    msg[charIndex] = '\0';
    manageIndex = charIndex;
    charIndex = 0;
    
    Serial.println("");
    Serial.print("Size of buffer ");
    Serial.println(bufferCounter);
    Serial.println("");    
    // Allocate the correct amount of memory for the payload copy
    byte* p = (byte*)malloc(bufferCounter);
    // Copy the payload to the new buffer
    
    memcpy(p, msg, bufferCounter);
    Serial.println("");
    Serial.print("Message: ");
    for (int u = 0; u < bufferCounter; u++)
    {
      Serial.print(p[u],HEX);
    }
    Serial.println("");    
    client.publish("myTopic", p, bufferCounter);    
    // Free the memory
    free(p);
    okPrint = false;
    bufferCounter = 0;
  }
}

Can’t find what am I doing wrong ::slight_smile:

Thanks

I'm using an ESP8266 with Arduino core, I get from the Serial monitor "0FF022333232FF"

There is nothing in the code you posted that prints anything that way. Post your actual serial output.

I have to remove the '0' before the byte I need,so remove this "00FF 0002 0233 0302 32FF ".

So, what is the problem?

Hi PaulS,

thank you for your reply,

I’m using an ESP8266 with Arduino core, I get from the Serial monitor “0FF022333232FF”

Sorry, my mistake on this.

I get that input from another board connected to the Serial Hardware. So the print out from the array is correct; I mean:

p[0] = 0; p[1] = FF; p[2] = 0; p[3] = 2; etc

but when I do the client.publish(“myTopic”, p, bufferCounter); I find on the broker that the array has become

p[0] = 00; p[1] = FF; p[2] = 00; p[3] = 02; etc So I found another ‘0’.

Don’t know if it’s the client.publish(“myTopic”, p, bufferCounter); that “resizes” the array ?

Hope is clear enough ???

Don't know if it's the client.publish("myTopic", p, bufferCounter); that "resizes" the array ?

I don't know what client is an instance of, but it appears that publish() is sending each byte as two characters. The value 0 gets sent as "00". The value 0xFF gets sent as "FF". The value 2 gets sent as "02".

I'm not clear on why that is a problem, or if there is another publish() method that takes a string rather than an array of bytes.

DCloud:

    for (int u = 0; u < bufferCounter; u++)

{
      Serial.print(p[u],HEX);
    }

The problem is that you don’t print those zeros to the serial monitor. Serial.print(0x02, HEX); prints “2”, while you would expect it to print “02”.
You don’t have to delete anything, "00FF 0002 0233 0302 32FF " is correct.

Try this instead of Serial.print(x, HEX):

void printHex(Stream &s, uint8_t x) {
  s.print(nibble_to_hex(x >> 4));
  s.print(nibble_to_hex(x));
}

char nibble_to_hex(uint8_t nibble) {  // convert a 4-bit nibble to a hexadecimal character
  nibble &= 0xF;
  return nibble > 9 ? nibble - 10 + 'A' : nibble + '0';
}
  uint8_t p[] = { 0x00, 0xFF, 0x00, 0x02, 0x02, 0x33, 0x03, 0x02, 0x32, 0xFF };
  size_t size = sizeof(p) / sizeof(p[0]);
  for (int i = 0; i < size; i++) {
    printHex(Serial, p[i]);
  }

Your formatting seems to suggest that the numbers are in groups of two bytes. If that’s the case, and you want to treat them as uint16_t numbers, add this:

template <class T> void printHex(Stream &s, T x) {
  for (int i = 0; i < sizeof(x); i++) {
    printHex(s, ((uint8_t*)(&x))[i]);
  }
}
  uint16_t *q = (uint16_t *) p;
  size = sizeof(p) / sizeof(q[0]);
  for (int i = 0; i < size; i++) {
    printHex(Serial, q[i]);
    Serial.print(' ');
  }

Replace sizeof(p) by the number of bytes you received (bufferCounter?)

Pieter

Hi Pieter,

thank you for your reply.

If I understand, your code will print on the Serial monitor the '0' right? But what about the array send by the publish()? I don't need to correct the Serial.print() part, my problem is on the broker side.

Thanks again :)

my problem is on the broker side.

Fancy footwork, there, but we still don’t know what the problem is, or why you think that this is the place to get help with code on the PC.

Let’s say you receive “F0” on the serial monitor.
You have no way of knowing whether the code was:

Serial.print(0x0F, HEX);
Serial.print(0x00, HEX);

or

Serial.print(0xF0, HEX);

You have to print the leading zeros for the result to be unambiguous.

Each byte can be represented using 2 hexadecimal characters (28 == 162), so for each byte in your p array, you have to print exactly 2 characters.
The broker does this correctly, your code does not.

Also, why do you copy msg to a new array? Why do you dynamically allocate that new array, if you know that its maximum length is the same as msg? It’s a waste of resources, and could cause memory problems in the long run.

Pieter

Also, why do you copy msg to a new array? Why do you dynamically allocate that new array, if you know that its maximum length is the same as msg? It's a waste of resources, and could cause memory problems in the long run.

Got it and changed it. :)

Thanks