Parsing char Arduino side with PySerialTransfer/SerialTransfer

Hello friends,

I'm using the PySerialTransfer library GitHub - PowerBroker2/pySerialTransfer: Python package to transfer data in a fast, reliable, and packetized form

I'm trying to trigger some action in the Arduino Leonardo side when a specific char is received from python. I could have use int instead of char message but I take this as an exercice :slight_smile:

All the manipulation I tried failed... I'm starting to be tired of this and probably missing some perspective from this point.

So, here my Python:

X1 = [0, 0, 0, 0, 0, ... , 0]
X2 = [1, 1, 1, 1, 1, .... , 1] ---> X1 and X2 are long array

try:
    link = txfer.SerialTransfer('COM8', 115200, debug=True)
    link.open()

    start = 0
    step = 10
    counter = 0

    while counter < len(X1):
        sendSize = 0

        X1_= X1[start:start+step] ---> I split it in order to get under 254 bytes per packet.
        X2_= X2[start:start+step]
        message = "notes"
        
        messageSize = link.tx_obj(message) 
        sendSize += messageSize

        X1Size = link.tx_obj(X1_, sendSize) - sendSize
        sendSize += X1Size

        X2Size = link.tx_obj(X2_, sendSize) - sendSize
        sendSize += X2Size

        link.send(sendSize, packet_id=0) ---> I recently tried to add packet_id information to don't messing up the receiving part.
        counter += len(X1_)

        #print('SENT: {} {} {}'.format(message, X1_, X2_))

        while not link.available():
            pass

        rec_message = link.rx_obj(obj_type=type(message), obj_byte_size=messageSize)
        rec_X1 = link.rx_obj(obj_type=type(X1_), obj_byte_size=X1Size, list_format='i', start_pos = messageSize)
        rec_X2 = link.rx_obj(obj_type=type(X2_), obj_byte_size=X2Size, list_format='i', start_pos = messageSize + X1Size)

        start += step
        print("Recu:\t{} - {} et {}".format(rec_message, rec_X1, rec_X2))


    while True:
        sendSize2 = 0
        message2 = "click"
        messageSize = link.tx_obj(message2)
        sendSize2 += messageSize

        print("Ready to click...")
        link.send(sendSize2, packet_id=0)
        #print('SENT: {}'.format(message2))

        while not link.available():
            pass

        rec_message = link.rx_obj(obj_type=type(message2), obj_byte_size=messageSize)
        print("Recu:\t{}".format(rec_message))

        raise KeyboardInterrupt

except KeyboardInterrupt:
    try:
        link.close()
    except:
        pass

except:
    import traceback
    traceback.print_exc()

    try:
        link.close()
    except:
        pass

And my Arduino:

#include "SerialTransfer.h"
#include "Keyboard.h"
#include "Mouse.h"

SerialTransfer myTransfer;

int32_t X1[10];
int32_t X2[10];

int32_t X1G[] = {};
int32_t X2G[] = {};

char message[5];

#Stuff I tried....
char notes[] = "notes";
char clickOk[] = "click";

void setup()
{
  Keyboard.begin();
  Mouse.begin();
  Serial.begin(115200);
  myTransfer.begin(Serial, true);
}

void loop()
{
  if(myTransfer.available())
  {
    uint16_t recSize = 0;
    recSize = myTransfer.rxObj(message, recSize);

    if (strcmp(message, clickOk)) ---> Here my problem. How to check the received message and do action?
    {
      recSize = myTransfer.rxObj(X1, recSize);
      recSize = myTransfer.rxObj(X2, recSize);
  
      memmove(X1G + sizeof(X1G), noteTime, sizeof(X1));
      memmove(X2G + sizeof(X2G), noteType, sizeof(X2));
  
      uint16_t sendSize = 0;
      
      sendSize = myTransfer.txObj(message, sendSize);
      sendSize = myTransfer.txObj(X1, sendSize);
      sendSize = myTransfer.txObj(X2, sendSize);
      
      myTransfer.sendData(sendSize);
     
      delay(50);
    }
    else if (strcmp(message, clickOk))
    {
      uint16_t sendSize2 = 0;
      sendSize2 = myTransfer.txObj(message, sendSize2);
      myTransfer.sendDatum(sendSize2);
      Mouse.click();
    }
  }
}

My FTDI card will be coming soon, it should be easier for debugging, but in the meantime any help will be appreciated :slight_smile:

I'm a beginner in this wide world. Maybe my mechanism is completely broken, so feel free to suggest another solution to get what I want.

Bye,
Vouncat

 if (strcmp(message, clickOk)) ---> Here my problem. How to check the received message and do action?

Is the message that you receive a zero terminated string ? If so then

 if (strcmp(message, clickOk) == 0)

will be true if the 2 strings match

See https://www.cplusplus.com/reference/cstring/strcmp/

I already tried this but KO.

According to the library, I think the message doesn't end by a zero string : Saving List onto Arduino ยท Issue #32 ยท PowerBroker2/pySerialTransfer ยท GitHub

It's sent as a packet

01111110 00000000 11111111 00000000 00000000 00000000 ... 00000000 10000001
|      | |      | |      | |      | |      | |      | | | |      | |______|__Stop byte
|      | |      | |      | |      | |      | |      | | | |______|___________8-bit CRC
|      | |      | |      | |      | |      | |      | |_|____________________Rest of payload
|      | |      | |      | |      | |      | |______|________________________2nd payload byte
|      | |      | |      | |      | |______|_________________________________1st payload byte
|      | |      | |      | |______|__________________________________________# of payload bytes
|      | |      | |______|___________________________________________________COBS Overhead byte
|      | |______|____________________________________________________________Packet ID (0 by default)
|______|_____________________________________________________________________Start byte (constant)

I tried, to convert bytes to char and so on, but without success...

You have another problem

char message[5];  //an array of chars with 5 elements

If the message contained "clickOK" and did have a terminating zero it would not fit in the message array

You could compare message with the first 5 bytes of clickOK by doing something like this (untested)

if (memcmp(message, clickOK, 5) == 0)  //true if matched
1 Like

Oh, I'll try this tonight :hugs:

It would be even simpler if you sent single character commands because you could do a direct comparison between them

Yes sure, but like I said, it was kinda exercice to me.

Thank You HelicopterMan it's solved my problem!
Have a nice day o/

@UKHeliBob I got another pbm...

I want to concat each X1 array I received to an unique array X1G.

#include "SerialTransfer.h"

SerialTransfer myTransfer;

int32_t X1[10];
int32_t X1G[] = {};

void setup()
{
  Serial.begin(9600);
  myTransfer.begin(Serial);
}

void loop()
{
  if(myTransfer.available())
  {
    uint16_t recSize = 0;
    recSize = myTransfer.rxObj(X1, recSize);

    memmove(X1G + sizeof(X1G), X1, sizeof(X1));
   }
}

Should I set the size of X1G before and use for loop instead?
As far as possible I want to use 1 simple line with memcpy or memmove...

int32_t X1G[] = {};

Start by declaring this array properly. You must tell the compiler how many elements should it have ?

Beyond that I don't understand what you are trying to do

Ok, so I need to sent the expected size of X1G through python first (because I want to automate and not to sent the size each time).... I didn't want to use that but ok.

I want to add each new array X1 I receive to the unique X1G.
X1 being set to new each time.

When you declare an array you can either explicitly tell the compiler how many elements there are by putting the number in the square brackets or you can let the compiler work it out from the number of initial values the you supply at compile time.

What you can't do is to declare an array with a variable as the number of elements in the array in the square brackets. You can, of course, declare the empty array with more than enough elements and not use all of them X1G array looks like before and after adding a new X1 array

I am sorry, but I still don't understand what you are trying to do. Please give an example of what the

So here my protocol :

  • In python side I create a long array and each time this script will run, the array size may change.
  • In order to send this long array I need to split it.
  • I sent to Arduino each array chokes with PySerialTransfer.
  • In the Arduino Side, each time I receive the pySerialTransfer message (so a choke of initial array), I want to concat it with the last received array, and so on to get back the initial array.

I know I could use some for loop with counter...but the memcpy/memmove solution looks at me :wink:

I'll adapt this solution and I'll give up on my wish to use memcpy. Thanks anyway and sorry about topic nesting.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.