package cam;
import java.net.*;
import java.io.*;
public class Camera {
String name = null;
int[] ipv4adr = null;
String ipName = null;
int port = 0;
String authentication = null;
/* Used for debugging. If true, more info is output to console */
private final static boolean DEBUG = true;
/* Constructors */
public Camera() {}
public Camera(int[] ipv4adr, int port, String authentication) {
this.ipv4adr = ipv4adr;
this.port = port;
this.authentication = utils.Base64.encode(authentication);
name = getName();
}
public Camera(String ipName, int[] ipv4adr, int port, String authentication) {
this.ipName = ipName;
this.ipv4adr = ipv4adr;
this.port = port;
this.authentication = utils.Base64.encode(authentication);
name = getName();
}
/* Methods */
/**
* Send a simple request using the cameras CGI interface
* @param request request-string according to cameras CGI interface
* @return String representation of camera built-in server response
*/
public String getResponse(String request) {
String response = null;
/* Return null if IP address is uninitialized */
if((ipv4adr == null && ipName == null) || port == 0)
return response;
/* setup request-string */
String requestURL = getBaseURLString();
requestURL += request;
/* Create a URL object */
URL url = null;
try {
url = new URL(requestURL);
}
catch (MalformedURLException e) {
System.out.println(e);
return response;
}
if(DEBUG) System.out.println("url is:" + url);
/* Setup connection, also sends the request which is incorporated in the URL */
InputStream inStream = null;
URLConnection con = null;
try {
con = url.openConnection();
con.connect();
inStream = con.getInputStream();
}
catch (IOException e) {
System.out.println(e);
inStream = null;
return response;
}
/* Get response */
byte[] resBytes = new byte[1024];
int count = 0;
try {
count = inStream.read(resBytes, 0, resBytes.length);
}
catch (IOException e) {
System.out.println(e);
return response;
}
response = "";
/* Convert byte-response to String */
for(int i = 0; i < count; i++)
response += (char) resBytes[i];
try {
inStream.close();
} catch (IOException e) {
System.out.println(e);
}
inStream = null;
return response.trim();
}
/**
* Get camera name using socket if necessary to get it from camera
* @return Camera name
*/
public String getName() {
if(name != null)
return name;
if((ipv4adr == null) || (port == 0))
return null;
ConnectionWrapper camConn = null;
if(ipName == null)
camConn = new ConnectionWrapper(ipv4adr, port);
else
camConn = new ConnectionWrapper(ipName, port);
String requestString = "GET /Get?Func=CameraName&Kind=1 HTTP/1.1\r\n" +
"Host: "+ getIPAsString() +"\r\n" +
"Authorization: Basic " + authentication + "\r\n" +
"\r\n";
if(DEBUG) System.out.println("Request:\n" + requestString);
byte[] requestBytes = requestString.getBytes();
try {
camConn.outStream.write(requestBytes, 0, requestBytes.length);
}
catch (IOException e) {
System.out.println("Failed to write to stream:\n" + e);
camConn.close();
return name;
}
byte[] responseBytes = new byte[1024];
int count = 0;
try {
count = camConn.inStream.read(responseBytes, 0, responseBytes.length); // Receive "HTTP/1.0 200 OK" packet
if(new String(responseBytes, 0, count).indexOf("HTTP/1.0 200 OK") != -1 )
count = camConn.inStream.read(responseBytes, 0, responseBytes.length);
}
catch (Exception e) {
System.out.println(e);
camConn.close();
return name;
}
String temp = new String(responseBytes, 0, count);
//System.out.println("Response:\n" + temp);
String finder = "Data:";
int nameIndex = ( temp.indexOf(finder) + finder.length() );
name = temp.substring(nameIndex, temp.indexOf('\r', nameIndex));
camConn.close();
return name;
}
/**
* Connects to camera, and captures an MJPEG stream (sequence of JPEG images), untrimmed (some content
* info and boundary info included). Needs to be extended/altered with trimming and length control.
*/
public void getMJPEGStream(long durationSeconds) {
// Return if uninitialized
if((ipv4adr == null && ipName == null) || (port == 0) || (authentication == null))
return;
// Set up connection and streams, prepare CGI-request to camera
ConnectionWrapper camConn = null;
if(ipName == null)
camConn = new ConnectionWrapper(ipv4adr, port);
else
camConn = new ConnectionWrapper(ipName, port);
InputStream mjpegStream = camConn.inStream;
String requestString = "GET /nphMotionJpeg?Resolution=320x240&Quality=Standard HTTP/1.1\r\n" +
"Host: "+ getIPAsString() +"\r\n" +
"Authorization: Basic " + authentication + "\r\n" +
"\r\n";
if(DEBUG) System.out.print("Request:\n" + requestString);
byte[] requestBytes = requestString.getBytes();
// Output-file
FileOutputStream fstream = null;
try {
fstream = new FileOutputStream("mjpeg_" + name + "_" + utils.Timestamp.getStringTime() + ".mjpeg");
}
catch (FileNotFoundException e) {
System.out.println(e);
}
// Array to store bytes read from network-stream
byte[] streamBytes = new byte[4096];
int count = 0;
// Send request to camera
try {
camConn.outStream.write(requestBytes, 0, requestBytes.length);
}
catch (IOException e) {
System.out.println(e);
camConn.close();
}
// First packet is "HTTP/1.0 200 OK\r\n". Can be dismissed.
try {
while(mjpegStream.available() <= 0) ;
count = mjpegStream.read(streamBytes, 0, streamBytes.length);
if(DEBUG) System.out.println("Read " + count + " trimmable bytes from camera stream during stream initialization");
} catch (IOException e) {
System.out.println(e);
}
// When to stop reading from stream
long endTime = System.currentTimeMillis() + (durationSeconds * 1000);
while(System.currentTimeMillis() < endTime) {
try {
while(mjpegStream.available() <= 0) ; // This might be dangerous when reading stream for long time
count = mjpegStream.read(streamBytes, 0, streamBytes.length);
fstream.write(streamBytes, 0, count);
if(DEBUG) System.out.println("Read " + count + " bytes from camera stream");
} catch (IOException e) {
System.out.println(e);
}
}
camConn.close();
try {
fstream.close();
} catch (IOException e) {
System.out.println(e);
}
}
/**
* Connects to camera, and captures an MPEG4 stream, with or without sound.
*/
public void getMPEG4Stream(long durationSeconds) {
// Return if uninitialized
if((ipv4adr == null && ipName == null) || (port == 0) || (authentication == null))
return;
// Set up connection and streams, prepare CGI-request to camera
ConnectionWrapper camConn = null;
if(ipName == null)
camConn = new ConnectionWrapper(ipv4adr, port);
else
camConn = new ConnectionWrapper(ipName, port);
InputStream mjpegStream = camConn.inStream;
// Format is <rtpOverHttp?Url=nphMpeg4/audio-resol>
String requestString = "GET /rtpOverHttp?Url=nphMpeg4/nil-320x240 HTTP/1.1\r\n" +
"Host: "+ getIPAsString() +"\r\n" +
"Authorization: Basic " + authentication + "\r\n" +
"\r\n";
if(DEBUG) System.out.print("Request:\n" + requestString);
byte[] requestBytes = requestString.getBytes();
// Output-file
FileOutputStream fstream = null;
try {
fstream = new FileOutputStream("mpeg4_" + name + "_" + utils.Timestamp.getStringTime() + ".mpeg4");
}
catch (FileNotFoundException e) {
System.out.println(e);
}
// Array to store bytes read from network-stream
byte[] streamBytes = new byte[4096];
int count = 0;
// Send request to camera
try {
camConn.outStream.write(requestBytes, 0, requestBytes.length);
}
catch (IOException e) {
System.out.println(e);
camConn.close();
}
// First 2 packets are "HTTP/1.0 200 OK\r\n" and "Content-type: video/x-pcc-nwc-rtp\r\n\r\n". Can be dismissed.
for(int i = 0; i < 2; i++) {
try {
while(mjpegStream.available() <= 0) ;
count = mjpegStream.read(streamBytes, 0, streamBytes.length);
if(DEBUG) System.out.println("Read " + count + " trimmable bytes from camera stream during stream initialization");
} catch (IOException e) {
System.out.println(e);
}
}
// When to stop reading from stream
long endTime = System.currentTimeMillis() + (durationSeconds * 1000);
while(System.currentTimeMillis() < endTime) {
try {
while(mjpegStream.available() <= 0) ; // This might be dangerous when reading stream for long time
count = mjpegStream.read(streamBytes, 0, streamBytes.length);
fstream.write(streamBytes, 0, count);
if(DEBUG) System.out.println("Read " + count + " bytes from camera stream");
} catch (IOException e) {
System.out.println(e);
}
}
camConn.close();
try {
fstream.close();
} catch (IOException e) {
System.out.println(e);
}
}
/**
* Method to return base URL string in
* format "http://ipName:port/"
* or "http://ip[0].ip[1].ip[2].ip[3]:port/"
* @return Base URL
*/
private String getBaseURLString() {
String s = "http://";
if(ipName == null)
s += getIPAsString();
else
s += ipName;
s += ":" + port + "/";
return s;
}
/**
* Get IP address as a string in format ip[0].ip[1].ip[2].ip[3]
* @return IP address
*/
private String getIPAsString() {
String s = "";
for(int i = 0; i < 4; i++) {
s += ipv4adr[i];
if(i < 3) s += ".";
}
return s;
}
}