📄 gsmspotter.java
字号:
/* * Created on Jun 29, 2004 */package org.placelab.midp;import java.io.DataInputStream;import java.io.DataOutputStream;import java.io.IOException;import java.io.InputStream;import javax.microedition.io.Connector;import javax.microedition.io.SocketConnection;import org.placelab.core.BeaconMeasurement;import org.placelab.core.BeaconReading;import org.placelab.core.Measurement;import org.placelab.spotter.SpotterException;import org.placelab.spotter.SyncSpotter;import org.placelab.util.StringUtil;/** * This spotter polls a localhost server running on the phone. This is a * synchronous spotter that makes a blocking read request to the server, returning * when the read completes. * * NEW: The GSMSpotter now supports operation in the emulator by using log files that * were uploaded by the StumbleUploadProxy placed inside the jar to get the Measurements. * The build.xml helps here by only placing those log files in the jar when the do-emulate * target is selected. */public class GSMSpotter extends SyncSpotter { //the server passes back parameterNumber values //cellId,areaId,signalStrength,MCC,MNC,networkName private int parameterNumber = 6; private long scanIntervalMillis; SocketConnection sc = null; DataInputStream is = null; DataOutputStream dos = null; private boolean simulated; private InputStream logReader = null; /** * Construct a GSMSpotter with default scan time of 1 second * */ public GSMSpotter() { this(1000); } /** * Construct a GSMSpotter * @param intervalMillis time between scans */ public GSMSpotter(long intervalMillis) { super(); scanIntervalMillis = intervalMillis; if(setupLogReader()) { simulated = true; } else { simulated = false; } } /* * The idea here is to go through the jar file, looking for uploaded-log-i files. * If none are found, then it is assumed we are running on the actual device. * If some are found, then it is assumed that we are running in the simulator. * The build script ties in here by only putting in the log files when the emulate * target is specified. * * The most recent log file in the jar is used. */ private boolean setupLogReader() { int i = 0; InputStream stream1 = this.getClass().getResourceAsStream("/compressed-log-" + i + ".txt"); InputStream stream2; if(stream1 == null) { System.out.println("GSMSpotter LogReader: cannot find resource"); return false; } else { System.out.println("GSMSpotter LogReader: found resource"); } i++; while(true) { stream2 = stream1; stream1 = this.getClass().getResourceAsStream("/compressed-log-" + i + ".txt"); if(stream1 != null) { try { stream2.close(); } catch (IOException ioe) { } } else { logReader = stream2; return true; } } } /* * (non-Javadoc) * @see org.placelab.spotter.Spotter#open() */ public void open() throws SpotterException { if(simulated) return; try { //native server runs on port 4040 sc = (SocketConnection) Connector.open("socket://127.0.0.1:4040"); if(sc == null) throw new SpotterException("Cannot open socket to native GSM spotter"); sc.setSocketOption(SocketConnection.DELAY, 0); is = sc.openDataInputStream(); dos = sc.openDataOutputStream(); } catch (IOException ioe) { throw new SpotterException("Cannot open stream to native GSM spotter"); } } /* * (non-Javadoc) * @see org.placelab.spotter.Spotter#close() */ public void close() throws SpotterException { try { if (is != null) is.close(); if (sc != null) sc.close(); if (dos != null) dos.close(); if (logReader != null) logReader.close(); } catch (IOException ioe) { throw new SpotterException("Cannot close stream to native GSM spotter"); } } /** * Polls the native server for a GSM reading * @return Measurement containing a GSM reading * @throws IOException * @throws SpotterException */ private Measurement queryServer() throws IOException,SpotterException { StringBuffer message = new StringBuffer(""); //open connection if(dos == null) throw new SpotterException("GSMSpotter.query: output stream not open"); if(is == null) throw new SpotterException("GSMSpotter.query: input stream not open"); byte[] b = { 1 }; dos.write(b); dos.flush(); //get data int ch; while ((ch = is.read()) != -1) { if (ch == '\n') break; message = message.append((char) ch); } //parse data String data[] = StringUtil.split(message.toString(), ','); if (data.length == parameterNumber) { String cellId = data[0]; String areaId = data[1]; String signalStrength = data[2]; String MCC = data[3]; String MNC = data[4]; String networkName = data[5]; //construct a GSM Reading GSMReading[] grs = new GSMReading[1]; GSMReading gr = new GSMReading(cellId, areaId, signalStrength, MCC, MNC, networkName); grs[0] = gr; //construct a beaconmeasurement return new BeaconMeasurement(System.currentTimeMillis(), grs); } return null; } private BeaconMeasurement currentMeasurement = null; private BeaconMeasurement nextMeasurement = null; private long sampleTime = 0; private long timeToWait = 0; /* * The phone stores the logs in such a way that it only records the Measurements * when they change in order to save space. Given that, I continue to return * the same Measurement until it is time for the next Measurement */ private Measurement readLog() throws IOException, SpotterException { if(sampleTime == 0) { sampleTime = System.currentTimeMillis(); currentMeasurement = readGSMMeasurement(); if(currentMeasurement != null) { nextMeasurement = readGSMMeasurement(); } } else if(timeToWait != -1 && (System.currentTimeMillis() - sampleTime) > timeToWait) { currentMeasurement = nextMeasurement; nextMeasurement = readGSMMeasurement(); } else { return currentMeasurement; } if(nextMeasurement == null) { logReader.close(); logReader = null; // current measurement is the last measurement, so it lasts forever timeToWait = -1; } else if(timeToWait != -1) { timeToWait = nextMeasurement.getTimestamp() - currentMeasurement.getTimestamp(); } // this may be null if the log is empty. hope this is ok. return currentMeasurement; } // helper method. simply reads a contigous BeaconMeasurement from the log // other types of measurements or readings are just ignored // returns null if the file is done private BeaconMeasurement readGSMMeasurement() throws IOException { while(true) { byte[] byteLine = new byte[256]; boolean checkNext = false; for(int i=0;i<byteLine.length;i++) { int value = logReader.read(); if(value == -1) { // EOF return null; } byte b = (byte)value; if (((char) b) == '\r') { checkNext = true; } else if (checkNext) { if (((char) b) == '\n') { byte[] tempBytes = byteLine; //array needs to be exact length byteLine = new byte[i - 1]; System.arraycopy(tempBytes, 0, byteLine, 0, i - 1); break; } checkNext = false; } byteLine[i] = b; } String line = new String(byteLine,0,byteLine.length); if(line == null) return null; if(line.startsWith("#")) { //this would be the #Placelab v2 string // do it again, its the first line continue; } else if(line.equals("DONE")) { //we're done here System.out.println("GSMSpotter: Log is done"); return null; } else { //it must be a measurement Measurement m = Measurement.fromCompressedBytes(byteLine); if (m != null) { if(m instanceof BeaconMeasurement) { // cull non-gsm readings BeaconMeasurement ret = new BeaconMeasurement(m.getTimestamp()); BeaconReading[] readings = ((BeaconMeasurement)m).getReadings(); for(int j = 0; j < readings.length; j++) { if(readings[j] instanceof GSMReading) { ret.addReading(readings[j]); } } return ret; } else continue; } else { continue; } } } } /* * (non-Javadoc) * @see org.placelab.spotter.SyncSpotter#getMeasurementImpl() */ protected Measurement getMeasurementImpl() throws SpotterException { try { if(!simulated) { return queryServer(); } else { return readLog(); } } catch (IOException e) { throw new SpotterException(e.getMessage()); } } /** * Returns the scan interval for polling the native server * @return nextScanInterval */ protected long nextScanInterval() { return scanIntervalMillis; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -