背景 我想要压力传感器(他们正在工作)触发内置摄像头并在猫上床时拍照,上传图片并给我发电子邮件,以便我可以在网站上查看实时图像。
PHP服务器
我在这个结构的根上有一个php server running
127.0.0.1:8080
:
NetworkedCat -->
data --> script-cat.php
index.html
NetworkedCat.pde
img.jpg
save2web.php
swiftmailer --> libs, etc
在浏览器上进行测试save2web.php
和cat-script.php
正在运行,即脚本正在上传和通过电子邮件发送。
Arduino的
Arduino应用应该执行以下操作:
压力传感器()也在读取和打印,并且已经校准了阈值。
但NetworkedCat.pde
不是由串行事件触发的。
请注意:
Arduino Processing在另一个localhost
打开port 80
,因为php server
适用于8080
。
如果我缩短处理代码,并仅测试图像捕获和上传,则可以正常工作。所以,bug必须与串行事件有关。
为什么以下处理代码不起作用?
/*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。
答案 0 :(得分:3)
可能最好在Arduino特定版本的堆栈交换上问这个问题。
我的建议让Arduino Processing拍摄(猫的照片)。然后让它将图片上传到PHP网络应用程序。
然后PHP网络应用程序应该接收文件上传(图片)并发送电子邮件给那些想通过电子邮件接收的人。
似乎您在端口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 Processing与PHP Server在同一台计算机上运行,那么"localhost"
将作为服务器连接。
答案 1 :(得分:0)
String mailUrl
应该包含整个字符串:"http://127.0.0.1:8080/cat-script.php"
,而不仅仅是相对于cat-script.php
目录的脚本位置root
。
另外,save2web.php
脚本中存在一个错误 - 此问题中没有出现错误,导致图像无法上传。 move_uploaded_file($fileTempName, $path.fileName);
未包含".fileName"
)
现在一切正常。