Arduino处理客户端无法将文件上传到PHP服务器

9

背景 我希望压力传感器(它们正在工作)能够触发内置摄像头,在猫睡觉时拍照,上传图片并通过电子邮件发送给我,这样我就可以在网站上查看实时图像。

PHP服务器 我有一个运行在根目录下的php服务器,地址为127.0.0.1:8080

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

在浏览器上测试,save2web.phpcat-script.php可以正常工作,也就是说,脚本正在上传和发送电子邮件。

Arduino

Arduino应该执行以下操作:

  1. 接收来自压力传感器的输入
  2. 验证是否超过阈值
  3. 从内置摄像头拍照
  4. 将图片上传到网站
  5. 发送电子邮件通知有关上传的信息

压力传感器()也在读取和打印,并且已经校准了阈值。

但是,NetworkedCat.pde没有被串行事件触发。

请注意:

Arduino Processing在另一个端口80上打开localhost,因为php服务器8080上工作。

如果我缩短处理代码,并仅测试图像捕获和上传,则可以正常工作。 因此,错误必须与串行事件有关。

为什么下面的处理代码不起作用?

/*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;
  }
}

编辑:

通过排除,这个错误应该在最后一个函数里,但我还没有找到它:

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);
 }

以下是被提出的内容:

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)

在遇到 Not a Number 异常时:

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

我的系统是 Unix。


@vnpnlz 不是,但如果我绕过处理运行PHP脚本,文件将成功上传到同一目录。 - 8-Bit Borges
@MikeCAT,必须是一只猫,用于猫项目... 1.好的 2.你指的是变量声明时的"/save2web.php"吗? 3.你是指仅在此处使用" HTTP/1.1\r\n"吗? 4.你所说的“数据”是指什么? - 8-Bit Borges
@data_garden 2. 是的 3. 不,HTTP请求中的所有换行符 4. 数据作为表单数据(消息正文)发送 固定代码:http://codepad.org/u3ZafLLW - MikeCAT
@MikeCAT 谢谢你的代码。使用后我得到了以下结果: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
1
@Verhagen 功能需求:我想要使用压力传感器(它们已经工作)来触发内置摄像头,在猫上床时拍照,上传图片并通过电子邮件通知我,以便我可以在网站上查看实时图像。 - 8-Bit Borges
显示剩余20条评论
2个回答

3

建议在Arduino特定版本的堆栈交换上提出这个问题可能更好。

我的建议让Arduino处理拍摄(猫的)图片。然后让它上传图片到PHP Web应用程序。

然后,PHP Web应用程序应该接收文件上传(图片),并向那些希望通过电子邮件接收的人发送电子邮件。

enter image description here

似乎您正在端口8080上运行PHP服务器,那么Arduino Processing应用程序也需要连接到该端口!因此,请更新您的代码,以便客户端连接到服务器:
Arduino Processing(客户端)需要知道PHP服务器在网络中的位置。因此,它需要知道服务器的DNS名称或IP地址。因此,请更正下面代码中的字符串"name-or-ip"
//open a new connection to the server
thisClient = new Client(this, "name-or-ip", 8080);

提示:如果Arduino处理程序在同一台计算机上运行PHP服务器,则"localhost"将作为服务器连接工作。


嘿,我仍然遇到与上述相同的Java异常,尽管将端口切换到8080。但我已经意识到,在这一行中我也遇到了NaN异常:sensorValue = map(NaN, 0, 1023, 0, height);;不知道为什么sensorValueNaN;浮点数在控制台上正确打印。 - 8-Bit Borges

0

String mailUrl 应包含整个字符串:"http://127.0.0.1:8080/cat-script.php",而不仅仅是相对于 root 目录的脚本位置 cat-script.php

此外,在 save2web.php 脚本中存在一个错误 - 不在此问题中,导致无法上传图像。 move_uploaded_file($fileTempName, $path.fileName); 没有包括 ".fileName"

现在一切正常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接