Permalink
Browse files

Merge branch 'predictive_protocols'

  • Loading branch information...
2 parents 954d021 + 9faa007 commit 9216a0221c03d4e5a33ec8caa1422a8deeabebb7 @theterg theterg committed Sep 28, 2011
@@ -7,11 +7,11 @@ Bundle-Version: 1.0.0
Bundle-Vendor: theterg
Bundle-Description: The Remote Monitoring demo - using com.buglabs.xbee
Bug-Bundle-Type: Application
-BUG-API-Version: 2.0.2
Import-Package: com.buglabs.application,
com.buglabs.util,
com.buglabs.xbee,
com.buglabs.xbee.protocol,
org.osgi.framework,
org.osgi.service.log,
org.osgi.util.tracker
+BUG-API-Version: 2.0.2
@@ -3,18 +3,14 @@
import java.util.Arrays;
import java.util.Map;
+import org.osgi.service.log.LogService;
+
+import com.buglabs.application.ServiceTrackerHelper.ManagedRunnable;
import com.buglabs.xbee.XBeeCallback;
import com.buglabs.xbee.XBeeController;
import com.buglabs.xbee.protocol.MaxbotixRangefinder;
import com.buglabs.xbee.protocol.PIRMotion;
-import com.buglabs.xbee.protocol.SerialDevice;
import com.buglabs.xbee.protocol.SparkfunWeatherboard;
-import com.buglabs.xbee.protocol.XBeeProtocol;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.service.log.LogService;
-
-import com.buglabs.application.ServiceTrackerHelper.ManagedRunnable;
/**
* This class represents the running application when all service dependencies are fulfilled.
*
@@ -26,35 +22,23 @@
* finer grained service binding logic, see ServiceTrackerHelper.openServiceTracker(BundleContext context, String[] services, Filter filter, ServiceTrackerCustomizer customizer)
*/
public class RemoteMonDemoAPIApplication implements ManagedRunnable, XBeeCallback {
- final int[] WEATHER_ADDRESS = {0x00, 0x03};
- final int[] MOTION_ADDRESS = {0x00, 0x02};
- final int[] RANGE_ADDRESS = {0x00, 0x01};
-
private XBeeController xbc;
private LogService ls;
- private SparkfunWeatherboard weather;
- private MaxbotixRangefinder range;
- private PIRMotion motion;
@Override
public void dataRecieved(Map<String, Object> data) {
- /*if ((XBeeProtocol)data.get("protocol") == motion){
- ilog("Motion detected!");
- ilog((String)xbc.getResponse(RANGE_ADDRESS).get("Range"));
- ilog((String)xbc.getResponse(WEATHER_ADDRESS).get("Temperature"));
- }*/
- if ((XBeeProtocol)data.get("protocol") == weather){
+ if ((Class<?>)data.get("class") == SparkfunWeatherboard.class){
ilog("Weather data from "+Integer.toHexString(((int[])data.get("address"))[1]));
ilog("Temperature: "+data.get("Temperature"));
ilog("Humidity: "+data.get("Humidity"));
ilog("Dewpoint: "+data.get("Dewpoint"));
ilog("Pressure: "+data.get("Pressure"));
ilog("Light: "+data.get("Light"));
- } else if ((XBeeProtocol)data.get("protocol") == range){
+ } else if ((Class<?>)data.get("class") == MaxbotixRangefinder.class){
String range = (String) data.get("Range");
ilog("Range from "+Integer.toHexString(((int[])data.get("address"))[1])
+": "+range);
- } else if ((XBeeProtocol)data.get("protocol") == motion){
+ } else if ((Class<?>)data.get("class") == PIRMotion.class){
ilog("Motion detected from "+Integer.toHexString(((int[])data.get("address"))[1]));
} else {
ilog("Unknown data: "+Arrays.toString((int[])data.get("raw")));
@@ -66,19 +50,19 @@ public void run(Map<Object, Object> services) {
xbc = (XBeeController) services.get(XBeeController.class.getName());
ls = (LogService) services.get(LogService.class.getName());
ilog("start");
- weather = new SparkfunWeatherboard(WEATHER_ADDRESS, xbc);
- range = new MaxbotixRangefinder(RANGE_ADDRESS, xbc);
- motion = new PIRMotion(MOTION_ADDRESS , xbc);
+ xbc.addPredictive(SparkfunWeatherboard.class);
+ xbc.addPredictive(MaxbotixRangefinder.class);
+ xbc.addPredictive(PIRMotion.class);
}
@Override
public void shutdown() {
- xbc.removeListener(WEATHER_ADDRESS);
- xbc.removeListener(RANGE_ADDRESS);
- xbc.removeListener(MOTION_ADDRESS);
+ xbc.removeAll(SparkfunWeatherboard.class);
+ xbc.removeAll(MaxbotixRangefinder.class);
+ xbc.removeAll(PIRMotion.class);
ilog("Stop");
}
- void ilog(String message){ ls.log(ls.LOG_INFO, "["+this.getClass().getSimpleName()+"] "+message); }
+ void ilog(String message){ ls.log(LogService.LOG_INFO, "["+this.getClass().getSimpleName()+"] "+message); }
}
@@ -2,6 +2,7 @@
import java.util.Map;
+import com.buglabs.xbee.protocol.BaseXBeeProtocol;
import com.buglabs.xbee.protocol.XBeeProtocol;
import com.rapplogic.xbee.api.XBee;
@@ -11,4 +12,6 @@
public XBee getXBee();
public Map<String,Object> getResponse();
public Map<String,Object> getResponse(int[] addr);
+ public void addPredictive(Class proto);
+ public void removeAll(Class proto);
}
@@ -1,7 +1,9 @@
package com.buglabs.xbee;
+import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -12,6 +14,7 @@
import org.osgi.util.tracker.ServiceTracker;
import com.buglabs.application.ServiceTrackerHelper.ManagedRunnable;
+import com.buglabs.xbee.protocol.BaseXBeeProtocol;
import com.buglabs.xbee.protocol.XBeeProtocol;
import com.rapplogic.xbee.api.ApiId;
import com.rapplogic.xbee.api.AtCommand;
@@ -39,9 +42,10 @@
private Thread t;
private LogService ls;
private boolean running = true;
- private String devnode = "/dev/ttyUSB0";
+ private String devnode = "/dev/ttyXbee0";
private int baud = 9600;
private Map<XBeeAddress, XBeeProtocol> protocols;
+ private Set<Class> expectedProtocols;
private BundleContext _context;
private ServiceTracker tracker;
@@ -59,6 +63,41 @@ public void processResponse(XBeeResponse res) {
whiteboardNotify(ret);
}
+ private Map<String,Object> predictiveParse(XBeeResponse res){
+ Map<String,Object> ret = null;
+ if (res.getApiId() == ApiId.AT_RESPONSE)
+ return null;
+ boolean found = false;
+ for (int i=0;i<VALID_APIID.length;i++)
+ if (res.getApiId() == VALID_APIID[i])
+ found = true;
+ if (!found){
+ return null;
+ }
+ RxBaseResponse pkt = (RxBaseResponse)res;
+ for (Class proto:expectedProtocols){
+ XBeeProtocol candidate = null;
+ try {
+ candidate = (XBeeProtocol) proto.newInstance();
+ } catch (InstantiationException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IllegalAccessException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ if (candidate == null){
+ continue;
+ }
+ if (candidate.parseable(res)){
+ candidate.setAddr(pkt.getSourceAddress());
+ addListener(candidate);
+ return candidate.parse(res);
+ }
+ }
+ return null;
+ }
+
private Map<String,Object> parseResponse(XBeeResponse res){
//Shortcut - AT_Responses should only be synchronous
//Also, ATMY is used as a ping, so we need to filter it out
@@ -83,16 +122,24 @@ public void processResponse(XBeeResponse res) {
//so we shouldn't report unparseable data.
if (ret != null){
ret.put("protocol", protocols.get(pkt.getSourceAddress()));
+ ret.put("class", protocols.get(pkt.getSourceAddress()).getClass());
ret.put("address", pkt.getSourceAddress().getAddress());
}
return ret;
//If we don't know where the packet came from, we can't parse it!
//Send the raw (but still unescaped) packet bytes.
} else {
if (tracker.size() > 0){
- ret = new HashMap<String,Object>();
- ret.put("raw", pkt.getProcessedPacketBytes());
- ret.put("address", pkt.getSourceAddress().getAddress());
+ //If we have listeners, try to guess the protocol for them.
+ dlog("Attempting to guess the protocol...");
+ ret = predictiveParse(res);
+ if (ret != null){
+ dlog("prediction success: "+protocols.get(pkt.getSourceAddress()).getClass().getName());
+ ret.put("protocol", protocols.get(pkt.getSourceAddress()));
+ ret.put("class", protocols.get(pkt.getSourceAddress()).getClass());
+ ret.put("address", pkt.getSourceAddress().getAddress());
+ }
+ return ret;
} else {
dlog("data(no consumers):"+ByteUtils.toString(pkt.getProcessedPacketBytes()));
}
@@ -165,11 +212,29 @@ public XBeeMonitor(BundleContext context){
return ret;
}
+ @Override
+ public void addPredictive(Class proto) {
+ expectedProtocols.add(proto);
+ }
+
+ @Override
+ public void removeAll(Class proto) {
+ boolean success = expectedProtocols.remove(proto);
+ Map<XBeeAddress, XBeeProtocol> copyOfProtocols = new HashMap<XBeeAddress, XBeeProtocol>(protocols);
+ for (Map.Entry<XBeeAddress, XBeeProtocol> entry : copyOfProtocols.entrySet()){
+ if (entry.getValue().getClass() == proto){
+ dlog("removing protocol at "+ByteUtils.toBase16(entry.getKey().getAddress()));
+ protocols.remove(entry.getKey());
+ }
+ }
+ }
+
@Override
public void run(Map<Object, Object> services) {
// TODO Auto-generated method stub
ls = (LogService) services.get(LogService.class.getName());
protocols = new HashMap<XBeeAddress, XBeeProtocol>();
+ expectedProtocols = new HashSet<Class>();
t = new Thread(this, "XBee Monitor");
t.start();
_context.registerService(XBeeController.class.getName(), this, null);
@@ -12,6 +12,9 @@
protected Map<String, Object> last = null;
protected XBeeAddress addr;
protected XBeeController con;
+
+ public BaseXBeeProtocol(){
+ }
public BaseXBeeProtocol(int[] address, XBeeController controller){
if (address.length > 2)
@@ -45,5 +48,14 @@ public String toString(Map<String, Object> data) {
public String toString(){
return toString(last);
}
+ @Override
+ public boolean parseable(XBeeResponse res) {
+ return false;
+ }
+
+ @Override
+ public void setAddr(XBeeAddress address) {
+ addr = address;
+ }
}
@@ -13,6 +13,8 @@
import com.rapplogic.xbee.util.ByteUtils;
public class MaxbotixRangefinder extends BaseXBeeProtocol {
+ public MaxbotixRangefinder(){
+ }
public MaxbotixRangefinder(int[] address, XBeeController con) {
super(address, con);
@@ -43,5 +45,18 @@ public String toString(Map<String, Object> data) {
+"): "+data.get("Range");
return ret;
}
+
+ @Override
+ public boolean parseable(XBeeResponse res){
+ if (res.getApiId() != ApiId.RX_16_RESPONSE)
+ return false;
+ RxResponse pkt = (RxResponse) res;
+ String data = ByteUtils.toString(pkt.getData());
+ data = data.replaceAll("\n", "");
+ data = data.replaceAll("\r", "");
+ if ((data.charAt(0) == 'R')&&(data.length() == 4))
+ return true;
+ return false;
+ }
}
@@ -12,6 +12,9 @@
import com.rapplogic.xbee.api.wpan.RxResponseIoSample;
public class PIRMotion extends BaseXBeeProtocol {
+ public PIRMotion(){
+ }
+
public PIRMotion(int[] address, XBeeController con) {
super(address, con);
}
@@ -31,5 +34,12 @@ public PIRMotion(int[] address, XBeeController con) {
public String toString(Map<String, Object> data) {
return "Motion detected from "+Integer.toHexString(((int[])data.get("address"))[1]);
}
+
+ @Override
+ public boolean parseable(XBeeResponse res){
+ if (res.getApiId() == ApiId.RX_16_IO_RESPONSE)
+ return true;
+ return false;
+ }
}
@@ -17,6 +17,8 @@
import com.rapplogic.xbee.util.ByteUtils;
public class SerialDevice extends BaseXBeeProtocol {
+ public SerialDevice(){
+ }
public SerialDevice(int[] address, XBeeController con) {
super(address, con);
@@ -53,5 +55,12 @@ public void write(String data){
con.getXBee().sendAsynchronous(request);
} catch (XBeeException e) {}
}
+
+ @Override
+ public boolean parseable(XBeeResponse res){
+ if (!((res.getApiId() == ApiId.RX_16_RESPONSE)||(res.getApiId() == ApiId.RX_64_RESPONSE)))
+ return false;
+ return true;
+ }
}
@@ -13,6 +13,8 @@
import com.rapplogic.xbee.util.ByteUtils;
public class SparkfunWeatherboard extends BaseXBeeProtocol {
+ public SparkfunWeatherboard(){
+ }
public SparkfunWeatherboard(int[] address, XBeeController con) {
super(address, con);
@@ -57,5 +59,31 @@ public String toString(Map<String, Object> data) {
ret += "Light: "+data.get("Light")+"\r\n";
return ret;
}
+
+ @Override
+ public boolean parseable(XBeeResponse res){
+ if (res.getApiId() != ApiId.RX_16_RESPONSE)
+ return false;
+ RxResponse pkt = (RxResponse) res;
+ String data = ByteUtils.toString(pkt.getData());
+ data = data.replaceAll("\n", "");
+ data = data.replaceAll("\r", "");
+ if (data.charAt(0) != '$')
+ return false;
+ data = data.substring(2);
+ String[] values = data.split(",");
+ if (values.length != 10){
+ return false;
+ }
+ if (!values[9].contains("*")){
+ return false;
+ }
+ int[] floats = {0,2,3,4,5,7,8};
+ for (int idx:floats){
+ if (!values[idx].contains("."))
+ return false;
+ }
+ return true;
+ }
}
@@ -9,5 +9,7 @@
public Map<String, Object> parse(XBeeResponse res);
public Map<String, Object> lastSample();
public XBeeAddress getAddr();
+ public void setAddr(XBeeAddress address);
public String toString(Map<String, Object> data);
+ public boolean parseable(XBeeResponse res);
};

0 comments on commit 9216a02

Please sign in to comment.