9

Background I want pressure sensors (they are working) to trigger the built-in camera and take a picture when cat goes to bed, upload the pic and email me so I can go check out the real-time image on web-site.

PHP Server I have a php server running 127.0.0.1:8080 on the root of this structure:

 NetworkedCat -->
                  data --> script-cat.php
                  index.html 
                  NetworkedCat.pde 
                  img.jpg
                  save2web.php
                  swiftmailer --> libs, etc

Testing on browser, save2web.php and cat-script.php are working, that is, scripts are uploading and emailing.

Arduino

The Arduino app should do the following:

  1. receive an input from a pressure sensor
  2. verify whether threshold is surpassed
  3. take picture from build-in camera
  4. upload pic to website
  5. send mail informing about the upload

The pressure sensor () is also reading and printing, and threshold has been calibrated.

But NetworkedCat.pde is NOT triggered by the serial events.

Please note:

Arduino Processing opens localhost at another port 80, because php server works on 8080.

If I shorten the Processing code, and test the image capture and upload only, it works. so, the bug must be related to the serial events.

Why is the Processing code below not working?

/*Serial String reader
Context: Arduino

Reads in a string of characters until it gets a linefeed (ASCII 10).
then converts the string into a number
*/

import processing.serial.*;
import processing.video.*;
import processing.net.*;

Serial myPort;              //the serial port
float sensorValue = 0;      //the value form the sensor
float prevSensorValue = 0;  //previous value from the sensor
int threshold = 200;        //above this number, the cat is on the mat

int currentTime = 0;       //the current time as a single number
int lastMailTime = 0;      //last minute you sent a mail
int mailInterval = 60;     //minimum seconds betweeen mails
String mailUrl = "cat-script.php";
int lastPicture = 0;       //last minute you sent a picture
int lastPictureTime = 0;   //last minute you sent a picture
int pictureInterval = 10;  //minimum seconds between pictures

Capture myCam;            //camera capture library instance
String fileName = "img.jpg"; //file name for the picture

//location on your server for the picture script:
String pictureScriptUrl = "save2web.php";
String boundary = "----H4rkNrF"; //string boundary for the post request

Client thisClient;        //instance for the net library


//float xPos = 0;             //horizontal position of the graph
//float lastXPos = 0;         //previous horizontal position  



void setup(){
  size(400, 300);
  //list all the available serial ports
  println(Serial.list());

  myPort = new Serial(this, Serial.list()[7], 9600);

  //reads bytes into a buffer until you get a newline (ASCII 10);
  myPort.bufferUntil('\n');

  //set initial background and smooth drawing:
  background(#543174);
  smooth();
  //for a list of cameras on your computer, use this line:
  println(Capture.list());

  //use the default camera for capture at 30 fps
  myCam = new Capture(this, width, height, 30);
  myCam.start();
}

void draw(){
  //make a single number fmor the current hour, minute, and second
  currentTime = hour() * 3600 + minute() * 60 + second();

  if (myCam.available() == true) {
    //draw the camera image to the screen;
    myCam.read();
    set(0, 0, myCam);

    //get the time as a string
    String timeStamp = nf(hour(), 2) + ":" + nf(minute(), 2)
    + ":" + nf(second(), 2) + "   " + nf(day(), 2) + "-"
    + nf(month(), 2) + "-" + nf(year(), 4);

    //draw a dropshadow for the time text:
    fill(15);
    text(timeStamp, 11, height - 19);
    //draw the main time next
    fill(255);
    text(timeStamp, 10, height - 20);
  }
}

void serialEvent (Serial myPort){
  //get the ASCII string
  String inString = myPort.readStringUntil('\n');

  if (inString != null){
    //trim off any whitespace:
    inString = trim(inString);
    //convert to an int and map to the screen height
    sensorValue = float(inString);
    //println(sensorValue);
    sensorValue = map(sensorValue, 0, 1023, 0, height);
    println(sensorValue);

    if (sensorValue > threshold){
      if(currentTime - lastPictureTime > pictureInterval){
        PImage thisFrame = get();
        thisFrame.save(fileName);
        postPicture();
        lastPictureTime = currentTime;
      }
      //if the last reading was less than the threshold
      //then the cat just got on the mat
      if(prevSensorValue <= threshold){
        println("Cat is on the mat.");
        sendMail();
      }
    }
    else{
      //if the sensor value is less than the threshold,
      //and the previous value was greater, then the cat
      //just left the mat
      if (prevSensorValue > threshold){
        println("Cat is not on the mat.");
      }
    }
    //save the current value for the next time
    prevSensorValue = sensorValue;
  }
}


void sendMail(){
  //how long has passed since the last mail
  int timeDifference = currentTime - lastMailTime;

  if( timeDifference > mailInterval){
    String[] mailScript = loadStrings(mailUrl);
    println("results from mail script:");
    println(mailScript);

    //save the current minute for next time
    lastMailTime = currentTime;
  }
}

EDIT:

By exclusion, the bug is in this last function, but I still haven't found it:

void postPicture(){
 //load the saved image into an array of bytes
  byte[] thisFile=loadBytes(fileName);


//open a new connection to the server
 thisClient = new Client(this, "localhost", 80);

//make an HTTP POST request:
thisClient.write("POST " + pictureScriptUrl + " HTTP/1.1\n");

thisClient.write("Host: localhost\n");

//tell the server you're sending the POST in multiple parts
//and send a unique string that will delineate the parts
thisClient.write("Content-Type: multipart/form-data; boundary=");

thisClient.write(boundary + "\n");


//form the beginning of the request
String requestHead ="--" + boundary + "\n";

requestHead +="Content-Disposition: form-data; name=\"file\"; ";
requestHead += "filename=\"" + fileName + "\"\n";
requestHead +="Content-Type: image/jpeg\n\n";


//form the end of the request
String tail="\n\n--" + boundary + "--\n";


//calculate and send the length of the total request
//including the head of the request, the file, and the tail
int contentLength = requestHead.length() + thisFile.length + tail.length();

 thisClient.write("Content-Length: " + contentLength + "\n\n");
 //send the header of the request, the file and the tail
 thisClient.write(requestHead);
 thisClient.write(thisFile);
 thisClient.write(tail);
 }

This is what is being raised:

java.lang.NullPointerException
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at    javax.imageio.stream.FileCacheImageOutputStream.close(FileCacheImageOutputStream.java:238)
at com.sun.imageio.stream.StreamCloser$CloseAction.performAction(StreamCloser.java:130)
at com.sun.imageio.stream.StreamCloser$1.run(StreamCloser.java:74)
at java.lang.Thread.run(Thread.java:745)

PLUS a Not a Number exception:

sensorValue = map(NaN, 1023, 0, height);

My system is Unix.

8-Bit Borges
  • 9,643
  • 29
  • 101
  • 198
  • have you check the permission of the directory where you are trying to upload the files? – MuntingInsekto Oct 06 '15 at 05:18
  • @vnpnlz no, but the files are sucessfully uploaded on the same directory if I run the PHP scripts bypassing Processing. – 8-Bit Borges Oct 06 '15 at 05:28
  • There seems to be some bugs in your `postPicture` in this code: 1. there must be a space between the method `POST` and the path. 2. a slash should be at the beginning of the path. 3. `\r\n` should be used instead of `\n` as newline in HTTP. 4.you had excess newline at the beginning and end of the data. – MikeCAT Oct 06 '15 at 13:22
  • @MikeCAT, it had to be a Cat, for a Cat project... 1.ok 2. you mean `"/save2web.php"`, at the declaration of variable? 3. you mean only here `" HTTP/1.1\r\n"` ? 4. what do you mean by "data"? – 8-Bit Borges Oct 07 '15 at 02:04
  • @data_garden 2. yes 3. no, all newlines in HTTP request 4. the data sent as form data (message body) fixed code: http://codepad.org/u3ZafLLW – MikeCAT Oct 07 '15 at 12:15
  • @MikeCAT thank you for the code. this is what I get after using it: `java.lang.NullPointerException at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) at javax.imageio.stream.FileCacheImageOutputStream.close(FileCacheImageOutputStream.java:238) at com.sun.imageio.stream.StreamCloser$CloseAction.performAction(StreamCloser.java:130) at com.sun.imageio.stream.StreamCloser$1.run(StreamCloser.java:74) at java.lang.Thread.run(Thread.java:745)` – 8-Bit Borges Oct 07 '15 at 22:03
  • Is the code availabel somewhere, like in GitHub or so? I like to look at the full classes not these snippets. Hard to see / detect issue with just some parts of the code. What libraries are used etc... – Verhagen Oct 14 '15 at 15:08
  • Improve the question, with what is working and what is not working. What is the function of the PHP server? Is this all ok? These Java snippets, is this the Arduino client, trying to upload some data? What communication does not go well? Arduino to/from PHP Server ? Some client extracting data from the PHP server ? – Verhagen Oct 14 '15 at 15:11
  • It is unclear where the Java comes in, is that on the Arduino ? What is the overall functionality you want to accomplish? – Verhagen Oct 14 '15 at 15:14
  • @Verhagen the processing libraries are `serial`, `video` and `net`. The code above is all the Processing code there is. Java comes in within Processing software. do you need PHP codes? I can send it to you. but all PHP code (to upload picture and mail me) is working outside Processing, via PHP server on the same directory. – 8-Bit Borges Oct 15 '15 at 04:57
  • 1
    @Verhagen the functionality: I want pressure sensors (they are working) to trigger the built-in camera and take a picture when cat goes to bed, upload the pic and email me so I can go check out the real-time image on web-site. – 8-Bit Borges Oct 15 '15 at 05:01
  • @data_garden Ok, makes a lot more sense now! :) Question, does this code run on the PHP Server or on the Arduino ? – Verhagen Oct 15 '15 at 05:07
  • @Verhagen serial communication being printed in Processing, float numbers. I have a simpler Processing file where `postPicture()` method works when the keyboard takes the picture. that is: a simpler program uploads the picture alright. the problem comes when I try to trigger this function via arduino. Processing reads the data, but it won't upload it, nor email me. so, I figure it is something wrong with `serialEvent()` method and/or `sendMail()` method. hope this helps to improve clarity. – 8-Bit Borges Oct 15 '15 at 05:08
  • Seems you are using http://playground.arduino.cc/Interfacing/Processing ? – Verhagen Oct 15 '15 at 05:10
  • PHP server was being used on port 8080 for testing purposes. I reckon `new Client(this, "localhost", 80)` class opens another connection, on port 80, and runs on Arduino/Processing. I wonder if there is any conflict when both ports are being served on localhost. – 8-Bit Borges Oct 15 '15 at 05:12
  • @Verhagen no, I am using Processing only, which connects to the port being used by Arduino, #7 on my port list. – 8-Bit Borges Oct 15 '15 at 05:15
  • @Verhagen I run `sudo php -S 127.0.0.1:8080` on the same directory where Processing opens its server connection. – 8-Bit Borges Oct 15 '15 at 05:17
  • What is the function of the PHP server ? – Verhagen Oct 15 '15 at 05:42
  • The Arduino app, does not need to open it's own port (on port 80). For as far as understand from you question, the Arduino does just take the picture and upload it to the PHP server. And it also sent an e-mail (also to the PHP Server, which I do not understand). The PHP server should know, that the picture was received, if you use some file upload function, of the php server. – Verhagen Oct 15 '15 at 05:44
  • @Verhagen PHP file has a fairly large body...but theres the `move_uploaded_file($fileTempName, $path);`, is this what you mean? – 8-Bit Borges Oct 15 '15 at 05:44
  • If you want to sent picture to outside world, if would be better to do that through the php application, which also receives the picture. – Verhagen Oct 15 '15 at 05:45
  • @Verhagen :-) yes, but I am stubborn, I MUST do it with processing first, because I am a big fan of this platform. – 8-Bit Borges Oct 15 '15 at 05:48
  • @Verhagen I don't have arduino on me now, but I will try your suggestion, sir, and will get back to you. the kindest of answers, yours! see you soon – 8-Bit Borges Oct 15 '15 at 06:12
  • Sure no issue :) success – Verhagen Oct 15 '15 at 06:23
  • @Verhagen hey, I still get the same Java exception as stated above, albeit switching the port to 8080. but I've realized that I am getting NaN exception as well, on this line: sensorValue = map(NaN, 0, 1023, 0, height);; don't know why sensorValue is NaN; float numbers are being printed correctely on the console.. – – 8-Bit Borges Oct 16 '15 at 22:07

2 Answers2

3

Probably better to ask this question on Arduino specific version of stack exchange.

My suggestion Let Arduino Processing take the picture (of the cat). And let it upload the picture to the PHP web-app.

Then the PHP web-app, should receive the file upload (the picture) and sent an e-mail to those who like to receive it by e-mail.

enter image description here

Seems you are running the PHP server on port 8080, then the Arduino Processing app, also need to connect to that port! So update your code, so that the client connects to the server:

The Arduino Processing (the client), need to know, where the PHP server is located on the network. So it need to know the DNS name or the IP-address of the server. So correct the string "name-or-ip", in the below code!

//open a new connection to the server
thisClient = new Client(this, "name-or-ip", 8080);

Tip: In case Arduino Processing is running on the same computer as PHP Server, then "localhost" will work as server connection.

Community
  • 1
  • 1
Verhagen
  • 3,885
  • 26
  • 36
  • hey, I still get the same Java exception as stated above, albeit switching the port to 8080. but I've realized that I am getting `NaN` exception as well, on this line: `sensorValue = map(NaN, 0, 1023, 0, height);`; don't know why `sensorValue` is `NaN`; float numbers are being printed correctely on the console.. – 8-Bit Borges Oct 16 '15 at 05:38
0

String mailUrl should include the whole string: "http://127.0.0.1:8080/cat-script.php", and not just the script location cat-script.php relative to root directory.

also, there was a bug in the save2web.php script -not present in this question, that was preventing image from being uploaded. move_uploaded_file($fileTempName, $path.fileName); had not included ".fileName")

everything works fine now.

8-Bit Borges
  • 9,643
  • 29
  • 101
  • 198