Introduction
This is a project for an Android phone that takes pictures and broadcasts the phone GPS coordinates using the amateur radio APRS infrastructure. I'm using it as a backup tracker for a high altitude balloon project, but it can be used for a couple things such as setting in one place and storing time lapse photos, or keeping track of where the phone is graphically on a map.
For example, I set it in my backyard because I knew ducks were visiting periodically and was able to get this picture:
And here is a picture of using aprs.fi to track the phone's location as it moves around (ducks were not involved in this one):
Background
APRS is an amateur radio based technology for communicating information using packet radio. There is an internet infrastructure for it as well (not using a radio at all) which is convenient because you get all the mapping and tracking amateur radio infrastructure such as aprs.fi for free. If you aren't a licensed amateur radio operator, you won't be able to use this code as-is and will have to modify how it posts GPS information and would need to implement the mapping yourself. It is interesting and fairly easy to get an amateur radio license though so I would encourage you to go that route.
Using the Code
The attached code is an Eclipse project that targets Android 2.1. It will also work on Android 1.5 if you want to target that version as well. I upgraded it just to have more exposed camera functionality for setting picture quality and other attributes. There are three main pieces to the project:
- Retrieving GPS coordinates and altitude information
- Taking and storing a picture from the phone camera on an SD card
- Submitting the GPS information through the existing APRS infrastructure
Additionally, there is also some code to save the information entered so it doesn't have to be re-typed every time. The main reason I added this is for the callsign and passcode used so the GPS information can be sent to the APRS servers. If you aren't a licensed amateur radio operator, you won't have anything to put here and will have to either change the code to post to your own server (and then display it on a map) or go get yourself an amateur radio license.
I am mostly a .NET developer during the day so setting up Eclipse and Android was a new thing for me. So if you are an experienced Java developer and see any strangeness in the Java code, that is why! I found the process to be pretty straightforward and very similar to using Visual Studio for .NET Micro projects. For the most part, things just work and you can debug on the device itself which is very nice.
- Retrieving GPS coordinates and altitude information:
All you need for GPS location and altitude is a reference to the location manager. The rest of the code is just formatting it for the APRS infrastructure.
Location location = locationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
String latitude =
getAsDegreesMinutesSeconds(location.getLatitude(), "N", "S");
String longitude =
getAsDegreesMinutesSeconds(location.getLongitude(), "E", "W");
String altitude =
ExactNumDigits(((int)location.getAltitude()) + "", 6);
- Taking and storing a picture from the phone camera on an SD card:
This took lots of trial and error to get right, but appears simple once it is done. Make sure you start a preview before taking a picture (though you don't have to show it apparently) and always clean up once done so if the user switches from your app to a camera based app, they can still use the camera.
public void takePicture() {
try {
toastText("Taking picture");
Camera camera = Camera.open();
camera.setErrorCallback(errorCallback);
try {
camera.startPreview();
camera.takePicture(null, null, jpegCallback);
} finally {
camera.stopPreview();
camera.release();
camera = null;
}
} catch(Exception ex) {
toastText(ex.toString());
}
}
Camera.ErrorCallback errorCallback = new Camera.ErrorCallback() {
public void onError(int arg0, Camera arg1) {
toastText("Camera error: " + arg0);
}
};
PictureCallback jpegCallback = new PictureCallback() {
public void onPictureTaken(byte[] data, Camera camera) {
String filePath = String.format("/sdcard/Pics/%1$s.jpg",
new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss").format(new Date()));
toastText("Writing " + data.length + " bytes to " + filePath);
FileOutputStream outStream = null;
try {
outStream = new FileOutputStream(filePath);
outStream.write(data);
outStream.close();
} catch (Exception e) {
toastText(e.toString());
}
}
};
- Submitting the GPS information through the existing APRS infrastructure:
For more information, see the APRS standard for how information should be submitted but it is just a normal TCP/IP connection, sending and receiving string
s between the client and the server. If the callsign/passcode don't match up, the server will not accept the position report and you won't see it on sites such as aprs.fi.
Socket socket = null;
try {
socket = new Socket("texas.aprs2.net", 14580);
BufferedReader inReader = new BufferedReader(
new InputStreamReader(socket.getInputStream())
);
String input = inReader.readLine();
PrintWriter out = new PrintWriter(
new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())
),
true
);
String loginText =
String.format("user %1$s pass %2$s -1 vers APRSAndroid 1.0_00 filter m/5",
callSign,
passCode
);
out.println(loginText);
input = inReader.readLine();
if(!input.startsWith(String.format("# logresp %1$s verified", callSign)))
throw new Exception("Unable to verify call sign/pass code");
String locationString =
String.format("%1$s>APRS,TCPIP*:=%2$s/0%3$s$/A=%4$sAPRSAndroid",
callSign,
latitude,
longitude,
altitude
);
out.println(locationString);
toastText(
String.format("Sent location %1$s/%2$s /A=%3$s for %4$s",
latitude,
longitude,
altitude,
callSign
));
} catch (Exception e) {
toastText("Unable to connect: " + e.getMessage());
}
finally {
try {
if(socket != null) {
socket.close();
}
} catch (IOException e1) { }
}
Summary
So that is all that is needed to have a $100 device that can broadcast GPS position and automatically take pictures! The Android device I used is an AT&T Backflip, easily procurable off of Ebay and something I really enjoy using. I think this is a nice and easy way of automating pictures similar to using CHDK but with the ability to debug on the device and also use the phone's additional capabilities such as GPS and network access. Below is a screenshot of the interface - it won't win me any UI design awards but gives enough control over all the features.
Enjoy!