Python / Arduino Communication

Hello!

Currently I am working on a project where Arduino and Raspberry PI need to communicate with each other. At the moment the Arduino can send data to the Raspberry PI, this works fine.
But the data that the Arduino receives from the Raspberry PI not displayed correctly.

See the code below. After sending 'Hello World' to the raspberry PI, the Arduino should receive a code which needs to be stored. But the Serialprintln(codevalue) does not return the right value.

I have read many forums but it still does not work. Can someone help me out?

Also with the Serial Monitor the right value is not returned.

char ID[] = "HY08V21234567865"; //ID of container
String codevalue;

void setup() {
   // Define inputs and outputs:
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(BAUD);
  Serial.setTimeout(60000);
  Serial.print("Hello World, from Arduino");
  Serial.print(";");
  Serial.println(ID);
  delay(5);
  if (Serial.available() > 0){
     codevalue = Serial.readString();
     Serial.println(codevalue); #this is the part of the code that does not work
  }
  Serial.println(codevalue);
}

what do you think happens if the data does not arrive to the arduino within 5ms after boot? --> Serial.available() will be null and you'll go to the loop

I suppose the loop is empty ? (it's missing in your code)

try this:

char ID[] = "HY08V21234567865"; //ID of container
String codevalue;

void setup() {
  // Define inputs and outputs:
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(BAUD);
  Serial.print("Hello World, from Arduino");
  Serial.print(";");
  Serial.println(ID);
  while (!Serial.available()); // active wait for data to arrive
  codevalue = Serial.readString();
  Serial.println(codevalue); #this is the part of the code that does not work
}

void loop() {}

(missing the pins declaration etc, I suppose you have that)

No, the loop is not empty. I have just simplified the code, the loop works fine! :slight_smile:

while (!Serial.available());

This part of the code works better!! However, if I try it on my computer with the serial monitor it returns the string value first and after that an empty string. Is it possible to only return the string value with the text?
Reason why want this is because I need to use this value later on in my loop!

If I try it with the Python code on my raspberry PI, it only returns the empty string. So the text is not shown.
See below a part of my Python code.

import serial
import time

if __name__ == '__main__':
     ser = serial.Serial('/dev/ttyACM0', 9600, timeout=1)

     while True:
            if ser.in_waiting >0:
            line = ser.read().decode('utf-8').rstrip()
            print(line)
            print("going to execute task....")
          
                  if "Hello World, from Arduino" in line: 
                      key = "1234"   #extend this with key generator
                      ser.write(str(key).encode('utf-8'))  #this is the string that Arduino should read!
                      time.sleep(10)
                      code = ser.readline().decode('utf-8').rstrip() #this is to check whether the right string is received 
                      print(code)


if I try it on my computer with the serial monitor it returns the string value first and after that an empty string

post the code you use, it's hard to see what you have done.

taking a more general view, using Serial.readString() is not great. I would suggest to study Serial Input Basics to handle this

Yes, I can share the code. It is not finished yet, so that can make it a bit confusing.

I had a code where the Arduino sensor data is encrypted with AES encryption and after that send to the raspberry PI.
Now, I am working on the code to change it in such a way that the Arduino receives the AES Key and IV from the raspberry PI. So the Arduino does not generate the AES Key and IV by itself.

In the loop, the KEY and IV received from the raspberry PI will be used to send encrypted sensor data.

#include "AESLib.h" 
#define BAUD 9600
char ID[] = "HY08V21234567865"; //ID of container
String key;
String IV;

AESLib aesLib;

#define INPUT_BUFFER_LIMIT (128+1) // designed for Arduino UNO, not stress-tested anymore (this works with readBuffer[129])
#define trigPin 8 
#define echoPin 10

long duration;
float longitude;
float latitude;
int k; //determine length long

unsigned char cleartext[INPUT_BUFFER_LIMIT] = {0}; // THIS IS INPUT BUFFER (FOR TEXT)
unsigned char ciphertext[2*INPUT_BUFFER_LIMIT] = {0}; // THIS IS OUTPUT BUFFER (FOR BASE64-ENCODED ENCRYPTED DATA)
unsigned char readBuffer [18] = {0}; //Waarde 0 er achter gezet omdat het nog toegekend moet worden. 

// AES Encryption Key (same as in node-js example)
byte aes_key[] = {  57, 36, 24, 25, 28, 86, 32, 41, 31, 36, 91, 36, 51, 74, 63, 89 }; //DELETE LATER ON

// General initialization vector (same as in node-js example) (you must use your own IV's in production for full security!!!)
byte aes_iv[16] = { 52, 58, 87, 63}; //DELETE LATER ON

// Generate IV (once)    DELETE LATER ON
void aes_init() {
  aesLib.gen_iv(aes_iv);
  aesLib.set_paddingmode((paddingMode)0);
}

uint16_t encrypt_to_ciphertext(char * msg, uint16_t msgLen, byte iv[]) {
  //Serial.println("Calling encrypt (string)...");
  // aesLib.get_cipher64_length(msgLen);
  int cipherlength = aesLib.encrypt((byte*)msg, msgLen, (char*)ciphertext, aes_key, sizeof(aes_key), iv);
                   // uint16_t encrypt(byte input[], uint16_t input_length, char * output, byte key[],int bits, byte my_iv[]);
  return cipherlength;
}

uint16_t decrypt_to_cleartext(byte msg[], uint16_t msgLen, byte iv[]) {
  Serial.print("Calling decrypt...; ");
  uint16_t dec_bytes = aesLib.decrypt(msg, msgLen, (char*)cleartext, aes_key, sizeof(aes_key), iv);
  Serial.print("Decrypted bytes: "); Serial.println(dec_bytes);
  return dec_bytes;
}

void setup() {
   // Define inputs and outputs:
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
  Serial.begin(BAUD);
  Serial.setTimeout(15000); //was 60000 in de originele code
  Serial.print("Hello World, from Arduino");
  Serial.print(";");
  Serial.println(ID);
  delay(10);
  while (!Serial.available());
  key = Serial.readString();
  Serial.println(key);
  while (!Serial.available());
  IV = Serial.readString();
  Serial.println(IV);
  aes_init(); // generate random IV, should be called only once? causes crash if repeated...
}

/* non-blocking wait function */
void wait(unsigned long milliseconds) {
  unsigned long timeout = millis() + milliseconds;
  while (millis() < timeout) {
    yield();
  }
}

unsigned long loopcount = 0;

// Working IV buffer: Will be updated after encryption to follow up on next block.
// But we don't want/need that in this test, so we'll copy this over with enc_iv_to/enc_iv_from
// in each loop to keep the test at IV iteration 1. We could go further, but we'll get back to that later when needed.

// General initialization vector (same as in node-js example) (you must use your own IV's in production for full security!!!)
byte enc_iv[16] =      { 52 };
byte enc_iv_to[16]   = { 52 };
byte enc_iv_from[16] = { 52 };

I had a code where the Arduino sensor data is encrypted with AES encryption and after that send to the raspberry PI.

I remember that one :wink:

Now, I am working on the code to change it in such a way that the Arduino receives the AES Key and IV from the raspberry PI. So the Arduino does not generate the AES Key and IV by itself.

so if I intercept the Serial communication I get all your secrets ? :slight_smile:

So you have a script on standby on the raspberry PI that is opening a specific port and waiting for some data to arrive. The python script expects some sort of handshake (here it has to inclue the string "Hello World, from Arduino") and you send the key back and then wait for an arbitrary 10ms and expect to read something back from the Arduino. is that correct?

(PS: read() will only get 1 byte I think)

Yes that is correct! With "Hello World, from Arduino" the Arduino can connect to a simulated 'IoT network' where the raspberry acts as a gateway.

so if I intercept the Serial communication I get all your secrets ? :slight_smile:

And this is something I still need to figure out!
But for now, thank you for your help again! I appreciate it a lot.

so does the script get the full handshake?

Not yet! Thanks, will adapt the script :slightly_smiling_face:

if you send the handshake from Arduino using Serial.println() you are sending "\r\n" at the end (CR/LF) of the communication. You could use that as a marker and in your python code

if ser.in_waiting >0 :
  line = ser.readline()[:-2] #the -2 thingy gets rid of the CR/LF
  if line :
    print(line)
    if "Hello World, from Arduino" in line : 
      ...

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