Python script called by Process never end

Hi guys,

I am trying to execute a python script through Process.runShellCommand...
It does successfully executed but the script never return any data from doing:

        while(p2.available())
        {
          output2 += (char)p2.read();
        }
        Serial.println(output2);

So the sketch is blocked by the script calling and it cannot continue to execute the following sentences.
Here I leave to you the sketch code (a part of it) and the python script code:

sketch.ino

        Process p2;
        p2.begin("/usr/bin/python");
        p2.addParameter("/mnt/sda1/webexample/sendLogTempByMail.py");
        //following parameters are some sensor temperature values 
        p2.addParameter("25.75");
        p2.addParameter("25.00");
        p2.addParameter("25.25");
        p2.run();
        String output2 = "";
        while(p2.available())
        {
          output2 += (char)p2.read();
        }
        Serial.println(output2);

sendLogTempByMail.py

from datetime import datetime
import smtplib, sys
from email.mime.text import MIMEText

degree = u"\u2103"

USERNAME = "arturofelixchari@gmail.com"
PASSWORD = "mypasswd"

MAILTO = ''

with open('/mnt/sda1/webexample/admin_emails.config') as data:
    datalines = (line.rstrip('\n') for line in data)
    for line in datalines:
        MAILTO += line
        MAILTO += ', '

MAILTO = MAILTO[:-2]

msg = MIMEText('Temp. at S1 = '+str(sys.argv[1])+' '+degree.encode("utf-8")+'\nTemp. at S2 = '+str(sys.argv[2])+' '+degree.encode("utf-8")+'\nTemp. at S3 = '+str(sys.argv[3])+' '+degree.encode("utf-8"))
                                                                                                                                                                                                                                                    
msg['Subject'] = 'TempLog ['+datetime.now().strftime('%Y-%m-%d %H:%M:%S')+']'
msg['From'] = USERNAME
msg['To'] = MAILTO    

server = smtplib.SMTP('smtp.gmail.com:587')
server.ehlo_or_helo_if_needed()
server.starttls()
server.ehlo_or_helo_if_needed()
server.login(USERNAME,PASSWORD)
server.sendmail(USERNAME, MAILTO.split(","), msg.as_string())
server.quit()

Thanks in advance for any suggestion or correction,
Regards.

Arthur.

Your python code is not printing anything, am I right? What output do you expect to see?

Hi Federico!
Thank you for the quick reply!

You're right, I don't write any print line sentence in the python script, but that isn't the root issue....
I wanted to refer to the deadlock sketch occurred after the execution of 'run' process sentence.
All is done fine in the first 'loop' sketch, the mails to admin are sent. But never it continue to executing following sentences and never the second 'loop' is executed.

I dont know if I am giving a good explanation of this trouble. Sorry for my English :frowning:

Regards.

Arthur.

Can you post the whole sketch?

#include <YunServer.h>
#include <YunClient.h>
#include <FileIO.h>
#include <Process.h>
#include <OneWire.h>
#include <DallasTemperature.h>

// Setup a oneWire instance to communicate with any OneWire devices (at digital pin 8)
OneWire oneWire(8);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

DeviceAddress Probe01 = { 0x28, 0xF8, 0x9D, 0x22, 0x05, 0x00, 0x00, 0xD4 }; 
DeviceAddress Probe02 = { 0x28, 0x4C, 0xA8, 0x22, 0x05, 0x00, 0x00, 0x59 };
DeviceAddress Probe03 = { 0x28, 0x65, 0xB3, 0x22, 0x05, 0x00, 0x00, 0x75 };

// The server instance 
YunServer server; 
YunClient client;
 
void setup() {
  
  Serial.begin(9600);
  Bridge.begin();
  
  FileSystem.begin();

  server.listenOnLocalhost();
  server.begin();
}
 
void loop() {
  
  // Initialize the Temperature measurement library
  sensors.begin();
  
  // set the resolution to 10 bit (Can be 9 to 12 bits .. lower is faster)
  sensors.setResolution(Probe01, 10);
  sensors.setResolution(Probe02, 10);
  sensors.setResolution(Probe03, 10);
  
  sensors.requestTemperatures();  
  
  client = server.accept();
 
  if (client) {
    
    File statesensor_file = FileSystem.open("/www/sd/webexample/sensors_states.config", FILE_READ);
    
    //these files just stores one char value: 1 or 0
    //variable for reading enabled (1) o disabled (0) value
    char c1 = NULL ; char c2 = NULL; char c3 = NULL;
    
    if (statesensor_file){
       while(statesensor_file.available()){
         statesensor_file.seek(3);  //move read pointer to read 0/1 value
         c1 = statesensor_file.read();  
         statesensor_file.seek(8);
         c2 = statesensor_file.read();
         statesensor_file.seek(13);
         c3 = statesensor_file.read();
         break;
       } 
    }
    statesensor_file.close(); 

    String command = client.readString();
    command.trim();
    if (command == "temperature") {
      
      Serial.println("temperature command was readed by client");
      
      client.print("<p style='margin-left:220px'><strong> Current temperature at sensor 1: </strong></p>");
      printHtmlHeaderTemp(c1,1);      
      client.print("
");
      client.print("<p style='margin-left:220px'><strong> Current temperature at sensor 2: </strong></p>");
      printHtmlHeaderTemp(c2,2);      
      client.print("
");
      client.print("<p style='margin-left:220px'><strong> Current temperature at sensor 3: </strong></p>");
      printHtmlHeaderTemp(c3,3);      
      
      //Querying the temperature values of sensor to avoid device damages
      // cases are: 2 values (enabled/disabled) to 3 sensors sensors possible cases
      if (((c1 == '1') && (printTemperature(Probe01) > 30.00)) || 
          ((c2 == '1') && (printTemperature(Probe02) > 30.00)) ||
           ((c3 == '1') && (printTemperature(Probe03) > 30.00)))
        { 

        Process p2;
        char command[] = "python /mnt/sda1/webexample/sendLogTempByMail.py ";
        char tempF[5];
        if (c1 == '1'){
          dtostrf(printTemperature(Probe01), 5, 2, tempF);
          strcat(command,tempF);
          strcat(command," ");
        }
        else
            strcat(command, "DISABLED ");
        
        if (c2 == '1'){
          dtostrf(printTemperature(Probe02), 5, 2, tempF); 
          strcat(command,tempF);
          strcat(command," ");
        }
        else strcat(command, "DISABLED ");
        
        if (c3 == '1'){
          dtostrf(printTemperature(Probe03), 5, 2, tempF);
          strcat(command,tempF);
        }
        else strcat(command, "DISABLED");
        
        p2.runShellCommand(command);
        while(p2.running());
        String output2 = "";
        while(p2.available())
        {
          output2 += (char)p2.read();
        }
        Serial.println(output2);
    }
   
  }

  client.stop();
}

  delay(900);
}

/*-----( Declare User-written Functions )-----*/
float printTemperature(DeviceAddress deviceAddress)
{
   if (sensors.getTempC(deviceAddress) == -127.00) 
     return -127;
   else
     return sensors.getTempC(deviceAddress);  
}// End printTemperature

void printHtmlHeaderTemp (char c, unsigned sensorNum){
        
  if (c == '0')  
    client.print("<p style='color:#FF0000; margin-left:220px'><em> DISABLED </em></p>");    
      
  else if (c == '1')
  {     
    client.print("<p style='color:#FF0000; margin-left:220px'>");
    if (sensorNum == 1)
      client.print(printTemperature(Probe01));
    else if (sensorNum == 2)
          client.print(printTemperature(Probe02));
    else
          client.print(printTemperature(Probe03));

    client.print(" °C");
    client.print("</p>");
  }
  
}

Now, I see the output from python script. I've added a line (print 'Emails have been sent successfully' ) at the bottom of it.
I get this message in Serial Monitor and all is done well: really the emails were sent. But after that, the sketch does not going to the next loop. It seems like the sketch is waiting for something... deadlock...?

My Temperature Web Monitor is stuck with the last values until the sensors were less than 30 °C, and never are updated for the next loop...

Thank you for your attention.

Regards.

Try adding some Serial.println: start with one right after loop() { and one after if (client) {. Keep on until you find the point in your code where execution interrupts

Well... I've added some Serial.println statements like Federico recommended to me.
I've attached the Serial Monitor output.

Clearly, the job is done well: I received the output from python script... it seems like the process which invoked it, has been executed and finish. But in the next loop after this, all is friezed and the Temperature Web Monitor do not update sensor temperature values any more.
I am very frustrated, this job is taking me longer time than expected :~

Regards.

Arthur.

Hi for anybody that would be seeing this topic...

I did make some advances... I figured out that the python script call by Process object is not the root trouble.
I have commented the process run line and it still freezing in the following loop.
Maybe the trouble comes from working with some variables inside the if statement

Here I post a part of code above (only the 'loop' method) that I've modified, which still fails when the sketch flows towards the if statement:

void loop() {
  
  // Initialize the Temperature measurement library
  sensors.begin();
  
  // set the resolution to 10 bit (Can be 9 to 12 bits .. lower is faster)
  sensors.setResolution(Probe01, 10);
  sensors.setResolution(Probe02, 10);
  sensors.setResolution(Probe03, 10);
  
  sensors.requestTemperatures();  
  
  client = server.accept();
 
  if (client) {
    
    File statesensor_file = FileSystem.open("/www/sd/webexample/sensors_states.config", FILE_READ);
    
    //these files just stores one char value: 1 or 0
    //variable for reading enabled (1) o disabled (0) value
    char c1 = NULL ; char c2 = NULL; char c3 = NULL;
    
    if (statesensor_file){
       while(statesensor_file.available()){
         statesensor_file.seek(3);  //move read pointer to read 0/1 value
         c1 = statesensor_file.read();  
         statesensor_file.seek(8);
         c2 = statesensor_file.read();
         statesensor_file.seek(13);
         c3 = statesensor_file.read();
         break;
       } 
    }
    statesensor_file.close(); 

    String command = client.readString();
    command.trim();
    if (command == "temperature") {
      
      Serial.println("temperature command was readed by client");
      
      client.print("<p style='margin-left:220px'><strong> Current temperature at sensor 1: </strong></p>");
      printHtmlHeaderTemp(c1,1);      
      client.print("
");
      client.print("<p style='margin-left:220px'><strong> Current temperature at sensor 2: </strong></p>");
      printHtmlHeaderTemp(c2,2);      
      client.print("
");
      client.print("<p style='margin-left:220px'><strong> Current temperature at sensor 3: </strong></p>");
      printHtmlHeaderTemp(c3,3);      
      
      //Querying the temperature values of sensor to avoid device damages
      // cases are: 2 values (enabled/disabled) to 3 sensors sensors possible cases
      if (((c1 == '1') && (printTemperature(Probe01) > 30.00)) || 
          ((c2 == '1') && (printTemperature(Probe02) > 30.00)) ||
           ((c3 == '1') && (printTemperature(Probe03) > 30.00)))
        { 
        
        char command[] = "python /mnt/sda1/webexample/sendLogTempByMail.py ";
        char tempF[5];
        if (c1 == '1'){
          dtostrf(printTemperature(Probe01), 5, 2, tempF); 
          strcat(command,tempF);
          strcat(command," ");
        }
        else 
          strcat(command, "DISABLED ");
        
    }
   
  }
  
  client.stop();
  Serial.println("client stop");
}

  delay(900);
  Serial.println("loop end");
}
// loop end

Any suggestion will be very helpful.
Regards.

Arthur.

Try commenting decreasing size of code: the whole "if" block for example then the inner "while", until you spot the problematic code

Hi Federico,
Thanks you again for repy.

I figured out that the probematic code is into the ¨while¨ block which asks for the file opened.

while(statesensor_file.available())

The program flow never enter to this block in the following loop after were executed the code inside the IF block that ask about sensor temperature values. Thus, the variables c1, c2, c3 will be NULL, and the sketch will throws a runtime exception.

Any suggestion will be welcome.

Regards.
Arturo.

Hi Frederico,
I have exact the same issue. In the setup I read a file from the SD card. This is the code.

void readFunctions(){
  
  FileSystem.begin();
   File functionFile = FileSystem.open("/mnt/sd/arduino/function.txt", FILE_READ);

  while (functionFile.available()) {
    digitalWrite(13, LOW); 
    char ch = functionFile.read();      // run through file, 1 char at a time
    if (ch != ';' && ch > '9'){
      Bridge.put(String(ch), String(stat_off));
      Serial.println(ch);
    }
    delay(200);
  }

  // close the file:
  functionFile.close();
}

void setup()
{

  // Bridge startup
  pinMode(13, OUTPUT);
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);  

  Serial.begin(9600);   // Initialize the Serial
  // Wait until a Serial Monitor is connected.
  while (!Serial);

  // Listen for incoming connection
  server.listenOnLocalhost();
  server.begin();

  pinMode(sOutPin, INPUT);                 	// Set SOUT from RFID pin
  pinMode(enablePin, OUTPUT);              	// Set enablePin as OUTPUT to connect it to the RFID /ENABLE pin

  digitalWrite(enablePin, LOW);            	// Activate the RFID reader

  pinMode(doorBuzzerPin, OUTPUT);              //door buzzer
  pinMode(doorOpenerPin, OUTPUT);              //door opener
  Serial.println("vor readFunctions");
  readFunctions();
  1. If the linux is started and the Yun is connected to computer by usb and the sketch new uploaded, everything works fine. I get all output.
  2. If the Yun is connected with a external power supply and started from scratch the sketch is hanging at this statement while (functionFile.available()) { . I checked this behavior with LED on the Yun. In the setup I switch the LED on and in the readFunction I switch the LED off. If the Yun is powered externally the LED is not turned off

Andreas