diff --git a/.classpath b/.classpath deleted file mode 100644 index 29da01f..0000000 --- a/.classpath +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/.gitignore b/.gitignore index 934e0e0..ab2ad75 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,78 @@ -/bin -/target + +# Created by https://www.gitignore.io/api/java,eclipse,maven + +### Java ### +*.class + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.ear + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + + +### Eclipse ### + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath + +# Eclipse Core +.project + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# JDT-specific (Eclipse Java Development Tools) +.classpath + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +*.log + + +### Maven ### +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +test-output/ diff --git a/.project b/.project deleted file mode 100644 index ede8aac..0000000 --- a/.project +++ /dev/null @@ -1,17 +0,0 @@ - - - xbee-api - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - diff --git a/build.properties b/build.properties deleted file mode 100644 index e69de29..0000000 diff --git a/build.xml b/build.xml deleted file mode 100644 index 5e89f62..0000000 --- a/build.xml +++ /dev/null @@ -1,118 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/RXTXcomm.jar b/lib/RXTXcomm.jar deleted file mode 100644 index 84e5f01..0000000 Binary files a/lib/RXTXcomm.jar and /dev/null differ diff --git a/lib/log4j.jar b/lib/log4j.jar deleted file mode 100644 index 493a3cc..0000000 Binary files a/lib/log4j.jar and /dev/null differ diff --git a/librxtxSerial.jnilib b/librxtxSerial.jnilib deleted file mode 100644 index b15dfa5..0000000 Binary files a/librxtxSerial.jnilib and /dev/null differ diff --git a/librxtxSerial.so b/librxtxSerial.so deleted file mode 100644 index e60c5e6..0000000 Binary files a/librxtxSerial.so and /dev/null differ diff --git a/pom.xml b/pom.xml index 274dba4..f868e7c 100644 --- a/pom.xml +++ b/pom.xml @@ -5,44 +5,51 @@ com.rapplogic xbeeapi jar - 0.9.1-SNAPSHOT + 0.9.2-SNAPSHOT XBee-API UTF-8 + 1.8 + 1.8 - src - - - resources - - - org.apache.maven.plugins maven-compiler-plugin + 3.5.1 - 1.5 - 1.5 + 1.8 + 1.8 - - org.rxtx - rxtx - 2.1.7 + + org.scream3r + jssc + 2.8.0 - log4j log4j - 1.2.16 + 1.2.17 + + + org.testng + testng + 6.9.10 + test + + + org.assertj + assertj-core + 3.3.0 + test \ No newline at end of file diff --git a/rxtxSerial.dll b/rxtxSerial.dll deleted file mode 100644 index c0e6b58..0000000 Binary files a/rxtxSerial.dll and /dev/null differ diff --git a/src/com/rapplogic/xbee/RxTxSerialEventListener.java b/src/com/rapplogic/xbee/RxTxSerialEventListener.java deleted file mode 100644 index c19f349..0000000 --- a/src/com/rapplogic/xbee/RxTxSerialEventListener.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.rapplogic.xbee; - -import gnu.io.SerialPortEvent; - -public interface RxTxSerialEventListener { - public void handleSerialEvent(SerialPortEvent event); -} diff --git a/src/com/rapplogic/xbee/SerialPortConnection.java b/src/com/rapplogic/xbee/SerialPortConnection.java deleted file mode 100644 index 6e73b5c..0000000 --- a/src/com/rapplogic/xbee/SerialPortConnection.java +++ /dev/null @@ -1,174 +0,0 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee; - -import gnu.io.CommPortIdentifier; -import gnu.io.PortInUseException; -import gnu.io.SerialPort; -import gnu.io.SerialPortEvent; -import gnu.io.SerialPortEventListener; -import gnu.io.UnsupportedCommOperationException; - -import java.io.BufferedOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.Enumeration; -import java.util.TooManyListenersException; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.XBeeException; - -/** - * This class encapsulates a RXTX serial port, providing access to input/output streams, - * and notifying the subclass of new data events via the handleSerialData method. - * - * @author andrew - * - */ -public class SerialPortConnection implements XBeeConnection, SerialPortEventListener { - - private final static Logger log = Logger.getLogger(SerialPortConnection.class); - - private InputStream inputStream; - private OutputStream outputStream; - - private SerialPort serialPort; - - public SerialPortConnection() { - - } - - public void openSerialPort(String port, int baudRate) throws PortInUseException, UnsupportedCommOperationException, TooManyListenersException, IOException, XBeeException { - this.openSerialPort(port, "XBee", 0, baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, SerialPort.FLOWCONTROL_NONE); - } - - public void openSerialPort(String port, String appName, int timeout, int baudRate) throws PortInUseException, UnsupportedCommOperationException, TooManyListenersException, IOException, XBeeException { - this.openSerialPort(port, appName, timeout, baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, SerialPort.FLOWCONTROL_NONE); - } - - @SuppressWarnings("unchecked") - public void openSerialPort(String port, String appName, int timeout, int baudRate, int dataBits, int stopBits, int parity, int flowControl) throws PortInUseException, UnsupportedCommOperationException, TooManyListenersException, IOException, XBeeException { - // Apparently you can't query for a specific port, but instead must iterate - Enumeration portList = CommPortIdentifier.getPortIdentifiers(); - - CommPortIdentifier portId = null; - - boolean found = false; - - while (portList.hasMoreElements()) { - - portId = portList.nextElement(); - - if (portId.getPortType() == CommPortIdentifier.PORT_SERIAL) { - - //log.debug("Found port: " + portId.getName()); - - if (portId.getName().equals(port)) { - //log.debug("Using Port: " + portId.getName()); - found = true; - break; - } - } - } - - if (!found) { - throw new XBeeException("Could not find port: " + port); - } - - serialPort = (SerialPort) portId.open(appName, timeout); - - serialPort.setSerialPortParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); - serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); - - // activate the DATA_AVAILABLE notifier - serialPort.notifyOnDataAvailable(true); - - // activate the OUTPUT_BUFFER_EMPTY notifier - //serialPort.notifyOnOutputEmpty(true); - - serialPort.addEventListener(this); - - inputStream = serialPort.getInputStream(); - outputStream = new BufferedOutputStream(serialPort.getOutputStream()); - } - - /** - * Shuts down RXTX - */ - @Override - public void close() throws IOException { - try { - serialPort.getInputStream().close(); - } catch (NullPointerException e) { - - } - - try { - serialPort.getOutputStream().close(); - } catch (NullPointerException e) { - - } - - try { - // this call blocks while thread is attempting to read from inputstream - serialPort.close(); - } catch (NullPointerException e) { - - } - } - - public OutputStream getOutputStream() { - return outputStream; - } - - public InputStream getInputStream() { - return inputStream; - } - - public void serialEvent(SerialPortEvent event) { - - switch (event.getEventType()) { - case SerialPortEvent.DATA_AVAILABLE: - - try { - if (this.getInputStream().available() > 0) { - try { - log.debug("serialEvent: " + serialPort.getInputStream().available() + " bytes available"); - - synchronized (this) { - this.notify(); - } - } catch (Exception e) { - log.error("Error in handleSerialData method", e); - } - } else { - log.warn("We were notified of new data but available() is returning 0"); - } - } catch (IOException ex) { - // it's best not to throw the exception because the RXTX thread may not be prepared to handle - log.error("RXTX error in serialEvent method", ex); - } - default: - log.debug("Ignoring serial port event type: " + event.getEventType()); - } - } -} \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/ApiId.java b/src/main/java/com/rapplogic/xbee/api/ApiId.java similarity index 100% rename from src/com/rapplogic/xbee/api/ApiId.java rename to src/main/java/com/rapplogic/xbee/api/ApiId.java diff --git a/src/com/rapplogic/xbee/api/Checksum.java b/src/main/java/com/rapplogic/xbee/api/Checksum.java similarity index 95% rename from src/com/rapplogic/xbee/api/Checksum.java rename to src/main/java/com/rapplogic/xbee/api/Checksum.java index e0fa669..8d12374 100644 --- a/src/com/rapplogic/xbee/api/Checksum.java +++ b/src/main/java/com/rapplogic/xbee/api/Checksum.java @@ -1,99 +1,99 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Computes and verifies packet checksums - *

- * @author andrew - * - */ -public class Checksum { - - private final static Logger log = Logger.getLogger(Checksum.class); - - public int checksum = 0; - - /** - * Don't add Checksum byte when computing checksum!! - * - * @param val - */ - public void addByte(int val) { - checksum+= val; - } - - /** - * Computes checksum and stores in checksum instance variable - * - * @return - */ - public void compute() { - // discard values > 1 byte - checksum = 0xff & checksum; - // perform 2s complement - checksum = 0xff - checksum; - - log.debug("computed checksum is " + ByteUtils.formatByte(checksum)); - } - - /** - * First add all relevant bytes, including checksum - * - * @return - */ - public boolean verify() { - checksum = checksum & 0xff; - log.debug("verify checksum is " + checksum); - return 0xff == checksum; - } - - public int getChecksum() { - return checksum; - } - - public static void main(String[] args) { - //83 56 78 24 00 01 02 00 03 ff 85 - Checksum ck = new Checksum(); - - ck.addByte(0x83); - ck.addByte(0x56); - ck.addByte(0x78); - ck.addByte(0x26); - ck.addByte(0x00); - ck.addByte(0x01); - ck.addByte(0x02); - ck.addByte(0x00); - ck.addByte(0x03); - ck.addByte(0xff); - // checksum - ck.addByte(0x83); - - // checksum is 0x83 - //ck.compute(); - ck.verify(); - - System.out.println("checksum is " + ByteUtils.formatByte(ck.getChecksum())); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Computes and verifies packet checksums + *

+ * @author andrew + * + */ +public class Checksum { + + private final static Logger log = Logger.getLogger(Checksum.class); + + public int checksum = 0; + + /** + * Don't add Checksum byte when computing checksum!! + * + * @param val + */ + public void addByte(int val) { + checksum+= val; + } + + /** + * Computes checksum and stores in checksum instance variable + * + * @return + */ + public void compute() { + // discard values > 1 byte + checksum = 0xff & checksum; + // perform 2s complement + checksum = 0xff - checksum; + + log.debug("computed checksum is " + ByteUtils.formatByte(checksum)); + } + + /** + * First add all relevant bytes, including checksum + * + * @return + */ + public boolean verify() { + checksum = checksum & 0xff; + log.debug("verify checksum is " + checksum); + return 0xff == checksum; + } + + public int getChecksum() { + return checksum; + } + + public static void main(String[] args) { + //83 56 78 24 00 01 02 00 03 ff 85 + Checksum ck = new Checksum(); + + ck.addByte(0x83); + ck.addByte(0x56); + ck.addByte(0x78); + ck.addByte(0x26); + ck.addByte(0x00); + ck.addByte(0x01); + ck.addByte(0x02); + ck.addByte(0x00); + ck.addByte(0x03); + ck.addByte(0xff); + // checksum + ck.addByte(0x83); + + // checksum is 0x83 + //ck.compute(); + ck.verify(); + + System.out.println("checksum is " + ByteUtils.formatByte(ck.getChecksum())); + } +} diff --git a/src/com/rapplogic/xbee/api/CollectTerminator.java b/src/main/java/com/rapplogic/xbee/api/CollectTerminator.java similarity index 100% rename from src/com/rapplogic/xbee/api/CollectTerminator.java rename to src/main/java/com/rapplogic/xbee/api/CollectTerminator.java diff --git a/src/com/rapplogic/xbee/api/HardwareVersion.java b/src/main/java/com/rapplogic/xbee/api/HardwareVersion.java similarity index 96% rename from src/com/rapplogic/xbee/api/HardwareVersion.java rename to src/main/java/com/rapplogic/xbee/api/HardwareVersion.java index feedf4d..a3b5f7c 100644 --- a/src/com/rapplogic/xbee/api/HardwareVersion.java +++ b/src/main/java/com/rapplogic/xbee/api/HardwareVersion.java @@ -1,75 +1,76 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - - -/** - * Represents a XBee Address. - *

- * @author andrew - * - */ -public class HardwareVersion { - - public enum RadioType { - SERIES1("Series 1"), - SERIES1_PRO("Series 1 Pro"), - SERIES2("Series 2"), - SERIES2_PRO("Series 2 Pro"), - SERIES2B_PRO("Series 2B Pro"), - UNKNOWN("Unknown"); - - private String name; - - RadioType(String name) { - this.name = name; - } - - public String toString() { - return name; - } - } - - public static RadioType parse(AtCommandResponse response) throws XBeeException { - - if (!response.getCommand().equals("HV")) { - throw new IllegalArgumentException("This is only applicable to the HV command"); - } - - if (!response.isOk()) { - throw new XBeeException("Attempt to query HV parameter failed"); - } - - switch (response.getValue()[0]) { - case 0x17: - return RadioType.SERIES1; - case 0x18: - return RadioType.SERIES1_PRO; - case 0x19: - return RadioType.SERIES2; - case 0x1a: - return RadioType.SERIES2_PRO; - case 0x1e: - return RadioType.SERIES2B_PRO; - } - - return RadioType.UNKNOWN; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import com.rapplogic.xbee.api.responses.AtCommandResponse; + +/** + * Represents a XBee Address. + *

+ * @author andrew + * + */ +public class HardwareVersion { + + public enum RadioType { + SERIES1("Series 1"), + SERIES1_PRO("Series 1 Pro"), + SERIES2("Series 2"), + SERIES2_PRO("Series 2 Pro"), + SERIES2B_PRO("Series 2B Pro"), + UNKNOWN("Unknown"); + + private String name; + + RadioType(String name) { + this.name = name; + } + + public String toString() { + return name; + } + } + + public static RadioType parse(AtCommandResponse response) throws XBeeException { + + if (!response.getCommand().equals("HV")) { + throw new IllegalArgumentException("This is only applicable to the HV command"); + } + + if (!response.isOk()) { + throw new XBeeException("Attempt to query HV parameter failed"); + } + + switch (response.getValue()[0]) { + case 0x17: + return RadioType.SERIES1; + case 0x18: + return RadioType.SERIES1_PRO; + case 0x19: + return RadioType.SERIES2; + case 0x1a: + return RadioType.SERIES2_PRO; + case 0x1e: + return RadioType.SERIES2B_PRO; + } + + return RadioType.UNKNOWN; + } +} diff --git a/src/com/rapplogic/xbee/api/IPacketParser.java b/src/main/java/com/rapplogic/xbee/api/IPacketParser.java similarity index 100% rename from src/com/rapplogic/xbee/api/IPacketParser.java rename to src/main/java/com/rapplogic/xbee/api/IPacketParser.java diff --git a/src/com/rapplogic/xbee/api/IXBee.java b/src/main/java/com/rapplogic/xbee/api/IXBee.java similarity index 100% rename from src/com/rapplogic/xbee/api/IXBee.java rename to src/main/java/com/rapplogic/xbee/api/IXBee.java diff --git a/src/com/rapplogic/xbee/api/InputStreamThread.java b/src/main/java/com/rapplogic/xbee/api/InputStreamThread.java similarity index 86% rename from src/com/rapplogic/xbee/api/InputStreamThread.java rename to src/main/java/com/rapplogic/xbee/api/InputStreamThread.java index 8ac92e1..0a3fce8 100644 --- a/src/com/rapplogic/xbee/api/InputStreamThread.java +++ b/src/main/java/com/rapplogic/xbee/api/InputStreamThread.java @@ -1,225 +1,224 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.io.IOException; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingQueue; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.XBeeConnection; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Reads data from the input stream and hands off to PacketParser for packet parsing. - * Notifies XBee class when a new packet is parsed - *

- * @author andrew - * - */ -public class InputStreamThread implements Runnable { - - private final static Logger log = Logger.getLogger(InputStreamThread.class); - - private Thread thread; - private ExecutorService listenerPool; - private volatile boolean done = false; - private final XBeeConnection connection; - private XBeeConfiguration conf; - - public XBeeConnection getXBeeConnection() { - return connection; - } - - private final BlockingQueue responseQueue = new LinkedBlockingQueue(); - - // TODO use weak references - private final List packetListenerList = new LinkedList(); - - public List getPacketListenerList() { - return packetListenerList; - } - - public BlockingQueue getResponseQueue() { - return responseQueue; - } - - public InputStreamThread(final XBeeConnection connection, XBeeConfiguration conf) { - this.connection = connection; - this.conf = conf; - - // Create an executor to deliver incoming packets to listeners. We'll use a single - // thread with an unbounded queue. - listenerPool = Executors.newSingleThreadExecutor(); - - thread = new Thread(this); - thread.setName("InputStreamThread"); - thread.start(); - - log.debug("starting packet parser thread"); - } - - private void addResponse(final XBeeResponse response) throws InterruptedException { - - if (conf.getResponseQueueFilter() != null) { - if (conf.getResponseQueueFilter().accept(response)) { - this.addToResponseQueue(response); - } - } else { - this.addToResponseQueue(response); - } - - listenerPool.submit(new Runnable() { - public void run() { - // must synchronize to avoid java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(Unknown Source) - // this occurs if packet listener add/remove is called while we are iterating - - synchronized (packetListenerList) { - for (PacketListener pl : packetListenerList) { - try { - if (pl != null) { - pl.processResponse(response); - } else { - log.warn("PacketListener is null, size is " + packetListenerList.size()); - } - } catch (Throwable th) { - log.warn("Exception in packet listener", th); - } - } - } - } - }); - } - - private void addToResponseQueue(final XBeeResponse response) throws InterruptedException{ - - if (conf.getMaxQueueSize() == 0) { - // warn - return; - } - // trim the queue - while (responseQueue.size() >= conf.getMaxQueueSize()) { - log.info("Response queue has reached the maximum size of " + conf.getMaxQueueSize() + " packets. Trimming a packet from head of queue to make room"); - responseQueue.poll(); - } - - responseQueue.put(response); - } - - public void run() { - - int val = -1; - - XBeeResponse response = null; - PacketParser packetStream = null; - - try { - while (!done) { - try { - if (connection.getInputStream().available() > 0) { - log.debug("About to read from input stream"); - val = connection.getInputStream().read(); - log.debug("Read " + ByteUtils.formatByte(val) + " from input stream"); - - if (val == XBeePacket.SpecialByte.START_BYTE.getValue()) { - packetStream = new PacketParser(connection.getInputStream()); - response = packetStream.parsePacket(); - - if (log.isInfoEnabled()) { - log.info("Received packet from XBee: " + response); -// log.debug("Received packet: int[] packet = {" + ByteUtils.toBase16(response.getRawPacketBytes(), ", ") + "};"); - } - - // success - this.addResponse(response); - } else { - log.warn("expected start byte but got this " + ByteUtils.toBase16(val) + ", discarding"); - } - } else { - log.debug("No data available.. waiting for new data event"); - - // we will wait here for RXTX to notify us of new data - synchronized (this.connection) { - // There's a chance that we got notified after the first in.available check - if (connection.getInputStream().available() > 0) { - continue; - } - - // wait until new data arrives - this.connection.wait(); - } - } - } catch (Exception e) { - if (e instanceof InterruptedException) throw ((InterruptedException)e); - - log.error("Error while parsing packet:", e); - - if (e instanceof IOException) { - // this is thrown by RXTX if the serial device unplugged while we are reading data; if we are waiting then it will waiting forever - log.error("Serial device IOException.. exiting"); - break; - } - } - } - } catch(InterruptedException ie) { - // We've been told to stop -- the user called the close() method - log.info("Packet parser thread was interrupted. This occurs when close() is called"); - } catch (Throwable t) { - log.error("Error in input stream thread.. exiting", t); - } finally { - try { - if (connection != null) { - connection.close(); - } - - if (listenerPool != null) { - try { - listenerPool.shutdownNow(); - } catch (Throwable t) { - log.warn("Failed to shutdown listner thread pool", t); - } - } - } catch (Throwable t) { - log.error("Error in input stream thread finally", t); - } - } - - log.info("InputStreamThread is exiting"); - } - - public void setDone(boolean done) { - this.done = done; - } - - public void interrupt() { - if (thread != null) { - try { - thread.interrupt(); - } catch (Exception e) { - log.warn("Error interrupting parser thread", e); - } - } - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.connections.XBeeConnection; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Reads data from the input stream and hands off to PacketParser for packet parsing. + * Notifies XBee class when a new packet is parsed + *

+ * @author andrew + * + */ +public class InputStreamThread implements Runnable { + + private final static Logger log = Logger.getLogger(InputStreamThread.class); + + private Thread thread; + private ExecutorService listenerPool; + private volatile boolean done = false; + private final XBeeConnection connection; + private XBeeConfiguration conf; + + public XBeeConnection getXBeeConnection() { + return connection; + } + + private final BlockingQueue responseQueue = new LinkedBlockingQueue(); + + // TODO use weak references + private final List packetListenerList = new LinkedList(); + + + public List getPacketListenerList() { + return packetListenerList; + } + + public BlockingQueue getResponseQueue() { + return responseQueue; + } + + public InputStreamThread(final XBeeConnection connection, XBeeConfiguration conf) { + this.connection = connection; + this.conf = conf; + + // Create an executor to deliver incoming packets to listeners. We'll use a single + // thread with an unbounded queue. + listenerPool = Executors.newSingleThreadExecutor(); + + thread = new Thread(this); + thread.setName("InputStreamThread"); + thread.start(); + + log.debug("starting packet parser thread"); + } + + private void addResponse(final XBeeResponse response) throws InterruptedException { + + if (conf.getResponseQueueFilter() != null) { + if (conf.getResponseQueueFilter().accept(response)) { + this.addToResponseQueue(response); + } + } else { + this.addToResponseQueue(response); + } + + listenerPool.submit(new Runnable() { + public void run() { + // must synchronize to avoid java.util.ConcurrentModificationException at java.util.AbstractList$Itr.checkForComodification(Unknown Source) + // this occurs if packet listener add/remove is called while we are iterating + + synchronized (packetListenerList) { + for (PacketListener pl : packetListenerList) { + try { + if (pl != null) { + pl.processResponse(response); + } else { + log.warn("PacketListener is null, size is " + packetListenerList.size()); + } + } catch (Throwable th) { + log.warn("Exception in packet listener", th); + } + } + } + } + }); + } + + private void addToResponseQueue(final XBeeResponse response) throws InterruptedException{ + + if (conf.getMaxQueueSize() == 0) { + // warn + return; + } + // trim the queue + while (responseQueue.size() >= conf.getMaxQueueSize()) { + log.info("Response queue has reached the maximum size of " + conf.getMaxQueueSize() + " packets. Trimming a packet from head of queue to make room"); + responseQueue.poll(); + } + + responseQueue.put(response); + } + + public void run() { + + int val = -1; + + XBeeResponse response = null; + PacketParser packetStream = null; + + try { + while (!done) { + try { + if (connection.hasData()) { + log.debug("About to read from input stream"); + + val = connection.getByte(); + log.debug("Read " + ByteUtils.formatByte(val) + " from input stream"); + + if (val == XBeePacket.SpecialByte.START_BYTE.getValue()) { + packetStream = new PacketParser(connection); + response = packetStream.parsePacket(); + + log.info("Received packet from XBee: " + response); + + // success + this.addResponse(response); + } else { + log.warn("expected start byte but got this " + ByteUtils.toBase16(val) + ", discarding"); + } + } else { + log.debug("No data available.. waiting for new data event"); + + // we will wait here for RXTX to notify us of new data + synchronized (this.connection) { + // There's a chance that we got notified after the first in.available check + if (connection.hasData()) { + continue; + } + + // wait until new data arrives + this.connection.wait(); + } + } + } catch (Exception e) { + if (e instanceof InterruptedException) throw ((InterruptedException)e); + + log.error("Error while parsing packet:", e); + + if (e instanceof IOException) { + // this is thrown by RXTX if the serial device unplugged while we are reading data; if we are waiting then it will waiting forever + log.error("Serial device IOException.. exiting"); + break; + } + } + } + } catch(InterruptedException ie) { + // We've been told to stop -- the user called the close() method + log.info("Packet parser thread was interrupted. This occurs when close() is called"); + } catch (Throwable t) { + log.error("Error in input stream thread.. exiting", t); + } finally { + try { + if (connection != null) { + connection.close(); + } + + if (listenerPool != null) { + try { + listenerPool.shutdownNow(); + } catch (Throwable t) { + log.warn("Failed to shutdown listner thread pool", t); + } + } + } catch (Throwable t) { + log.error("Error in input stream thread finally", t); + } + } + + log.info("InputStreamThread is exiting"); + } + + public void setDone(boolean done) { + this.done = done; + } + + public void interrupt() { + if (thread != null) { + try { + thread.interrupt(); + } catch (Exception e) { + log.warn("Error interrupting parser thread", e); + } + } + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/PacketListener.java b/src/main/java/com/rapplogic/xbee/api/PacketListener.java similarity index 100% rename from src/com/rapplogic/xbee/api/PacketListener.java rename to src/main/java/com/rapplogic/xbee/api/PacketListener.java diff --git a/src/com/rapplogic/xbee/api/PacketParser.java b/src/main/java/com/rapplogic/xbee/api/PacketParser.java similarity index 94% rename from src/com/rapplogic/xbee/api/PacketParser.java rename to src/main/java/com/rapplogic/xbee/api/PacketParser.java index f685b2d..818cf1e 100644 --- a/src/com/rapplogic/xbee/api/PacketParser.java +++ b/src/main/java/com/rapplogic/xbee/api/PacketParser.java @@ -1,385 +1,384 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.io.IOException; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.wpan.RxResponse16; -import com.rapplogic.xbee.api.wpan.RxResponse64; -import com.rapplogic.xbee.api.wpan.RxResponseIoSample; -import com.rapplogic.xbee.api.wpan.TxStatusResponse; -import com.rapplogic.xbee.api.zigbee.ZNetExplicitRxResponse; -import com.rapplogic.xbee.api.zigbee.ZNetNodeIdentificationResponse; -import com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse; -import com.rapplogic.xbee.api.zigbee.ZNetRxResponse; -import com.rapplogic.xbee.api.zigbee.ZNetTxStatusResponse; -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.IIntInputStream; -import com.rapplogic.xbee.util.InputStreamWrapper; -import com.rapplogic.xbee.util.IntArrayOutputStream; - -/** - * Reads a packet from the input stream, verifies checksum and creates an XBeeResponse object - *

- * Notes: - *

- * Escaped bytes increase packet length but packet stated length only indicates un-escaped bytes. - * Stated length includes all bytes after Length bytes, not including the checksum - *

- * @author Andrew Rapp - * - */ -public class PacketParser implements IIntInputStream, IPacketParser { - - private final static Logger log = Logger.getLogger(PacketParser.class); - - private IIntInputStream in; - - // size of packet after special bytes have been escaped - private XBeePacketLength length; - private Checksum checksum = new Checksum(); - - private boolean done = false; - - private int bytesRead; - private int escapeBytes; - - private XBeeResponse response; - private ApiId apiId; - private int intApiId; - - private static Map> handlerMap = new HashMap>(); - - // TODO reuse this object for all packets - - // experiment to preserve original byte array for transfer over network (Starts with length) - private IntArrayOutputStream rawBytes = new IntArrayOutputStream(); - - static { - // TODO put all response handlers in specific packet and load all. implement static handlesApi method - handlerMap.put(ApiId.AT_RESPONSE.getValue(), AtCommandResponse.class); - handlerMap.put(ApiId.MODEM_STATUS_RESPONSE.getValue(), ModemStatusResponse.class); - handlerMap.put(ApiId.REMOTE_AT_RESPONSE.getValue(), RemoteAtResponse.class); - handlerMap.put(ApiId.RX_16_IO_RESPONSE.getValue(), RxResponseIoSample.class); - handlerMap.put(ApiId.RX_64_IO_RESPONSE.getValue(), RxResponseIoSample.class); - handlerMap.put(ApiId.RX_16_RESPONSE.getValue(), RxResponse16.class); - handlerMap.put(ApiId.RX_64_RESPONSE.getValue(), RxResponse64.class); - handlerMap.put(ApiId.TX_STATUS_RESPONSE.getValue(), TxStatusResponse.class); - handlerMap.put(ApiId.ZNET_EXPLICIT_RX_RESPONSE.getValue(), ZNetExplicitRxResponse.class); - handlerMap.put(ApiId.ZNET_IO_NODE_IDENTIFIER_RESPONSE.getValue(), ZNetNodeIdentificationResponse.class); - handlerMap.put(ApiId.ZNET_IO_SAMPLE_RESPONSE.getValue(), ZNetRxIoSampleResponse.class); - handlerMap.put(ApiId.ZNET_RX_RESPONSE.getValue(), ZNetRxResponse.class); - handlerMap.put(ApiId.ZNET_TX_STATUS_RESPONSE.getValue(), ZNetTxStatusResponse.class); - } - - static void registerResponseHandler(int apiId, Class clazz) { - if (handlerMap.get(apiId) == null) { - log.info("Registering response handler " + clazz.getCanonicalName() + " for apiId: " + apiId); - } else { - log.warn("Overriding existing implementation: " + handlerMap.get(apiId).getCanonicalName() + ", with " + clazz.getCanonicalName() + " for apiId: " + apiId); - } - - handlerMap.put(apiId, clazz); - } - - static void unRegisterResponseHandler(int apiId) { - if (handlerMap.get(apiId) != null) { - log.info("Unregistering response handler " + handlerMap.get(apiId).getCanonicalName() + " for apiId: " + apiId); - handlerMap.remove(apiId); - } else { - throw new IllegalArgumentException("No response handler for: " + apiId); - } - } - - public PacketParser(InputStream in) { - this.in = new InputStreamWrapper(in); - } - - // for parsing a packet from a byte array - public PacketParser(IIntInputStream in) { - this.in = in; - } - - /** - * This method is guaranteed (unless I screwed up) to return an instance of XBeeResponse and should never throw an exception - * If an exception occurs, it will be packaged and returned as an ErrorResponse. - * - * @return - */ - public XBeeResponse parsePacket() { - - Exception exception = null; - - try { - // BTW, length doesn't account for escaped bytes - int msbLength = this.read("Length MSB"); - int lsbLength = this.read("Length LSB"); - - // length of api structure, starting here (not including start byte or length bytes, or checksum) - this.length = new XBeePacketLength(msbLength, lsbLength); - - log.debug("packet length is " + String.format("[0x%03X]", length.getLength())); - - // total packet length = stated length + 1 start byte + 1 checksum byte + 2 length bytes - - intApiId = this.read("API ID"); - - this.apiId = ApiId.get(intApiId); - - if (apiId == null) { - this.apiId = ApiId.UNKNOWN; - } - - log.info("Handling ApiId: " + apiId); - - // TODO parse I/O data page 12. 82 API Identifier Byte for 64 bit address A/D data (83 is for 16bit A/D data) - - for (Integer handlerApiId : handlerMap.keySet()) { - if (intApiId == handlerApiId) { - log.debug("Found response handler for apiId [" + ByteUtils.toBase16(intApiId) + "]: " + handlerMap.get(handlerApiId).getCanonicalName()); - response = (XBeeResponse) handlerMap.get(handlerApiId).newInstance(); - response.parse(this); - break; - } - } - - if (response == null) { - log.info("Did not find a response handler for ApiId [" + ByteUtils.toBase16(intApiId) + "]. Returning GenericResponse"); - response = new GenericResponse(); - response.parse(this); - } - - response.setChecksum(this.read("Checksum")); - - if (!this.isDone()) { - throw new XBeeParseException("There are remaining bytes according to stated packet length but we have read all the bytes we thought were required for this packet (if that makes sense)"); - } - - response.finish(); - } catch (Exception e) { - // added bytes read for troubleshooting - log.error("Failed due to exception. Returning ErrorResponse. bytes read: " + ByteUtils.toBase16(rawBytes.getIntArray()), e); - exception = e; - - response = new ErrorResponse(); - - ((ErrorResponse)response).setErrorMsg(exception.getMessage()); - // but this isn't - ((ErrorResponse)response).setException(e); - } - - if (response != null) { - response.setLength(length); - response.setApiId(apiId); - // preserve original byte array for transfer over networks - response.setRawPacketBytes(rawBytes.getIntArray()); - } - - return response; - } - - /** - * Same as read() but logs the context of the byte being read. useful for debugging - */ - public int read(String context) throws IOException { - int b = this.read(); - log.debug("Read " + context + " byte, val is " + ByteUtils.formatByte(b)); - return b; - } - - /** - * This method should only be called by read() - * - * @throws IOException - */ - private int readFromStream() throws IOException { - int b = in.read(); - // save raw bytes to transfer via network - rawBytes.write(b); - - return b; - } - - /** - * This method reads bytes from the underlying input stream and performs the following tasks: - * 1. Keeps track of how many bytes we've read - * 2. Un-escapes bytes if necessary and verifies the checksum. - */ - public int read() throws IOException { - - if (done) { - throw new XBeeParseException("Packet has read all of its bytes"); - } - - int b = this.readFromStream(); - - - if (b == -1) { - throw new XBeeParseException("Read -1 from input stream while reading packet!"); - } - - if (XBeePacket.isSpecialByte(b)) { - log.debug("Read special byte that needs to be unescaped"); - - if (b == XBeePacket.SpecialByte.ESCAPE.getValue()) { - log.debug("found escape byte"); - // read next byte - b = this.readFromStream(); - - log.debug("next byte is " + ByteUtils.formatByte(b)); - b = 0x20 ^ b; - log.debug("unescaped (xor) byte is " + ByteUtils.formatByte(b)); - - escapeBytes++; - } else { - // TODO some responses such as AT Response for node discover do not escape the bytes?? shouldn't occur if AP mode is 2? - // while reading remote at response Found unescaped special byte base10=19,base16=0x13,base2=00010011 at position 5 - log.warn("Found unescaped special byte " + ByteUtils.formatByte(b) + " at position " + bytesRead); - } - } - - bytesRead++; - - // do this only after reading length bytes - if (bytesRead > 2) { - - // when verifying checksum you must add the checksum that we are verifying - // checksum should only include unescaped bytes!!!! - // when computing checksum, do not include start byte, length, or checksum; when verifying, include checksum - checksum.addByte(b); - - log.debug("Read byte " + ByteUtils.formatByte(b) + " at position " + bytesRead + ", packet length is " + this.length.get16BitValue() + ", #escapeBytes is " + escapeBytes + ", remaining bytes is " + this.getRemainingBytes()); - - // escape bytes are not included in the stated packet length - if (this.getFrameDataBytesRead() >= (length.get16BitValue() + 1)) { - // this is checksum and final byte of packet - done = true; - - log.debug("Checksum byte is " + b); - - if (!checksum.verify()) { - throw new XBeeParseException("Checksum is incorrect. Expected 0xff, but got " + checksum.getChecksum()); - } - } - } - - return b; - } - - /** - * Reads all remaining bytes except for checksum - * @return - * @throws IOException - */ - public int[] readRemainingBytes() throws IOException { - - // minus one since we don't read the checksum - int[] value = new int[this.getRemainingBytes() - 1]; - - log.debug("There are " + value.length + " remaining bytes"); - - for (int i = 0; i < value.length; i++) { - value[i] = this.read("Remaining bytes " + i); - } - - return value; - } - - public XBeeAddress64 parseAddress64() throws IOException { - XBeeAddress64 addr = new XBeeAddress64(); - - for (int i = 0; i < 8; i++) { - addr.getAddress()[i] = this.read("64-bit Address byte " + i); - } - - return addr; - } - - public XBeeAddress16 parseAddress16() throws IOException { - XBeeAddress16 addr16 = new XBeeAddress16(); - - addr16.setMsb(this.read("Address 16 MSB")); - addr16.setLsb(this.read("Address 16 LSB")); - - return addr16; - } - - /** - * Returns number of bytes remaining, relative to the stated packet length (not including checksum). - * @return - */ - public int getFrameDataBytesRead() { - // subtract out the 2 length bytes - return this.getBytesRead() - 2; - } - - /** - * Number of bytes remaining to be read, including the checksum - * @return - */ - public int getRemainingBytes() { - // add one for checksum byte (not included) in packet length - return this.length.get16BitValue() - this.getFrameDataBytesRead() + 1; - } - - // get unescaped packet length - // get escaped packet length - - /** - * Does not include any escape bytes - * @return - */ - public int getBytesRead() { - return bytesRead; - } - - public void setBytesRead(int bytesRead) { - this.bytesRead = bytesRead; - } - - public boolean isDone() { - return done; - } - - public void setDone(boolean done) { - this.done = done; - } - - public int getChecksum() { - return checksum.getChecksum(); - } - - public XBeePacketLength getLength() { - return length; - } - - public ApiId getApiId() { - return apiId; - } - - public int getIntApiId() { - return this.intApiId; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.api.responses.ErrorResponse; +import com.rapplogic.xbee.api.responses.GenericResponse; +import com.rapplogic.xbee.api.responses.ModemStatusResponse; +import com.rapplogic.xbee.api.responses.RemoteAtResponse; +import com.rapplogic.xbee.api.wpan.RxResponse16; +import com.rapplogic.xbee.api.wpan.RxResponse64; +import com.rapplogic.xbee.api.wpan.RxResponseIoSample; +import com.rapplogic.xbee.api.wpan.TxStatusResponse; +import com.rapplogic.xbee.api.zigbee.ZNetExplicitRxResponse; +import com.rapplogic.xbee.api.zigbee.ZNetNodeIdentificationResponse; +import com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse; +import com.rapplogic.xbee.api.zigbee.ZNetRxResponse; +import com.rapplogic.xbee.api.zigbee.ZNetTxStatusResponse; +import com.rapplogic.xbee.connections.XBeeConnection; +import com.rapplogic.xbee.util.ByteUtils; +import com.rapplogic.xbee.util.IIntInputStream; +import com.rapplogic.xbee.util.IntArrayOutputStream; + +/** + * Reads a packet from the input stream, verifies checksum and creates an XBeeResponse object + *

+ * Notes: + *

+ * Escaped bytes increase packet length but packet stated length only indicates un-escaped bytes. + * Stated length includes all bytes after Length bytes, not including the checksum + *

+ * @author Andrew Rapp + * + */ +public class PacketParser implements IIntInputStream, IPacketParser { + + private final static Logger log = Logger.getLogger(PacketParser.class); + + // size of packet after special bytes have been escaped + private XBeePacketLength length; + private Checksum checksum = new Checksum(); + + private boolean done = false; + + private int bytesRead; + private int escapeBytes; + + private XBeeResponse response; + private ApiId apiId; + private int intApiId; + + private final XBeeConnection connection; + + private static Map> handlerMap = new HashMap>(); + + // TODO reuse this object for all packets + + // experiment to preserve original byte array for transfer over network (Starts with length) + private IntArrayOutputStream rawBytes = new IntArrayOutputStream(); + + static { + // TODO put all response handlers in specific packet and load all. implement static handlesApi method + handlerMap.put(ApiId.AT_RESPONSE.getValue(), AtCommandResponse.class); + handlerMap.put(ApiId.MODEM_STATUS_RESPONSE.getValue(), ModemStatusResponse.class); + handlerMap.put(ApiId.REMOTE_AT_RESPONSE.getValue(), RemoteAtResponse.class); + handlerMap.put(ApiId.RX_16_IO_RESPONSE.getValue(), RxResponseIoSample.class); + handlerMap.put(ApiId.RX_64_IO_RESPONSE.getValue(), RxResponseIoSample.class); + handlerMap.put(ApiId.RX_16_RESPONSE.getValue(), RxResponse16.class); + handlerMap.put(ApiId.RX_64_RESPONSE.getValue(), RxResponse64.class); + handlerMap.put(ApiId.TX_STATUS_RESPONSE.getValue(), TxStatusResponse.class); + handlerMap.put(ApiId.ZNET_EXPLICIT_RX_RESPONSE.getValue(), ZNetExplicitRxResponse.class); + handlerMap.put(ApiId.ZNET_IO_NODE_IDENTIFIER_RESPONSE.getValue(), ZNetNodeIdentificationResponse.class); + handlerMap.put(ApiId.ZNET_IO_SAMPLE_RESPONSE.getValue(), ZNetRxIoSampleResponse.class); + handlerMap.put(ApiId.ZNET_RX_RESPONSE.getValue(), ZNetRxResponse.class); + handlerMap.put(ApiId.ZNET_TX_STATUS_RESPONSE.getValue(), ZNetTxStatusResponse.class); + } + + static void registerResponseHandler(int apiId, Class clazz) { + if (handlerMap.get(apiId) == null) { + log.info("Registering response handler " + clazz.getCanonicalName() + " for apiId: " + apiId); + } else { + log.warn("Overriding existing implementation: " + handlerMap.get(apiId).getCanonicalName() + ", with " + clazz.getCanonicalName() + " for apiId: " + apiId); + } + + handlerMap.put(apiId, clazz); + } + + static void unRegisterResponseHandler(int apiId) { + if (handlerMap.get(apiId) != null) { + log.info("Unregistering response handler " + handlerMap.get(apiId).getCanonicalName() + " for apiId: " + apiId); + handlerMap.remove(apiId); + } else { + throw new IllegalArgumentException("No response handler for: " + apiId); + } + } + + public PacketParser(XBeeConnection connection) { + this.connection = connection; + } + + /** + * This method is guaranteed (unless I screwed up) to return an instance of XBeeResponse and should never throw an exception + * If an exception occurs, it will be packaged and returned as an ErrorResponse. + * + * @return + */ + public XBeeResponse parsePacket() { + + Exception exception = null; + + try { + // BTW, length doesn't account for escaped bytes + int msbLength = this.read("Length MSB"); + int lsbLength = this.read("Length LSB"); + + // length of api structure, starting here (not including start byte or length bytes, or checksum) + this.length = new XBeePacketLength(msbLength, lsbLength); + + log.debug("packet length is " + String.format("[0x%03X]", length.getLength())); + + // total packet length = stated length + 1 start byte + 1 checksum byte + 2 length bytes + + intApiId = this.read("API ID"); + + this.apiId = ApiId.get(intApiId); + + if (apiId == null) { + this.apiId = ApiId.UNKNOWN; + } + + log.info("Handling ApiId: " + apiId); + + // TODO parse I/O data page 12. 82 API Identifier Byte for 64 bit address A/D data (83 is for 16bit A/D data) + + for (Integer handlerApiId : handlerMap.keySet()) { + if (intApiId == handlerApiId) { + log.debug("Found response handler for apiId [" + ByteUtils.toBase16(intApiId) + "]: " + handlerMap.get(handlerApiId).getCanonicalName()); + response = (XBeeResponse) handlerMap.get(handlerApiId).newInstance(); + response.parse(this); + break; + } + } + + if (response == null) { + log.info("Did not find a response handler for ApiId [" + ByteUtils.toBase16(intApiId) + "]. Returning GenericResponse"); + response = new GenericResponse(); + response.parse(this); + } + + response.setChecksum(this.read("Checksum")); + + if (!this.isDone()) { + throw new XBeeParseException("There are remaining bytes according to stated packet length but we have read all the bytes we thought were required for this packet (if that makes sense)"); + } + + response.finish(); + } catch (Exception e) { + // added bytes read for troubleshooting + log.error("Failed due to exception. Returning ErrorResponse. bytes read: " + ByteUtils.toBase16(rawBytes.getIntArray()), e); + exception = e; + + response = new ErrorResponse(); + + ((ErrorResponse)response).setErrorMsg(exception.getMessage()); + // but this isn't + ((ErrorResponse)response).setException(e); + } + + if (response != null) { + response.setLength(length); + response.setApiId(apiId); + // preserve original byte array for transfer over networks + response.setRawPacketBytes(rawBytes.getIntArray()); + } + + return response; + } + + /** + * Same as read() but logs the context of the byte being read. useful for debugging + */ + public int read(String context) throws IOException { + int b = this.read(); + log.debug("Read " + context + " byte, val is " + ByteUtils.formatByte(b)); + return b; + } + + /** + * This method should only be called by read() + * + * @throws IOException + */ + private int readFromStream() throws IOException { + int b = connection.getByte(); + // save raw bytes to transfer via network + rawBytes.write(b); + + return b; + } + + /** + * This method reads bytes from the underlying input stream and performs the following tasks: + * 1. Keeps track of how many bytes we've read + * 2. Un-escapes bytes if necessary and verifies the checksum. + */ + public int read() throws IOException { + + if (done) { + throw new XBeeParseException("Packet has read all of its bytes"); + } + + int b = this.readFromStream(); + + + if (b == -1) { + throw new XBeeParseException("Read -1 from input stream while reading packet!"); + } + + if (XBeePacket.isSpecialByte(b)) { + log.debug("Read special byte that needs to be unescaped"); + + if (b == XBeePacket.SpecialByte.ESCAPE.getValue()) { + log.debug("found escape byte"); + // read next byte + b = this.readFromStream(); + + log.debug("next byte is " + ByteUtils.formatByte(b)); + b = 0x20 ^ b; + log.debug("unescaped (xor) byte is " + ByteUtils.formatByte(b)); + + escapeBytes++; + } else { + // TODO some responses such as AT Response for node discover do not escape the bytes?? shouldn't occur if AP mode is 2? + // while reading remote at response Found unescaped special byte base10=19,base16=0x13,base2=00010011 at position 5 + log.warn("Found unescaped special byte " + ByteUtils.formatByte(b) + " at position " + bytesRead); + } + } + + bytesRead++; + + // do this only after reading length bytes + if (bytesRead > 2) { + + // when verifying checksum you must add the checksum that we are verifying + // checksum should only include unescaped bytes!!!! + // when computing checksum, do not include start byte, length, or checksum; when verifying, include checksum + checksum.addByte(b); + + log.debug("Read byte " + ByteUtils.formatByte(b) + " at position " + bytesRead + ", packet length is " + this.length.get16BitValue() + ", #escapeBytes is " + escapeBytes + ", remaining bytes is " + this.getRemainingBytes()); + + // escape bytes are not included in the stated packet length + if (this.getFrameDataBytesRead() >= (length.get16BitValue() + 1)) { + // this is checksum and final byte of packet + done = true; + + log.debug("Checksum byte is " + b); + + if (!checksum.verify()) { + throw new XBeeParseException("Checksum is incorrect. Expected 0xff, but got " + checksum.getChecksum()); + } + } + } + + return b; + } + + /** + * Reads all remaining bytes except for checksum + * @return + * @throws IOException + */ + public int[] readRemainingBytes() throws IOException { + + // minus one since we don't read the checksum + int[] value = new int[this.getRemainingBytes() - 1]; + + log.debug("There are " + value.length + " remaining bytes"); + + for (int i = 0; i < value.length; i++) { + value[i] = this.read("Remaining bytes " + i); + } + + return value; + } + + public XBeeAddress64 parseAddress64() throws IOException { + XBeeAddress64 addr = new XBeeAddress64(); + + for (int i = 0; i < 8; i++) { + addr.getAddress()[i] = this.read("64-bit Address byte " + i); + } + + return addr; + } + + public XBeeAddress16 parseAddress16() throws IOException { + XBeeAddress16 addr16 = new XBeeAddress16(); + + addr16.setMsb(this.read("Address 16 MSB")); + addr16.setLsb(this.read("Address 16 LSB")); + + return addr16; + } + + /** + * Returns number of bytes remaining, relative to the stated packet length (not including checksum). + * @return + */ + public int getFrameDataBytesRead() { + // subtract out the 2 length bytes + return this.getBytesRead() - 2; + } + + /** + * Number of bytes remaining to be read, including the checksum + * @return + */ + public int getRemainingBytes() { + // add one for checksum byte (not included) in packet length + return this.length.get16BitValue() - this.getFrameDataBytesRead() + 1; + } + + // get unescaped packet length + // get escaped packet length + + /** + * Does not include any escape bytes + * @return + */ + public int getBytesRead() { + return bytesRead; + } + + public void setBytesRead(int bytesRead) { + this.bytesRead = bytesRead; + } + + public boolean isDone() { + return done; + } + + public void setDone(boolean done) { + this.done = done; + } + + public int getChecksum() { + return checksum.getChecksum(); + } + + public XBeePacketLength getLength() { + return length; + } + + public ApiId getApiId() { + return apiId; + } + + public int getIntApiId() { + return this.intApiId; + } +} diff --git a/src/com/rapplogic/xbee/api/ResponseFilter.java b/src/main/java/com/rapplogic/xbee/api/ResponseFilter.java similarity index 100% rename from src/com/rapplogic/xbee/api/ResponseFilter.java rename to src/main/java/com/rapplogic/xbee/api/ResponseFilter.java diff --git a/src/com/rapplogic/xbee/api/XBee.java b/src/main/java/com/rapplogic/xbee/api/XBee.java similarity index 91% rename from src/com/rapplogic/xbee/api/XBee.java rename to src/main/java/com/rapplogic/xbee/api/XBee.java index ca1bc03..42b7b22 100644 --- a/src/com/rapplogic/xbee/api/XBee.java +++ b/src/main/java/com/rapplogic/xbee/api/XBee.java @@ -1,627 +1,629 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.TimeUnit; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.SerialPortConnection; -import com.rapplogic.xbee.XBeeConnection; -import com.rapplogic.xbee.api.HardwareVersion.RadioType; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * This is an API for communicating with Digi XBee 802.15.4 and ZigBee radios - * via the serial port - *

- * @author Andrew Rapp - * - */ -public class XBee implements IXBee { - - private final static Logger log = Logger.getLogger(XBee.class); - - // object to synchronize on to protect access to sendPacket - private Object sendPacketBlock = new Object(); - private XBeeConnection xbeeConnection; - private InputStreamThread parser; - private XBeeConfiguration conf; - private RadioType type; - - public XBee() { - this(new XBeeConfiguration().withMaxQueueSize(100).withStartupChecks(true)); - } - - public XBee(XBeeConfiguration conf) { - this.conf = conf; - - if (this.conf.isShutdownHook()) { - Runtime.getRuntime().addShutdownHook(new Thread() { - public void run() { - if (isConnected()) { - log.info("ShutdownHook is closing connection"); - close(); - } - } - }); - } - } - - private void doStartupChecks() throws XBeeException { - // Perform startup checks - try { - AtCommandResponse ap = this.sendAtCommand(new AtCommand("AP")); - - if (!ap.isOk()) { - throw new XBeeException("Attempt to query AP parameter failed"); - } - - if (ap.getValue()[0] != 2) { - log.warn("XBee radio is in API mode without escape characters (AP=1). The radio must be configured in API mode with escape bytes (AP=2) for use with this library."); - - log.info("Attempting to set AP to 2"); - ap = this.sendAtCommand(new AtCommand("AP", 2)); - - if (ap.isOk()) { - log.info("Successfully set AP mode to 2. This setting will not persist a power cycle without the WR (write) command"); - } else { - throw new XBeeException("Attempt to set AP=2 failed"); - } - } else { - log.info("Radio is in correct AP mode (AP=2)"); - } - - ap = this.sendAtCommand(new AtCommand("HV")); - - RadioType radioType = HardwareVersion.parse(ap); - - log.info("XBee radio is " + radioType); - - if (radioType == RadioType.UNKNOWN) { - log.warn("Unknown radio type (HV): " + ap.getValue()[0]); - } - - AtCommandResponse vr = this.sendAtCommand(new AtCommand("VR")); - - if (vr.isOk()) { - log.info("Firmware version is " + ByteUtils.toBase16(vr.getValue())); - } - - this.clearResponseQueue(); - } catch (XBeeTimeoutException ex) { - throw new XBeeException("AT command timed-out while attempt to set/read in API mode. Check that the XBee radio is in API mode (AP=2); it will not function propertly in AP=1"); - } - } - - /** - * If XBeeConnection.startUpChecks is set to true (default), this method will check if the AP parameter - * is set correctly and attempt to update if AP=1. If AP=0 (Transparent mode), an - * exception will be thrown. - */ - public void open(String port, int baudRate) throws XBeeException { - try { - if (this.isConnected()) { - throw new IllegalStateException("Cannot open new connection -- existing connection is still open. Please close first"); - } - - this.type = null; - - SerialPortConnection serial = new SerialPortConnection(); - serial.openSerialPort(port, baudRate); - - this.initConnection(serial); - } catch (XBeeException e) { - throw e; - } catch (Exception e) { - throw new XBeeException(e); - } - } - - public static void registerResponseHandler(int apiId, Class clazz) { - PacketParser.registerResponseHandler(apiId, clazz); - } - - public static void unRegisterResponseHandler(int apiId) { - PacketParser.unRegisterResponseHandler(apiId); - } - - /** - * Allows a protocol specific implementation of XBeeConnection to be used instead of the default RXTX connection. - * The connection must already be established as the interface has no means to do so. - */ - public void initProviderConnection(XBeeConnection connection) throws XBeeException { - if (this.isConnected()) { - throw new IllegalStateException("Cannot open new connection -- existing connection is still open. Please close first"); - } - - initConnection(connection); - } - - private void initConnection(XBeeConnection conn) throws XBeeException { - try { - this.xbeeConnection = conn; - - parser = new InputStreamThread(this.xbeeConnection, conf); - - // startup heuristics - if (conf.isStartupChecks()) { - this.doStartupChecks(); - } - } catch (XBeeException e) { - throw e; - } catch (Exception e) { - throw new XBeeException(e); - } - } - - public void addPacketListener(PacketListener packetListener) { - if (parser == null) { - throw new IllegalStateException("No connection"); - } - - synchronized (parser.getPacketListenerList()) { - this.parser.getPacketListenerList().add(packetListener); - } - } - - public void removePacketListener(PacketListener packetListener) { - if (parser == null) { - throw new IllegalStateException("No connection"); - } - - synchronized (parser.getPacketListenerList()) { - this.parser.getPacketListenerList().remove(packetListener); - } - } - - public void sendRequest(XBeeRequest request) throws IOException { - if (this.type != null) { - // TODO use interface to mark series type - if (type == RadioType.SERIES1 && request.getClass().getPackage().getName().indexOf("api.zigbee") > -1) { - throw new IllegalArgumentException("You are connected to a Series 1 radio but attempting to send Series 2 requests"); - } else if (type == RadioType.SERIES2 && request.getClass().getPackage().getName().indexOf("api.wpan") > -1) { - throw new IllegalArgumentException("You are connected to a Series 2 radio but attempting to send Series 1 requests"); - } - } - - log.info("Sending request to XBee: " + request); - this.sendPacket(request.getXBeePacket()); - } - - /** - * It's possible for packets to get interspersed if multiple threads send simultaneously. - * This method is not thread-safe because doing so would introduce a synchronized performance penalty - * for the vast majority of users that will not never need thread safety. - * That said, it is responsibility of the user to provide synchronization if multiple threads are sending. - * - * Not thread safe. - * - * @param packet - * @throws IOException - */ - public void sendPacket(XBeePacket packet) throws IOException { - this.sendPacket(packet.getByteArray()); - } - - /** - * This exists solely for the XMPP project. Use sendRequest instead - * - * Not Thread Safe - * - * @param packet - * @throws RuntimeException when serial device is disconnected - */ - public void sendPacket(int[] packet) throws IOException { - // TODO should we synchronize on read lock so we are sending/recv. simultaneously? - // TODO call request listener with byte array - - if (!this.isConnected()) { - throw new XBeeNotConnectedException(); - } - - if (log.isInfoEnabled()) { - log.info("Sending packet to XBee " + ByteUtils.toBase16(packet)); - } - - for (int packetByte : packet) { - // if connection lost - //Caused by: com.rapplogic.xbee.api.XBeeException - //Caused by: java.io.IOException: Input/output error in writeArray - xbeeConnection.getOutputStream().write(packetByte); - } - - xbeeConnection.getOutputStream().flush(); - } - - /** - * Sends an XBeeRequest though the XBee interface in an asynchronous manner, such that - * it will return immediately, without waiting for a response. - * Refer to the getResponse method for obtaining a response - * - * Not thread safe - * - * @param request - * @throws XBeeException - */ - public void sendAsynchronous(XBeeRequest request) throws XBeeException { - - try { - this.sendRequest(request); - } catch (Exception e) { - throw new XBeeException(e); - } - } - - /** - * Uses sendSynchronous to send an AtCommand and collect the response - *

- * Timeout value is fixed at 5 seconds - * - * @deprecated Use this.sendSynchronous(command, timeout); - * @param command - * @return - * @throws XBeeException - */ - public AtCommandResponse sendAtCommand(AtCommand command) throws XBeeException { - return (AtCommandResponse) this.sendSynchronous(command, 5000); - } - - /** - * Synchronous method for sending an XBeeRequest and obtaining the - * corresponding response (response that has same frame id). - *

- * This method returns the first response object with a matching frame id, within the timeout - * period, so it is important to use a unique frame id (relative to previous subsequent requests). - *

- * This method must only be called with requests that receive a response of - * type XBeeFrameIdResponse. All other request types will timeout. - *

- * Keep in mind responses received here will also be available through the getResponse method - * and the packet listener. If you would prefer to not have these responses added to the response queue, - * you can add a ResponseQueueFilter via XBeeConfiguration to ignore packets that are sent in response to - * a request. Another alternative is to call clearResponseQueue prior to calling this method. - *

- * It is recommended to use a timeout of at least 5 seconds, since some responses can take a few seconds or more - * (e.g. if remote radio is not powered on). - *

- * This method is thread-safe - * - * @param xbeeRequest - * - * @return - * @throws XBeeException - * @throws XBeeTimeoutException thrown if no matching response is identified - */ - public XBeeResponse sendSynchronous(final XBeeRequest xbeeRequest, int timeout) throws XBeeTimeoutException, XBeeException { - if (xbeeRequest.getFrameId() == XBeeRequest.NO_RESPONSE_FRAME_ID) { - throw new XBeeException("Frame Id cannot be 0 for a synchronous call -- it will always timeout as there is no response!"); - } - - PacketListener pl = null; - - try { - final List container = new LinkedList(); - - // this makes it thread safe -- prevents multiple threads from writing to output stream simultaneously - synchronized (sendPacketBlock) { - this.sendRequest(xbeeRequest); - } - - pl = new PacketListener() { - // TODO handle error response as well - public void processResponse(XBeeResponse response) { - if (response instanceof XBeeFrameIdResponse && ((XBeeFrameIdResponse)response).getFrameId() == xbeeRequest.getFrameId()) { - // frame id matches -- yay we found it - container.add(response); - - synchronized(container) { - container.notify(); - } - } - } - }; - - this.addPacketListener(pl); - - synchronized (container) { - try { - container.wait(timeout); - } catch (InterruptedException e) { } - } - - if (container.size() == 0) { - // we didn't find a matching packet - throw new XBeeTimeoutException(); - } - - return (XBeeResponse) container.get(0); - } catch (IOException io) { - throw new XBeeException(io); - } finally { - if (pl != null) { - this.removePacketListener(pl); - } - } - } - - /** - * Uses sendSynchronous timeout defined in XBeeConfiguration (default is 5000ms) - */ - public XBeeResponse sendSynchronous(final XBeeRequest request) throws XBeeTimeoutException, XBeeException { - return this.sendSynchronous(request, conf.getSendSynchronousTimeout()); - } - - - /** - * Same as getResponse(int) but does not timeout. - * It's highly recommend that you always use a timeout because - * if the serial connection dies under certain conditions, you will end up waiting forever! - *

- * Consider using the PacketListener for asynchronous (non-blocking) behavior - * - * @return - * @throws XBeeException - */ - public XBeeResponse getResponse() throws XBeeException { - return getResponseTimeout(null); - } - - /** - * This method returns an XBeeResponse from the queue, if available, or - * waits up to "timeout" milliseconds for a response. - *

- * There are three possible outcomes: - *

- * 1. A packet is returned within "timeout" milliseconds
- * 2. An XBeeTimeoutException is thrown (i.e. queue was empty for duration of timeout)
- * 3. Null is returned if timeout is 0 and queue is empty.
- *

- * @param timeout milliseconds to wait for a response. A value of zero disables the timeout - * @return - * @throws XBeeException - * @throws XBeeTimeoutException if timeout occurs before a response is received - */ - public XBeeResponse getResponse(int timeout) throws XBeeException, XBeeTimeoutException { - return this.getResponseTimeout(timeout); - } - - private XBeeResponse getResponseTimeout(Integer timeout) throws XBeeException, XBeeTimeoutException { - - // seeing this with xmpp - if (!this.isConnected()) { - throw new XBeeNotConnectedException(); - } - - XBeeResponse response; - try { - if (timeout != null) { - response = parser.getResponseQueue().poll(timeout, TimeUnit.MILLISECONDS); - } else { - response = parser.getResponseQueue().take(); - } - } catch (InterruptedException e) { - throw new XBeeException("Error while attempting to remove packet from queue", e); - } - - if (response == null && timeout > 0) { - throw new XBeeTimeoutException(); - } - - return response; - } - -// public List collectResponses(int wait, ResponseFilter filter, CollectTerminator terminator) throws XBeeException { -// -// } - - /** - * Collects responses until the timeout is reached or the CollectTerminator returns true - * - * @param wait - * @param terminator - * @return - * @throws XBeeException - */ - public List collectResponses(int wait, CollectTerminator terminator) throws XBeeException { - - // seeing this with xmpp - if (!this.isConnected()) { - throw new XBeeNotConnectedException(); - } - - long start = System.currentTimeMillis(); - long callStart = 0; - int waitTime; - - List responseList = new ArrayList(); - XBeeResponse response = null; - - try { - while (true) { - // compute the remaining wait time - waitTime = wait - (int)(System.currentTimeMillis() - start); - - if (waitTime <= 0) { - break; - } - - log.debug("calling getResponse with waitTime: " + waitTime); - - if (log.isDebugEnabled()) { - callStart = System.currentTimeMillis(); - } - - response = this.getResponse(waitTime); - - if (log.isDebugEnabled()) { - log.debug("Got response in " + (System.currentTimeMillis() - callStart)); - } - - responseList.add(response); - - if (terminator != null && terminator.stop(response)) { - log.debug("Found terminating response.. exiting"); - break; - } - } - } catch (XBeeTimeoutException e) { - // ok, we'll just return whatever is in the list - } catch (XBeeException e) { - throw e; - } - - log.debug("Time is up.. returning list with " + responseList.size() + " packets"); - - return responseList; - } - - /** - * Collects responses for wait milliseconds and returns responses as List - * - * @param wait - * @return - * @throws XBeeException - */ - public List collectResponses(int wait) throws XBeeException { - return this.collectResponses(wait, null); - } - - /** - * Returns the number of packets available in the response queue for immediate consumption - * - * @return - */ - public int getResponseQueueSize() { - // seeing this with xmpp - if (!this.isConnected()) { - throw new XBeeNotConnectedException(); - } - - return parser.getResponseQueue().size(); - } - - /** - * Shuts down RXTX and packet parser thread - */ - public void close() { - - if (!this.isConnected()) { - throw new IllegalStateException("XBee is not connected"); - } - - // shutdown parser thread - if (parser != null) { - parser.setDone(true); - // interrupts thread, if waiting. does not interrupt thread if blocking on read - // serial port close will be closed prior to thread exit - parser.interrupt(); - } - - try { -// xbeeConnection.getOutputStream().close(); - xbeeConnection.close(); - } catch (IOException e) { - log.warn("Failed to close connection", e); - } - - - - this.type = null; - parser = null; - xbeeConnection = null; - } - - /** - * Indicates if serial port connection has been established. - * The open method may be called if this returns true - * - * @return - */ - public boolean isConnected() { - try { - if (parser.getXBeeConnection().getInputStream() != null && parser.getXBeeConnection().getOutputStream() != null) { - return true; - } - - return false; - } catch (Exception e) { - return false; - } - } - - // TODO move to its own class - private int sequentialFrameId = 0xff; - - public int getCurrentFrameId() { - // TODO move to separate class (e.g. FrameIdCounter) - return sequentialFrameId; - } - - /** - * This is useful for obtaining a frame id when composing your XBeeRequest. - * It will return frame ids in a sequential manner until the maximum is reached (0xff) - * and it flips to 1 and starts over. - * - * Not Thread-safe - * - * @return - */ - public int getNextFrameId() { - if (sequentialFrameId == 0xff) { - // flip - sequentialFrameId = 1; - } else { - sequentialFrameId++; - } - - return sequentialFrameId; - } - - /** - * Updates the frame id. Any value between 1 and ff is valid - * - * @param val - * Jan 24, 2009 - */ - public void updateFrameId(int val) { - if (val <=0 || val > 0xff) { - throw new IllegalArgumentException("invalid frame id"); - } - - this.sequentialFrameId = val; - } - - /** - * Removes all packets off of the response queue - */ - public void clearResponseQueue() { - // seeing this with xmpp - if (!this.isConnected()) { - throw new XBeeNotConnectedException(); - } - - parser.getResponseQueue().clear(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.HardwareVersion.RadioType; +import com.rapplogic.xbee.api.requests.AtCommand; +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.api.responses.XBeeFrameIdResponse; +import com.rapplogic.xbee.connections.XBeeConnection; +import com.rapplogic.xbee.connections.connectionprovider.IConnectionProvider; +import com.rapplogic.xbee.connections.connectionprovider.SerialPortConnectionProvider; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * This is an API for communicating with Digi XBee 802.15.4 and ZigBee radios + * via the serial port + *

+ * @author Andrew Rapp + * + */ +public class XBee implements IXBee { + + private final static Logger log = Logger.getLogger(XBee.class); + + // object to synchronize on to protect access to sendPacket + private Object sendPacketBlock = new Object(); + private XBeeConnection xbeeConnection; + private InputStreamThread parser; + private final XBeeConfiguration conf; + private XBeeInformation info; + private RadioType type; + private final IConnectionProvider connectionProvider; + + public XBee() { + this(new XBeeConfiguration().withMaxQueueSize(100).withStartupChecks(true).withConnectionProvider(new SerialPortConnectionProvider())); + } + + public XBee(XBeeConfiguration conf) { + this.conf = conf; + this.connectionProvider = conf.getConnectionProvider(); + + if (this.conf.isShutdownHook()) { + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + if (isConnected()) { + log.info("ShutdownHook is closing connection"); + close(); + } + } + }); + } + } + + private void doStartupChecks() throws XBeeException { + // Perform startup checks + try { + AtCommandResponse ap = this.sendAtCommand(new AtCommand("AP")); + + if (!ap.isOk()) { + throw new XBeeException("Attempt to query AP parameter failed"); + } + + if (ap.getValue()[0] != 2) { + log.warn("XBee radio is in API mode without escape characters (AP=1). The radio must be configured in API mode with escape bytes (AP=2) for use with this library."); + + log.info("Attempting to set AP to 2"); + ap = this.sendAtCommand(new AtCommand("AP", 2)); + + if (ap.isOk()) { + log.info("Successfully set AP mode to 2. This setting will not persist a power cycle without the WR (write) command"); + } else { + throw new XBeeException("Attempt to set AP=2 failed"); + } + } else { + log.info("Radio is in correct AP mode (AP=2)"); + } + + ap = this.sendAtCommand(new AtCommand("HV")); + + RadioType radioType = HardwareVersion.parse(ap); + + log.info("XBee radio is " + radioType); + + if (radioType == RadioType.UNKNOWN) { + log.warn("Unknown radio type (HV): " + ap.getValue()[0]); + } + + AtCommandResponse vr = this.sendAtCommand(new AtCommand("VR")); + + if (vr.isOk()) { + log.info("Firmware version is " + ByteUtils.toBase16(vr.getValue())); + } + + AtCommandResponse id = this.sendAtCommand(new AtCommand("ID")); + + AtCommandResponse sh = this.sendAtCommand(new AtCommand("SH")); + + AtCommandResponse sl = this.sendAtCommand(new AtCommand("SL")); + + info = new XBeeInformation(radioType, vr.getValue(), id.getValue(), sh.getValue(), sl.getValue()); + + this.clearResponseQueue(); + } catch (XBeeTimeoutException ex) { + throw new XBeeException("AT command timed-out while attempt to set/read in API mode. Check that the XBee radio is in API mode (AP=2); it will not function propertly in AP=1"); + } + } + + + /** + * If XBeeConnection.startUpChecks is set to true (default), this method will check if the AP parameter + * is set correctly and attempt to update if AP=1. If AP=0 (Transparent mode), an + * exception will be thrown. + */ + public void open(String port, int baudRate) throws XBeeException { + try { + if (this.isConnected()) { + throw new IllegalStateException("Cannot open new connection -- existing connection is still open. Please close first"); + } + + this.type = null; + + this.initConnection(connectionProvider.open(port, baudRate)); + } catch (XBeeException e) { + throw e; + } catch (Exception e) { + throw new XBeeException(e); + } + } + + public static void registerResponseHandler(int apiId, Class clazz) { + PacketParser.registerResponseHandler(apiId, clazz); + } + + public static void unRegisterResponseHandler(int apiId) { + PacketParser.unRegisterResponseHandler(apiId); + } + + /** + * Allows a protocol specific implementation of XBeeConnection to be used instead of the default RXTX connection. + * The connection must already be established as the interface has no means to do so. + */ + public void initProviderConnection(XBeeConnection connection) throws XBeeException { + if (this.isConnected()) { + throw new IllegalStateException("Cannot open new connection -- existing connection is still open. Please close first"); + } + + initConnection(connection); + } + + private void initConnection(XBeeConnection conn) throws XBeeException { + try { + this.xbeeConnection = conn; + + parser = new InputStreamThread(this.xbeeConnection, conf); + + // startup heuristics + if (conf.isStartupChecks()) { + this.doStartupChecks(); + } + } catch (XBeeException e) { + throw e; + } catch (Exception e) { + throw new XBeeException(e); + } + } + + public void addPacketListener(PacketListener packetListener) { + if (parser == null) { + throw new IllegalStateException("No connection"); + } + + synchronized (parser.getPacketListenerList()) { + this.parser.getPacketListenerList().add(packetListener); + } + } + + public void removePacketListener(PacketListener packetListener) { + if (parser == null) { + throw new IllegalStateException("No connection"); + } + + synchronized (parser.getPacketListenerList()) { + this.parser.getPacketListenerList().remove(packetListener); + } + } + + public void sendRequest(XBeeRequest request) throws IOException { + if (this.type != null) { + // TODO use interface to mark series type + if (type == RadioType.SERIES1 && request.getClass().getPackage().getName().indexOf("api.zigbee") > -1) { + throw new IllegalArgumentException("You are connected to a Series 1 radio but attempting to send Series 2 requests"); + } else if (type == RadioType.SERIES2 && request.getClass().getPackage().getName().indexOf("api.wpan") > -1) { + throw new IllegalArgumentException("You are connected to a Series 2 radio but attempting to send Series 1 requests"); + } + } + + log.info("Sending request to XBee: " + request); + this.sendPacket(request.getXBeePacket()); + } + + /** + * It's possible for packets to get interspersed if multiple threads send simultaneously. + * This method is not thread-safe because doing so would introduce a synchronized performance penalty + * for the vast majority of users that will not never need thread safety. + * That said, it is responsibility of the user to provide synchronization if multiple threads are sending. + * + * Not thread safe. + * + * @param packet + * @throws IOException + */ + public void sendPacket(XBeePacket packet) throws IOException { + this.sendPacket(packet.getByteArray()); + } + + /** + * This exists solely for the XMPP project. Use sendRequest instead + * + * Not Thread Safe + * + * @param packet + * @throws RuntimeException when serial device is disconnected + */ + public void sendPacket(int[] packet) throws IOException { + // TODO should we synchronize on read lock so we are sending/recv. simultaneously? + + if (!this.isConnected()) { + throw new XBeeNotConnectedException(); + } + + if (log.isInfoEnabled()) { + log.info("Sending packet to XBee " + ByteUtils.toBase16(packet)); + } + + xbeeConnection.writeIntArray(packet); + } + + /** + * Sends an XBeeRequest though the XBee interface in an asynchronous manner, such that + * it will return immediately, without waiting for a response. + * Refer to the getResponse method for obtaining a response + * + * Not thread safe + * + * @param request + * @throws XBeeException + */ + public void sendAsynchronous(XBeeRequest request) throws XBeeException { + + try { + this.sendRequest(request); + } catch (Exception e) { + throw new XBeeException(e); + } + } + + /** + * Uses sendSynchronous to send an AtCommand and collect the response + *

+ * Timeout value is fixed at 5 seconds + * + * @deprecated Use this.sendSynchronous(command, timeout); + * @param command + * @return + * @throws XBeeException + */ + public AtCommandResponse sendAtCommand(AtCommand command) throws XBeeException { + return (AtCommandResponse) this.sendSynchronous(command, 5000); + } + + /** + * Synchronous method for sending an XBeeRequest and obtaining the + * corresponding response (response that has same frame id). + *

+ * This method returns the first response object with a matching frame id, within the timeout + * period, so it is important to use a unique frame id (relative to previous subsequent requests). + *

+ * This method must only be called with requests that receive a response of + * type XBeeFrameIdResponse. All other request types will timeout. + *

+ * Keep in mind responses received here will also be available through the getResponse method + * and the packet listener. If you would prefer to not have these responses added to the response queue, + * you can add a ResponseQueueFilter via XBeeConfiguration to ignore packets that are sent in response to + * a request. Another alternative is to call clearResponseQueue prior to calling this method. + *

+ * It is recommended to use a timeout of at least 5 seconds, since some responses can take a few seconds or more + * (e.g. if remote radio is not powered on). + *

+ * This method is thread-safe + * + * @param xbeeRequest + * + * @return + * @throws XBeeException + * @throws XBeeTimeoutException thrown if no matching response is identified + */ + public XBeeResponse sendSynchronous(final XBeeRequest xbeeRequest, int timeout) throws XBeeTimeoutException, XBeeException { + if (xbeeRequest.getFrameId() == XBeeRequest.NO_RESPONSE_FRAME_ID) { + throw new XBeeException("Frame Id cannot be 0 for a synchronous call -- it will always timeout as there is no response!"); + } + + PacketListener pl = null; + + try { + final List container = new LinkedList(); + + // this makes it thread safe -- prevents multiple threads from writing to output stream simultaneously + synchronized (sendPacketBlock) { + this.sendRequest(xbeeRequest); + } + + pl = new PacketListener() { + // TODO handle error response as well + public void processResponse(XBeeResponse response) { + if (response instanceof XBeeFrameIdResponse && ((XBeeFrameIdResponse)response).getFrameId() == xbeeRequest.getFrameId()) { + // frame id matches -- yay we found it + container.add(response); + + synchronized(container) { + container.notify(); + } + } + } + }; + + this.addPacketListener(pl); + + synchronized (container) { + try { + container.wait(timeout); + } catch (InterruptedException e) { } + } + + if (container.size() == 0) { + // we didn't find a matching packet + throw new XBeeTimeoutException(); + } + + return (XBeeResponse) container.get(0); + } catch (IOException io) { + throw new XBeeException(io); + } finally { + if (pl != null) { + this.removePacketListener(pl); + } + } + } + + /** + * Uses sendSynchronous timeout defined in XBeeConfiguration (default is 5000ms) + */ + public XBeeResponse sendSynchronous(final XBeeRequest request) throws XBeeTimeoutException, XBeeException { + return this.sendSynchronous(request, conf.getSendSynchronousTimeout()); + } + + + /** + * Same as getResponse(int) but does not timeout. + * It's highly recommend that you always use a timeout because + * if the serial connection dies under certain conditions, you will end up waiting forever! + *

+ * Consider using the PacketListener for asynchronous (non-blocking) behavior + * + * @return + * @throws XBeeException + */ + public XBeeResponse getResponse() throws XBeeException { + return getResponseTimeout(null); + } + + /** + * This method returns an XBeeResponse from the queue, if available, or + * waits up to "timeout" milliseconds for a response. + *

+ * There are three possible outcomes: + *

+ * 1. A packet is returned within "timeout" milliseconds
+ * 2. An XBeeTimeoutException is thrown (i.e. queue was empty for duration of timeout)
+ * 3. Null is returned if timeout is 0 and queue is empty.
+ *

+ * @param timeout milliseconds to wait for a response. A value of zero disables the timeout + * @return + * @throws XBeeException + * @throws XBeeTimeoutException if timeout occurs before a response is received + */ + public XBeeResponse getResponse(int timeout) throws XBeeException, XBeeTimeoutException { + return this.getResponseTimeout(timeout); + } + + private XBeeResponse getResponseTimeout(Integer timeout) throws XBeeException, XBeeTimeoutException { + + // seeing this with xmpp + if (!this.isConnected()) { + throw new XBeeNotConnectedException(); + } + + XBeeResponse response; + try { + if (timeout != null) { + response = parser.getResponseQueue().poll(timeout, TimeUnit.MILLISECONDS); + } else { + response = parser.getResponseQueue().take(); + } + } catch (InterruptedException e) { + throw new XBeeException("Error while attempting to remove packet from queue", e); + } + + if (response == null && timeout > 0) { + throw new XBeeTimeoutException(); + } + + return response; + } + +// public List collectResponses(int wait, ResponseFilter filter, CollectTerminator terminator) throws XBeeException { +// +// } + + /** + * Collects responses until the timeout is reached or the CollectTerminator returns true + * + * @param wait + * @param terminator + * @return + * @throws XBeeException + */ + public List collectResponses(int wait, CollectTerminator terminator) throws XBeeException { + + // seeing this with xmpp + if (!this.isConnected()) { + throw new XBeeNotConnectedException(); + } + + long start = System.currentTimeMillis(); + long callStart = 0; + int waitTime; + + List responseList = new ArrayList(); + XBeeResponse response = null; + + try { + while (true) { + // compute the remaining wait time + waitTime = wait - (int)(System.currentTimeMillis() - start); + + if (waitTime <= 0) { + break; + } + + log.debug("calling getResponse with waitTime: " + waitTime); + + if (log.isDebugEnabled()) { + callStart = System.currentTimeMillis(); + } + + response = this.getResponse(waitTime); + + if (log.isDebugEnabled()) { + log.debug("Got response in " + (System.currentTimeMillis() - callStart)); + } + + responseList.add(response); + + if (terminator != null && terminator.stop(response)) { + log.debug("Found terminating response.. exiting"); + break; + } + } + } catch (XBeeTimeoutException e) { + // ok, we'll just return whatever is in the list + } catch (XBeeException e) { + throw e; + } + + log.debug("Time is up.. returning list with " + responseList.size() + " packets"); + + return responseList; + } + + /** + * Collects responses for wait milliseconds and returns responses as List + * + * @param wait + * @return + * @throws XBeeException + */ + public List collectResponses(int wait) throws XBeeException { + return this.collectResponses(wait, null); + } + + /** + * Returns the number of packets available in the response queue for immediate consumption + * + * @return + */ + public int getResponseQueueSize() { + // seeing this with xmpp + if (!this.isConnected()) { + throw new XBeeNotConnectedException(); + } + + return parser.getResponseQueue().size(); + } + + /** + * Shuts down RXTX and packet parser thread + */ + public void close() { + + if (!this.isConnected()) { + throw new IllegalStateException("XBee is not connected"); + } + + // shutdown parser thread + if (parser != null) { + parser.setDone(true); + // interrupts thread, if waiting. does not interrupt thread if blocking on read + // serial port close will be closed prior to thread exit + parser.interrupt(); + } + + try { + xbeeConnection.close(); + } catch (IOException e) { + log.warn("Failed to close connection", e); + } + + this.type = null; + parser = null; + xbeeConnection = null; + } + + /** + * Indicates if serial port connection has been established. + * The open method may be called if this returns true + * + * @return + */ + public boolean isConnected() { + try { + return xbeeConnection.isConnected(); + } catch (Exception e) { + return false; + } + } + + // TODO move to its own class + private int sequentialFrameId = 0xff; + + public int getCurrentFrameId() { + // TODO move to separate class (e.g. FrameIdCounter) + return sequentialFrameId; + } + + /** + * This is useful for obtaining a frame id when composing your XBeeRequest. + * It will return frame ids in a sequential manner until the maximum is reached (0xff) + * and it flips to 1 and starts over. + * + * Not Thread-safe + * + * @return + */ + public int getNextFrameId() { + if (sequentialFrameId == 0xff) { + // flip + sequentialFrameId = 1; + } else { + sequentialFrameId++; + } + + return sequentialFrameId; + } + + /** + * Updates the frame id. Any value between 1 and ff is valid + * + * @param val + * Jan 24, 2009 + */ + public void updateFrameId(int val) { + if (val <=0 || val > 0xff) { + throw new IllegalArgumentException("invalid frame id"); + } + + this.sequentialFrameId = val; + } + + /** + * Removes all packets off of the response queue + */ + public void clearResponseQueue() { + // seeing this with xmpp + if (!this.isConnected()) { + throw new XBeeNotConnectedException(); + } + + parser.getResponseQueue().clear(); + } + + public XBeeInformation getInformation() { + return info; + } +} diff --git a/src/com/rapplogic/xbee/api/XBeeAddress.java b/src/main/java/com/rapplogic/xbee/api/XBeeAddress.java similarity index 96% rename from src/com/rapplogic/xbee/api/XBeeAddress.java rename to src/main/java/com/rapplogic/xbee/api/XBeeAddress.java index 975c5a2..95846af 100644 --- a/src/com/rapplogic/xbee/api/XBeeAddress.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeAddress.java @@ -1,42 +1,42 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Represents a XBee Address. - *

- * @author andrew - * - */ -public abstract class XBeeAddress { - - - public XBeeAddress() { - - } - - public abstract int[] getAddress(); - - public String toString() { - return ByteUtils.toBase16(this.getAddress()); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Represents a XBee Address. + *

+ * @author andrew + * + */ +public abstract class XBeeAddress { + + + public XBeeAddress() { + + } + + public abstract int[] getAddress(); + + public String toString() { + return ByteUtils.toBase16(this.getAddress()); + } +} diff --git a/src/com/rapplogic/xbee/api/XBeeAddress16.java b/src/main/java/com/rapplogic/xbee/api/XBeeAddress16.java similarity index 96% rename from src/com/rapplogic/xbee/api/XBeeAddress16.java rename to src/main/java/com/rapplogic/xbee/api/XBeeAddress16.java index df09286..c619c9c 100644 --- a/src/com/rapplogic/xbee/api/XBeeAddress16.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeAddress16.java @@ -1,98 +1,98 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import com.rapplogic.xbee.util.DoubleByte; - -/** - * Represents a 16-bit XBee Address. - *

- * @author andrew - * - */ -public class XBeeAddress16 extends XBeeAddress { - - public static final XBeeAddress16 BROADCAST = new XBeeAddress16(0xFF, 0xFF); - public static final XBeeAddress16 ZNET_BROADCAST = new XBeeAddress16(0xFF, 0xFE); - - private DoubleByte doubleByte = new DoubleByte(); - - /** - * Provide address as msb byte and lsb byte - * - * @param msb - * @param lsb - */ - public XBeeAddress16(int msb, int lsb) { - this.doubleByte.setMsb(msb); - this.doubleByte.setLsb(lsb); - } - - public XBeeAddress16(int[] arr) { - this.doubleByte.setMsb(arr[0]); - this.doubleByte.setLsb(arr[1]); - } - - public XBeeAddress16() { - - } - - public int get16BitValue() { - return this.doubleByte.get16BitValue(); - } - - public int getMsb() { - return this.doubleByte.getMsb(); - } - - public void setMsb(int msb) { - this.doubleByte.setMsb(msb); - } - - public int getLsb() { - return this.doubleByte.getLsb(); - } - - public void setLsb(int lsb) { - this.doubleByte.setLsb(lsb); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - XBeeAddress16 that = (XBeeAddress16) o; - - if (doubleByte != null ? !doubleByte.equals(that.doubleByte) : that.doubleByte != null) return false; - - return true; - } - - @Override - public int hashCode() { - return doubleByte != null ? doubleByte.hashCode() : 0; - } - - @Override - public int[] getAddress() { - return new int[] { this.doubleByte.getMsb(), this.doubleByte.getLsb() }; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import com.rapplogic.xbee.util.DoubleByte; + +/** + * Represents a 16-bit XBee Address. + *

+ * @author andrew + * + */ +public class XBeeAddress16 extends XBeeAddress { + + public static final XBeeAddress16 BROADCAST = new XBeeAddress16(0xFF, 0xFF); + public static final XBeeAddress16 ZNET_BROADCAST = new XBeeAddress16(0xFF, 0xFE); + + private DoubleByte doubleByte = new DoubleByte(); + + /** + * Provide address as msb byte and lsb byte + * + * @param msb + * @param lsb + */ + public XBeeAddress16(int msb, int lsb) { + this.doubleByte.setMsb(msb); + this.doubleByte.setLsb(lsb); + } + + public XBeeAddress16(int[] arr) { + this.doubleByte.setMsb(arr[0]); + this.doubleByte.setLsb(arr[1]); + } + + public XBeeAddress16() { + + } + + public int get16BitValue() { + return this.doubleByte.get16BitValue(); + } + + public int getMsb() { + return this.doubleByte.getMsb(); + } + + public void setMsb(int msb) { + this.doubleByte.setMsb(msb); + } + + public int getLsb() { + return this.doubleByte.getLsb(); + } + + public void setLsb(int lsb) { + this.doubleByte.setLsb(lsb); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + XBeeAddress16 that = (XBeeAddress16) o; + + if (doubleByte != null ? !doubleByte.equals(that.doubleByte) : that.doubleByte != null) return false; + + return true; + } + + @Override + public int hashCode() { + return doubleByte != null ? doubleByte.hashCode() : 0; + } + + @Override + public int[] getAddress() { + return new int[] { this.doubleByte.getMsb(), this.doubleByte.getLsb() }; + } +} diff --git a/src/com/rapplogic/xbee/api/XBeeAddress64.java b/src/main/java/com/rapplogic/xbee/api/XBeeAddress64.java similarity index 96% rename from src/com/rapplogic/xbee/api/XBeeAddress64.java rename to src/main/java/com/rapplogic/xbee/api/XBeeAddress64.java index a222d95..0834533 100644 --- a/src/com/rapplogic/xbee/api/XBeeAddress64.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeAddress64.java @@ -1,121 +1,121 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.util.StringTokenizer; -import java.util.Arrays; - -/** - * Represents a 64-bit XBee Address - *

- * @author andrew - * - */ -public class XBeeAddress64 extends XBeeAddress { - - public static final XBeeAddress64 BROADCAST = new XBeeAddress64(new int[] {0, 0, 0, 0, 0, 0, 0xff, 0xff}); - public static final XBeeAddress64 ZNET_COORDINATOR = new XBeeAddress64(new int[] {0, 0, 0, 0, 0, 0, 0, 0}); - - private int[] address; - - /** - * Parses an 64-bit XBee address from a string representation - * May be contain spaces ## ## ## ## ## ## ## ## or without ################ but cannot use the 0x prefix - * ex: 0013A200408B98FF or 00 13 A2 00 40 8B 98 FF - * - * @param addressStr - */ - public XBeeAddress64(String addressStr) { - address = new int[8]; - - if (addressStr.contains(" ")) { - StringTokenizer st = new StringTokenizer(addressStr, " "); - - for (int i = 0; i < address.length; i++) { - String byteStr = st.nextToken(); - address[i] = Integer.parseInt(byteStr, 16); - } - } else { - // secretly also handle no space format - for (int i = 0; i < address.length; i++) { - address[i] = Integer.parseInt(addressStr.substring(i*2, i*2+2), 16); - } - } - } - - /** - * Creates a 64-bit address - * - * @param b1 MSB - * @param b2 - * @param b3 - * @param b4 - * @param b5 - * @param b6 - * @param b7 - * @param b8 LSB - */ - public XBeeAddress64(int b1, int b2, int b3, int b4, int b5, int b6, int b7, int b8) { - address = new int[8]; - - address[0] = b1; - address[1] = b2; - address[2] = b3; - address[3] = b4; - address[4] = b5; - address[5] = b6; - address[6] = b7; - address[7] = b8; - } - - public XBeeAddress64(int[] address) { - this.address = address; - } - - public XBeeAddress64() { - address = new int[8]; - } - - public void setAddress(int[] address) { - this.address = address; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - XBeeAddress64 that = (XBeeAddress64) o; - - if (!Arrays.equals(address, that.address)) return false; - - return true; - } - - @Override - public int hashCode() { - return address != null ? Arrays.hashCode(address) : 0; - } - - @Override - public int[] getAddress() { - return address; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import java.util.StringTokenizer; +import java.util.Arrays; + +/** + * Represents a 64-bit XBee Address + *

+ * @author andrew + * + */ +public class XBeeAddress64 extends XBeeAddress { + + public static final XBeeAddress64 BROADCAST = new XBeeAddress64(new int[] {0, 0, 0, 0, 0, 0, 0xff, 0xff}); + public static final XBeeAddress64 ZNET_COORDINATOR = new XBeeAddress64(new int[] {0, 0, 0, 0, 0, 0, 0, 0}); + + private int[] address; + + /** + * Parses an 64-bit XBee address from a string representation + * May be contain spaces ## ## ## ## ## ## ## ## or without ################ but cannot use the 0x prefix + * ex: 0013A200408B98FF or 00 13 A2 00 40 8B 98 FF + * + * @param addressStr + */ + public XBeeAddress64(String addressStr) { + address = new int[8]; + + if (addressStr.contains(" ")) { + StringTokenizer st = new StringTokenizer(addressStr, " "); + + for (int i = 0; i < address.length; i++) { + String byteStr = st.nextToken(); + address[i] = Integer.parseInt(byteStr, 16); + } + } else { + // secretly also handle no space format + for (int i = 0; i < address.length; i++) { + address[i] = Integer.parseInt(addressStr.substring(i*2, i*2+2), 16); + } + } + } + + /** + * Creates a 64-bit address + * + * @param b1 MSB + * @param b2 + * @param b3 + * @param b4 + * @param b5 + * @param b6 + * @param b7 + * @param b8 LSB + */ + public XBeeAddress64(int b1, int b2, int b3, int b4, int b5, int b6, int b7, int b8) { + address = new int[8]; + + address[0] = b1; + address[1] = b2; + address[2] = b3; + address[3] = b4; + address[4] = b5; + address[5] = b6; + address[6] = b7; + address[7] = b8; + } + + public XBeeAddress64(int[] address) { + this.address = address; + } + + public XBeeAddress64() { + address = new int[8]; + } + + public void setAddress(int[] address) { + this.address = address; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + XBeeAddress64 that = (XBeeAddress64) o; + + if (!Arrays.equals(address, that.address)) return false; + + return true; + } + + @Override + public int hashCode() { + return address != null ? Arrays.hashCode(address) : 0; + } + + @Override + public int[] getAddress() { + return address; + } +} diff --git a/src/com/rapplogic/xbee/api/XBeeConfiguration.java b/src/main/java/com/rapplogic/xbee/api/XBeeConfiguration.java similarity index 79% rename from src/com/rapplogic/xbee/api/XBeeConfiguration.java rename to src/main/java/com/rapplogic/xbee/api/XBeeConfiguration.java index 6fb5070..3bbfe57 100644 --- a/src/com/rapplogic/xbee/api/XBeeConfiguration.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeConfiguration.java @@ -1,5 +1,9 @@ package com.rapplogic.xbee.api; +import com.rapplogic.xbee.api.responses.NoRequestResponse; +import com.rapplogic.xbee.connections.connectionprovider.IConnectionProvider; +import com.rapplogic.xbee.connections.connectionprovider.SerialPortConnectionProvider; + public class XBeeConfiguration { private boolean shutdownHook = false; @@ -7,6 +11,7 @@ public class XBeeConfiguration { private int maxQueueSize = 100; private int sendSynchronousTimeout = 5000; private ResponseFilter responseQueueFilter; + private IConnectionProvider connectionProvider; private final ResponseFilter noRequestResponseQueueFilter = new ResponseFilter() { public boolean accept(XBeeResponse response) { @@ -15,7 +20,7 @@ public boolean accept(XBeeResponse response) { }; public XBeeConfiguration() { - + } /** @@ -66,6 +71,16 @@ public XBeeConfiguration withSendSynchronousTimeout(int sendSynchronousTimeout) this.sendSynchronousTimeout = sendSynchronousTimeout; return this; } + + public XBeeConfiguration withConnectionProvider(IConnectionProvider connectionProvider) { + this.connectionProvider = connectionProvider; + return this; + } + + public XBeeConfiguration withDefaultConnectionProvider() { + this.connectionProvider = new SerialPortConnectionProvider(); + return this; + } /** * Only adds responses that implement NoRequestResponse @@ -96,4 +111,8 @@ public int getSendSynchronousTimeout() { public boolean isShutdownHook() { return shutdownHook; } + + public IConnectionProvider getConnectionProvider() { + return connectionProvider; + } } diff --git a/src/com/rapplogic/xbee/api/XBeeException.java b/src/main/java/com/rapplogic/xbee/api/XBeeException.java similarity index 96% rename from src/com/rapplogic/xbee/api/XBeeException.java rename to src/main/java/com/rapplogic/xbee/api/XBeeException.java index 38b57f6..e119350 100644 --- a/src/com/rapplogic/xbee/api/XBeeException.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeException.java @@ -1,58 +1,58 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -/** - * I usually detest checked exceptions but given this is a public api, it is reasonable to - * notify users what they can expect. - * - * @author andrew - * - */ -public class XBeeException extends Exception { - - private static final long serialVersionUID = -5501299728920565639L; - private Exception cause; - - public XBeeException(String message) { - super(message); - } - - public XBeeException(String message, Exception e) { - super(message, e); - } - - public XBeeException() { - super(); - } - - public XBeeException(Exception cause) { - super(); - this.setCause(cause); - } - - public Exception getCause() { - return cause; - } - - public void setCause(Exception cause) { - this.cause = cause; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +/** + * I usually detest checked exceptions but given this is a public api, it is reasonable to + * notify users what they can expect. + * + * @author andrew + * + */ +public class XBeeException extends Exception { + + private static final long serialVersionUID = -5501299728920565639L; + private Exception cause; + + public XBeeException(String message) { + super(message); + } + + public XBeeException(String message, Exception e) { + super(message, e); + } + + public XBeeException() { + super(); + } + + public XBeeException(Exception cause) { + super(); + this.setCause(cause); + } + + public Exception getCause() { + return cause; + } + + public void setCause(Exception cause) { + this.cause = cause; + } +} diff --git a/src/main/java/com/rapplogic/xbee/api/XBeeInformation.java b/src/main/java/com/rapplogic/xbee/api/XBeeInformation.java new file mode 100644 index 0000000..e10f571 --- /dev/null +++ b/src/main/java/com/rapplogic/xbee/api/XBeeInformation.java @@ -0,0 +1,88 @@ +package com.rapplogic.xbee.api; + +import com.rapplogic.xbee.api.HardwareVersion.RadioType; + +public class XBeeInformation { + enum XBeeMode { + COORDINATOR, ROUTER, END_DEVICE, UNKNOWN; + } + private final RadioType hardwareVersion; + private final int firmwareVersion; + private final long panID; + private final int serialHigh; + private final int serialLow; + private final XBeeMode mode; + private long lastReceivedMessage; + + public XBeeInformation(RadioType hardwareVersion, int[] firmwareVersion, int[] panID, int[] serialHigh, int[] seriallow) { + + this.hardwareVersion = hardwareVersion; + + this.firmwareVersion = firmwareVersion[0] << 8 | firmwareVersion[1]; + + this.panID = (long)panID[0] << 56 | (long)panID[1] << 48 | (long)panID[2] << 40 | (long)panID[3] << 32 | + panID[4] << 24 | panID[5] << 16 | panID[6] << 8 | panID[7]; + + this.serialHigh = serialHigh[0] << 24 | serialHigh[1] << 16 | serialHigh[2] << 8 | serialHigh[3]; + + this.serialLow = seriallow[0] << 24 | seriallow[1] << 16 | seriallow[2] << 8 | seriallow[3]; + + this.mode = getModeFromFirmwareVersion(firmwareVersion); + } + + private XBeeMode getModeFromFirmwareVersion(int[] firmwareVersion) { + // First byte of the firmware version tells us which mode we're running in + // in case we're using API mode (which we always should be). + switch(firmwareVersion[0]) { + case 0x21: + return XBeeMode.COORDINATOR; + case 0x23: + return XBeeMode.ROUTER; + case 0x29: + return XBeeMode.END_DEVICE; + default: + return XBeeMode.UNKNOWN; + } + } + + public XBeeMode getMode() { + return mode; + } + + public void touchLastReceivedTime() { + lastReceivedMessage = System.currentTimeMillis(); + } + + public RadioType getHardwareVersion() { + return hardwareVersion; + } + + public int getFirmwareVersion() { + return firmwareVersion; + } + + public long getPanID() { + return panID; + } + + public int getSerialHigh() { + return serialHigh; + } + + public int getSerialLow() { + return serialLow; + } + + public long getLastReceivedMessage() { + return lastReceivedMessage; + } + + @Override + public String toString() { + return "XBeeInformation [hardwareVersion=" + hardwareVersion + + ", firmwareVersion=" + String.format("%02X", firmwareVersion) + ", panID=" + String.format("%08X", panID) + + ", serialHigh=" + String.format("%04X", serialHigh) + ", serialLow=" + String.format("%04X", serialLow) + + ", mode " + mode.toString() + "]"; + } + +} diff --git a/src/com/rapplogic/xbee/api/XBeeNotConnectedException.java b/src/main/java/com/rapplogic/xbee/api/XBeeNotConnectedException.java similarity index 93% rename from src/com/rapplogic/xbee/api/XBeeNotConnectedException.java rename to src/main/java/com/rapplogic/xbee/api/XBeeNotConnectedException.java index 34fbc7a..398b00e 100644 --- a/src/com/rapplogic/xbee/api/XBeeNotConnectedException.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeNotConnectedException.java @@ -1,33 +1,35 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -/** - * Indicates there is not connection to the radio - *

- * @author andrew - * - */ -public class XBeeNotConnectedException extends RuntimeException { - - public XBeeNotConnectedException() { - super(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +/** + * Indicates there is not connection to the radio + *

+ * @author andrew + * + */ +public class XBeeNotConnectedException extends RuntimeException { + + private static final long serialVersionUID = -9072619514834558213L; + + public XBeeNotConnectedException() { + super(); + } +} diff --git a/src/com/rapplogic/xbee/api/XBeePacket.java b/src/main/java/com/rapplogic/xbee/api/XBeePacket.java similarity index 96% rename from src/com/rapplogic/xbee/api/XBeePacket.java rename to src/main/java/com/rapplogic/xbee/api/XBeePacket.java index 2aa35d9..cccb3c9 100644 --- a/src/com/rapplogic/xbee/api/XBeePacket.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeePacket.java @@ -1,330 +1,330 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Packages a frame data array into an XBee packet. - *

- * @author andrew - * - */ -public class XBeePacket { - - public enum SpecialByte { - START_BYTE (0x7e), // ~ - ESCAPE (0x7d), // } - XON (0x11), - XOFF (0x13); - - private static final Map lookup = new HashMap(); - - static { - for(SpecialByte s : EnumSet.allOf(SpecialByte.class)) { - lookup.put(s.getValue(), s); - } - } - - public static SpecialByte get(int value) { - return lookup.get(value); - } - - private final int value; - - SpecialByte(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - private final static Logger log = Logger.getLogger(XBeePacket.class); - - private int[] packet; - - /** - * Performs the necessary activities to construct an XBee packet from the frame data. - * This includes: computing the checksum, escaping the necessary bytes, adding the start byte and length bytes. - * - * The format of a packet is as follows: - * - * start byte - msb length byte - lsb length byte - frame data - checksum byte - * - * @param frameData - */ - public XBeePacket(int[] frameData) { - - // checksum is always computed on pre-escaped packet - Checksum checksum = new Checksum(); - - for (int aFrameData : frameData) { - checksum.addByte(aFrameData); - } - - checksum.compute(); - - // packet size is frame data + start byte + 2 length bytes + checksum byte - packet = new int[frameData.length + 4]; - packet[0] = SpecialByte.START_BYTE.getValue(); - - // Packet length does not include escape bytes or start, length and checksum bytes - XBeePacketLength length = new XBeePacketLength(frameData.length); - - // msb length (will be zero until maybe someday when > 255 bytes packets are supported) - packet[1] = length.getMsb(); - // lsb length - packet[2] = length.getLsb(); - - for (int i = 0; i < frameData.length; i++) { - if (frameData[i] > 255) { - throw new RuntimeException("Packet values must not be greater than one byte (255): " + frameData[i]); - } - - packet[3 + i] = frameData[i]; - } - - // set last byte as checksum - // note: if checksum is not correct, XBee won't send out packet or return error. ask me how I know. - - packet[packet.length - 1] = checksum.getChecksum(); - -// for (int i = 0; i < packet.length; i++) { -// log.debug("XBeeApi pre-escape packet byte " + i + " is " + ByteUtils.toBase16(packet[i])); -// } - - int preEscapeLength = packet.length; - - // TODO save escaping for the serial out method. this is an unnecessary operation - packet = escapePacket(packet); - - if (log.isDebugEnabled()) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("Packet: "); - for (int i = 0; i < packet.length; i++) { - stringBuilder.append(ByteUtils.toBase16(packet[i])); - if (i < packet.length - 1) { - stringBuilder.append(" "); - } - } - log.debug(stringBuilder); - - log.debug("pre-escape packet size is " + preEscapeLength + ", post-escape packet size is " + packet.length); - } - } - - /** - * Escape all bytes in packet after start byte, and including checksum - * - * @param packet - * @return - */ - private static int[] escapePacket(int[] packet) { - int escapeBytes = 0; - - // escape packet. start at one so we don't escape the start byte - for (int i = 1; i < packet.length; i++) { - if (isSpecialByte(packet[i])) { - log.debug("escapeFrameData: packet byte requires escaping byte " + ByteUtils.toBase16(packet[i])); - escapeBytes++; - } - } - - if (escapeBytes == 0) { - return packet; - } else { - log.debug("packet requires escaping"); - - int[] escapePacket = new int[packet.length + escapeBytes]; - - int pos = 1; - - escapePacket[0] = SpecialByte.START_BYTE.getValue(); - - for (int i = 1; i < packet.length; i++) { - if (isSpecialByte(packet[i])) { - escapePacket[pos] = SpecialByte.ESCAPE.getValue(); - escapePacket[++pos] = 0x20 ^ packet[i]; - - log.debug("escapeFrameData: xor'd byte is 0x" + Integer.toHexString(escapePacket[pos])); - } else { - escapePacket[pos] = packet[i]; - } - - pos++; - } - - return escapePacket; - } - } - - /** - * @deprecated use getByteArray - * @return - */ - public int[] getPacket() { - return this.getByteArray(); - } - - public int[] getByteArray() { - return packet; - } - - public static boolean isSpecialByte(int b) { - return b == SpecialByte.START_BYTE.getValue() || b == SpecialByte.ESCAPE.getValue() || b == SpecialByte.XON.getValue() || - b == SpecialByte.XOFF.getValue(); - - } - - public String toString() { - return ByteUtils.toBase16(this.packet); - } - - /** - * Must be called with unescapted packet - * - * @param packet - * @return - */ - public static int getPacketLength(int[] packet) { - return new XBeePacketLength(packet[1], packet[2]).getLength(); - } - - /** - * Returns true if the packet is valid, Verifies both escaped and un-escaped packets - * - * @param packet - * @return - */ - public static boolean verify(int[] packet) { - boolean valid = true; - - try { - if (packet[0] != SpecialByte.START_BYTE.getValue()) { - return false; - } - - if (packetEndsWithEscapeByte(packet)) { - // packet can never end on a escape byte since the following byte is xor to unescape and will result in a array out of bounds exception - // this is an incomplete packet - return false; - } - - // first need to un-escape packet since escape bytes complicate things - int[] unEscaped = unEscapePacket(packet); - - // in theory 3 bytes are the minimum for 0 byte packet with no escape bytes. any less it can't be valid - if (unEscaped.length < 3) { - return false; - } - - int len = getPacketLength(unEscaped); - - // total packet length = stated length + 1 start byte + 1 checksum byte + 2 length bytes - // stated packet length does include escaping bytes, so actual packet size can be much larger, almost double - int expectedPacketLength = len + 4; - - // if we are less bytes than expected packet length it can't be valid - if (unEscaped.length != expectedPacketLength) { - return false; - } - - int[] frameData = new int[len]; - - Checksum checksum = new Checksum(); - - for (int i = 3; i < unEscaped.length - 1; i++) { - frameData[i - 3] = unEscaped[i]; - checksum.addByte(frameData[i - 3]); - } - - // add checksum byte to verify -- the last byte - checksum.addByte(unEscaped[unEscaped.length - 1]); - - if (!checksum.verify()) { - valid = false; - } - } catch (Exception e) { - throw new RuntimeException("Packet verification failed with error: ", e); - } - - return valid; - } - - public static boolean packetEndsWithEscapeByte(int[] packet) { - return (packet[packet.length - 1] == SpecialByte.ESCAPE.getValue()); - } - - /** - * - * @param packet - * @return - * @throws IncompletePacketException - */ - public static int[] unEscapePacket(int[] packet) { - - int escapeBytes = 0; - - if (packetEndsWithEscapeByte(packet)) { - //packet can never end on a escape byte since the following byte is xor to unescape and will result in a array out of bounds exception - throw new RuntimeException("Invalid packet -- packet cannot end with an escape byte " + ByteUtils.toBase16(packet)); - } - - // first check if escape byte exists, if not we don't allocate a new array - for (int b : packet) { - if (b == SpecialByte.ESCAPE.getValue()) { - escapeBytes++; - } - } - - if (escapeBytes == 0) { - return packet; - } - - int[] unEscapedPacket = new int[packet.length - escapeBytes]; - - int pos = 0; - - for (int i = 0; i < packet.length; i++) { - if (packet[i] == SpecialByte.ESCAPE.getValue()) { - // discard escape byte and un-escape following byte - if (i >= packet.length - 1) { - return packet; - } - - unEscapedPacket[pos] = 0x20 ^ packet[++i]; - } else { - unEscapedPacket[pos] = packet[i]; - } - - pos++; - } - - return unEscapedPacket; - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Packages a frame data array into an XBee packet. + *

+ * @author andrew + * + */ +public class XBeePacket { + + public enum SpecialByte { + START_BYTE (0x7e), // ~ + ESCAPE (0x7d), // } + XON (0x11), + XOFF (0x13); + + private static final Map lookup = new HashMap(); + + static { + for(SpecialByte s : EnumSet.allOf(SpecialByte.class)) { + lookup.put(s.getValue(), s); + } + } + + public static SpecialByte get(int value) { + return lookup.get(value); + } + + private final int value; + + SpecialByte(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + private final static Logger log = Logger.getLogger(XBeePacket.class); + + private int[] packet; + + /** + * Performs the necessary activities to construct an XBee packet from the frame data. + * This includes: computing the checksum, escaping the necessary bytes, adding the start byte and length bytes. + * + * The format of a packet is as follows: + * + * start byte - msb length byte - lsb length byte - frame data - checksum byte + * + * @param frameData + */ + public XBeePacket(int[] frameData) { + + // checksum is always computed on pre-escaped packet + Checksum checksum = new Checksum(); + + for (int aFrameData : frameData) { + checksum.addByte(aFrameData); + } + + checksum.compute(); + + // packet size is frame data + start byte + 2 length bytes + checksum byte + packet = new int[frameData.length + 4]; + packet[0] = SpecialByte.START_BYTE.getValue(); + + // Packet length does not include escape bytes or start, length and checksum bytes + XBeePacketLength length = new XBeePacketLength(frameData.length); + + // msb length (will be zero until maybe someday when > 255 bytes packets are supported) + packet[1] = length.getMsb(); + // lsb length + packet[2] = length.getLsb(); + + for (int i = 0; i < frameData.length; i++) { + if (frameData[i] > 255) { + throw new RuntimeException("Packet values must not be greater than one byte (255): " + frameData[i]); + } + + packet[3 + i] = frameData[i]; + } + + // set last byte as checksum + // note: if checksum is not correct, XBee won't send out packet or return error. ask me how I know. + + packet[packet.length - 1] = checksum.getChecksum(); + +// for (int i = 0; i < packet.length; i++) { +// log.debug("XBeeApi pre-escape packet byte " + i + " is " + ByteUtils.toBase16(packet[i])); +// } + + int preEscapeLength = packet.length; + + // TODO save escaping for the serial out method. this is an unnecessary operation + packet = escapePacket(packet); + + if (log.isDebugEnabled()) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("Packet: "); + for (int i = 0; i < packet.length; i++) { + stringBuilder.append(ByteUtils.toBase16(packet[i])); + if (i < packet.length - 1) { + stringBuilder.append(" "); + } + } + log.debug(stringBuilder); + + log.debug("pre-escape packet size is " + preEscapeLength + ", post-escape packet size is " + packet.length); + } + } + + /** + * Escape all bytes in packet after start byte, and including checksum + * + * @param packet + * @return + */ + private static int[] escapePacket(int[] packet) { + int escapeBytes = 0; + + // escape packet. start at one so we don't escape the start byte + for (int i = 1; i < packet.length; i++) { + if (isSpecialByte(packet[i])) { + log.debug("escapeFrameData: packet byte requires escaping byte " + ByteUtils.toBase16(packet[i])); + escapeBytes++; + } + } + + if (escapeBytes == 0) { + return packet; + } else { + log.debug("packet requires escaping"); + + int[] escapePacket = new int[packet.length + escapeBytes]; + + int pos = 1; + + escapePacket[0] = SpecialByte.START_BYTE.getValue(); + + for (int i = 1; i < packet.length; i++) { + if (isSpecialByte(packet[i])) { + escapePacket[pos] = SpecialByte.ESCAPE.getValue(); + escapePacket[++pos] = 0x20 ^ packet[i]; + + log.debug("escapeFrameData: xor'd byte is 0x" + Integer.toHexString(escapePacket[pos])); + } else { + escapePacket[pos] = packet[i]; + } + + pos++; + } + + return escapePacket; + } + } + + /** + * @deprecated use getByteArray + * @return + */ + public int[] getPacket() { + return this.getByteArray(); + } + + public int[] getByteArray() { + return packet; + } + + public static boolean isSpecialByte(int b) { + return b == SpecialByte.START_BYTE.getValue() || b == SpecialByte.ESCAPE.getValue() || b == SpecialByte.XON.getValue() || + b == SpecialByte.XOFF.getValue(); + + } + + public String toString() { + return ByteUtils.toBase16(this.packet); + } + + /** + * Must be called with unescapted packet + * + * @param packet + * @return + */ + public static int getPacketLength(int[] packet) { + return new XBeePacketLength(packet[1], packet[2]).getLength(); + } + + /** + * Returns true if the packet is valid, Verifies both escaped and un-escaped packets + * + * @param packet + * @return + */ + public static boolean verify(int[] packet) { + boolean valid = true; + + try { + if (packet[0] != SpecialByte.START_BYTE.getValue()) { + return false; + } + + if (packetEndsWithEscapeByte(packet)) { + // packet can never end on a escape byte since the following byte is xor to unescape and will result in a array out of bounds exception + // this is an incomplete packet + return false; + } + + // first need to un-escape packet since escape bytes complicate things + int[] unEscaped = unEscapePacket(packet); + + // in theory 3 bytes are the minimum for 0 byte packet with no escape bytes. any less it can't be valid + if (unEscaped.length < 3) { + return false; + } + + int len = getPacketLength(unEscaped); + + // total packet length = stated length + 1 start byte + 1 checksum byte + 2 length bytes + // stated packet length does include escaping bytes, so actual packet size can be much larger, almost double + int expectedPacketLength = len + 4; + + // if we are less bytes than expected packet length it can't be valid + if (unEscaped.length != expectedPacketLength) { + return false; + } + + int[] frameData = new int[len]; + + Checksum checksum = new Checksum(); + + for (int i = 3; i < unEscaped.length - 1; i++) { + frameData[i - 3] = unEscaped[i]; + checksum.addByte(frameData[i - 3]); + } + + // add checksum byte to verify -- the last byte + checksum.addByte(unEscaped[unEscaped.length - 1]); + + if (!checksum.verify()) { + valid = false; + } + } catch (Exception e) { + throw new RuntimeException("Packet verification failed with error: ", e); + } + + return valid; + } + + public static boolean packetEndsWithEscapeByte(int[] packet) { + return (packet[packet.length - 1] == SpecialByte.ESCAPE.getValue()); + } + + /** + * + * @param packet + * @return + * @throws IncompletePacketException + */ + public static int[] unEscapePacket(int[] packet) { + + int escapeBytes = 0; + + if (packetEndsWithEscapeByte(packet)) { + //packet can never end on a escape byte since the following byte is xor to unescape and will result in a array out of bounds exception + throw new RuntimeException("Invalid packet -- packet cannot end with an escape byte " + ByteUtils.toBase16(packet)); + } + + // first check if escape byte exists, if not we don't allocate a new array + for (int b : packet) { + if (b == SpecialByte.ESCAPE.getValue()) { + escapeBytes++; + } + } + + if (escapeBytes == 0) { + return packet; + } + + int[] unEscapedPacket = new int[packet.length - escapeBytes]; + + int pos = 0; + + for (int i = 0; i < packet.length; i++) { + if (packet[i] == SpecialByte.ESCAPE.getValue()) { + // discard escape byte and un-escape following byte + if (i >= packet.length - 1) { + return packet; + } + + unEscapedPacket[pos] = 0x20 ^ packet[++i]; + } else { + unEscapedPacket[pos] = packet[i]; + } + + pos++; + } + + return unEscapedPacket; + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/XBeePacketHandler.java b/src/main/java/com/rapplogic/xbee/api/XBeePacketHandler.java similarity index 97% rename from src/com/rapplogic/xbee/api/XBeePacketHandler.java rename to src/main/java/com/rapplogic/xbee/api/XBeePacketHandler.java index 8138546..68ee116 100644 --- a/src/com/rapplogic/xbee/api/XBeePacketHandler.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeePacketHandler.java @@ -1,24 +1,24 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -public interface XBeePacketHandler { - public void handlePacket(XBeeResponse response); -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +public interface XBeePacketHandler { + public void handlePacket(XBeeResponse response); +} diff --git a/src/com/rapplogic/xbee/api/XBeePacketLength.java b/src/main/java/com/rapplogic/xbee/api/XBeePacketLength.java similarity index 96% rename from src/com/rapplogic/xbee/api/XBeePacketLength.java rename to src/main/java/com/rapplogic/xbee/api/XBeePacketLength.java index ddef4d1..3cbabcf 100644 --- a/src/com/rapplogic/xbee/api/XBeePacketLength.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeePacketLength.java @@ -1,49 +1,49 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import com.rapplogic.xbee.util.DoubleByte; - -/** - * Supports a 16-bit XBee packet length - *

- * @author andrew - * - */ -public class XBeePacketLength extends DoubleByte { - - /** - * Manual says max packet length is 100 bytes so not sure why 2 bytes are needed - * - * @param msb - * @param lsb - */ - public XBeePacketLength(int msb, int lsb) { - super(msb, lsb); - } - - public XBeePacketLength(int length) { - super(length); - } - - public int getLength() { - return this.get16BitValue(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import com.rapplogic.xbee.util.DoubleByte; + +/** + * Supports a 16-bit XBee packet length + *

+ * @author andrew + * + */ +public class XBeePacketLength extends DoubleByte { + + /** + * Manual says max packet length is 100 bytes so not sure why 2 bytes are needed + * + * @param msb + * @param lsb + */ + public XBeePacketLength(int msb, int lsb) { + super(msb, lsb); + } + + public XBeePacketLength(int length) { + super(length); + } + + public int getLength() { + return this.get16BitValue(); + } +} diff --git a/src/com/rapplogic/xbee/api/XBeeParseException.java b/src/main/java/com/rapplogic/xbee/api/XBeeParseException.java similarity index 97% rename from src/com/rapplogic/xbee/api/XBeeParseException.java rename to src/main/java/com/rapplogic/xbee/api/XBeeParseException.java index d27be89..dcd14f0 100644 --- a/src/com/rapplogic/xbee/api/XBeeParseException.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeParseException.java @@ -1,29 +1,29 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -public class XBeeParseException extends RuntimeException { - - private static final long serialVersionUID = 6752060371295132748L; - - public XBeeParseException(String s) { - super(s); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +public class XBeeParseException extends RuntimeException { + + private static final long serialVersionUID = 6752060371295132748L; + + public XBeeParseException(String s) { + super(s); + } +} diff --git a/src/com/rapplogic/xbee/api/XBeeRequest.java b/src/main/java/com/rapplogic/xbee/api/XBeeRequest.java similarity index 96% rename from src/com/rapplogic/xbee/api/XBeeRequest.java rename to src/main/java/com/rapplogic/xbee/api/XBeeRequest.java index 9cf62fc..5648d0d 100644 --- a/src/com/rapplogic/xbee/api/XBeeRequest.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeRequest.java @@ -1,85 +1,85 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.io.Serializable; - - -/** - * The super class of all XBee transmit packets. - * Constructs frame data portion of an XBee packet - *

- * @author andrew - * - */ - -public abstract class XBeeRequest implements Serializable { - - private static final long serialVersionUID = -9181542059678009341L; - - public static final int DEFAULT_FRAME_ID = 1; - // XBee will not generate a TX Status Packet if this frame id sent - public static final int NO_RESPONSE_FRAME_ID = 0; - - private ApiId apiId; - private int frameId; - - public XBeeRequest() { - - } - - // TODO create XBeePacket(XBeeRequest) constructor and move operation there - public XBeePacket getXBeePacket() { - int[] frameData = this.getFrameData(); - - if (frameData == null) { - throw new RuntimeException("frame data is null"); - } - - // TODO xbee packet should handle api/frame id - XBeePacket packet = new XBeePacket(frameData); - - return packet; - } - - public abstract int[] getFrameData(); - - public ApiId getApiId() { - return apiId; - } - - public int getFrameId() { - return frameId; - } - - public String toString() { - return "apiId=" + this.getApiId() + ",frameId=" + this.getFrameId(); - } - - public void setApiId(ApiId apiId) { - this.apiId = apiId; - } - - public void setFrameId(int frameId) { - this.frameId = frameId; - } - - // TODO clear method to reuse request -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import java.io.Serializable; + + +/** + * The super class of all XBee transmit packets. + * Constructs frame data portion of an XBee packet + *

+ * @author andrew + * + */ + +public abstract class XBeeRequest implements Serializable { + + private static final long serialVersionUID = -9181542059678009341L; + + public static final int DEFAULT_FRAME_ID = 1; + // XBee will not generate a TX Status Packet if this frame id sent + public static final int NO_RESPONSE_FRAME_ID = 0; + + private ApiId apiId; + private int frameId; + + public XBeeRequest() { + + } + + // TODO create XBeePacket(XBeeRequest) constructor and move operation there + public XBeePacket getXBeePacket() { + int[] frameData = this.getFrameData(); + + if (frameData == null) { + throw new RuntimeException("frame data is null"); + } + + // TODO xbee packet should handle api/frame id + XBeePacket packet = new XBeePacket(frameData); + + return packet; + } + + public abstract int[] getFrameData(); + + public ApiId getApiId() { + return apiId; + } + + public int getFrameId() { + return frameId; + } + + public String toString() { + return "apiId=" + this.getApiId() + ",frameId=" + this.getFrameId(); + } + + public void setApiId(ApiId apiId) { + this.apiId = apiId; + } + + public void setFrameId(int frameId) { + this.frameId = frameId; + } + + // TODO clear method to reuse request +} diff --git a/src/com/rapplogic/xbee/api/XBeeResponse.java b/src/main/java/com/rapplogic/xbee/api/XBeeResponse.java similarity index 95% rename from src/com/rapplogic/xbee/api/XBeeResponse.java rename to src/main/java/com/rapplogic/xbee/api/XBeeResponse.java index bd6ea25..4b53c18 100644 --- a/src/com/rapplogic/xbee/api/XBeeResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeResponse.java @@ -1,194 +1,192 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.io.IOException; -import java.io.Serializable; -import java.util.Arrays; - -import com.rapplogic.xbee.util.ByteUtils; - -/** - * The super class of all XBee Receive packets - * - * @author andrew - * - */ -public abstract class XBeeResponse implements Serializable { - - // TODO consider adding UUID to each response - - private static final long serialVersionUID = -7038123612643874495L; - - // the raw (escaped) bytes of this packet (minus start byte) - // this is the most compact representation of the packet; - // useful for sending the packet over a wire (e.g. xml), - // for later reconstitution - private int[] rawPacketBytes; - private int[] processedPacketBytes; - - private ApiId apiId; - private int checksum; - - private XBeePacketLength length; - - private boolean error = false; - - public XBeeResponse() { - - } - - public XBeePacketLength getLength() { - return length; - } - - public void setLength(XBeePacketLength length) { - this.length = length; - } - - public ApiId getApiId() { - return apiId; - } - - public void setApiId(ApiId apiId) { - this.apiId = apiId; - } - - public int getChecksum() { - return checksum; - } - - public void setChecksum(int checksum) { - this.checksum = checksum; - } - - /** - * Indicates an error occurred during the parsing of the packet. - * This may indicate a bug in this software or in the XBee firmware. - * Absence of an error does not indicate the request was successful; - * you will need to inspect the status byte of the response object (if available) - * to determine success. - * - * @return - */ - public boolean isError() { - return error; - } - - public void setError(boolean error) { - this.error = error; - } - - /** - * @deprecated Use getRawPacketBytes instead - * @return - */ - public int[] getPacketBytes() { - return this.getRawPacketBytes(); - } - - /** - * Returns an array all bytes (as received off radio, including escape bytes) in packet except the start byte. - * - * @return - */ - public int[] getRawPacketBytes() { - return rawPacketBytes; - } - - /** - * Returns an array of all bytes (after being un-escaped) in the packet except the start byte. - * @return - */ - public int[] getProcessedPacketBytes() { - return processedPacketBytes; - } - - public void setRawPacketBytes(int[] packetBytes) { - this.rawPacketBytes = packetBytes; - this.processedPacketBytes = XBeePacket.unEscapePacket(packetBytes); - } - - /** - * For internal use only. Called after successful parsing to allow subclass to do any final processing before delivery - */ - public void finish() { - - } - - /** - * All subclasses must implement to parse the packet from the input stream. - * The subclass must parse all bytes in the packet starting after the API_ID, and - * up to but not including the checksum. Reading either more or less bytes that expected will - * result in an error. - * - * @param parser - * @throws IOException - */ - protected abstract void parse(IPacketParser parser) throws IOException; - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((apiId == null) ? 0 : apiId.hashCode()); - result = prime * result + checksum; - result = prime * result + (error ? 1231 : 1237); - result = prime * result + ((length == null) ? 0 : length.hashCode()); - result = prime * result + Arrays.hashCode(rawPacketBytes); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - XBeeResponse other = (XBeeResponse) obj; - if (apiId == null) { - if (other.apiId != null) - return false; - } else if (!apiId.equals(other.apiId)) - return false; - if (checksum != other.checksum) - return false; - if (error != other.error) - return false; - if (length == null) { - if (other.length != null) - return false; - } else if (!length.equals(other.length)) - return false; - if (!Arrays.equals(rawPacketBytes, other.rawPacketBytes)) - return false; - return true; - } - - public String toString() { - // 8/19/09 fixed null pointer on length.get16BitValue - return "apiId=" + this.apiId + - ",length=" + (length == null ? "null" : length.get16BitValue()) + - ",checksum=" + ByteUtils.toBase16(checksum) + - ",error=" + this.error; - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +import java.io.IOException; +import java.io.Serializable; +import java.util.Arrays; + +import com.rapplogic.xbee.util.ByteUtils; + +/** + * The super class of all XBee Receive packets + * + * @author andrew + * + */ +public abstract class XBeeResponse implements Serializable { + + private static final long serialVersionUID = -7038123612643874495L; + + // the raw (escaped) bytes of this packet (minus start byte) + // this is the most compact representation of the packet; + // useful for sending the packet over a wire (e.g. xml), + // for later reconstitution + private int[] rawPacketBytes; + private int[] processedPacketBytes; + + private ApiId apiId; + private int checksum; + + private XBeePacketLength length; + + private boolean error = false; + + public XBeeResponse() { + + } + + public XBeePacketLength getLength() { + return length; + } + + public void setLength(XBeePacketLength length) { + this.length = length; + } + + public ApiId getApiId() { + return apiId; + } + + public void setApiId(ApiId apiId) { + this.apiId = apiId; + } + + public int getChecksum() { + return checksum; + } + + public void setChecksum(int checksum) { + this.checksum = checksum; + } + + /** + * Indicates an error occurred during the parsing of the packet. + * This may indicate a bug in this software or in the XBee firmware. + * Absence of an error does not indicate the request was successful; + * you will need to inspect the status byte of the response object (if available) + * to determine success. + * + * @return + */ + public boolean isError() { + return error; + } + + public void setError(boolean error) { + this.error = error; + } + + /** + * @deprecated Use getRawPacketBytes instead + * @return + */ + public int[] getPacketBytes() { + return this.getRawPacketBytes(); + } + + /** + * Returns an array all bytes (as received off radio, including escape bytes) in packet except the start byte. + * + * @return + */ + public int[] getRawPacketBytes() { + return rawPacketBytes; + } + + /** + * Returns an array of all bytes (after being un-escaped) in the packet except the start byte. + * @return + */ + public int[] getProcessedPacketBytes() { + return processedPacketBytes; + } + + public void setRawPacketBytes(int[] packetBytes) { + this.rawPacketBytes = packetBytes; + this.processedPacketBytes = XBeePacket.unEscapePacket(packetBytes); + } + + /** + * For internal use only. Called after successful parsing to allow subclass to do any final processing before delivery + */ + public void finish() { + + } + + /** + * All subclasses must implement to parse the packet from the input stream. + * The subclass must parse all bytes in the packet starting after the API_ID, and + * up to but not including the checksum. Reading either more or less bytes that expected will + * result in an error. + * + * @param parser + * @throws IOException + */ + protected abstract void parse(IPacketParser parser) throws IOException; + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((apiId == null) ? 0 : apiId.hashCode()); + result = prime * result + checksum; + result = prime * result + (error ? 1231 : 1237); + result = prime * result + ((length == null) ? 0 : length.hashCode()); + result = prime * result + Arrays.hashCode(rawPacketBytes); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + XBeeResponse other = (XBeeResponse) obj; + if (apiId == null) { + if (other.apiId != null) + return false; + } else if (!apiId.equals(other.apiId)) + return false; + if (checksum != other.checksum) + return false; + if (error != other.error) + return false; + if (length == null) { + if (other.length != null) + return false; + } else if (!length.equals(other.length)) + return false; + if (!Arrays.equals(rawPacketBytes, other.rawPacketBytes)) + return false; + return true; + } + + public String toString() { + // 8/19/09 fixed null pointer on length.get16BitValue + return "apiId=" + this.apiId + + ",length=" + (length == null ? "null" : length.get16BitValue()) + + ",checksum=" + ByteUtils.toBase16(checksum) + + ",error=" + this.error; + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/XBeeTimeoutException.java b/src/main/java/com/rapplogic/xbee/api/XBeeTimeoutException.java similarity index 96% rename from src/com/rapplogic/xbee/api/XBeeTimeoutException.java rename to src/main/java/com/rapplogic/xbee/api/XBeeTimeoutException.java index 485a982..bb66bcc 100644 --- a/src/com/rapplogic/xbee/api/XBeeTimeoutException.java +++ b/src/main/java/com/rapplogic/xbee/api/XBeeTimeoutException.java @@ -1,35 +1,35 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -/** - * Indicates an operation did not succeed within the alloted time - *

- * @author andrew - * - */ -public class XBeeTimeoutException extends XBeeException { - - private static final long serialVersionUID = 1045336675379821890L; - - public XBeeTimeoutException() { - super(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api; + +/** + * Indicates an operation did not succeed within the alloted time + *

+ * @author andrew + * + */ +public class XBeeTimeoutException extends XBeeException { + + private static final long serialVersionUID = 1045336675379821890L; + + public XBeeTimeoutException() { + super(); + } +} diff --git a/src/com/rapplogic/xbee/api/AtCommand.java b/src/main/java/com/rapplogic/xbee/api/requests/AtCommand.java similarity index 94% rename from src/com/rapplogic/xbee/api/AtCommand.java rename to src/main/java/com/rapplogic/xbee/api/requests/AtCommand.java index fd6b2dc..03a81c0 100644 --- a/src/com/rapplogic/xbee/api/AtCommand.java +++ b/src/main/java/com/rapplogic/xbee/api/requests/AtCommand.java @@ -1,138 +1,142 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.IntArrayOutputStream; - -/** - * API technique to set/query commands - *

- * WARNING: Any changes made will not survive a power cycle unless written to memory with WR command - * According to the manual, the WR command can only be written so many times.. however many that is. - *

- * API ID: 0x8 - *

- * Determining radio type with HV:
- * Byte 1, Part Number
- * x17, XB24 (series 1)
- * x18, XBP24 (series 1)
- * x19, XB24-B (series 2)
- * x1A, XBP24-B (series 2)
- *

- * XB24-ZB
- * XBP24-ZB
- * @author andrew - */ -public class AtCommand extends XBeeRequest { - - private String command; - private int[] value; - -// // common i/o pin settings. it is up to the developer to ensure the setting is applicable to the pin (e.g. not all pins support analog input) -// public enum IoSetting { -// DISABLED (new int[] {0x0}), -// ANALOG_INPUT (new int[] {0x2}), -// DIGITAL_INPUT (new int[] {0x3}), -// DIGITAL_OUTPUT_LOW (new int[] {0x4}), -// DIGITAL_OUTPUT_HIGH (new int[] {0x5}); -// -// private final int[] value; -// -// IoSetting(int[] value) { -// this.value = value; -// } -// } - - public AtCommand(String command) { - this(command, null, DEFAULT_FRAME_ID); - } - - public AtCommand(String command, int value) { - this(command, new int[] {value}, DEFAULT_FRAME_ID); - } - - public AtCommand(String command, int value[]) { - this(command, value, DEFAULT_FRAME_ID); - } - - /** - * Warning: frameId must be > 0 for a response - * - * @param command - * @param value - * @param frameId - */ - public AtCommand(String command, int[] value, int frameId) { - this.command = command; - this.value = value; - this.setFrameId(frameId); - } - - public int[] getFrameData() { - if (command.length() > 2) { - throw new IllegalArgumentException("Command should be two characters. Do not include AT prefix"); - } - - IntArrayOutputStream out = new IntArrayOutputStream(); - - // api id - out.write(this.getApiId().getValue()); - // frame id - out.write(this.getFrameId()); - // at command byte 1 - out.write((int) command.substring(0, 1).toCharArray()[0]); - // at command byte 2 - out.write((int) command.substring(1, 2).toCharArray()[0]); - - // int value is up to four bytes to represent command value - if (value != null) { - out.write(value); - } - - return out.getIntArray(); - } - - public ApiId getApiId() { - return ApiId.AT_COMMAND; - } - - public String getCommand() { - return command; - } - - public void setCommand(String command) { - this.command = command; - } - - public int[] getValue() { - return value; - } - - public void setValue(int[] value) { - this.value = value; - } - - public String toString() { - return super.toString() + - ",command=" + this.command + - ",value=" + (value == null ? "null" : ByteUtils.toBase16(value)); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.requests; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBeeRequest; +import com.rapplogic.xbee.util.ByteUtils; +import com.rapplogic.xbee.util.IntArrayOutputStream; + +/** + * API technique to set/query commands + *

+ * WARNING: Any changes made will not survive a power cycle unless written to memory with WR command + * According to the manual, the WR command can only be written so many times.. however many that is. + *

+ * API ID: 0x8 + *

+ * Determining radio type with HV:
+ * Byte 1, Part Number
+ * x17, XB24 (series 1)
+ * x18, XBP24 (series 1)
+ * x19, XB24-B (series 2)
+ * x1A, XBP24-B (series 2)
+ *

+ * XB24-ZB
+ * XBP24-ZB
+ * @author andrew + */ +public class AtCommand extends XBeeRequest { + + private static final long serialVersionUID = -3820024650079482977L; + + private String command; + private int[] value; + +// // common i/o pin settings. it is up to the developer to ensure the setting is applicable to the pin (e.g. not all pins support analog input) +// public enum IoSetting { +// DISABLED (new int[] {0x0}), +// ANALOG_INPUT (new int[] {0x2}), +// DIGITAL_INPUT (new int[] {0x3}), +// DIGITAL_OUTPUT_LOW (new int[] {0x4}), +// DIGITAL_OUTPUT_HIGH (new int[] {0x5}); +// +// private final int[] value; +// +// IoSetting(int[] value) { +// this.value = value; +// } +// } + + public AtCommand(String command) { + this(command, null, DEFAULT_FRAME_ID); + } + + public AtCommand(String command, int value) { + this(command, new int[] {value}, DEFAULT_FRAME_ID); + } + + public AtCommand(String command, int value[]) { + this(command, value, DEFAULT_FRAME_ID); + } + + /** + * Warning: frameId must be > 0 for a response + * + * @param command + * @param value + * @param frameId + */ + public AtCommand(String command, int[] value, int frameId) { + this.command = command; + this.value = value; + this.setFrameId(frameId); + } + + public int[] getFrameData() { + if (command.length() > 2) { + throw new IllegalArgumentException("Command should be two characters. Do not include AT prefix"); + } + + IntArrayOutputStream out = new IntArrayOutputStream(); + + // api id + out.write(this.getApiId().getValue()); + // frame id + out.write(this.getFrameId()); + // at command byte 1 + out.write((int) command.substring(0, 1).toCharArray()[0]); + // at command byte 2 + out.write((int) command.substring(1, 2).toCharArray()[0]); + + // int value is up to four bytes to represent command value + if (value != null) { + out.write(value); + } + + return out.getIntArray(); + } + + public ApiId getApiId() { + return ApiId.AT_COMMAND; + } + + public String getCommand() { + return command; + } + + public void setCommand(String command) { + this.command = command; + } + + public int[] getValue() { + return value; + } + + public void setValue(int[] value) { + this.value = value; + } + + public String toString() { + return super.toString() + + ",command=" + this.command + + ",value=" + (value == null ? "null" : ByteUtils.toBase16(value)); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/AtCommandQueue.java b/src/main/java/com/rapplogic/xbee/api/requests/AtCommandQueue.java similarity index 88% rename from src/com/rapplogic/xbee/api/AtCommandQueue.java rename to src/main/java/com/rapplogic/xbee/api/requests/AtCommandQueue.java index f2c81b0..6882ddf 100644 --- a/src/com/rapplogic/xbee/api/AtCommandQueue.java +++ b/src/main/java/com/rapplogic/xbee/api/requests/AtCommandQueue.java @@ -1,43 +1,48 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -/** - * AT Command Queue - *

- * API ID: 0x9 - *

- * @author andrew - * - */ -public class AtCommandQueue extends AtCommand { - //TODO test - public AtCommandQueue(String command) { - this(command, null, DEFAULT_FRAME_ID); - } - - public AtCommandQueue(String command, int[] value, int frameId) { - super(command, value, frameId); - } - - public ApiId getApiId() { - return ApiId.AT_COMMAND_QUEUE; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.requests; + +import com.rapplogic.xbee.api.ApiId; + +/** + * AT Command Queue + *

+ * API ID: 0x9 + *

+ * @author andrew + * + */ +public class AtCommandQueue extends AtCommand { + + private static final long serialVersionUID = 8000847616413855924L; + + //TODO test + public AtCommandQueue(String command) { + this(command, null, DEFAULT_FRAME_ID); + } + + public AtCommandQueue(String command, int[] value, int frameId) { + super(command, value, frameId); + } + + public ApiId getApiId() { + return ApiId.AT_COMMAND_QUEUE; + } +} diff --git a/src/com/rapplogic/xbee/api/RemoteAtRequest.java b/src/main/java/com/rapplogic/xbee/api/requests/RemoteAtRequest.java similarity index 96% rename from src/com/rapplogic/xbee/api/RemoteAtRequest.java rename to src/main/java/com/rapplogic/xbee/api/requests/RemoteAtRequest.java index 9a05393..ce62539 100644 --- a/src/com/rapplogic/xbee/api/RemoteAtRequest.java +++ b/src/main/java/com/rapplogic/xbee/api/requests/RemoteAtRequest.java @@ -17,8 +17,12 @@ * along with XBee-API. If not, see . */ -package com.rapplogic.xbee.api; +package com.rapplogic.xbee.api.requests; +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeRequest; import com.rapplogic.xbee.util.IntArrayOutputStream; /** @@ -35,6 +39,8 @@ * */ public class RemoteAtRequest extends AtCommand { + + private static final long serialVersionUID = 916569156209610858L; private XBeeAddress64 remoteAddr64; private XBeeAddress16 remoteAddr16; diff --git a/src/com/rapplogic/xbee/api/AtCommandResponse.java b/src/main/java/com/rapplogic/xbee/api/responses/AtCommandResponse.java similarity index 94% rename from src/com/rapplogic/xbee/api/AtCommandResponse.java rename to src/main/java/com/rapplogic/xbee/api/responses/AtCommandResponse.java index dab1b1a..7d357fe 100644 --- a/src/com/rapplogic/xbee/api/AtCommandResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/responses/AtCommandResponse.java @@ -1,153 +1,156 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.io.IOException; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Sent in response to an AtCommand - *

- * API ID: 0x88 - *

- * @author andrew - * - */ -public class AtCommandResponse extends XBeeFrameIdResponse { - - public enum Status { -// 0 = OK -// 1 = ERROR -// 2 = Invalid Command -// 3 = Invalid Parameter -// 4 = Remote Command Transmission Failed - - OK (0), - ERROR (1), - INVALID_COMMAND (2), - INVALID_PARAMETER (3), - NO_RESPONSE (4); // series 1 remote AT only according to spec. also series 2 in 2x64 zb pro firmware - - private static final Map lookup = new HashMap(); - - static { - for(Status s : EnumSet.allOf(Status.class)) { - lookup.put(s.getValue(), s); - } - } - - public static Status get(int value) { - return lookup.get(value); - } - - private final int value; - - Status(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - private int char1; - private int char2; - private Status status; - // response value msb to lsb - private int[] value; - - public AtCommandResponse() { - - } - - public int getChar1() { - return char1; - } - - - public void setChar1(int char1) { - this.char1 = char1; - } - - - public int getChar2() { - return char2; - } - - - public void setChar2(int char2) { - this.char2 = char2; - } - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - public boolean isOk() { - return status == Status.OK; - } - - // TODO should return null if not specified - /** - * Returns the command data byte array. - * A zero length array will be returned if the command data is not specified. - * This is the case if the at command set a value, or executed a command that does - * not have a value (like FR) - * - * @return - */ - public int[] getValue() { - return value; - } - - public void setValue(int[] data) { - this.value = data; - } - - public String getCommand() { - return String.valueOf((char)this.char1) + String.valueOf((char)this.char2); - } - - public void parse(IPacketParser parser) throws IOException { - this.setFrameId(parser.read("AT Response Frame Id")); - this.setChar1(parser.read("AT Response Char 1")); - this.setChar2(parser.read("AT Response Char 2")); - this.setStatus(Status.get(parser.read("AT Response Status"))); - - this.setValue(parser.readRemainingBytes()); - } - - public String toString() { - return "command=" + this.getCommand() + - ",status=" + this.getStatus() + ",value=" + - (this.value == null ? "null" : ByteUtils.toBase16(this.getValue())) + - "," + - super.toString(); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.responses; + +import java.io.IOException; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Sent in response to an AtCommand + *

+ * API ID: 0x88 + *

+ * @author andrew + * + */ +public class AtCommandResponse extends XBeeFrameIdResponse { + + private static final long serialVersionUID = 3989959825185846517L; + + public enum Status { +// 0 = OK +// 1 = ERROR +// 2 = Invalid Command +// 3 = Invalid Parameter +// 4 = Remote Command Transmission Failed + + OK (0), + ERROR (1), + INVALID_COMMAND (2), + INVALID_PARAMETER (3), + NO_RESPONSE (4); // series 1 remote AT only according to spec. also series 2 in 2x64 zb pro firmware + + private static final Map lookup = new HashMap(); + + static { + for(Status s : EnumSet.allOf(Status.class)) { + lookup.put(s.getValue(), s); + } + } + + public static Status get(int value) { + return lookup.get(value); + } + + private final int value; + + Status(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + private int char1; + private int char2; + private Status status; + // response value msb to lsb + private int[] value; + + public AtCommandResponse() { + + } + + public int getChar1() { + return char1; + } + + + public void setChar1(int char1) { + this.char1 = char1; + } + + + public int getChar2() { + return char2; + } + + + public void setChar2(int char2) { + this.char2 = char2; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public boolean isOk() { + return status == Status.OK; + } + + // TODO should return null if not specified + /** + * Returns the command data byte array. + * A zero length array will be returned if the command data is not specified. + * This is the case if the at command set a value, or executed a command that does + * not have a value (like FR) + * + * @return + */ + public int[] getValue() { + return value; + } + + public void setValue(int[] data) { + this.value = data; + } + + public String getCommand() { + return String.valueOf((char)this.char1) + String.valueOf((char)this.char2); + } + + public void parse(IPacketParser parser) throws IOException { + this.setFrameId(parser.read("AT Response Frame Id")); + this.setChar1(parser.read("AT Response Char 1")); + this.setChar2(parser.read("AT Response Char 2")); + this.setStatus(Status.get(parser.read("AT Response Status"))); + + this.setValue(parser.readRemainingBytes()); + } + + public String toString() { + return "command=" + this.getCommand() + + ",status=" + this.getStatus() + ",value=" + + (this.value == null ? "null" : ByteUtils.toBase16(this.getValue())) + + "," + + super.toString(); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/ErrorResponse.java b/src/main/java/com/rapplogic/xbee/api/responses/ErrorResponse.java similarity index 87% rename from src/com/rapplogic/xbee/api/ErrorResponse.java rename to src/main/java/com/rapplogic/xbee/api/responses/ErrorResponse.java index c36fd8d..ef38514 100644 --- a/src/com/rapplogic/xbee/api/ErrorResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/responses/ErrorResponse.java @@ -1,69 +1,75 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -/** - * Represents a Java error during packet parsing. - * This is the only class that extends XBeeResponse and does not map - * to a XBee API ID - *

- * @author andrew - * - */ -public class ErrorResponse extends XBeeResponse { - - private String errorMsg; - private Exception exception; - - public ErrorResponse() { - super(); - this.setApiId(ApiId.ERROR_RESPONSE); - this.setError(true); - } - - /** - * A bit redundant in that it is the same as getException.getMessage() - * - * @return - */ - public String getErrorMsg() { - return errorMsg; - } - - public void setErrorMsg(String errorMsg) { - this.errorMsg = errorMsg; - } - - public Exception getException() { - return exception; - } - - public void setException(Exception exception) { - this.exception = exception; - } - - public void parse(IPacketParser parser) { - // nothing to do - } - - public String toString() { - return super.toString() + ",errorMsg=" + this.errorMsg + ",exception=" + this.exception; - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.responses; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeResponse; + +/** + * Represents a Java error during packet parsing. + * This is the only class that extends XBeeResponse and does not map + * to a XBee API ID + *

+ * @author andrew + * + */ +public class ErrorResponse extends XBeeResponse { + + private static final long serialVersionUID = 8103651351769538022L; + + private String errorMsg; + private Exception exception; + + public ErrorResponse() { + super(); + this.setApiId(ApiId.ERROR_RESPONSE); + this.setError(true); + } + + /** + * A bit redundant in that it is the same as getException.getMessage() + * + * @return + */ + public String getErrorMsg() { + return errorMsg; + } + + public void setErrorMsg(String errorMsg) { + this.errorMsg = errorMsg; + } + + public Exception getException() { + return exception; + } + + public void setException(Exception exception) { + this.exception = exception; + } + + public void parse(IPacketParser parser) { + // nothing to do + } + + public String toString() { + return super.toString() + ",errorMsg=" + this.errorMsg + ",exception=" + this.exception; + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/GenericResponse.java b/src/main/java/com/rapplogic/xbee/api/responses/GenericResponse.java similarity index 87% rename from src/com/rapplogic/xbee/api/GenericResponse.java rename to src/main/java/com/rapplogic/xbee/api/responses/GenericResponse.java index c04cc37..33b8201 100644 --- a/src/com/rapplogic/xbee/api/GenericResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/responses/GenericResponse.java @@ -1,52 +1,57 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.io.IOException; - -/** - * Container for unknown response - *

- * @author andrew - * - */ -public class GenericResponse extends XBeeResponse { - - private int genericApiId; - - public GenericResponse() { - - } - - public int getGenericApiId() { - return genericApiId; - } - - public void setGenericApiId(int genericApiId) { - this.genericApiId = genericApiId; - } - - public void parse(IPacketParser parser) throws IOException { - //eat packet bytes -- they will be save to bytearray and stored in response - parser.readRemainingBytes(); - // TODO gotta save it because it isn't know to the enum apiId won't - this.setGenericApiId(parser.getIntApiId()); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.responses; + +import java.io.IOException; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeResponse; + +/** + * Container for unknown response + *

+ * @author andrew + * + */ +public class GenericResponse extends XBeeResponse { + + private static final long serialVersionUID = -4460804659208803948L; + + private int genericApiId; + + public GenericResponse() { + + } + + public int getGenericApiId() { + return genericApiId; + } + + public void setGenericApiId(int genericApiId) { + this.genericApiId = genericApiId; + } + + public void parse(IPacketParser parser) throws IOException { + //eat packet bytes -- they will be save to bytearray and stored in response + parser.readRemainingBytes(); + // TODO gotta save it because it isn't know to the enum apiId won't + this.setGenericApiId(parser.getIntApiId()); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/ModemStatusResponse.java b/src/main/java/com/rapplogic/xbee/api/responses/ModemStatusResponse.java similarity index 92% rename from src/com/rapplogic/xbee/api/ModemStatusResponse.java rename to src/main/java/com/rapplogic/xbee/api/responses/ModemStatusResponse.java index f885d8b..ec68116 100644 --- a/src/com/rapplogic/xbee/api/ModemStatusResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/responses/ModemStatusResponse.java @@ -1,113 +1,118 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import java.io.IOException; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -/** - * RF module status messages are sent from the module in response to specific conditions. - *

- * API ID: 0x8a - *

- * @author andrew - * - */ -public class ModemStatusResponse extends XBeeResponse implements NoRequestResponse { - - private final static Logger log = Logger.getLogger(ModemStatusResponse.class); - - public enum Status { - HARDWARE_RESET (0), - WATCHDOG_TIMER_RESET (1), - ASSOCIATED (2), - DISASSOCIATED (3), - SYNCHRONIZATION_LOST (4), - COORDINATOR_REALIGNMENT (5), - COORDINATOR_STARTED (6), - NETWORK_SEC_KEY_UPDATED (7), - VOLTAGE_SUPPLY_EXCEEDED (0x0D), - MODEM_CONFIG_CHANGED (0x11), - STACK_ERROR (0x80), - UNKNOWN(-1); - - - private static final Map lookup = new HashMap(); - - static { - for(Status s : EnumSet.allOf(Status.class)) { - lookup.put(s.getValue(), s); - } - } - - public static Status get(int value) { - return lookup.get(value); - } - - private final int value; - - Status(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - private Status status; - - public ModemStatusResponse() { - - } - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - protected void parse(IPacketParser parser) throws IOException { - int value = parser.read("Modem Status"); - - if (value >= 0x80) { - this.setStatus(ModemStatusResponse.Status.STACK_ERROR); - } else { - ModemStatusResponse.Status status = ModemStatusResponse.Status.get(value); - - if (status == null) { - log.warn("Unknown status " + value); - this.setStatus(ModemStatusResponse.Status.UNKNOWN); - } else { - this.setStatus(status); - } - } - } - - public String toString() { - return super.toString() + ",status=" + this.status; - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.responses; + +import java.io.IOException; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeResponse; + +/** + * RF module status messages are sent from the module in response to specific conditions. + *

+ * API ID: 0x8a + *

+ * @author andrew + * + */ +public class ModemStatusResponse extends XBeeResponse implements NoRequestResponse { + + private static final long serialVersionUID = 1410454529315058759L; + + private final static Logger log = Logger.getLogger(ModemStatusResponse.class); + + public enum Status { + HARDWARE_RESET (0), + WATCHDOG_TIMER_RESET (1), + ASSOCIATED (2), + DISASSOCIATED (3), + SYNCHRONIZATION_LOST (4), + COORDINATOR_REALIGNMENT (5), + COORDINATOR_STARTED (6), + NETWORK_SEC_KEY_UPDATED (7), + VOLTAGE_SUPPLY_EXCEEDED (0x0D), + MODEM_CONFIG_CHANGED (0x11), + STACK_ERROR (0x80), + UNKNOWN(-1); + + + private static final Map lookup = new HashMap(); + + static { + for(Status s : EnumSet.allOf(Status.class)) { + lookup.put(s.getValue(), s); + } + } + + public static Status get(int value) { + return lookup.get(value); + } + + private final int value; + + Status(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + private Status status; + + public ModemStatusResponse() { + + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + protected void parse(IPacketParser parser) throws IOException { + int value = parser.read("Modem Status"); + + if (value >= 0x80) { + this.setStatus(ModemStatusResponse.Status.STACK_ERROR); + } else { + ModemStatusResponse.Status status = ModemStatusResponse.Status.get(value); + + if (status == null) { + log.warn("Unknown status " + value); + this.setStatus(ModemStatusResponse.Status.UNKNOWN); + } else { + this.setStatus(status); + } + } + } + + public String toString() { + return super.toString() + ",status=" + this.status; + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/NoRequestResponse.java b/src/main/java/com/rapplogic/xbee/api/responses/NoRequestResponse.java similarity index 84% rename from src/com/rapplogic/xbee/api/NoRequestResponse.java rename to src/main/java/com/rapplogic/xbee/api/responses/NoRequestResponse.java index aea7004..21486ae 100644 --- a/src/com/rapplogic/xbee/api/NoRequestResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/responses/NoRequestResponse.java @@ -1,4 +1,4 @@ -package com.rapplogic.xbee.api; +package com.rapplogic.xbee.api.responses; /** * This filter is used to capture only RX packets that are not a response to a TX packet. diff --git a/src/com/rapplogic/xbee/api/RemoteAtResponse.java b/src/main/java/com/rapplogic/xbee/api/responses/RemoteAtResponse.java similarity index 94% rename from src/com/rapplogic/xbee/api/RemoteAtResponse.java rename to src/main/java/com/rapplogic/xbee/api/responses/RemoteAtResponse.java index 8421311..6b9fade 100644 --- a/src/com/rapplogic/xbee/api/RemoteAtResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/responses/RemoteAtResponse.java @@ -17,10 +17,14 @@ * along with XBee-API. If not, see . */ -package com.rapplogic.xbee.api; +package com.rapplogic.xbee.api.responses; import java.io.IOException; +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; + //TODO Now supported by series 1 XBee. parseIoSample now needs to handle series 1 and 2 diff --git a/src/com/rapplogic/xbee/api/XBeeFrameIdResponse.java b/src/main/java/com/rapplogic/xbee/api/responses/XBeeFrameIdResponse.java similarity index 88% rename from src/com/rapplogic/xbee/api/XBeeFrameIdResponse.java rename to src/main/java/com/rapplogic/xbee/api/responses/XBeeFrameIdResponse.java index 4a30b03..48ec3e4 100644 --- a/src/com/rapplogic/xbee/api/XBeeFrameIdResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/responses/XBeeFrameIdResponse.java @@ -1,45 +1,48 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api; - -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Represents all XBee responses that contain a frame id - *

- * @author andrew - * - */ -public abstract class XBeeFrameIdResponse extends XBeeResponse { - - private int frameId; - - public int getFrameId() { - return frameId; - } - - public void setFrameId(int frameId) { - this.frameId = frameId; - } - - public String toString() { - return super.toString() + ",frameId=" + ByteUtils.toBase16(this.frameId); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.responses; + +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Represents all XBee responses that contain a frame id + *

+ * @author andrew + * + */ +public abstract class XBeeFrameIdResponse extends XBeeResponse { + + private static final long serialVersionUID = -1719082648663672811L; + + private int frameId; + + public int getFrameId() { + return frameId; + } + + public void setFrameId(int frameId) { + this.frameId = frameId; + } + + public String toString() { + return super.toString() + ",frameId=" + ByteUtils.toBase16(this.frameId); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/wpan/IoSample.java b/src/main/java/com/rapplogic/xbee/api/wpan/IoSample.java similarity index 96% rename from src/com/rapplogic/xbee/api/wpan/IoSample.java rename to src/main/java/com/rapplogic/xbee/api/wpan/IoSample.java index 337f8e5..3ebfe01 100644 --- a/src/com/rapplogic/xbee/api/wpan/IoSample.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/IoSample.java @@ -1,288 +1,288 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Series 1 XBee. Represents an I/O Sample, sent from a remote radio. - * Each I/O packet (RxResponseIoSample) may contain one for more IoSample instances. - *

- * This class is accessed from the getSamples() method of RxResponseIoSample, which - * returns an array of IoSample objects. - *

- * Provides access to XBee's 8 Digital (0-7) and 6 Analog (0-5) IO pins - *

- * @author andrew - * - */ -public class IoSample { - - private RxResponseIoSample parent; - - private Integer dioMsb; - private Integer dioLsb; - private Integer[] analog = new Integer[6]; - - public IoSample(RxResponseIoSample parent) { - this.parent = parent; - } - - public void setDioMsb(Integer dioMsb) { - this.dioMsb = dioMsb; - } - - public void setDioLsb(Integer dioLsb) { - this.dioLsb = dioLsb; - } - - public Integer getDioMsb() { - return dioMsb; - } - - public Integer getDioLsb() { - return dioLsb; - } - - /** - * Returns the 10-bit analog value of the specified pin. - * Returns null if pin is not configured for Analog input. - * - * @return - */ - public Integer getAnalog(int pin) { - if (parent.isAnalogEnabled(pin)) { - return analog[pin]; - } - - return null; - } - - public Integer getAnalog0() { - return this.getAnalog(0); - } - - public void setAnalog0(Integer analog0) { - analog[0] = analog0; - } - - /** - * Returns the 10-bit analog value of pin 19 (D1), when this pin configured for Analog Input (D1=2) - * Returns null if pin 19 is not configured for Analog input. - * - * @return - */ - public Integer getAnalog1() { - return this.getAnalog(1); - } - - public void setAnalog1(Integer analog1) { - analog[1] = analog1; - } - - /** - * Returns the 10-bit analog value of pin 18 (D2), when this pin configured for Analog Input (D2=2) - * Returns null if pin 18 is not configured for Analog input. - * - * @return - */ - public Integer getAnalog2() { - return this.getAnalog(2); - } - - public void setAnalog2(Integer analog2) { - analog[2] = analog2; - } - - /** - * Returns the 10-bit analog value of pin 17 (D3), when this pin configured for Analog Input (D3=2) - * Returns null if pin 17 is not configured for Analog input. - * - * @return - */ - public Integer getAnalog3() { - return this.getAnalog(3); - } - - public void setAnalog3(Integer analog3) { - analog[3] = analog3; - } - - /** - * Returns the 10-bit analog value of pin 11 (D4), when this pin configured for Analog Input (D4=2) - * Returns null if pin 11 is not configured for Analog input. - * - * @return - */ - public Integer getAnalog4() { - return this.getAnalog(4); - } - - public void setAnalog4(Integer analog4) { - analog[4] = analog4; - } - - /** - * Returns the 10-bit analog value of pin 15 (D5), when this pin configured for Analog Input (D5=2) - * Returns null if pin 15 is not configured for Analog input. - * - * @return - */ - public Integer getAnalog5() { - return this.getAnalog(5); - } - - public void setAnalog5(Integer analog5) { - analog[5] = analog5; - } - - /** - * Returns the digital value of the specified pin. - * Returns null if pin is not configured for Digital input - * - * @return - */ - public Boolean isDigitalOn(int pin) { - - if (!parent.isDigitalEnabled(pin)) { - return null; - } - - if (pin >= 0 && pin <= 7) { - return ByteUtils.getBit(dioLsb, pin + 1); - } else { - // pin 8 - return ByteUtils.getBit(dioMsb, 1); - } - } - - /** - * Returns the digital value of pin 20 (D0) when this pin is configured for Digital input (D0=3) - * Returns null if pin 20 is not configured for Digital input - * - * @return - */ - public Boolean isD0On() { - return this.isDigitalOn(0); - } - - /** - * Returns the digital value of pin 19 (D1) when this pin is configured for Digital input (D1=3) - * Returns null if pin 19 is not configured for Digital input - * - * @return - */ - public Boolean isD1On() { - return this.isDigitalOn(1); - } - - /** - * Returns the digital value of pin 18 (D2) when this pin is configured for Digital input (D2=3) - * Returns null if pin 18 is not configured for Digital input - * - * @return - */ - public Boolean isD2On() { - return this.isDigitalOn(2); - } - - /** - * Returns the digital value of pin 17 (D3) when this pin is configured for Digital input (D3=3) - * Returns null if pin 17 is not configured for Digital input - * - * @return - */ - public Boolean isD3On() { - return this.isDigitalOn(3); } - - /** - * Returns the digital value of pin 11 (D4) when this pin is configured for Digital input (D4=3) - * Returns null if pin 11 is not configured for Digital input - * - * @return - */ - public Boolean isD4On() { - return this.isDigitalOn(4); - } - - /** - * Returns the digital value of pin 15 (D5) when this pin is configured for Digital input (D5=3) - * Returns null if pin 15 is not configured for Digital input - * - * @return - */ - public Boolean isD5On() { - return this.isDigitalOn(5); - } - - /** - * Returns the digital value of pin 16 (D6) when this pin is configured for Digital input (D6=3) - * Returns null if pin 16 is not configured for Digital input - * - * @return - */ - public Boolean isD6On() { - return this.isDigitalOn(6); - } - - /** - * Returns the digital value of pin 12 (D7) when this pin is configured for Digital input (D7=3) - * Returns null if pin 12 is not configured for Digital input - * - * @return - */ - public Boolean isD7On() { - return this.isDigitalOn(7); - } - - /** - * Returns the digital value of pin 9 (D8) when this pin is configured for Digital input (D8=3) - * Returns null if pin 9 is not configured for Digital input - * - * @return - */ - public Boolean isD8On() { - return this.isDigitalOn(8); - } - - - public String toString() { - StringBuilder builder = new StringBuilder(); - // TODO only prefix with comma if not first entry written. Use reflection - - if (parent.containsDigital()) { - for (int i = 0; i <= 8; i++) { - if (parent.isDigitalEnabled(i)) { - builder.append(",digital[" + i + "]=" + (this.isDigitalOn(i) ? "high" : "low")); - } - } - } - - if (parent.containsAnalog()) { - for (int i = 0; i <= 5; i++) { - if (parent.isAnalogEnabled(i)) { - builder.append(",analog[" + i + "]=" + this.getAnalog(i)); - } - } - } - - return builder.toString(); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Series 1 XBee. Represents an I/O Sample, sent from a remote radio. + * Each I/O packet (RxResponseIoSample) may contain one for more IoSample instances. + *

+ * This class is accessed from the getSamples() method of RxResponseIoSample, which + * returns an array of IoSample objects. + *

+ * Provides access to XBee's 8 Digital (0-7) and 6 Analog (0-5) IO pins + *

+ * @author andrew + * + */ +public class IoSample { + + private RxResponseIoSample parent; + + private Integer dioMsb; + private Integer dioLsb; + private Integer[] analog = new Integer[6]; + + public IoSample(RxResponseIoSample parent) { + this.parent = parent; + } + + public void setDioMsb(Integer dioMsb) { + this.dioMsb = dioMsb; + } + + public void setDioLsb(Integer dioLsb) { + this.dioLsb = dioLsb; + } + + public Integer getDioMsb() { + return dioMsb; + } + + public Integer getDioLsb() { + return dioLsb; + } + + /** + * Returns the 10-bit analog value of the specified pin. + * Returns null if pin is not configured for Analog input. + * + * @return + */ + public Integer getAnalog(int pin) { + if (parent.isAnalogEnabled(pin)) { + return analog[pin]; + } + + return null; + } + + public Integer getAnalog0() { + return this.getAnalog(0); + } + + public void setAnalog0(Integer analog0) { + analog[0] = analog0; + } + + /** + * Returns the 10-bit analog value of pin 19 (D1), when this pin configured for Analog Input (D1=2) + * Returns null if pin 19 is not configured for Analog input. + * + * @return + */ + public Integer getAnalog1() { + return this.getAnalog(1); + } + + public void setAnalog1(Integer analog1) { + analog[1] = analog1; + } + + /** + * Returns the 10-bit analog value of pin 18 (D2), when this pin configured for Analog Input (D2=2) + * Returns null if pin 18 is not configured for Analog input. + * + * @return + */ + public Integer getAnalog2() { + return this.getAnalog(2); + } + + public void setAnalog2(Integer analog2) { + analog[2] = analog2; + } + + /** + * Returns the 10-bit analog value of pin 17 (D3), when this pin configured for Analog Input (D3=2) + * Returns null if pin 17 is not configured for Analog input. + * + * @return + */ + public Integer getAnalog3() { + return this.getAnalog(3); + } + + public void setAnalog3(Integer analog3) { + analog[3] = analog3; + } + + /** + * Returns the 10-bit analog value of pin 11 (D4), when this pin configured for Analog Input (D4=2) + * Returns null if pin 11 is not configured for Analog input. + * + * @return + */ + public Integer getAnalog4() { + return this.getAnalog(4); + } + + public void setAnalog4(Integer analog4) { + analog[4] = analog4; + } + + /** + * Returns the 10-bit analog value of pin 15 (D5), when this pin configured for Analog Input (D5=2) + * Returns null if pin 15 is not configured for Analog input. + * + * @return + */ + public Integer getAnalog5() { + return this.getAnalog(5); + } + + public void setAnalog5(Integer analog5) { + analog[5] = analog5; + } + + /** + * Returns the digital value of the specified pin. + * Returns null if pin is not configured for Digital input + * + * @return + */ + public Boolean isDigitalOn(int pin) { + + if (!parent.isDigitalEnabled(pin)) { + return null; + } + + if (pin >= 0 && pin <= 7) { + return ByteUtils.getBit(dioLsb, pin + 1); + } else { + // pin 8 + return ByteUtils.getBit(dioMsb, 1); + } + } + + /** + * Returns the digital value of pin 20 (D0) when this pin is configured for Digital input (D0=3) + * Returns null if pin 20 is not configured for Digital input + * + * @return + */ + public Boolean isD0On() { + return this.isDigitalOn(0); + } + + /** + * Returns the digital value of pin 19 (D1) when this pin is configured for Digital input (D1=3) + * Returns null if pin 19 is not configured for Digital input + * + * @return + */ + public Boolean isD1On() { + return this.isDigitalOn(1); + } + + /** + * Returns the digital value of pin 18 (D2) when this pin is configured for Digital input (D2=3) + * Returns null if pin 18 is not configured for Digital input + * + * @return + */ + public Boolean isD2On() { + return this.isDigitalOn(2); + } + + /** + * Returns the digital value of pin 17 (D3) when this pin is configured for Digital input (D3=3) + * Returns null if pin 17 is not configured for Digital input + * + * @return + */ + public Boolean isD3On() { + return this.isDigitalOn(3); } + + /** + * Returns the digital value of pin 11 (D4) when this pin is configured for Digital input (D4=3) + * Returns null if pin 11 is not configured for Digital input + * + * @return + */ + public Boolean isD4On() { + return this.isDigitalOn(4); + } + + /** + * Returns the digital value of pin 15 (D5) when this pin is configured for Digital input (D5=3) + * Returns null if pin 15 is not configured for Digital input + * + * @return + */ + public Boolean isD5On() { + return this.isDigitalOn(5); + } + + /** + * Returns the digital value of pin 16 (D6) when this pin is configured for Digital input (D6=3) + * Returns null if pin 16 is not configured for Digital input + * + * @return + */ + public Boolean isD6On() { + return this.isDigitalOn(6); + } + + /** + * Returns the digital value of pin 12 (D7) when this pin is configured for Digital input (D7=3) + * Returns null if pin 12 is not configured for Digital input + * + * @return + */ + public Boolean isD7On() { + return this.isDigitalOn(7); + } + + /** + * Returns the digital value of pin 9 (D8) when this pin is configured for Digital input (D8=3) + * Returns null if pin 9 is not configured for Digital input + * + * @return + */ + public Boolean isD8On() { + return this.isDigitalOn(8); + } + + + public String toString() { + StringBuilder builder = new StringBuilder(); + // TODO only prefix with comma if not first entry written. Use reflection + + if (parent.containsDigital()) { + for (int i = 0; i <= 8; i++) { + if (parent.isDigitalEnabled(i)) { + builder.append(",digital[" + i + "]=" + (this.isDigitalOn(i) ? "high" : "low")); + } + } + } + + if (parent.containsAnalog()) { + for (int i = 0; i <= 5; i++) { + if (parent.isAnalogEnabled(i)) { + builder.append(",analog[" + i + "]=" + this.getAnalog(i)); + } + } + } + + return builder.toString(); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/wpan/RxBaseResponse.java b/src/main/java/com/rapplogic/xbee/api/wpan/RxBaseResponse.java similarity index 94% rename from src/com/rapplogic/xbee/api/wpan/RxBaseResponse.java rename to src/main/java/com/rapplogic/xbee/api/wpan/RxBaseResponse.java index 1a20d8e..0706943 100644 --- a/src/com/rapplogic/xbee/api/wpan/RxBaseResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/RxBaseResponse.java @@ -1,100 +1,101 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import java.io.IOException; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.XBeeAddress; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.IIntInputStream; - -/** - * Series 1 XBee. Common elements of 16 and 64 bit Address Receive packets - *

- * @author andrew - * - */ -public abstract class RxBaseResponse extends XBeeResponse { - - private XBeeAddress sourceAddress; - - private int rssi; - private int options; - - public RxBaseResponse() { - - } - - public int getRssi() { - return rssi; - } - - public void setRssi(int rssi) { - this.rssi = rssi; - } - - public int getOptions() { - return options; - } - - public void setOptions(int options) { - this.options = options; - } - - public boolean isAddressBroadcast() { - return ByteUtils.getBit(options, 2); - } - - public boolean isPanBroadcast() { - return ByteUtils.getBit(options, 3); - } - - /** - * Returns either a XBeeAddress16 or XBeeAddress64 - * depending on if the packet is configured for 16 or 64 bit addressing. - * - * @return - */ - public XBeeAddress getSourceAddress() { - return sourceAddress; - } - - public void setSourceAddress(XBeeAddress sourceAddress) { - this.sourceAddress = sourceAddress; - } - - protected void parseBase(IPacketParser parser) throws IOException { - int rssi = parser.read("RSSI"); - - // rssi is a negative dbm value - this.setRssi(-rssi); - - int options = parser.read("Options"); - - this.setOptions(options); - } - - public String toString() { - return super.toString() + ",sourceAddress=" + this.getSourceAddress() + ",rssi=" + this.getRssi() + ",options=" + this.getOptions() + - ",isAddressBroadcast=" + this.isAddressBroadcast() + ",isPanBroadcast=" + this.isPanBroadcast(); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import java.io.IOException; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeAddress; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Series 1 XBee. Common elements of 16 and 64 bit Address Receive packets + *

+ * @author andrew + * + */ +public abstract class RxBaseResponse extends XBeeResponse { + + private static final long serialVersionUID = 4610077108257181555L; + + private XBeeAddress sourceAddress; + + private int rssi; + private int options; + + public RxBaseResponse() { + + } + + public int getRssi() { + return rssi; + } + + public void setRssi(int rssi) { + this.rssi = rssi; + } + + public int getOptions() { + return options; + } + + public void setOptions(int options) { + this.options = options; + } + + public boolean isAddressBroadcast() { + return ByteUtils.getBit(options, 2); + } + + public boolean isPanBroadcast() { + return ByteUtils.getBit(options, 3); + } + + /** + * Returns either a XBeeAddress16 or XBeeAddress64 + * depending on if the packet is configured for 16 or 64 bit addressing. + * + * @return + */ + public XBeeAddress getSourceAddress() { + return sourceAddress; + } + + public void setSourceAddress(XBeeAddress sourceAddress) { + this.sourceAddress = sourceAddress; + } + + protected void parseBase(IPacketParser parser) throws IOException { + int rssi = parser.read("RSSI"); + + // rssi is a negative dbm value + this.setRssi(-rssi); + + int options = parser.read("Options"); + + this.setOptions(options); + } + + public String toString() { + return super.toString() + ",sourceAddress=" + this.getSourceAddress() + ",rssi=" + this.getRssi() + ",options=" + this.getOptions() + + ",isAddressBroadcast=" + this.isAddressBroadcast() + ",isPanBroadcast=" + this.isPanBroadcast(); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/wpan/RxResponse.java b/src/main/java/com/rapplogic/xbee/api/wpan/RxResponse.java similarity index 95% rename from src/com/rapplogic/xbee/api/wpan/RxResponse.java rename to src/main/java/com/rapplogic/xbee/api/wpan/RxResponse.java index f045c6f..0f67d15 100644 --- a/src/com/rapplogic/xbee/api/wpan/RxResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/RxResponse.java @@ -1,60 +1,62 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import java.io.IOException; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.util.ByteUtils; - -public class RxResponse extends RxBaseResponse { - - private int[] data; - - public RxResponse() { - - } - - public int[] getData() { - return data; - } - - public void setData(int[] data) { - this.data = data; - } - - public void parse(IPacketParser parser) throws IOException { - int[] payload = new int[parser.getLength().getLength() - parser.getFrameDataBytesRead()]; - - int bytesRead = parser.getFrameDataBytesRead(); - - for (int i = 0; i < parser.getLength().getLength() - bytesRead; i++) { - payload[i] = parser.read("Payload byte " + i); - //log.debug("rx data payload [" + i + "] " + payload[i]); - } - - this.setData(payload); - } - - public String toString() { - return super.toString() + - ",data=" + ByteUtils.toBase16(this.data); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import java.io.IOException; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.util.ByteUtils; + +public class RxResponse extends RxBaseResponse { + + private static final long serialVersionUID = -221176512562200634L; + + private int[] data; + + public RxResponse() { + + } + + public int[] getData() { + return data; + } + + public void setData(int[] data) { + this.data = data; + } + + public void parse(IPacketParser parser) throws IOException { + int[] payload = new int[parser.getLength().getLength() - parser.getFrameDataBytesRead()]; + + int bytesRead = parser.getFrameDataBytesRead(); + + for (int i = 0; i < parser.getLength().getLength() - bytesRead; i++) { + payload[i] = parser.read("Payload byte " + i); + //log.debug("rx data payload [" + i + "] " + payload[i]); + } + + this.setData(payload); + } + + public String toString() { + return super.toString() + + ",data=" + ByteUtils.toBase16(this.data); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/wpan/RxResponse16.java b/src/main/java/com/rapplogic/xbee/api/wpan/RxResponse16.java similarity index 91% rename from src/com/rapplogic/xbee/api/wpan/RxResponse16.java rename to src/main/java/com/rapplogic/xbee/api/wpan/RxResponse16.java index b8f6c3a..79bc04c 100644 --- a/src/com/rapplogic/xbee/api/wpan/RxResponse16.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/RxResponse16.java @@ -1,50 +1,51 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import java.io.IOException; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.NoRequestResponse; -import com.rapplogic.xbee.api.XBeeAddress16; - -/** - * Series 1 XBee. 16-bit address Receive packet. - * This packet is received when a remote radio transmits a TxRequest16 - * packet to this radio's MY address - *

- * API ID: 0x81 - * - * @author andrew - * - */ -public class RxResponse16 extends RxResponse implements NoRequestResponse { - - public XBeeAddress16 getRemoteAddress() { - return (XBeeAddress16) this.getSourceAddress(); - } - - public void parse(IPacketParser parser) throws IOException { - this.setSourceAddress(parser.parseAddress16()); - super.parseBase(parser); - super.parse(parser); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import java.io.IOException; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.responses.NoRequestResponse; + +/** + * Series 1 XBee. 16-bit address Receive packet. + * This packet is received when a remote radio transmits a TxRequest16 + * packet to this radio's MY address + *

+ * API ID: 0x81 + * + * @author andrew + * + */ +public class RxResponse16 extends RxResponse implements NoRequestResponse { + + private static final long serialVersionUID = 5083877725752608901L; + + public XBeeAddress16 getRemoteAddress() { + return (XBeeAddress16) this.getSourceAddress(); + } + + public void parse(IPacketParser parser) throws IOException { + this.setSourceAddress(parser.parseAddress16()); + super.parseBase(parser); + super.parse(parser); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/wpan/RxResponse64.java b/src/main/java/com/rapplogic/xbee/api/wpan/RxResponse64.java similarity index 95% rename from src/com/rapplogic/xbee/api/wpan/RxResponse64.java rename to src/main/java/com/rapplogic/xbee/api/wpan/RxResponse64.java index cdfd581..b1f9c74 100644 --- a/src/com/rapplogic/xbee/api/wpan/RxResponse64.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/RxResponse64.java @@ -1,49 +1,51 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import java.io.IOException; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.XBeeAddress64; - -/** - * Series 1 XBee. 64-bit address Receive packet. - * This packet is received when a remote radio transmits a TxRequest64 - * packet to this radio's SH + SL address. - *

- * Note: MY address must be set to 0xffff to receive this packet type. - *

- * API ID: 0x80 - * - * @author andrew - */ -public class RxResponse64 extends RxResponse { - - public XBeeAddress64 getRemoteAddress() { - return (XBeeAddress64) this.getSourceAddress(); - } - - public void parse(IPacketParser parser) throws IOException { - this.setSourceAddress(parser.parseAddress64()); - super.parseBase(parser); - super.parse(parser); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import java.io.IOException; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeAddress64; + +/** + * Series 1 XBee. 64-bit address Receive packet. + * This packet is received when a remote radio transmits a TxRequest64 + * packet to this radio's SH + SL address. + *

+ * Note: MY address must be set to 0xffff to receive this packet type. + *

+ * API ID: 0x80 + * + * @author andrew + */ +public class RxResponse64 extends RxResponse { + + private static final long serialVersionUID = 5482472190377241887L; + + public XBeeAddress64 getRemoteAddress() { + return (XBeeAddress64) this.getSourceAddress(); + } + + public void parse(IPacketParser parser) throws IOException { + this.setSourceAddress(parser.parseAddress64()); + super.parseBase(parser); + super.parse(parser); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/wpan/RxResponseIoSample.java b/src/main/java/com/rapplogic/xbee/api/wpan/RxResponseIoSample.java similarity index 95% rename from src/com/rapplogic/xbee/api/wpan/RxResponseIoSample.java rename to src/main/java/com/rapplogic/xbee/api/wpan/RxResponseIoSample.java index 01d0f57..ccb3cfb 100644 --- a/src/com/rapplogic/xbee/api/wpan/RxResponseIoSample.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/RxResponseIoSample.java @@ -1,296 +1,298 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import java.io.IOException; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.NoRequestResponse; -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.IIntInputStream; - -/** - * Series 1 XBee. Represents an I/O sample - *

- * See http://code.google.com/p/xbee-api/wiki/XBeePins for information on configuring - * the XBee for digital/analog inputs. - *

- * API ID: 64-bit 0x82, 16-bit: 0x83 - *

- * @author andrew - * - */ -public class RxResponseIoSample extends RxBaseResponse implements NoRequestResponse { - - private final static Logger log = Logger.getLogger(RxResponseIoSample.class); - - public final static int ADC_CHANNEL1 = 0x7e; //01111110 - public final static int DIO_CHANNEL1 = 0x1; //00000001 - - private IoSample[] samples; - - private int channelIndicator1; - private int channelIndicator2; - - public RxResponseIoSample() { - - } - - public void parse(IPacketParser parser) throws IOException { - - if (parser.getApiId() == ApiId.RX_16_IO_RESPONSE) { - this.setSourceAddress(parser.parseAddress16()); - } else { - this.setSourceAddress(parser.parseAddress64()); - } - - super.parseBase(parser); - - log.debug("this is a I/O sample!"); - // first byte is # of samples - int sampleSize = parser.read("# I/O Samples"); - - // create i/o samples array - this.setSamples(new IoSample[sampleSize]); - - // channel indicator 1 - this.setChannelIndicator1(parser.read("Channel Indicator 1")); - - log.debug("channel indicator 1 is " + ByteUtils.formatByte(this.getChannelIndicator1())); - - // channel indicator 2 (dio) - this.setChannelIndicator2(parser.read("Channel Indicator 2")); - - log.debug("channel indicator 2 is " + ByteUtils.formatByte(this.getChannelIndicator2())); - - // collect each sample - for (int i = 0; i < this.getSamples().length; i++) { - - log.debug("parsing sample " + (i + 1)); - - IoSample sample = parseIoSample((IIntInputStream)parser); - - // attach sample to parent - this.getSamples()[i] = sample; - } - } - - private IoSample parseIoSample(IIntInputStream parser) throws IOException { - - IoSample sample = new IoSample(this); - - // DIO 8 occupies the first bit of the adcHeader - if (this.containsDigital()) { - // at least one DIO line is active - // next two bytes are DIO - - log.debug("Digital I/O was received"); - - sample.setDioMsb(parser.read("DIO MSB")); - sample.setDioLsb(parser.read("DIO LSB")); - } - - // ADC is active if any of bits 2-7 are on - if (this.containsAnalog()) { - // adc is active - // adc is 10 bits - - log.debug("Analog input was received"); - - // 10-bit values are read two bytes per sample - - int analog = 0; - - // Analog inputs A0-A5 are bits 2-7 of the adcHeader - - if (this.isA0Enabled()) { - sample.setAnalog0(ByteUtils.parse10BitAnalog(parser, analog)); - analog++; - } - - if (this.isA1Enabled()) { - sample.setAnalog1(ByteUtils.parse10BitAnalog(parser, analog)); - analog++; - } - - if (this.isA2Enabled()) { - sample.setAnalog2(ByteUtils.parse10BitAnalog(parser, analog)); - analog++; - } - - if (this.isA3Enabled()) { - sample.setAnalog3(ByteUtils.parse10BitAnalog(parser, analog)); - analog++; - } - - if (this.isA4Enabled()) { - sample.setAnalog4(ByteUtils.parse10BitAnalog(parser, analog)); - analog++; - } - - if (this.isA5Enabled()) { - sample.setAnalog5(ByteUtils.parse10BitAnalog(parser, analog)); - analog++; - } - - log.debug("There are " + analog + " analog inputs turned on"); - } - - return sample; - } - - public IoSample[] getSamples() { - return samples; - } - - public void setSamples(IoSample[] samples) { - this.samples = samples; - } - - public boolean isDigitalEnabled(int pin) { - if (pin >= 0 && pin <= 7) { - return ByteUtils.getBit(channelIndicator2, pin + 1); - } else if (pin == 8) { - return ByteUtils.getBit(channelIndicator1, 1); - } else { - throw new IllegalArgumentException("Unsupported pin: " + pin); - } - } - - public boolean isD0Enabled() { - return ByteUtils.getBit(channelIndicator2, 1); - } - - public boolean isD1Enabled() { - return ByteUtils.getBit(channelIndicator2, 2); - } - - public boolean isD2Enabled() { - return ByteUtils.getBit(channelIndicator2, 3); - } - - public boolean isD3Enabled() { - return ByteUtils.getBit(channelIndicator2, 4); - } - - public boolean isD4Enabled() { - return ByteUtils.getBit(channelIndicator2, 5); - } - - public boolean isD5Enabled() { - return ByteUtils.getBit(channelIndicator2, 6); - } - - public boolean isD6Enabled() { - return ByteUtils.getBit(channelIndicator2, 7); - } - - public boolean isD7Enabled() { - return ByteUtils.getBit(channelIndicator2, 8); - } - - public boolean isD8Enabled() { - return ByteUtils.getBit(channelIndicator1, 1); - } - - public boolean isAnalogEnabled(int pin) { - if (pin >= 0 && pin <= 5) { - return ByteUtils.getBit(channelIndicator1, pin + 2); - } else { - throw new IllegalArgumentException("Unsupported pin: " + pin); - } - } - - public boolean isA0Enabled() { - return ByteUtils.getBit(channelIndicator1, 2); - } - - public boolean isA1Enabled() { - return ByteUtils.getBit(channelIndicator1, 3); - } - - public boolean isA2Enabled() { - return ByteUtils.getBit(channelIndicator1, 4); - } - - public boolean isA3Enabled() { - return ByteUtils.getBit(channelIndicator1, 5); - } - - public boolean isA4Enabled() { - return ByteUtils.getBit(channelIndicator1, 6); - } - - public boolean isA5Enabled() { - return ByteUtils.getBit(channelIndicator1, 7); - } - - public int getChannelIndicator1() { - return channelIndicator1; - } - - public void setChannelIndicator1(int channelIndicator1) { - this.channelIndicator1 = channelIndicator1; - } - - public int getChannelIndicator2() { - return channelIndicator2; - } - - public void setChannelIndicator2(int channelIndicator2) { - this.channelIndicator2 = channelIndicator2; - } - - /** - * Return true if this packet contains at least one analog sample - */ - public boolean containsAnalog() { - // ADC is active if > 0 after channel mask is applied - return (this.channelIndicator1 & ADC_CHANNEL1) > 0; - } - - /** - * Returns true if this packet contains at least one digital sample - * - * @return - */ - public boolean containsDigital() { - // DIO 8 occupies the first bit of the adcHeader - return (this.channelIndicator1 & DIO_CHANNEL1) > 0 || this.channelIndicator2 > 0; - } - - public String toString() { - - StringBuilder sb = new StringBuilder(); - - sb.append(super.toString()); - - sb.append(",#samples=" + this.samples.length); - - for (int i = 0; i < samples.length; i++) { - sb.append(",Sample#" + (i + 1) + ":" + samples[i].toString() + "]"); - } - - return sb.toString(); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import java.io.IOException; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.responses.NoRequestResponse; +import com.rapplogic.xbee.util.ByteUtils; +import com.rapplogic.xbee.util.IIntInputStream; + +/** + * Series 1 XBee. Represents an I/O sample + *

+ * See http://code.google.com/p/xbee-api/wiki/XBeePins for information on configuring + * the XBee for digital/analog inputs. + *

+ * API ID: 64-bit 0x82, 16-bit: 0x83 + *

+ * @author andrew + * + */ +public class RxResponseIoSample extends RxBaseResponse implements NoRequestResponse { + + private static final long serialVersionUID = 3818093630598995408L; + + private final static Logger log = Logger.getLogger(RxResponseIoSample.class); + + public final static int ADC_CHANNEL1 = 0x7e; //01111110 + public final static int DIO_CHANNEL1 = 0x1; //00000001 + + private IoSample[] samples; + + private int channelIndicator1; + private int channelIndicator2; + + public RxResponseIoSample() { + + } + + public void parse(IPacketParser parser) throws IOException { + + if (parser.getApiId() == ApiId.RX_16_IO_RESPONSE) { + this.setSourceAddress(parser.parseAddress16()); + } else { + this.setSourceAddress(parser.parseAddress64()); + } + + super.parseBase(parser); + + log.debug("this is a I/O sample!"); + // first byte is # of samples + int sampleSize = parser.read("# I/O Samples"); + + // create i/o samples array + this.setSamples(new IoSample[sampleSize]); + + // channel indicator 1 + this.setChannelIndicator1(parser.read("Channel Indicator 1")); + + log.debug("channel indicator 1 is " + ByteUtils.formatByte(this.getChannelIndicator1())); + + // channel indicator 2 (dio) + this.setChannelIndicator2(parser.read("Channel Indicator 2")); + + log.debug("channel indicator 2 is " + ByteUtils.formatByte(this.getChannelIndicator2())); + + // collect each sample + for (int i = 0; i < this.getSamples().length; i++) { + + log.debug("parsing sample " + (i + 1)); + + IoSample sample = parseIoSample((IIntInputStream)parser); + + // attach sample to parent + this.getSamples()[i] = sample; + } + } + + private IoSample parseIoSample(IIntInputStream parser) throws IOException { + + IoSample sample = new IoSample(this); + + // DIO 8 occupies the first bit of the adcHeader + if (this.containsDigital()) { + // at least one DIO line is active + // next two bytes are DIO + + log.debug("Digital I/O was received"); + + sample.setDioMsb(parser.read("DIO MSB")); + sample.setDioLsb(parser.read("DIO LSB")); + } + + // ADC is active if any of bits 2-7 are on + if (this.containsAnalog()) { + // adc is active + // adc is 10 bits + + log.debug("Analog input was received"); + + // 10-bit values are read two bytes per sample + + int analog = 0; + + // Analog inputs A0-A5 are bits 2-7 of the adcHeader + + if (this.isA0Enabled()) { + sample.setAnalog0(ByteUtils.parse10BitAnalog(parser, analog)); + analog++; + } + + if (this.isA1Enabled()) { + sample.setAnalog1(ByteUtils.parse10BitAnalog(parser, analog)); + analog++; + } + + if (this.isA2Enabled()) { + sample.setAnalog2(ByteUtils.parse10BitAnalog(parser, analog)); + analog++; + } + + if (this.isA3Enabled()) { + sample.setAnalog3(ByteUtils.parse10BitAnalog(parser, analog)); + analog++; + } + + if (this.isA4Enabled()) { + sample.setAnalog4(ByteUtils.parse10BitAnalog(parser, analog)); + analog++; + } + + if (this.isA5Enabled()) { + sample.setAnalog5(ByteUtils.parse10BitAnalog(parser, analog)); + analog++; + } + + log.debug("There are " + analog + " analog inputs turned on"); + } + + return sample; + } + + public IoSample[] getSamples() { + return samples; + } + + public void setSamples(IoSample[] samples) { + this.samples = samples; + } + + public boolean isDigitalEnabled(int pin) { + if (pin >= 0 && pin <= 7) { + return ByteUtils.getBit(channelIndicator2, pin + 1); + } else if (pin == 8) { + return ByteUtils.getBit(channelIndicator1, 1); + } else { + throw new IllegalArgumentException("Unsupported pin: " + pin); + } + } + + public boolean isD0Enabled() { + return ByteUtils.getBit(channelIndicator2, 1); + } + + public boolean isD1Enabled() { + return ByteUtils.getBit(channelIndicator2, 2); + } + + public boolean isD2Enabled() { + return ByteUtils.getBit(channelIndicator2, 3); + } + + public boolean isD3Enabled() { + return ByteUtils.getBit(channelIndicator2, 4); + } + + public boolean isD4Enabled() { + return ByteUtils.getBit(channelIndicator2, 5); + } + + public boolean isD5Enabled() { + return ByteUtils.getBit(channelIndicator2, 6); + } + + public boolean isD6Enabled() { + return ByteUtils.getBit(channelIndicator2, 7); + } + + public boolean isD7Enabled() { + return ByteUtils.getBit(channelIndicator2, 8); + } + + public boolean isD8Enabled() { + return ByteUtils.getBit(channelIndicator1, 1); + } + + public boolean isAnalogEnabled(int pin) { + if (pin >= 0 && pin <= 5) { + return ByteUtils.getBit(channelIndicator1, pin + 2); + } else { + throw new IllegalArgumentException("Unsupported pin: " + pin); + } + } + + public boolean isA0Enabled() { + return ByteUtils.getBit(channelIndicator1, 2); + } + + public boolean isA1Enabled() { + return ByteUtils.getBit(channelIndicator1, 3); + } + + public boolean isA2Enabled() { + return ByteUtils.getBit(channelIndicator1, 4); + } + + public boolean isA3Enabled() { + return ByteUtils.getBit(channelIndicator1, 5); + } + + public boolean isA4Enabled() { + return ByteUtils.getBit(channelIndicator1, 6); + } + + public boolean isA5Enabled() { + return ByteUtils.getBit(channelIndicator1, 7); + } + + public int getChannelIndicator1() { + return channelIndicator1; + } + + public void setChannelIndicator1(int channelIndicator1) { + this.channelIndicator1 = channelIndicator1; + } + + public int getChannelIndicator2() { + return channelIndicator2; + } + + public void setChannelIndicator2(int channelIndicator2) { + this.channelIndicator2 = channelIndicator2; + } + + /** + * Return true if this packet contains at least one analog sample + */ + public boolean containsAnalog() { + // ADC is active if > 0 after channel mask is applied + return (this.channelIndicator1 & ADC_CHANNEL1) > 0; + } + + /** + * Returns true if this packet contains at least one digital sample + * + * @return + */ + public boolean containsDigital() { + // DIO 8 occupies the first bit of the adcHeader + return (this.channelIndicator1 & DIO_CHANNEL1) > 0 || this.channelIndicator2 > 0; + } + + public String toString() { + + StringBuilder sb = new StringBuilder(); + + sb.append(super.toString()); + + sb.append(",#samples=" + this.samples.length); + + for (int i = 0; i < samples.length; i++) { + sb.append(",Sample#" + (i + 1) + ":" + samples[i].toString() + "]"); + } + + return sb.toString(); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/wpan/TxRequest16.java b/src/main/java/com/rapplogic/xbee/api/wpan/TxRequest16.java similarity index 96% rename from src/com/rapplogic/xbee/api/wpan/TxRequest16.java rename to src/main/java/com/rapplogic/xbee/api/wpan/TxRequest16.java index df0291d..41c5db2 100644 --- a/src/com/rapplogic/xbee/api/wpan/TxRequest16.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/TxRequest16.java @@ -1,115 +1,117 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.util.IntArrayOutputStream; - -/** - * Series 1 XBee. 16-bit address Transmit Packet. This is received on the destination XBee - * radio as a RxResponse16 response - *

- * API ID: 0x1 - *

- * @author andrew - * - */ -public class TxRequest16 extends TxRequestBase { - - private XBeeAddress16 remoteAddr16; - - /** - * 16 bit Tx Request with default frame id and awk option - * - * Keep in mind that if you programmed the destination address with X-CTU, the unit is - * hex, so if you set MY=1234, use 0x1234. - * - * @param remoteAddr16 - * @param payload - */ - public TxRequest16(XBeeAddress16 remoteAddr16, int[] payload) { - this(remoteAddr16, DEFAULT_FRAME_ID, Option.UNICAST, payload); - } - - /** - * 16 bit Tx Request with frame id argument - * - * - * Payload size is limited to 100 bytes, according to MaxStream documentation. - * - * @param remoteAddr16 - * @param frameId - * @param payload - */ - public TxRequest16(XBeeAddress16 remoteAddr16, int frameId, int[] payload) { - this(remoteAddr16, frameId, Option.UNICAST, payload); - } - - /** - * Note: if option is DISABLE_ACK_OPTION you will not get a ack response and you must use the asynchronous send method - * - * @param remoteAddr16 - * @param frameId - * @param payload - * @param option - */ - public TxRequest16(XBeeAddress16 remoteAddr16, int frameId, Option option, int[] payload) { - this.remoteAddr16 = remoteAddr16; - this.setFrameId(frameId); - this.setOption(option); - this.setPayload(payload); - } - - public int[] getFrameData() { - // 3/6/10 fixed bug -- broadcast address is used with broadcast option, not no ACK - - IntArrayOutputStream out = new IntArrayOutputStream(); - - // api id - out.write(this.getApiId().getValue()); - // frame id (arbitrary byte that will be sent back with ack) - out.write(this.getFrameId()); - // destination address (broadcast is 0xFFFF) - out.write(remoteAddr16.getAddress()); - // options byte disable ack = 1, send pan id = 4 - out.write(this.getOption().getValue()); - out.write(this.getPayload()); - - return out.getIntArray(); - } - - public ApiId getApiId() { - return ApiId.TX_REQUEST_16; - } - - public XBeeAddress16 getRemoteAddr16() { - return remoteAddr16; - } - - public void setRemoteAddr16(XBeeAddress16 remoteAddr16) { - this.remoteAddr16 = remoteAddr16; - } - - public String toString() { - return super.toString() + - ",remoteAddress16=" + this.remoteAddr16; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.util.IntArrayOutputStream; + +/** + * Series 1 XBee. 16-bit address Transmit Packet. This is received on the destination XBee + * radio as a RxResponse16 response + *

+ * API ID: 0x1 + *

+ * @author andrew + * + */ +public class TxRequest16 extends TxRequestBase { + + private static final long serialVersionUID = -9195390160474504099L; + + private XBeeAddress16 remoteAddr16; + + /** + * 16 bit Tx Request with default frame id and awk option + * + * Keep in mind that if you programmed the destination address with X-CTU, the unit is + * hex, so if you set MY=1234, use 0x1234. + * + * @param remoteAddr16 + * @param payload + */ + public TxRequest16(XBeeAddress16 remoteAddr16, int[] payload) { + this(remoteAddr16, DEFAULT_FRAME_ID, Option.UNICAST, payload); + } + + /** + * 16 bit Tx Request with frame id argument + * + * + * Payload size is limited to 100 bytes, according to MaxStream documentation. + * + * @param remoteAddr16 + * @param frameId + * @param payload + */ + public TxRequest16(XBeeAddress16 remoteAddr16, int frameId, int[] payload) { + this(remoteAddr16, frameId, Option.UNICAST, payload); + } + + /** + * Note: if option is DISABLE_ACK_OPTION you will not get a ack response and you must use the asynchronous send method + * + * @param remoteAddr16 + * @param frameId + * @param payload + * @param option + */ + public TxRequest16(XBeeAddress16 remoteAddr16, int frameId, Option option, int[] payload) { + this.remoteAddr16 = remoteAddr16; + this.setFrameId(frameId); + this.setOption(option); + this.setPayload(payload); + } + + public int[] getFrameData() { + // 3/6/10 fixed bug -- broadcast address is used with broadcast option, not no ACK + + IntArrayOutputStream out = new IntArrayOutputStream(); + + // api id + out.write(this.getApiId().getValue()); + // frame id (arbitrary byte that will be sent back with ack) + out.write(this.getFrameId()); + // destination address (broadcast is 0xFFFF) + out.write(remoteAddr16.getAddress()); + // options byte disable ack = 1, send pan id = 4 + out.write(this.getOption().getValue()); + out.write(this.getPayload()); + + return out.getIntArray(); + } + + public ApiId getApiId() { + return ApiId.TX_REQUEST_16; + } + + public XBeeAddress16 getRemoteAddr16() { + return remoteAddr16; + } + + public void setRemoteAddr16(XBeeAddress16 remoteAddr16) { + this.remoteAddr16 = remoteAddr16; + } + + public String toString() { + return super.toString() + + ",remoteAddress16=" + this.remoteAddr16; + } +} diff --git a/src/com/rapplogic/xbee/api/wpan/TxRequest64.java b/src/main/java/com/rapplogic/xbee/api/wpan/TxRequest64.java similarity index 96% rename from src/com/rapplogic/xbee/api/wpan/TxRequest64.java rename to src/main/java/com/rapplogic/xbee/api/wpan/TxRequest64.java index 0b17750..c99d262 100644 --- a/src/com/rapplogic/xbee/api/wpan/TxRequest64.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/TxRequest64.java @@ -1,126 +1,128 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.util.IntArrayOutputStream; - -// TODO test setting DH/DL to 0 and SH/SL - -/** - * Series 1 XBee. 64-bit address Transmit Packet. This is received on the destination XBee - * radio as a RxResponse64 response - *

- * Constructs frame data portion of a 64-bit transmit request - *

- * Note: The MY address of the receiving XBee must be set to 0xffff to receive this as a RxResponse64; - * otherwise the packet will be transmitted but will be received as a RxResponse16 - *

- * API ID: 0x0 - *

- * @author andrew - * - */ -public class TxRequest64 extends TxRequestBase { - - private XBeeAddress64 remoteAddr64; - - /** - * 16 bit Tx Request with default frame id and awk option - * - * @param destinationAddress - * @param payload - */ - public TxRequest64(XBeeAddress64 destination, int[] payload) { - this(destination, DEFAULT_FRAME_ID, Option.UNICAST, payload); - } - - /** - * 16 bit Tx Request. - * - * Keep in mind that if you programmed the destination address with AT commands, it is in Hex, - * so prepend int with 0x (e.g. 0x1234). - * - * Payload size is limited to 100 bytes, according to MaxStream documentation. - * - * @param destinationAddress - * @param awkFrameId - * @param payload - */ - public TxRequest64(XBeeAddress64 destination, int frameId, int[] payload) { - this(destination, frameId, Option.UNICAST, payload); - } - - /** - * Note: if option is DISABLE_ACK_OPTION you will not get a ack response and you must use the asynchronous send method - * - * @param destinationAddress - * @param awkFrameId - * @param payload - * @param option - */ - public TxRequest64(XBeeAddress64 remoteAddr64, int frameId, Option option, int[] payload) { - this.remoteAddr64 = remoteAddr64; - this.setFrameId(frameId); - this.setOption(option); - this.setPayload(payload); - } - - public int[] getFrameData() { - - // 3/6/10 fixed bug -- broadcast address is used with broadcast option, not no ACK - - IntArrayOutputStream out = new IntArrayOutputStream(); - - // api id - out.write(this.getApiId().getValue()); - // frame id (arbitrary byte that will be sent back with ack) - out.write(this.getFrameId()); - // destination high (broadcast is 0xFFFF) - - // add 64-bit dest address - out.write(remoteAddr64.getAddress()); - - // options byte disable ack = 1, send pan id = 4 - out.write(this.getOption().getValue()); - out.write(this.getPayload()); - - return out.getIntArray(); - } - - public ApiId getApiId() { - return ApiId.TX_REQUEST_64; - } - - public XBeeAddress64 getRemoteAddr64() { - return remoteAddr64; - } - - public void setRemoteAddr64(XBeeAddress64 remoteAddr64) { - this.remoteAddr64 = remoteAddr64; - } - - public String toString() { - return super.toString() + - ",remoteAddress64=" + this.remoteAddr64.toString(); - } - -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.util.IntArrayOutputStream; + +// TODO test setting DH/DL to 0 and SH/SL + +/** + * Series 1 XBee. 64-bit address Transmit Packet. This is received on the destination XBee + * radio as a RxResponse64 response + *

+ * Constructs frame data portion of a 64-bit transmit request + *

+ * Note: The MY address of the receiving XBee must be set to 0xffff to receive this as a RxResponse64; + * otherwise the packet will be transmitted but will be received as a RxResponse16 + *

+ * API ID: 0x0 + *

+ * @author andrew + * + */ +public class TxRequest64 extends TxRequestBase { + + private static final long serialVersionUID = -6376854137744787256L; + + private XBeeAddress64 remoteAddr64; + + /** + * 16 bit Tx Request with default frame id and awk option + * + * @param destinationAddress + * @param payload + */ + public TxRequest64(XBeeAddress64 destination, int[] payload) { + this(destination, DEFAULT_FRAME_ID, Option.UNICAST, payload); + } + + /** + * 16 bit Tx Request. + * + * Keep in mind that if you programmed the destination address with AT commands, it is in Hex, + * so prepend int with 0x (e.g. 0x1234). + * + * Payload size is limited to 100 bytes, according to MaxStream documentation. + * + * @param destinationAddress + * @param awkFrameId + * @param payload + */ + public TxRequest64(XBeeAddress64 destination, int frameId, int[] payload) { + this(destination, frameId, Option.UNICAST, payload); + } + + /** + * Note: if option is DISABLE_ACK_OPTION you will not get a ack response and you must use the asynchronous send method + * + * @param destinationAddress + * @param awkFrameId + * @param payload + * @param option + */ + public TxRequest64(XBeeAddress64 remoteAddr64, int frameId, Option option, int[] payload) { + this.remoteAddr64 = remoteAddr64; + this.setFrameId(frameId); + this.setOption(option); + this.setPayload(payload); + } + + public int[] getFrameData() { + + // 3/6/10 fixed bug -- broadcast address is used with broadcast option, not no ACK + + IntArrayOutputStream out = new IntArrayOutputStream(); + + // api id + out.write(this.getApiId().getValue()); + // frame id (arbitrary byte that will be sent back with ack) + out.write(this.getFrameId()); + // destination high (broadcast is 0xFFFF) + + // add 64-bit dest address + out.write(remoteAddr64.getAddress()); + + // options byte disable ack = 1, send pan id = 4 + out.write(this.getOption().getValue()); + out.write(this.getPayload()); + + return out.getIntArray(); + } + + public ApiId getApiId() { + return ApiId.TX_REQUEST_64; + } + + public XBeeAddress64 getRemoteAddr64() { + return remoteAddr64; + } + + public void setRemoteAddr64(XBeeAddress64 remoteAddr64) { + this.remoteAddr64 = remoteAddr64; + } + + public String toString() { + return super.toString() + + ",remoteAddress64=" + this.remoteAddr64.toString(); + } + +} diff --git a/src/com/rapplogic/xbee/api/wpan/TxRequestBase.java b/src/main/java/com/rapplogic/xbee/api/wpan/TxRequestBase.java similarity index 96% rename from src/com/rapplogic/xbee/api/wpan/TxRequestBase.java rename to src/main/java/com/rapplogic/xbee/api/wpan/TxRequestBase.java index ce0bdf8..daf213d 100644 --- a/src/com/rapplogic/xbee/api/wpan/TxRequestBase.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/TxRequestBase.java @@ -1,111 +1,113 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import com.rapplogic.xbee.api.XBeeRequest; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Series 1 XBee. Super class for 16 and 64 bit address Transmit packets - *

- * @author andrew - * - */ -public abstract class TxRequestBase extends XBeeRequest { - - /** - * Maximum payload size as specified in the series 1 XBee manual. - * This is provided for reference only and is not used for validation - */ - public final static int MAX_PAYLOAD_SIZE = 100; - - private int maxPayloadSize; - - public enum Option { - - UNICAST (0), - DISABLE_ACK (1), - BROADCAST(4); - - private static final Map lookup = new HashMap(); - - static { - for(Option s : EnumSet.allOf(Option.class)) { - lookup.put(s.getValue(), s); - } - } - - public static Option get(int value) { - return lookup.get(value); - } - - private final int value; - - Option(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - private int[] payload; - private Option option; - - // TODO inconsistency: tx uses setPayload, rx uses getData - public int[] getPayload() { - return payload; - } - - public void setPayload(int[] payload) { - - if (this.getMaxPayloadSize() > 0 && payload.length > this.getMaxPayloadSize()) { - throw new IllegalArgumentException("Payload exceeds user-defined maximum payload size of " + this.getMaxPayloadSize() + " bytes. Please re-package into multiple packets"); - } - - this.payload = payload; - } - - public Option getOption() { - return option; - } - - public void setOption(Option option) { - this.option = option; - } - - public String toString() { - return super.toString() + ",option=" + this.option + - ",payload=" + ByteUtils.toBase16(this.payload); - } - - public int getMaxPayloadSize() { - return maxPayloadSize; - } - - public void setMaxPayloadSize(int maxPayloadSize) { - this.maxPayloadSize = maxPayloadSize; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import com.rapplogic.xbee.api.XBeeRequest; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Series 1 XBee. Super class for 16 and 64 bit address Transmit packets + *

+ * @author andrew + * + */ +public abstract class TxRequestBase extends XBeeRequest { + + private static final long serialVersionUID = -7813304462907316907L; + + /** + * Maximum payload size as specified in the series 1 XBee manual. + * This is provided for reference only and is not used for validation + */ + public final static int MAX_PAYLOAD_SIZE = 100; + + private int maxPayloadSize; + + public enum Option { + + UNICAST (0), + DISABLE_ACK (1), + BROADCAST(4); + + private static final Map lookup = new HashMap(); + + static { + for(Option s : EnumSet.allOf(Option.class)) { + lookup.put(s.getValue(), s); + } + } + + public static Option get(int value) { + return lookup.get(value); + } + + private final int value; + + Option(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + private int[] payload; + private Option option; + + // TODO inconsistency: tx uses setPayload, rx uses getData + public int[] getPayload() { + return payload; + } + + public void setPayload(int[] payload) { + + if (this.getMaxPayloadSize() > 0 && payload.length > this.getMaxPayloadSize()) { + throw new IllegalArgumentException("Payload exceeds user-defined maximum payload size of " + this.getMaxPayloadSize() + " bytes. Please re-package into multiple packets"); + } + + this.payload = payload; + } + + public Option getOption() { + return option; + } + + public void setOption(Option option) { + this.option = option; + } + + public String toString() { + return super.toString() + ",option=" + this.option + + ",payload=" + ByteUtils.toBase16(this.payload); + } + + public int getMaxPayloadSize() { + return maxPayloadSize; + } + + public void setMaxPayloadSize(int maxPayloadSize) { + this.maxPayloadSize = maxPayloadSize; + } +} diff --git a/src/com/rapplogic/xbee/api/wpan/TxStatusResponse.java b/src/main/java/com/rapplogic/xbee/api/wpan/TxStatusResponse.java similarity index 94% rename from src/com/rapplogic/xbee/api/wpan/TxStatusResponse.java rename to src/main/java/com/rapplogic/xbee/api/wpan/TxStatusResponse.java index de8071c..312bbdb 100644 --- a/src/com/rapplogic/xbee/api/wpan/TxStatusResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/TxStatusResponse.java @@ -1,123 +1,125 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import java.io.IOException; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.XBeeFrameIdResponse; - -/** - * Series 1 XBee. This is sent out the UART of the transmitting XBee immediately following - * a Transmit packet. Indicates if the Transmit (TxRequest16 or TxRequest64) - * was successful. - *

- * API ID: 0x89 - *

- * @author andrew - * - */ -public class TxStatusResponse extends XBeeFrameIdResponse { - - public enum Status { - - SUCCESS (0), - NO_ACK (1), - CCA_FAILURE(2), - PURGED(3); - - private static final Map lookup = new HashMap(); - - static { - for(Status s : EnumSet.allOf(Status.class)) { - lookup.put(s.getValue(), s); - } - } - - public static Status get(int value) { - return lookup.get(value); - } - - private final int value; - - Status(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - private Status status; - - public TxStatusResponse() { - - } - - public Status getStatus() { - return status; - } - - public void setStatus(Status status) { - this.status = status; - } - - /** - * Returns true if the delivery status is SUCCESS - */ - public boolean isSuccess() { - return this.status == Status.SUCCESS; - } - - // isError() was overridding XBeeResponse isError() - - public boolean isAckError() { - return this.status == Status.NO_ACK; - } - - public boolean isCcaError() { - return this.status == Status.CCA_FAILURE; - } - - public boolean isPurged() { - return this.status == Status.PURGED; - } - - - public void parse(IPacketParser parser) throws IOException { - // frame id - int frameId = parser.read("TxStatus Frame Id"); - this.setFrameId(frameId); - - //log.debug("frame id is " + frameId); - - // Status: 0=Success, 1= No Ack, 2= CCA Failure, 3= Purge - int status = parser.read("TX Status"); - this.setStatus(TxStatusResponse.Status.get(status)); - } - - public String toString() { - return super.toString() + ",status=" + this.getStatus(); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import java.io.IOException; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.responses.XBeeFrameIdResponse; + +/** + * Series 1 XBee. This is sent out the UART of the transmitting XBee immediately following + * a Transmit packet. Indicates if the Transmit (TxRequest16 or TxRequest64) + * was successful. + *

+ * API ID: 0x89 + *

+ * @author andrew + * + */ +public class TxStatusResponse extends XBeeFrameIdResponse { + + private static final long serialVersionUID = 3413667044925902290L; + + public enum Status { + + SUCCESS (0), + NO_ACK (1), + CCA_FAILURE(2), + PURGED(3); + + private static final Map lookup = new HashMap(); + + static { + for(Status s : EnumSet.allOf(Status.class)) { + lookup.put(s.getValue(), s); + } + } + + public static Status get(int value) { + return lookup.get(value); + } + + private final int value; + + Status(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + private Status status; + + public TxStatusResponse() { + + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + /** + * Returns true if the delivery status is SUCCESS + */ + public boolean isSuccess() { + return this.status == Status.SUCCESS; + } + + // isError() was overridding XBeeResponse isError() + + public boolean isAckError() { + return this.status == Status.NO_ACK; + } + + public boolean isCcaError() { + return this.status == Status.CCA_FAILURE; + } + + public boolean isPurged() { + return this.status == Status.PURGED; + } + + + public void parse(IPacketParser parser) throws IOException { + // frame id + int frameId = parser.read("TxStatus Frame Id"); + this.setFrameId(frameId); + + //log.debug("frame id is " + frameId); + + // Status: 0=Success, 1= No Ack, 2= CCA Failure, 3= Purge + int status = parser.read("TX Status"); + this.setStatus(TxStatusResponse.Status.get(status)); + } + + public String toString() { + return super.toString() + ",status=" + this.getStatus(); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/wpan/WpanNodeDiscover.java b/src/main/java/com/rapplogic/xbee/api/wpan/WpanNodeDiscover.java old mode 100755 new mode 100644 similarity index 91% rename from src/com/rapplogic/xbee/api/wpan/WpanNodeDiscover.java rename to src/main/java/com/rapplogic/xbee/api/wpan/WpanNodeDiscover.java index b574891..34ad04c --- a/src/com/rapplogic/xbee/api/wpan/WpanNodeDiscover.java +++ b/src/main/java/com/rapplogic/xbee/api/wpan/WpanNodeDiscover.java @@ -1,127 +1,123 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.wpan; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.AtCommandResponse; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.util.IntArrayInputStream; - -// tested ok via xmpp on 4/13/09 - -/** - * Series 1 XBee. Parses a Node Discover (ND) AT Command Response - */ -public class WpanNodeDiscover { - - private final static Logger log = Logger.getLogger(WpanNodeDiscover.class); - - private XBeeAddress16 nodeAddress16; - private XBeeAddress64 nodeAddress64; - private int rssi; - private String nodeIdentifier; - - public static WpanNodeDiscover parse(AtCommandResponse response) { - - if (!response.getCommand().equals("ND")) { - throw new IllegalArgumentException("This method is only applicable for the ND command"); - } - - int[] data = response.getValue(); - - if (data == null || data.length == 0) { - throw new IllegalArgumentException("ND command has no value"); - } - - IntArrayInputStream in = new IntArrayInputStream(data); - - WpanNodeDiscover nd = new WpanNodeDiscover(); - - nd.setNodeAddress16(new XBeeAddress16(in.read(2))); - - nd.setNodeAddress64(new XBeeAddress64(in.read(8))); - - nd.setRssi(-1*in.read()); - - StringBuilder ni = new StringBuilder(); - - int ch; - - // NI is terminated with 0 - while ((ch = in.read()) != 0) { - if (ch < 32 || ch > 126) { - throw new RuntimeException("Node Identifier " + ch + " is non-ascii"); - } - - ni.append((char)ch); - } - - nd.setNodeIdentifier(ni.toString()); - - return nd; - } - - public String toString() { - return "nodeAddress16=" + this.nodeAddress16 + - ", nodeAddress64=" + this.nodeAddress64 + - ", rssi=" + this.rssi + - ", nodeIdentifier=" + this.nodeIdentifier; - } - - - public XBeeAddress16 getNodeAddress16() { - return nodeAddress16; - } - - - public void setNodeAddress16(XBeeAddress16 my) { - this.nodeAddress16 = my; - } - - - public XBeeAddress64 getNodeAddress64() { - return nodeAddress64; - } - - - public void setNodeAddress64(XBeeAddress64 serial) { - this.nodeAddress64 = serial; - } - - - public String getNodeIdentifier() { - return nodeIdentifier; - } - - - public void setNodeIdentifier(String nodeIdentifier) { - this.nodeIdentifier = nodeIdentifier; - } - - public int getRssi() { - return rssi; - } - - public void setRssi(int rssi) { - this.rssi = rssi; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.wpan; + +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.util.IntArrayInputStream; + +// tested ok via xmpp on 4/13/09 + +/** + * Series 1 XBee. Parses a Node Discover (ND) AT Command Response + */ +public class WpanNodeDiscover { + + private XBeeAddress16 nodeAddress16; + private XBeeAddress64 nodeAddress64; + private int rssi; + private String nodeIdentifier; + + public static WpanNodeDiscover parse(AtCommandResponse response) { + + if (!response.getCommand().equals("ND")) { + throw new IllegalArgumentException("This method is only applicable for the ND command"); + } + + int[] data = response.getValue(); + + if (data == null || data.length == 0) { + throw new IllegalArgumentException("ND command has no value"); + } + + IntArrayInputStream in = new IntArrayInputStream(data); + + WpanNodeDiscover nd = new WpanNodeDiscover(); + + nd.setNodeAddress16(new XBeeAddress16(in.read(2))); + + nd.setNodeAddress64(new XBeeAddress64(in.read(8))); + + nd.setRssi(-1*in.read()); + + StringBuilder ni = new StringBuilder(); + + int ch; + + // NI is terminated with 0 + while ((ch = in.read()) != 0) { + if (ch < 32 || ch > 126) { + throw new RuntimeException("Node Identifier " + ch + " is non-ascii"); + } + + ni.append((char)ch); + } + + nd.setNodeIdentifier(ni.toString()); + + return nd; + } + + public String toString() { + return "nodeAddress16=" + this.nodeAddress16 + + ", nodeAddress64=" + this.nodeAddress64 + + ", rssi=" + this.rssi + + ", nodeIdentifier=" + this.nodeIdentifier; + } + + + public XBeeAddress16 getNodeAddress16() { + return nodeAddress16; + } + + + public void setNodeAddress16(XBeeAddress16 my) { + this.nodeAddress16 = my; + } + + + public XBeeAddress64 getNodeAddress64() { + return nodeAddress64; + } + + + public void setNodeAddress64(XBeeAddress64 serial) { + this.nodeAddress64 = serial; + } + + + public String getNodeIdentifier() { + return nodeIdentifier; + } + + + public void setNodeIdentifier(String nodeIdentifier) { + this.nodeIdentifier = nodeIdentifier; + } + + public int getRssi() { + return rssi; + } + + public void setRssi(int rssi) { + this.rssi = rssi; + } +} diff --git a/src/com/rapplogic/xbee/api/zigbee/AssociationStatus.java b/src/main/java/com/rapplogic/xbee/api/zigbee/AssociationStatus.java similarity index 95% rename from src/com/rapplogic/xbee/api/zigbee/AssociationStatus.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/AssociationStatus.java index 557ffff..d5bc26d 100644 --- a/src/com/rapplogic/xbee/api/zigbee/AssociationStatus.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/AssociationStatus.java @@ -1,71 +1,71 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import com.rapplogic.xbee.api.AtCommandResponse; - -// TODO create for wpan -public enum AssociationStatus { - SUCCESS (0, "Successful completion - Coordinator started or Router/End Device found and joined with a parent."), - NO_PAN (0x21, "Scan found no PANs"), - NO_VALID_PAN (0x22, "Scan found no valid PANs based on current SC and ID settings"), - NJ_EXPIRED (0x23, "Valid Coordinator or Routers found, but they are not allowing joining (NJ expired)"), - NJ_FAILED (0x27, "Node Joining attempt failed (typically due to incompatible security settings)"), - COORDINATOR_START_FAILED (0x2a, "Coordinator Start attempt failed"), - SCANNING_FOR_PARENT (0xff, "Scanning for a Parent"), - EXISTING_COORDINATOR_CHECK (0x2b, "Checking for an existing coordinator"); - - private static final Map lookup = new HashMap(); - - static { - for(AssociationStatus s : EnumSet.allOf(AssociationStatus.class)) { - lookup.put(s.getValue(), s); - } - } - - public static AssociationStatus get(int value) { - return lookup.get(value); - } - - public static AssociationStatus get(AtCommandResponse response) { - return AssociationStatus.get(response.getValue()[0]); - } - - private final int value; - private final String description; - - AssociationStatus(int value, String description) { - this.value = value; - this.description = description; - - } - - public int getValue() { - return value; - } - - public String getDescription() { - return description; - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import com.rapplogic.xbee.api.responses.AtCommandResponse; + +// TODO create for wpan +public enum AssociationStatus { + SUCCESS (0, "Successful completion - Coordinator started or Router/End Device found and joined with a parent."), + NO_PAN (0x21, "Scan found no PANs"), + NO_VALID_PAN (0x22, "Scan found no valid PANs based on current SC and ID settings"), + NJ_EXPIRED (0x23, "Valid Coordinator or Routers found, but they are not allowing joining (NJ expired)"), + NJ_FAILED (0x27, "Node Joining attempt failed (typically due to incompatible security settings)"), + COORDINATOR_START_FAILED (0x2a, "Coordinator Start attempt failed"), + SCANNING_FOR_PARENT (0xff, "Scanning for a Parent"), + EXISTING_COORDINATOR_CHECK (0x2b, "Checking for an existing coordinator"); + + private static final Map lookup = new HashMap(); + + static { + for(AssociationStatus s : EnumSet.allOf(AssociationStatus.class)) { + lookup.put(s.getValue(), s); + } + } + + public static AssociationStatus get(int value) { + return lookup.get(value); + } + + public static AssociationStatus get(AtCommandResponse response) { + return AssociationStatus.get(response.getValue()[0]); + } + + private final int value; + private final String description; + + AssociationStatus(int value, String description) { + this.value = value; + this.description = description; + + } + + public int getValue() { + return value; + } + + public String getDescription() { + return description; + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/zigbee/ZBForceSampleRequest.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZBForceSampleRequest.java similarity index 91% rename from src/com/rapplogic/xbee/api/zigbee/ZBForceSampleRequest.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZBForceSampleRequest.java index e29b9c3..9a60852 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZBForceSampleRequest.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZBForceSampleRequest.java @@ -1,44 +1,46 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeRequest; -import com.rapplogic.xbee.api.RemoteAtRequest; - -/** - * Uses Remote AT to send a Force Sample (IS) AT command to a remote XBee - * - * @author andrew - * - */ -public class ZBForceSampleRequest extends RemoteAtRequest { - - /** - * Creates a Force Sample Remote AT request - * - * @param dest64 - * @param command - */ - public ZBForceSampleRequest(XBeeAddress64 dest64) { - super(XBeeRequest.DEFAULT_FRAME_ID, dest64, XBeeAddress16.ZNET_BROADCAST, false, "IS", null); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeRequest; +import com.rapplogic.xbee.api.requests.RemoteAtRequest; + +/** + * Uses Remote AT to send a Force Sample (IS) AT command to a remote XBee + * + * @author andrew + * + */ +public class ZBForceSampleRequest extends RemoteAtRequest { + + private static final long serialVersionUID = -5556592595956235088L; + + /** + * Creates a Force Sample Remote AT request + * + * @param dest64 + * @param command + */ + public ZBForceSampleRequest(XBeeAddress64 dest64) { + super(XBeeRequest.DEFAULT_FRAME_ID, dest64, XBeeAddress16.ZNET_BROADCAST, false, "IS", null); + } +} diff --git a/src/com/rapplogic/xbee/api/zigbee/ZBNodeDiscover.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZBNodeDiscover.java similarity index 92% rename from src/com/rapplogic/xbee/api/zigbee/ZBNodeDiscover.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZBNodeDiscover.java index 46458c4..f0a98e0 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZBNodeDiscover.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZBNodeDiscover.java @@ -1,212 +1,208 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.AtCommandResponse; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.IntArrayInputStream; - -/** - * Series 2 XBee. Parses a Node Discover (ND) AT Command Response - *

- * @author andrew - * - */ -public class ZBNodeDiscover { - - private final static Logger log = Logger.getLogger(ZBNodeDiscover.class); - - public enum DeviceType { - DEV_TYPE_COORDINATOR (0), - DEV_TYPE_ROUTER (1), - DEV_TYPE_END_DEVICE (2); - - private static final Map lookup = new HashMap(); - - static { - for(DeviceType s : EnumSet.allOf(DeviceType.class)) { - lookup.put(s.getValue(), s); - } - } - - public static DeviceType get(int value) { - return lookup.get(value); - } - - private final int value; - - DeviceType(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - private XBeeAddress16 nodeAddress16; - private XBeeAddress64 nodeAddress64; - private String nodeIdentifier; - private XBeeAddress16 parent; - private DeviceType deviceType; - private int status; - private int[] profileId; - private int[] mfgId; - - public DeviceType getDeviceType() { - return deviceType; - } - - - public void setDeviceType(DeviceType deviceType) { - this.deviceType = deviceType; - } - - - public int getStatus() { - return status; - } - - - public void setStatus(int status) { - this.status = status; - } - - - public int[] getProfileId() { - return profileId; - } - - - public void setProfileId(int[] profileId) { - this.profileId = profileId; - } - - - public int[] getMfgId() { - return mfgId; - } - - - public void setMfgId(int[] mfgId) { - this.mfgId = mfgId; - } - - - public static ZBNodeDiscover parse(AtCommandResponse response) { - - if (!response.getCommand().equals("ND")) { - throw new RuntimeException("This method is only applicable for the ND command"); - } - - int[] data = response.getValue(); - - IntArrayInputStream in = new IntArrayInputStream(data); - - ZBNodeDiscover nd = new ZBNodeDiscover(); - - nd.setNodeAddress16(new XBeeAddress16(in.read(2))); - - nd.setNodeAddress64(new XBeeAddress64(in.read(8))); - - StringBuffer ni = new StringBuffer(); - - int ch; - - // NI is terminated with 0 - while ((ch = in.read()) != 0) { - if (ch < 32 || ch > 126) { - throw new RuntimeException("Node Identifier " + ch + " is non-ascii"); - } - - ni.append((char)ch); - } - - nd.setNodeIdentifier(ni.toString()); - - nd.setParent(new XBeeAddress16(in.read(2))); - nd.setDeviceType(DeviceType.get(in.read())); - // TODO this is being reported as 1 (router) for my end device - nd.setStatus(in.read()); - nd.setProfileId(in.read(2)); - nd.setMfgId(in.read(2)); - - return nd; - } - - public String toString() { - return "nodeAddress16=" + this.nodeAddress16 + - ", nodeAddress64=" + this.nodeAddress64 + - ", nodeIdentifier=" + this.nodeIdentifier + - ", parentAddress=" + this.getParent() + - ", deviceType=" + this.deviceType + - ", status=" + this.status + - ", profileId=" + ByteUtils.toBase16(this.profileId) + - ", mfgId=" + ByteUtils.toBase16(this.mfgId); - } - - - public XBeeAddress16 getNodeAddress16() { - return nodeAddress16; - } - - - public void setNodeAddress16(XBeeAddress16 my) { - this.nodeAddress16 = my; - } - - - public XBeeAddress64 getNodeAddress64() { - return nodeAddress64; - } - - - public void setNodeAddress64(XBeeAddress64 serial) { - this.nodeAddress64 = serial; - } - - - public String getNodeIdentifier() { - return nodeIdentifier; - } - - - public void setNodeIdentifier(String nodeIdentifier) { - this.nodeIdentifier = nodeIdentifier; - } - - - public XBeeAddress16 getParent() { - return parent; - } - - - public void setParent(XBeeAddress16 parent) { - this.parent = parent; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.util.ByteUtils; +import com.rapplogic.xbee.util.IntArrayInputStream; + +/** + * Series 2 XBee. Parses a Node Discover (ND) AT Command Response + *

+ * @author andrew + * + */ +public class ZBNodeDiscover { + + public enum DeviceType { + DEV_TYPE_COORDINATOR (0), + DEV_TYPE_ROUTER (1), + DEV_TYPE_END_DEVICE (2); + + private static final Map lookup = new HashMap(); + + static { + for(DeviceType s : EnumSet.allOf(DeviceType.class)) { + lookup.put(s.getValue(), s); + } + } + + public static DeviceType get(int value) { + return lookup.get(value); + } + + private final int value; + + DeviceType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + private XBeeAddress16 nodeAddress16; + private XBeeAddress64 nodeAddress64; + private String nodeIdentifier; + private XBeeAddress16 parent; + private DeviceType deviceType; + private int status; + private int[] profileId; + private int[] mfgId; + + public DeviceType getDeviceType() { + return deviceType; + } + + + public void setDeviceType(DeviceType deviceType) { + this.deviceType = deviceType; + } + + + public int getStatus() { + return status; + } + + + public void setStatus(int status) { + this.status = status; + } + + + public int[] getProfileId() { + return profileId; + } + + + public void setProfileId(int[] profileId) { + this.profileId = profileId; + } + + + public int[] getMfgId() { + return mfgId; + } + + + public void setMfgId(int[] mfgId) { + this.mfgId = mfgId; + } + + + public static ZBNodeDiscover parse(AtCommandResponse response) { + + if (!response.getCommand().equals("ND")) { + throw new RuntimeException("This method is only applicable for the ND command"); + } + + int[] data = response.getValue(); + + IntArrayInputStream in = new IntArrayInputStream(data); + + ZBNodeDiscover nd = new ZBNodeDiscover(); + + nd.setNodeAddress16(new XBeeAddress16(in.read(2))); + + nd.setNodeAddress64(new XBeeAddress64(in.read(8))); + + StringBuffer ni = new StringBuffer(); + + int ch; + + // NI is terminated with 0 + while ((ch = in.read()) != 0) { + if (ch < 32 || ch > 126) { + throw new RuntimeException("Node Identifier " + ch + " is non-ascii"); + } + + ni.append((char)ch); + } + + nd.setNodeIdentifier(ni.toString()); + + nd.setParent(new XBeeAddress16(in.read(2))); + nd.setDeviceType(DeviceType.get(in.read())); + // TODO this is being reported as 1 (router) for my end device + nd.setStatus(in.read()); + nd.setProfileId(in.read(2)); + nd.setMfgId(in.read(2)); + + return nd; + } + + public String toString() { + return "nodeAddress16=" + this.nodeAddress16 + + ", nodeAddress64=" + this.nodeAddress64 + + ", nodeIdentifier=" + this.nodeIdentifier + + ", parentAddress=" + this.getParent() + + ", deviceType=" + this.deviceType + + ", status=" + this.status + + ", profileId=" + ByteUtils.toBase16(this.profileId) + + ", mfgId=" + ByteUtils.toBase16(this.mfgId); + } + + + public XBeeAddress16 getNodeAddress16() { + return nodeAddress16; + } + + + public void setNodeAddress16(XBeeAddress16 my) { + this.nodeAddress16 = my; + } + + + public XBeeAddress64 getNodeAddress64() { + return nodeAddress64; + } + + + public void setNodeAddress64(XBeeAddress64 serial) { + this.nodeAddress64 = serial; + } + + + public String getNodeIdentifier() { + return nodeIdentifier; + } + + + public void setNodeIdentifier(String nodeIdentifier) { + this.nodeIdentifier = nodeIdentifier; + } + + + public XBeeAddress16 getParent() { + return parent; + } + + + public void setParent(XBeeAddress16 parent) { + this.parent = parent; + } +} diff --git a/src/com/rapplogic/xbee/api/zigbee/ZNetExplicitRxResponse.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetExplicitRxResponse.java similarity index 96% rename from src/com/rapplogic/xbee/api/zigbee/ZNetExplicitRxResponse.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZNetExplicitRxResponse.java index a4bcf2d..1e14a11 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZNetExplicitRxResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetExplicitRxResponse.java @@ -1,107 +1,109 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.io.IOException; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.DoubleByte; - -// TODO deprecate all ZNet* classes and replace with ZigBee* -/** - * Series 2 XBee. This packet is received when a remote XBee sends a ZNetExplicitTxRequest - *

- * Radio must be configured for explicit frames to use this class (AO=1) - *

- * API ID: 0x91 - */ -public class ZNetExplicitRxResponse extends ZNetRxResponse { - - private int sourceEndpoint; - private int destinationEndpoint; - private DoubleByte clusterId; - private DoubleByte profileId; - - public ZNetExplicitRxResponse() { - super(); - } - - public int getSourceEndpoint() { - return sourceEndpoint; - } - - public void setSourceEndpoint(int sourceEndpoint) { - this.sourceEndpoint = sourceEndpoint; - } - - public int getDestinationEndpoint() { - return destinationEndpoint; - } - - public void setDestinationEndpoint(int destinationEndpoint) { - this.destinationEndpoint = destinationEndpoint; - } - - public DoubleByte getClusterId() { - return clusterId; - } - - public void setClusterId(DoubleByte clusterId) { - this.clusterId = clusterId; - } - - public DoubleByte getProfileId() { - return profileId; - } - - public void setProfileId(DoubleByte profileId) { - this.profileId = profileId; - } - - public void parse(IPacketParser parser) throws IOException { - this.parseAddress(parser); - - this.setSourceEndpoint(parser.read("Reading Source Endpoint")); - this.setDestinationEndpoint(parser.read("Reading Destination Endpoint")); - DoubleByte clusterId = new DoubleByte(); - clusterId.setMsb(parser.read("Reading Cluster Id MSB")); - clusterId.setLsb(parser.read("Reading Cluster Id LSB")); - this.setClusterId(clusterId); - - DoubleByte profileId = new DoubleByte(); - profileId.setMsb(parser.read("Reading Profile Id MSB")); - profileId.setLsb(parser.read("Reading Profile Id LSB")); - this.setProfileId(profileId); - - this.parseOption(parser); - this.setData(parser.readRemainingBytes()); - } - - public String toString() { - return super.toString() + - ",sourceEndpoint=" + ByteUtils.toBase16(this.getSourceEndpoint()) + - ",destinationEndpoint=" + ByteUtils.toBase16(this.getDestinationEndpoint()) + - ",clusterId(msb)=" + ByteUtils.toBase16(this.getClusterId().getMsb()) + - ",clusterId(lsb)=" + ByteUtils.toBase16(this.getClusterId().getLsb()) + - ",profileId(msb)=" + ByteUtils.toBase16(this.getProfileId().getMsb()) + - ",profileId(lsb)=" + ByteUtils.toBase16(this.getProfileId().getLsb()); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.io.IOException; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.util.ByteUtils; +import com.rapplogic.xbee.util.DoubleByte; + +// TODO deprecate all ZNet* classes and replace with ZigBee* +/** + * Series 2 XBee. This packet is received when a remote XBee sends a ZNetExplicitTxRequest + *

+ * Radio must be configured for explicit frames to use this class (AO=1) + *

+ * API ID: 0x91 + */ +public class ZNetExplicitRxResponse extends ZNetRxResponse { + + private static final long serialVersionUID = -6559407185467903247L; + + private int sourceEndpoint; + private int destinationEndpoint; + private DoubleByte clusterId; + private DoubleByte profileId; + + public ZNetExplicitRxResponse() { + super(); + } + + public int getSourceEndpoint() { + return sourceEndpoint; + } + + public void setSourceEndpoint(int sourceEndpoint) { + this.sourceEndpoint = sourceEndpoint; + } + + public int getDestinationEndpoint() { + return destinationEndpoint; + } + + public void setDestinationEndpoint(int destinationEndpoint) { + this.destinationEndpoint = destinationEndpoint; + } + + public DoubleByte getClusterId() { + return clusterId; + } + + public void setClusterId(DoubleByte clusterId) { + this.clusterId = clusterId; + } + + public DoubleByte getProfileId() { + return profileId; + } + + public void setProfileId(DoubleByte profileId) { + this.profileId = profileId; + } + + public void parse(IPacketParser parser) throws IOException { + this.parseAddress(parser); + + this.setSourceEndpoint(parser.read("Reading Source Endpoint")); + this.setDestinationEndpoint(parser.read("Reading Destination Endpoint")); + DoubleByte clusterId = new DoubleByte(); + clusterId.setMsb(parser.read("Reading Cluster Id MSB")); + clusterId.setLsb(parser.read("Reading Cluster Id LSB")); + this.setClusterId(clusterId); + + DoubleByte profileId = new DoubleByte(); + profileId.setMsb(parser.read("Reading Profile Id MSB")); + profileId.setLsb(parser.read("Reading Profile Id LSB")); + this.setProfileId(profileId); + + this.parseOption(parser); + this.setData(parser.readRemainingBytes()); + } + + public String toString() { + return super.toString() + + ",sourceEndpoint=" + ByteUtils.toBase16(this.getSourceEndpoint()) + + ",destinationEndpoint=" + ByteUtils.toBase16(this.getDestinationEndpoint()) + + ",clusterId(msb)=" + ByteUtils.toBase16(this.getClusterId().getMsb()) + + ",clusterId(lsb)=" + ByteUtils.toBase16(this.getClusterId().getLsb()) + + ",profileId(msb)=" + ByteUtils.toBase16(this.getProfileId().getMsb()) + + ",profileId(lsb)=" + ByteUtils.toBase16(this.getProfileId().getLsb()); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/zigbee/ZNetExplicitTxRequest.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetExplicitTxRequest.java similarity index 96% rename from src/com/rapplogic/xbee/api/zigbee/ZNetExplicitTxRequest.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZNetExplicitTxRequest.java index ab8ce5b..db60a4d 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZNetExplicitTxRequest.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetExplicitTxRequest.java @@ -1,201 +1,203 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.DoubleByte; -import com.rapplogic.xbee.util.IntArrayOutputStream; - -/** - * Series 2 XBee. Sends a packet to a remote radio. The remote radio - * receives the packet as a ZNetExplicitRxResponse packet. - *

- * Radio must be configured for explicit frames to use this class (AO=1) - *

- * API ID: 0x11 - * - * @author andrew - * - */ -public class ZNetExplicitTxRequest extends ZNetTxRequest { - - public enum Endpoint { - ZDO_ENDPOINT(0), - COMMAND (0xe6), - DATA (0xe8); - - private static final Map lookup = new HashMap(); - - static { - for(Endpoint s : EnumSet.allOf(Endpoint.class)) { - lookup.put(s.getValue(), s); - } - } - - public static Endpoint get(int value) { - return lookup.get(value); - } - - private final int value; - - Endpoint(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - public enum ClusterId { - TRANSPARENT_SERIAL (Endpoint.DATA, 0x11), - SERIAL_LOOPBACK (Endpoint.DATA, 0x12), - IO_SAMPLE (Endpoint.DATA, 0x92), - XBEE_SENSOR (Endpoint.DATA, 0x94), - NODE_IDENTIFICATION (Endpoint.DATA, 0x95); - - private static final Map lookup = new HashMap(); - - static { - for(ClusterId s : EnumSet.allOf(ClusterId.class)) { - lookup.put(s.getValue(), s); - } - } - - public static ClusterId get(int value) { - return lookup.get(value); - } - - private final int value; - private final Endpoint endpoint; - - ClusterId(Endpoint endpoint, int value) { - this.endpoint = endpoint; - this.value = value; - } - - public int getValue() { - return value; - } - - public Endpoint getEndpoint() { - return this.endpoint; - } - } - - // TODO ZDO commands - - private int sourceEndpoint; - private int destinationEndpoint; - private DoubleByte clusterId; - private DoubleByte profileId; - - public final static DoubleByte znetProfileId = new DoubleByte(0xc1, 0x05); - public final static DoubleByte zdoProfileId = new DoubleByte(0, 0); - - public ZNetExplicitTxRequest(int frameId, XBeeAddress64 dest64, XBeeAddress16 dest16, int broadcastRadius, ZNetTxRequest.Option option, int[] payload, int sourceEndpoint, int destinationEndpoint, DoubleByte clusterId, DoubleByte profileId) { - super(frameId, dest64, dest16, broadcastRadius, option, payload); - this.sourceEndpoint = sourceEndpoint; - this.destinationEndpoint = destinationEndpoint; - this.clusterId = clusterId; - this.profileId = profileId; - } - - /** - * Gets frame data from tx request (super) and inserts necessary bytes - */ - public int[] getFrameData() { - - // get frame id from tx request - IntArrayOutputStream frameData = this.getFrameDataAsIntArrayOutputStream(); - - // overwrite api id - frameData.getInternalList().set(0, this.getApiId().getValue()); - - // insert explicit bytes - - // source endpoint - frameData.getInternalList().add(12, this.getSourceEndpoint()); - // dest endpoint - frameData.getInternalList().add(13, this.getDestinationEndpoint()); - // cluster id msb - frameData.getInternalList().add(14, this.getClusterId().getMsb()); - // cluster id lsb - frameData.getInternalList().add(15, this.getClusterId().getLsb()); - // profile id - frameData.getInternalList().add(16, this.getProfileId().getMsb()); - frameData.getInternalList().add(17, this.getProfileId().getLsb()); - - return frameData.getIntArray(); - } - - public ApiId getApiId() { - return ApiId.ZNET_EXPLICIT_TX_REQUEST; - } - - public int getSourceEndpoint() { - return sourceEndpoint; - } - - public void setSourceEndpoint(int sourceEndpoint) { - this.sourceEndpoint = sourceEndpoint; - } - - public int getDestinationEndpoint() { - return destinationEndpoint; - } - - public void setDestinationEndpoint(int destinationEndpoint) { - this.destinationEndpoint = destinationEndpoint; - } - - public DoubleByte getClusterId() { - return clusterId; - } - - public void setClusterId(DoubleByte clusterId) { - this.clusterId = clusterId; - } - - public DoubleByte getProfileId() { - return profileId; - } - - public void setProfileId(DoubleByte profileId) { - this.profileId = profileId; - } - - public String toString() { - return super.toString() + - ",sourceEndpoint=" + ByteUtils.toBase16(this.getSourceEndpoint()) + - ",destinationEndpoint=" + ByteUtils.toBase16(this.getDestinationEndpoint()) + - ",clusterId(msb)=" + ByteUtils.toBase16(this.getClusterId().getMsb()) + - ",clusterId(lsb)=" + ByteUtils.toBase16(this.getClusterId().getLsb()) + - ",profileId(msb)=" + ByteUtils.toBase16(this.getProfileId().getMsb()) + - ",profileId(lsb)=" + ByteUtils.toBase16(this.getProfileId().getLsb()); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.util.ByteUtils; +import com.rapplogic.xbee.util.DoubleByte; +import com.rapplogic.xbee.util.IntArrayOutputStream; + +/** + * Series 2 XBee. Sends a packet to a remote radio. The remote radio + * receives the packet as a ZNetExplicitRxResponse packet. + *

+ * Radio must be configured for explicit frames to use this class (AO=1) + *

+ * API ID: 0x11 + * + * @author andrew + * + */ +public class ZNetExplicitTxRequest extends ZNetTxRequest { + + private static final long serialVersionUID = -1208466120818907727L; + + public enum Endpoint { + ZDO_ENDPOINT(0), + COMMAND (0xe6), + DATA (0xe8); + + private static final Map lookup = new HashMap(); + + static { + for(Endpoint s : EnumSet.allOf(Endpoint.class)) { + lookup.put(s.getValue(), s); + } + } + + public static Endpoint get(int value) { + return lookup.get(value); + } + + private final int value; + + Endpoint(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + public enum ClusterId { + TRANSPARENT_SERIAL (Endpoint.DATA, 0x11), + SERIAL_LOOPBACK (Endpoint.DATA, 0x12), + IO_SAMPLE (Endpoint.DATA, 0x92), + XBEE_SENSOR (Endpoint.DATA, 0x94), + NODE_IDENTIFICATION (Endpoint.DATA, 0x95); + + private static final Map lookup = new HashMap(); + + static { + for(ClusterId s : EnumSet.allOf(ClusterId.class)) { + lookup.put(s.getValue(), s); + } + } + + public static ClusterId get(int value) { + return lookup.get(value); + } + + private final int value; + private final Endpoint endpoint; + + ClusterId(Endpoint endpoint, int value) { + this.endpoint = endpoint; + this.value = value; + } + + public int getValue() { + return value; + } + + public Endpoint getEndpoint() { + return this.endpoint; + } + } + + // TODO ZDO commands + + private int sourceEndpoint; + private int destinationEndpoint; + private DoubleByte clusterId; + private DoubleByte profileId; + + public final static DoubleByte znetProfileId = new DoubleByte(0xc1, 0x05); + public final static DoubleByte zdoProfileId = new DoubleByte(0, 0); + + public ZNetExplicitTxRequest(int frameId, XBeeAddress64 dest64, XBeeAddress16 dest16, int broadcastRadius, ZNetTxRequest.Option option, int[] payload, int sourceEndpoint, int destinationEndpoint, DoubleByte clusterId, DoubleByte profileId) { + super(frameId, dest64, dest16, broadcastRadius, option, payload); + this.sourceEndpoint = sourceEndpoint; + this.destinationEndpoint = destinationEndpoint; + this.clusterId = clusterId; + this.profileId = profileId; + } + + /** + * Gets frame data from tx request (super) and inserts necessary bytes + */ + public int[] getFrameData() { + + // get frame id from tx request + IntArrayOutputStream frameData = this.getFrameDataAsIntArrayOutputStream(); + + // overwrite api id + frameData.getInternalList().set(0, this.getApiId().getValue()); + + // insert explicit bytes + + // source endpoint + frameData.getInternalList().add(12, this.getSourceEndpoint()); + // dest endpoint + frameData.getInternalList().add(13, this.getDestinationEndpoint()); + // cluster id msb + frameData.getInternalList().add(14, this.getClusterId().getMsb()); + // cluster id lsb + frameData.getInternalList().add(15, this.getClusterId().getLsb()); + // profile id + frameData.getInternalList().add(16, this.getProfileId().getMsb()); + frameData.getInternalList().add(17, this.getProfileId().getLsb()); + + return frameData.getIntArray(); + } + + public ApiId getApiId() { + return ApiId.ZNET_EXPLICIT_TX_REQUEST; + } + + public int getSourceEndpoint() { + return sourceEndpoint; + } + + public void setSourceEndpoint(int sourceEndpoint) { + this.sourceEndpoint = sourceEndpoint; + } + + public int getDestinationEndpoint() { + return destinationEndpoint; + } + + public void setDestinationEndpoint(int destinationEndpoint) { + this.destinationEndpoint = destinationEndpoint; + } + + public DoubleByte getClusterId() { + return clusterId; + } + + public void setClusterId(DoubleByte clusterId) { + this.clusterId = clusterId; + } + + public DoubleByte getProfileId() { + return profileId; + } + + public void setProfileId(DoubleByte profileId) { + this.profileId = profileId; + } + + public String toString() { + return super.toString() + + ",sourceEndpoint=" + ByteUtils.toBase16(this.getSourceEndpoint()) + + ",destinationEndpoint=" + ByteUtils.toBase16(this.getDestinationEndpoint()) + + ",clusterId(msb)=" + ByteUtils.toBase16(this.getClusterId().getMsb()) + + ",clusterId(lsb)=" + ByteUtils.toBase16(this.getClusterId().getLsb()) + + ",profileId(msb)=" + ByteUtils.toBase16(this.getProfileId().getMsb()) + + ",profileId(lsb)=" + ByteUtils.toBase16(this.getProfileId().getLsb()); + } +} diff --git a/src/com/rapplogic/xbee/api/zigbee/ZNetNodeIdentificationResponse.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetNodeIdentificationResponse.java similarity index 96% rename from src/com/rapplogic/xbee/api/zigbee/ZNetNodeIdentificationResponse.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZNetNodeIdentificationResponse.java index db906a8..63c05e9 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZNetNodeIdentificationResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetNodeIdentificationResponse.java @@ -1,271 +1,273 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.io.IOException; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.zigbee.ZNetRxBaseResponse.Option; -import com.rapplogic.xbee.util.DoubleByte; - -public class ZNetNodeIdentificationResponse extends XBeeResponse { - - private final static Logger log = Logger.getLogger(ZNetNodeIdentificationResponse.class); - - // TODO this is repeated in NodeDiscover - public enum DeviceType { - COORDINATOR (0x1), - ROUTER (0x2), - END_DEVICE (0x3), - UNKNOWN(-1); - - private static final Map lookup = new HashMap(); - - static { - for(DeviceType s: EnumSet.allOf(DeviceType.class)) { - lookup.put(s.getValue(), s); - } - } - - public static DeviceType get(int value) { - return lookup.get(value); - } - - private final int value; - - DeviceType(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - public enum SourceAction { - PUSHBUTTON (0x1), - JOINING (0x2), - POWER_CYCLE(0x3), - UNKNOWN(-1); - - private static final Map lookup = new HashMap(); - - static { - for(SourceAction s: EnumSet.allOf(SourceAction.class)) { - lookup.put(s.getValue(), s); - } - } - - public static SourceAction get(int value) { - return lookup.get(value); - } - - private final int value; - - SourceAction(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - private XBeeAddress64 remoteAddress64; - private XBeeAddress16 remoteAddress16; - private Option option; - // TODO Digi WTF why duplicated?? p.70 - private XBeeAddress64 remoteAddress64_2; - private XBeeAddress16 remoteAddress16_2; - - private String nodeIdentifier; - private XBeeAddress16 parentAddress; - private DeviceType deviceType; - private SourceAction sourceAction; - private DoubleByte profileId; - private DoubleByte mfgId; - - public ZNetNodeIdentificationResponse() { - - } - - public XBeeAddress64 getRemoteAddress64() { - return remoteAddress64; - } - - public void setRemoteAddress64(XBeeAddress64 remoteAddress64) { - this.remoteAddress64 = remoteAddress64; - } - - public XBeeAddress16 getRemoteAddress16() { - return remoteAddress16; - } - - public void setRemoteAddress16(XBeeAddress16 remoteAddress16) { - this.remoteAddress16 = remoteAddress16; - } - - public Option getOption() { - return option; - } - - public void setOption(Option option) { - this.option = option; - } - - public XBeeAddress64 getRemoteAddress64_2() { - return remoteAddress64_2; - } - - public void setRemoteAddress64_2(XBeeAddress64 remoteAddress64_2) { - this.remoteAddress64_2 = remoteAddress64_2; - } - - public XBeeAddress16 getRemoteAddress16_2() { - return remoteAddress16_2; - } - - public void setRemoteAddress16_2(XBeeAddress16 remoteAddress16_2) { - this.remoteAddress16_2 = remoteAddress16_2; - } - - public String getNodeIdentifier() { - return nodeIdentifier; - } - - public void setNodeIdentifier(String nodeIdentifier) { - this.nodeIdentifier = nodeIdentifier; - } - - public XBeeAddress16 getParentAddress() { - return parentAddress; - } - - public void setParentAddress(XBeeAddress16 parentAddress) { - this.parentAddress = parentAddress; - } - - public DeviceType getDeviceType() { - return deviceType; - } - - public void setDeviceType(DeviceType deviceType) { - this.deviceType = deviceType; - } - - public SourceAction getSourceAction() { - return sourceAction; - } - - public void setSourceAction(SourceAction sourceAction) { - this.sourceAction = sourceAction; - } - - public DoubleByte getProfileId() { - return profileId; - } - - public void setProfileId(DoubleByte profileId) { - this.profileId = profileId; - } - - public DoubleByte getMfgId() { - return mfgId; - } - - public void setMfgId(DoubleByte mfgId) { - this.mfgId = mfgId; - } - - public void parse(IPacketParser parser) throws IOException { - this.setRemoteAddress64(parser.parseAddress64()); - this.setRemoteAddress16(parser.parseAddress16()); - - int option = parser.read("Option"); - - this.setOption(ZNetRxBaseResponse.getOption(option)); - - this.setRemoteAddress16_2(parser.parseAddress16()); - this.setRemoteAddress64_2(parser.parseAddress64()); - - - StringBuffer ni = new StringBuffer(); - - int ch = 0; - - // NI is terminated with 0 - while ((ch = parser.read("Node Identifier")) != 0) { - ni.append((char)ch); - } - - this.setNodeIdentifier(ni.toString()); - this.setParentAddress(parser.parseAddress16()); - - int deviceType = parser.read("Device Type"); - - if (DeviceType.get(deviceType) != null) { - this.setDeviceType(DeviceType.get(deviceType)); - } else { - log.warn("Unknown device type " + deviceType); - this.setDeviceType(DeviceType.UNKNOWN); - } - - int sourceAction = parser.read("Source Action"); - - if (SourceAction.get(sourceAction) != null) { - this.setSourceAction(SourceAction.get(sourceAction)); - } else { - log.warn("Unknown source event " + sourceAction); - this.setSourceAction(SourceAction.UNKNOWN); - } - - - DoubleByte profileId = new DoubleByte(); - profileId.setMsb(parser.read("Profile MSB")); - profileId.setLsb(parser.read("Profile LSB")); - this.setProfileId(profileId); - - DoubleByte mfgId = new DoubleByte(); - mfgId.setMsb(parser.read("MFG MSB")); - mfgId.setLsb(parser.read("MFG LSB")); - this.setMfgId(mfgId); - } - - @Override - public String toString() { - return "ZNetNodeIdentificationResponse [deviceType=" + deviceType - + ", mfgId=" + mfgId + ", nodeIdentifier=" + nodeIdentifier - + ", option=" + option + ", parentAddress=" + parentAddress - + ", profileId=" + profileId + ", remoteAddress16=" - + remoteAddress16 + ", remoteAddress16_2=" + remoteAddress16_2 - + ", remoteAddress64=" + remoteAddress64 - + ", remoteAddress64_2=" + remoteAddress64_2 - + ", sourceAction=" + sourceAction + "]" + - super.toString(); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.io.IOException; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.zigbee.ZNetRxBaseResponse.Option; +import com.rapplogic.xbee.util.DoubleByte; + +public class ZNetNodeIdentificationResponse extends XBeeResponse { + + private static final long serialVersionUID = 5182657003442708884L; + + private final static Logger log = Logger.getLogger(ZNetNodeIdentificationResponse.class); + + // TODO this is repeated in NodeDiscover + public enum DeviceType { + COORDINATOR (0x1), + ROUTER (0x2), + END_DEVICE (0x3), + UNKNOWN(-1); + + private static final Map lookup = new HashMap(); + + static { + for(DeviceType s: EnumSet.allOf(DeviceType.class)) { + lookup.put(s.getValue(), s); + } + } + + public static DeviceType get(int value) { + return lookup.get(value); + } + + private final int value; + + DeviceType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + public enum SourceAction { + PUSHBUTTON (0x1), + JOINING (0x2), + POWER_CYCLE(0x3), + UNKNOWN(-1); + + private static final Map lookup = new HashMap(); + + static { + for(SourceAction s: EnumSet.allOf(SourceAction.class)) { + lookup.put(s.getValue(), s); + } + } + + public static SourceAction get(int value) { + return lookup.get(value); + } + + private final int value; + + SourceAction(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + private XBeeAddress64 remoteAddress64; + private XBeeAddress16 remoteAddress16; + private Option option; + // TODO Digi WTF why duplicated?? p.70 + private XBeeAddress64 remoteAddress64_2; + private XBeeAddress16 remoteAddress16_2; + + private String nodeIdentifier; + private XBeeAddress16 parentAddress; + private DeviceType deviceType; + private SourceAction sourceAction; + private DoubleByte profileId; + private DoubleByte mfgId; + + public ZNetNodeIdentificationResponse() { + + } + + public XBeeAddress64 getRemoteAddress64() { + return remoteAddress64; + } + + public void setRemoteAddress64(XBeeAddress64 remoteAddress64) { + this.remoteAddress64 = remoteAddress64; + } + + public XBeeAddress16 getRemoteAddress16() { + return remoteAddress16; + } + + public void setRemoteAddress16(XBeeAddress16 remoteAddress16) { + this.remoteAddress16 = remoteAddress16; + } + + public Option getOption() { + return option; + } + + public void setOption(Option option) { + this.option = option; + } + + public XBeeAddress64 getRemoteAddress64_2() { + return remoteAddress64_2; + } + + public void setRemoteAddress64_2(XBeeAddress64 remoteAddress64_2) { + this.remoteAddress64_2 = remoteAddress64_2; + } + + public XBeeAddress16 getRemoteAddress16_2() { + return remoteAddress16_2; + } + + public void setRemoteAddress16_2(XBeeAddress16 remoteAddress16_2) { + this.remoteAddress16_2 = remoteAddress16_2; + } + + public String getNodeIdentifier() { + return nodeIdentifier; + } + + public void setNodeIdentifier(String nodeIdentifier) { + this.nodeIdentifier = nodeIdentifier; + } + + public XBeeAddress16 getParentAddress() { + return parentAddress; + } + + public void setParentAddress(XBeeAddress16 parentAddress) { + this.parentAddress = parentAddress; + } + + public DeviceType getDeviceType() { + return deviceType; + } + + public void setDeviceType(DeviceType deviceType) { + this.deviceType = deviceType; + } + + public SourceAction getSourceAction() { + return sourceAction; + } + + public void setSourceAction(SourceAction sourceAction) { + this.sourceAction = sourceAction; + } + + public DoubleByte getProfileId() { + return profileId; + } + + public void setProfileId(DoubleByte profileId) { + this.profileId = profileId; + } + + public DoubleByte getMfgId() { + return mfgId; + } + + public void setMfgId(DoubleByte mfgId) { + this.mfgId = mfgId; + } + + public void parse(IPacketParser parser) throws IOException { + this.setRemoteAddress64(parser.parseAddress64()); + this.setRemoteAddress16(parser.parseAddress16()); + + int option = parser.read("Option"); + + this.setOption(ZNetRxBaseResponse.getOption(option)); + + this.setRemoteAddress16_2(parser.parseAddress16()); + this.setRemoteAddress64_2(parser.parseAddress64()); + + + StringBuffer ni = new StringBuffer(); + + int ch = 0; + + // NI is terminated with 0 + while ((ch = parser.read("Node Identifier")) != 0) { + ni.append((char)ch); + } + + this.setNodeIdentifier(ni.toString()); + this.setParentAddress(parser.parseAddress16()); + + int deviceType = parser.read("Device Type"); + + if (DeviceType.get(deviceType) != null) { + this.setDeviceType(DeviceType.get(deviceType)); + } else { + log.warn("Unknown device type " + deviceType); + this.setDeviceType(DeviceType.UNKNOWN); + } + + int sourceAction = parser.read("Source Action"); + + if (SourceAction.get(sourceAction) != null) { + this.setSourceAction(SourceAction.get(sourceAction)); + } else { + log.warn("Unknown source event " + sourceAction); + this.setSourceAction(SourceAction.UNKNOWN); + } + + + DoubleByte profileId = new DoubleByte(); + profileId.setMsb(parser.read("Profile MSB")); + profileId.setLsb(parser.read("Profile LSB")); + this.setProfileId(profileId); + + DoubleByte mfgId = new DoubleByte(); + mfgId.setMsb(parser.read("MFG MSB")); + mfgId.setLsb(parser.read("MFG LSB")); + this.setMfgId(mfgId); + } + + @Override + public String toString() { + return "ZNetNodeIdentificationResponse [deviceType=" + deviceType + + ", mfgId=" + mfgId + ", nodeIdentifier=" + nodeIdentifier + + ", option=" + option + ", parentAddress=" + parentAddress + + ", profileId=" + profileId + ", remoteAddress16=" + + remoteAddress16 + ", remoteAddress16_2=" + remoteAddress16_2 + + ", remoteAddress64=" + remoteAddress64 + + ", remoteAddress64_2=" + remoteAddress64_2 + + ", sourceAction=" + sourceAction + "]" + + super.toString(); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/zigbee/ZNetRxBaseResponse.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxBaseResponse.java similarity index 95% rename from src/com/rapplogic/xbee/api/zigbee/ZNetRxBaseResponse.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxBaseResponse.java index df800a7..97e7a91 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZNetRxBaseResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxBaseResponse.java @@ -1,156 +1,158 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.io.IOException; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeResponse; - -/** - * Series 2 XBee. Super class of all Receive packets. - *

- * Note: ZNet RX packets do not include RSSI since it is a mesh network and potentially requires several - * hops to get to the destination. The RSSI of the last hop is available using the DB AT command. - * If your network is not mesh (i.e. composed of a single coordinator and end devices -- no routers) - * then the DB command should provide accurate RSSI. - *

- * @author Andrew Rapp - * - */ -public abstract class ZNetRxBaseResponse extends XBeeResponse { - - private final static Logger log = Logger.getLogger(ZNetRxBaseResponse.class); - - public enum Option { -// 0x01 - Packet Acknowledged -// 0x02 - Packet was a broadcast packet -// 0x20 - Packet encrypted with APS encryption -// 0x40 - Packet was sent from an end device (if known) -// Note: Option values can be combined. For example, a -// 0x40 and a 0x01 will show as a 0x41. Other possible -// values 0x21, 0x22, 0x41, 0x42, 0x60, 0x61, 0x62. - - // TODO ugh this is mess now with bitfield indicators - // TODO ditch the enum, and replace with a class that has isBroadcast(), isPacketAcknowledged() etc - - PACKET_ACKNOWLEDGED (0x01), - BROADCAST_PACKET (0x02), - PACKET_ENCRYPTED_WITH_APS (0x20), - PACKET_SENT_FROM_END_DEVICE(0x40), - PACKET_ACKNOWLEDGED_0x21 (0x21), - PACKET_ACKNOWLEDGED_0x41 (0x41), - PACKET_ACKNOWLEDGED_0x61 (0x61), - PACKET_ENCRYPTED_WITH_APS_PACKET_SENT_FROM_END_DEVICE (0x60), - BROADCAST_PACKET_0x22 (0x22), - BROADCAST_PACKET_0x42 (0x42), - BROADCAST_PACKET_0x62 (0x62), - UNKNOWN(-1); - - private static final Map lookup = new HashMap(); - - static { - for(Option s : EnumSet.allOf(Option.class)) { - lookup.put(s.getValue(), s); - } - } - - public static Option get(int value) { - return lookup.get(value); - } - - private final int value; - - Option(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - // TODO where is frame id?? - - private XBeeAddress64 remoteAddress64; - private XBeeAddress16 remoteAddress16; - private Option option; - - public ZNetRxBaseResponse() { - - } - - public XBeeAddress64 getRemoteAddress64() { - return remoteAddress64; - } - - public void setRemoteAddress64(XBeeAddress64 remoteAddress64) { - this.remoteAddress64 = remoteAddress64; - } - - public XBeeAddress16 getRemoteAddress16() { - return remoteAddress16; - } - - public void setRemoteAddress16(XBeeAddress16 remoteAddress16) { - this.remoteAddress16 = remoteAddress16; - } - - public Option getOption() { - return option; - } - - public void setOption(Option option) { - this.option = option; - } - - protected void parseAddress(IPacketParser parser) throws IOException { - this.setRemoteAddress64(parser.parseAddress64()); - this.setRemoteAddress16(parser.parseAddress16()); - } - - protected static Option getOption(int option) { - if (Option.get(option) != null) { - return Option.get(option); - } else { - log.warn("Unknown response option " + option); - return Option.UNKNOWN; - } - } - - protected void parseOption(IPacketParser parser) throws IOException { - int option = parser.read("ZNet RX Response Option"); - this.setOption(this.getOption(option)); - } - - public String toString() { - return super.toString() + - ",remoteAddress64=" + this.remoteAddress64 + - ",remoteAddress16=" + this.remoteAddress16 + - ",option=" + this.option; - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.io.IOException; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeResponse; + +/** + * Series 2 XBee. Super class of all Receive packets. + *

+ * Note: ZNet RX packets do not include RSSI since it is a mesh network and potentially requires several + * hops to get to the destination. The RSSI of the last hop is available using the DB AT command. + * If your network is not mesh (i.e. composed of a single coordinator and end devices -- no routers) + * then the DB command should provide accurate RSSI. + *

+ * @author Andrew Rapp + * + */ +public abstract class ZNetRxBaseResponse extends XBeeResponse { + + private static final long serialVersionUID = -6988650066046251132L; + + private final static Logger log = Logger.getLogger(ZNetRxBaseResponse.class); + + public enum Option { +// 0x01 - Packet Acknowledged +// 0x02 - Packet was a broadcast packet +// 0x20 - Packet encrypted with APS encryption +// 0x40 - Packet was sent from an end device (if known) +// Note: Option values can be combined. For example, a +// 0x40 and a 0x01 will show as a 0x41. Other possible +// values 0x21, 0x22, 0x41, 0x42, 0x60, 0x61, 0x62. + + // TODO ugh this is mess now with bitfield indicators + // TODO ditch the enum, and replace with a class that has isBroadcast(), isPacketAcknowledged() etc + + PACKET_ACKNOWLEDGED (0x01), + BROADCAST_PACKET (0x02), + PACKET_ENCRYPTED_WITH_APS (0x20), + PACKET_SENT_FROM_END_DEVICE(0x40), + PACKET_ACKNOWLEDGED_0x21 (0x21), + PACKET_ACKNOWLEDGED_0x41 (0x41), + PACKET_ACKNOWLEDGED_0x61 (0x61), + PACKET_ENCRYPTED_WITH_APS_PACKET_SENT_FROM_END_DEVICE (0x60), + BROADCAST_PACKET_0x22 (0x22), + BROADCAST_PACKET_0x42 (0x42), + BROADCAST_PACKET_0x62 (0x62), + UNKNOWN(-1); + + private static final Map lookup = new HashMap(); + + static { + for(Option s : EnumSet.allOf(Option.class)) { + lookup.put(s.getValue(), s); + } + } + + public static Option get(int value) { + return lookup.get(value); + } + + private final int value; + + Option(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + // TODO where is frame id?? + + private XBeeAddress64 remoteAddress64; + private XBeeAddress16 remoteAddress16; + private Option option; + + public ZNetRxBaseResponse() { + + } + + public XBeeAddress64 getRemoteAddress64() { + return remoteAddress64; + } + + public void setRemoteAddress64(XBeeAddress64 remoteAddress64) { + this.remoteAddress64 = remoteAddress64; + } + + public XBeeAddress16 getRemoteAddress16() { + return remoteAddress16; + } + + public void setRemoteAddress16(XBeeAddress16 remoteAddress16) { + this.remoteAddress16 = remoteAddress16; + } + + public Option getOption() { + return option; + } + + public void setOption(Option option) { + this.option = option; + } + + protected void parseAddress(IPacketParser parser) throws IOException { + this.setRemoteAddress64(parser.parseAddress64()); + this.setRemoteAddress16(parser.parseAddress16()); + } + + protected static Option getOption(int option) { + if (Option.get(option) != null) { + return Option.get(option); + } else { + log.warn("Unknown response option " + option); + return Option.UNKNOWN; + } + } + + protected void parseOption(IPacketParser parser) throws IOException { + int option = parser.read("ZNet RX Response Option"); + this.setOption(ZNetRxBaseResponse.getOption(option)); + } + + public String toString() { + return super.toString() + + ",remoteAddress64=" + this.remoteAddress64 + + ",remoteAddress16=" + this.remoteAddress16 + + ",option=" + this.option; + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/zigbee/ZNetRxIoSampleResponse.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxIoSampleResponse.java similarity index 95% rename from src/com/rapplogic/xbee/api/zigbee/ZNetRxIoSampleResponse.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxIoSampleResponse.java index c95d167..e930a62 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZNetRxIoSampleResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxIoSampleResponse.java @@ -1,549 +1,551 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.io.IOException; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.AtCommandResponse; -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.NoRequestResponse; -import com.rapplogic.xbee.api.XBeeParseException; -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.IIntInputStream; -import com.rapplogic.xbee.util.IntArrayInputStream; - -/** - * Series 2 XBee. Represents an I/O Sample response sent from a remote radio. - * Provides access to the XBee's 4 Analog (0-4), 11 Digital (0-7,10-12), and 1 Supply Voltage pins - *

- * Note: Series 2 XBee does not support multiple samples (IT) per packet - *

- * @author andrew - * - */ -public class ZNetRxIoSampleResponse extends ZNetRxBaseResponse implements NoRequestResponse { - - private final static Logger log = Logger.getLogger(ZNetRxIoSampleResponse.class); - - private int digitalChannelMaskMsb; - private int digitalChannelMaskLsb; - private int analogChannelMask; - - // all values that may not be in the packet use Integer to distinguish between null and non-null - private Integer dioMsb; - private Integer dioLsb; - - private final static int SUPPLY_VOLTAGE_INDEX = 4; - private Integer[] analog = new Integer[5]; - - public ZNetRxIoSampleResponse() { - - } - - public static ZNetRxIoSampleResponse parseIsSample(AtCommandResponse response) throws IOException { - - if (!response.getCommand().equals("IS")) { - throw new RuntimeException("This is only applicable to the \"IS\" AT command"); - } - - IntArrayInputStream in = new IntArrayInputStream(response.getValue()); - ZNetRxIoSampleResponse sample = new ZNetRxIoSampleResponse(); - sample.parseIoSample(in); - - return sample; - } - - public void parse(IPacketParser parser) throws IOException { - this.parseAddress(parser); - this.parseOption(parser); - this.parseIoSample((IIntInputStream)parser); - } - - /** - * This method is a bit non standard since it needs to parse an IO sample - * from either a RX response or a Remote AT/Local AT response (IS). - * - * @param ps - * @throws IOException - */ - public void parseIoSample(IIntInputStream parser) throws IOException { - // eat sample size.. always 1 - int size = parser.read("ZNet RX IO Sample Size"); - - if (size != 1) { - throw new XBeeParseException("Sample size is not supported if > 1 for ZNet I/O"); - } - - this.setDigitalChannelMaskMsb(parser.read("ZNet RX IO Sample Digital Mask 1")); - this.setDigitalChannelMaskLsb(parser.read("ZNet RX IO Sample Digital Mask 2")); - this.setAnalogChannelMask(parser.read("ZNet RX IO Sample Analog Channel Mask")); - - // zero out n/a bits - this.analogChannelMask = this.analogChannelMask & 0x8f; //10001111 - // zero out all but bits 3-5 - // TODO apparent bug: channel mask on ZigBee Pro firmware has DIO10/P0 as enabled even though it's set to 01 (RSSI). Digital value reports low. - this.digitalChannelMaskMsb = this.digitalChannelMaskMsb & 0x1c; //11100 - - if (this.containsDigital()) { - log.info("response contains digital data"); - // next two bytes are digital - this.setDioMsb(parser.read("ZNet RX IO DIO MSB")); - this.setDioLsb(parser.read("ZNet RX IO DIO LSB")); - } else { - log.info("response does not contain digital data"); - } - - // parse 10-bit analog values - - int enabledCount = 0; - - for (int i = 0; i < 4; i++) { - if (this.isAnalogEnabled(i)) { - log.info("response contains analog[" + i + "]"); - analog[i] = ByteUtils.parse10BitAnalog(parser, enabledCount); - enabledCount++; - } - } - - if (this.isSupplyVoltageEnabled()) { - analog[SUPPLY_VOLTAGE_INDEX] = ByteUtils.parse10BitAnalog(parser, enabledCount); - enabledCount++; - } - - log.debug("There are " + analog + " analog inputs in this packet"); - } - - public int getDigitalChannelMaskMsb() { - return digitalChannelMaskMsb; - } - - private void setDigitalChannelMaskMsb(int digitalChannelMask1) { - this.digitalChannelMaskMsb = digitalChannelMask1; - } - - public int getDigitalChannelMaskLsb() { - return digitalChannelMaskLsb; - } - - private void setDigitalChannelMaskLsb(int digitalChannelMask2) { - this.digitalChannelMaskLsb = digitalChannelMask2; - } - - public int getAnalogChannelMask() { - return analogChannelMask; - } - - private void setAnalogChannelMask(int analogChannelMask) { - this.analogChannelMask = analogChannelMask; - } - - /** - * Consider using isDigitalEnabled(pin) instead - * - * @return - */ - public boolean isD0Enabled() { - return this.isDigitalEnabled(0); - } - - public boolean isD1Enabled() { - return this.isDigitalEnabled(1); - } - - public boolean isD2Enabled() { - return this.isDigitalEnabled(2); - } - - public boolean isD3Enabled() { - return this.isDigitalEnabled(3); - } - - public boolean isD4Enabled() { - return this.isDigitalEnabled(4); - } - - public boolean isD5Enabled() { - return this.isDigitalEnabled(5); - } - - public boolean isD6Enabled() { - return this.isDigitalEnabled(6); - } - - public boolean isD7Enabled() { - return this.isDigitalEnabled(7); - } - - public boolean isD10Enabled() { - return this.isDigitalEnabled(10); - } - - public boolean isD11Enabled() { - return this.isDigitalEnabled(11); - } - - public boolean isD12Enabled() { - return this.isDigitalEnabled(12); - } - - /** - * Consider using isAnalogEnable(pin) instead - * - * @return - */ - public boolean isA0Enabled() { - return this.isAnalogEnabled(0); - } - - public boolean isA1Enabled() { - return this.isAnalogEnabled(1); - } - - public boolean isA2Enabled() { - return this.isAnalogEnabled(2); - } - - public boolean isA3Enabled() { - return this.isAnalogEnabled(3); - } - - public boolean isDigitalEnabled(int pin) { - if (pin >=0 && pin <= 7) { - return ByteUtils.getBit(this.digitalChannelMaskLsb, pin + 1); - } else if (pin >=10 && pin <= 12) { - return ByteUtils.getBit(this.digitalChannelMaskMsb, pin - 7); - } else { - throw new IllegalArgumentException("Unsupported pin: " + pin); - } - } - - public boolean isAnalogEnabled(int pin) { - if (pin >=0 && pin <= 3) { - return ByteUtils.getBit(this.analogChannelMask, pin + 1); - } else { - throw new IllegalArgumentException("Unsupported pin: " + pin); - } - } - - /** - * (from the spec) The voltage supply threshold is set with the V+ command. If the measured supply voltage falls - * below or equal to this threshold, the supply voltage will be included in the IO sample set. V+ is - * set to 0 by default (do not include the supply voltage). - - * @return - */ - public boolean isSupplyVoltageEnabled() { - return ByteUtils.getBit(this.analogChannelMask, 8); - } - - /** - * Consider using isDigitalOn(pin) - * - * @return - */ - public Boolean isD0On() { - if (isDigitalEnabled(0)) { - return isDigitalOn(0); - } - - return null; - } - - // consider using underscore for readability (isD1_On) - public Boolean isD1On() { - if (isDigitalEnabled(1)) { - return isDigitalOn(1); - } - - return null; - } - - public Boolean isD2On() { - if (isDigitalEnabled(2)) { - return isDigitalOn(2); - } - - return null; - } - - public Boolean isD3On() { - if (isDigitalEnabled(3)) { - return isDigitalOn(3); - } - - return null; - } - - public Boolean isD4On() { - if (isDigitalEnabled(4)) { - return isDigitalOn(4); - } - - return null; - } - - public Boolean isD5On() { - if (isDigitalEnabled(5)) { - return isDigitalOn(5); - } - - return null; - } - - public Boolean isD6On() { - if (isDigitalEnabled(6)) { - return isDigitalOn(6); - } - - return null; - } - - public Boolean isD7On() { - if (isDigitalEnabled(7)) { - return isDigitalOn(7); - } - - return null; - } - - public Boolean isD10On() { - if (isDigitalEnabled(10)) { - return isDigitalOn(10); - } - - return null; - } - - public Boolean isD11On() { - if (isDigitalEnabled(11)) { - return isDigitalOn(11); - } - - return null; - } - - public Boolean isD12On() { - if (isDigitalEnabled(12)) { - return isDigitalOn(12); - } - - return null; - } - - /** - * If digital I/O line (DIO0) is enabled: returns true if digital 0 is HIGH (ON); false if it is LOW (OFF). - * If digital I/O line is not enabled this method returns null as it has no value. - *

- * Important: the pin number corresponds to the logical pin (e.g. D4), not the physical pin number. - *

- * Digital I/O pins seem to report high when open circuit (unconnected) - * - * @return - */ - public Boolean isDigitalOn(int pin) { - if (this.isDigitalEnabled(pin)) { - if (pin >=0 && pin <= 7) { - return ByteUtils.getBit(dioLsb, pin + 1); - } else if (pin >=10 && pin <= 12) { - return ByteUtils.getBit(dioMsb, pin - 7); - } - } - - return null; - } - - /** - * Returns true if this sample contains data from digital inputs - * - * See manual page 68 for byte bit mapping - * - * @return - */ - public boolean containsDigital() { - return this.getDigitalChannelMaskMsb() > 0 || this.getDigitalChannelMaskLsb() > 0; - } - - /** - * Returns true if this sample contains data from analog inputs or supply voltage - * - * How does supply voltage get enabled?? - * - * See manual page 68 for byte bit mapping - * - * @return - */ - public boolean containsAnalog() { - return this.getAnalogChannelMask() > 0; - } - - /** - * Returns the DIO MSB, only if sample contains digital; null otherwise - * - * @return - */ - public Integer getDioMsb() { - return dioMsb; - } - - private void setDioMsb(Integer dioMsb) { - this.dioMsb = dioMsb; - } - - /** - * Returns the DIO LSB, only if sample contains digital; null otherwise - * - * @return - */ - public Integer getDioLsb() { - return dioLsb; - } - - private void setDioLsb(Integer dioLsb) { - this.dioLsb = dioLsb; - } - - /** - * Consider using getAnalog(pin) instead - * - * @return - */ - public Integer getAnalog0() { - return analog[0]; - } - - public void setAnalog0(Integer analog0) { - analog[0] = analog0; - } - - public Integer getAnalog1() { - return analog[1]; - } - - public void setAnalog1(Integer analog1) { - analog[1] = analog1; - } - - public Integer getAnalog2() { - return analog[2]; - } - - public void setAnalog2(Integer analog2) { - analog[2] = analog2; - } - - public Integer getAnalog3() { - return analog[3]; - } - - public void setAnalog3(Integer analog3) { - analog[3] = analog3; - } - - /** - * Returns a 10 bit value of ADC line 0, if enabled. - * Returns null if ADC line 0 is not enabled. - *

- * The range of Digi XBee series 2 ADC is 0 - 1.2V and although I couldn't find this in the spec - * a few google searches seems to confirm. When I connected 3.3V to just one of the ADC pins, it - * displayed its displeasure by reporting all ADC pins at 1023. - *

- * Analog pins seem to float around 512 when open circuit - *

- * The reason this returns null is to prevent bugs in the event that you thought you were reading the - * actual value when the pin is not enabled. - * - * @return - */ - public Integer getAnalog(int pin) { - if (this.isAnalogEnabled(pin)) { - return analog[pin]; - } - - return null; - } - -// public Integer getAnalog(int pin) { -// // analog starts 19 bytes after MSB length, if no dio enabled -// int startIndex = 18; -// -// if (!isAnalogEnabled(pin)) { -// // this pin is not turned on -// return null; -// } -// -// if (this.containsDigital()) { -// // make room for digital i/o -// startIndex+=2; -// } -// -// // start depends on how many pins before this pin are enabled -// for (int i = 0; i < pin; i++) { -// if (isAnalogEnabled(i)) { -// startIndex+=2; -// } -// } -// -// return (this.getProcessedPacketBytes()[startIndex] << 8) + this.getProcessedPacketBytes()[startIndex + 1]; -// } - - public Integer getSupplyVoltage() { - return analog[SUPPLY_VOLTAGE_INDEX]; - } - - public void setSupplyVoltage(Integer supplyVoltage) { - analog[SUPPLY_VOLTAGE_INDEX] = supplyVoltage; - } - - public String toString() { - StringBuilder builder = new StringBuilder(); - - builder.append(super.toString()); - - if (this.containsDigital()) { - for (int i = 0; i <= 7; i++) { - if (this.isDigitalEnabled(i)) { - builder.append(",digital[" + i + "]=" + (this.isDigitalOn(i) ? "high" : "low")); - } - } - - for (int i = 10; i <= 12; i++) { - if (this.isDigitalEnabled(i)) { - builder.append(",digital[" + i + "]=" + (this.isDigitalOn(i) ? "high" : "low")); - } - } - } - - if (this.containsAnalog()) { - for (int i = 0; i <= 3; i++) { - if (this.isAnalogEnabled(i)) { - builder.append(",analog[" + i + "]=" + this.getAnalog(i)); - } - } - - if (this.isSupplyVoltageEnabled()) { - builder.append(",supplyVoltage=" + this.getSupplyVoltage()); - } - } - - return builder.toString(); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.io.IOException; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeParseException; +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.api.responses.NoRequestResponse; +import com.rapplogic.xbee.util.ByteUtils; +import com.rapplogic.xbee.util.IIntInputStream; +import com.rapplogic.xbee.util.IntArrayInputStream; + +/** + * Series 2 XBee. Represents an I/O Sample response sent from a remote radio. + * Provides access to the XBee's 4 Analog (0-4), 11 Digital (0-7,10-12), and 1 Supply Voltage pins + *

+ * Note: Series 2 XBee does not support multiple samples (IT) per packet + *

+ * @author andrew + * + */ +public class ZNetRxIoSampleResponse extends ZNetRxBaseResponse implements NoRequestResponse { + + private static final long serialVersionUID = 8598971303883889698L; + + private final static Logger log = Logger.getLogger(ZNetRxIoSampleResponse.class); + + private int digitalChannelMaskMsb; + private int digitalChannelMaskLsb; + private int analogChannelMask; + + // all values that may not be in the packet use Integer to distinguish between null and non-null + private Integer dioMsb; + private Integer dioLsb; + + private final static int SUPPLY_VOLTAGE_INDEX = 4; + private Integer[] analog = new Integer[5]; + + public ZNetRxIoSampleResponse() { + + } + + public static ZNetRxIoSampleResponse parseIsSample(AtCommandResponse response) throws IOException { + + if (!response.getCommand().equals("IS")) { + throw new RuntimeException("This is only applicable to the \"IS\" AT command"); + } + + IntArrayInputStream in = new IntArrayInputStream(response.getValue()); + ZNetRxIoSampleResponse sample = new ZNetRxIoSampleResponse(); + sample.parseIoSample(in); + + return sample; + } + + public void parse(IPacketParser parser) throws IOException { + this.parseAddress(parser); + this.parseOption(parser); + this.parseIoSample((IIntInputStream)parser); + } + + /** + * This method is a bit non standard since it needs to parse an IO sample + * from either a RX response or a Remote AT/Local AT response (IS). + * + * @param ps + * @throws IOException + */ + public void parseIoSample(IIntInputStream parser) throws IOException { + // eat sample size.. always 1 + int size = parser.read("ZNet RX IO Sample Size"); + + if (size != 1) { + throw new XBeeParseException("Sample size is not supported if > 1 for ZNet I/O"); + } + + this.setDigitalChannelMaskMsb(parser.read("ZNet RX IO Sample Digital Mask 1")); + this.setDigitalChannelMaskLsb(parser.read("ZNet RX IO Sample Digital Mask 2")); + this.setAnalogChannelMask(parser.read("ZNet RX IO Sample Analog Channel Mask")); + + // zero out n/a bits + this.analogChannelMask = this.analogChannelMask & 0x8f; //10001111 + // zero out all but bits 3-5 + // TODO apparent bug: channel mask on ZigBee Pro firmware has DIO10/P0 as enabled even though it's set to 01 (RSSI). Digital value reports low. + this.digitalChannelMaskMsb = this.digitalChannelMaskMsb & 0x1c; //11100 + + if (this.containsDigital()) { + log.info("response contains digital data"); + // next two bytes are digital + this.setDioMsb(parser.read("ZNet RX IO DIO MSB")); + this.setDioLsb(parser.read("ZNet RX IO DIO LSB")); + } else { + log.info("response does not contain digital data"); + } + + // parse 10-bit analog values + + int enabledCount = 0; + + for (int i = 0; i < 4; i++) { + if (this.isAnalogEnabled(i)) { + log.info("response contains analog[" + i + "]"); + analog[i] = ByteUtils.parse10BitAnalog(parser, enabledCount); + enabledCount++; + } + } + + if (this.isSupplyVoltageEnabled()) { + analog[SUPPLY_VOLTAGE_INDEX] = ByteUtils.parse10BitAnalog(parser, enabledCount); + enabledCount++; + } + + log.debug("There are " + analog + " analog inputs in this packet"); + } + + public int getDigitalChannelMaskMsb() { + return digitalChannelMaskMsb; + } + + private void setDigitalChannelMaskMsb(int digitalChannelMask1) { + this.digitalChannelMaskMsb = digitalChannelMask1; + } + + public int getDigitalChannelMaskLsb() { + return digitalChannelMaskLsb; + } + + private void setDigitalChannelMaskLsb(int digitalChannelMask2) { + this.digitalChannelMaskLsb = digitalChannelMask2; + } + + public int getAnalogChannelMask() { + return analogChannelMask; + } + + private void setAnalogChannelMask(int analogChannelMask) { + this.analogChannelMask = analogChannelMask; + } + + /** + * Consider using isDigitalEnabled(pin) instead + * + * @return + */ + public boolean isD0Enabled() { + return this.isDigitalEnabled(0); + } + + public boolean isD1Enabled() { + return this.isDigitalEnabled(1); + } + + public boolean isD2Enabled() { + return this.isDigitalEnabled(2); + } + + public boolean isD3Enabled() { + return this.isDigitalEnabled(3); + } + + public boolean isD4Enabled() { + return this.isDigitalEnabled(4); + } + + public boolean isD5Enabled() { + return this.isDigitalEnabled(5); + } + + public boolean isD6Enabled() { + return this.isDigitalEnabled(6); + } + + public boolean isD7Enabled() { + return this.isDigitalEnabled(7); + } + + public boolean isD10Enabled() { + return this.isDigitalEnabled(10); + } + + public boolean isD11Enabled() { + return this.isDigitalEnabled(11); + } + + public boolean isD12Enabled() { + return this.isDigitalEnabled(12); + } + + /** + * Consider using isAnalogEnable(pin) instead + * + * @return + */ + public boolean isA0Enabled() { + return this.isAnalogEnabled(0); + } + + public boolean isA1Enabled() { + return this.isAnalogEnabled(1); + } + + public boolean isA2Enabled() { + return this.isAnalogEnabled(2); + } + + public boolean isA3Enabled() { + return this.isAnalogEnabled(3); + } + + public boolean isDigitalEnabled(int pin) { + if (pin >=0 && pin <= 7) { + return ByteUtils.getBit(this.digitalChannelMaskLsb, pin + 1); + } else if (pin >=10 && pin <= 12) { + return ByteUtils.getBit(this.digitalChannelMaskMsb, pin - 7); + } else { + throw new IllegalArgumentException("Unsupported pin: " + pin); + } + } + + public boolean isAnalogEnabled(int pin) { + if (pin >=0 && pin <= 3) { + return ByteUtils.getBit(this.analogChannelMask, pin + 1); + } else { + throw new IllegalArgumentException("Unsupported pin: " + pin); + } + } + + /** + * (from the spec) The voltage supply threshold is set with the V+ command. If the measured supply voltage falls + * below or equal to this threshold, the supply voltage will be included in the IO sample set. V+ is + * set to 0 by default (do not include the supply voltage). + + * @return + */ + public boolean isSupplyVoltageEnabled() { + return ByteUtils.getBit(this.analogChannelMask, 8); + } + + /** + * Consider using isDigitalOn(pin) + * + * @return + */ + public Boolean isD0On() { + if (isDigitalEnabled(0)) { + return isDigitalOn(0); + } + + return null; + } + + // consider using underscore for readability (isD1_On) + public Boolean isD1On() { + if (isDigitalEnabled(1)) { + return isDigitalOn(1); + } + + return null; + } + + public Boolean isD2On() { + if (isDigitalEnabled(2)) { + return isDigitalOn(2); + } + + return null; + } + + public Boolean isD3On() { + if (isDigitalEnabled(3)) { + return isDigitalOn(3); + } + + return null; + } + + public Boolean isD4On() { + if (isDigitalEnabled(4)) { + return isDigitalOn(4); + } + + return null; + } + + public Boolean isD5On() { + if (isDigitalEnabled(5)) { + return isDigitalOn(5); + } + + return null; + } + + public Boolean isD6On() { + if (isDigitalEnabled(6)) { + return isDigitalOn(6); + } + + return null; + } + + public Boolean isD7On() { + if (isDigitalEnabled(7)) { + return isDigitalOn(7); + } + + return null; + } + + public Boolean isD10On() { + if (isDigitalEnabled(10)) { + return isDigitalOn(10); + } + + return null; + } + + public Boolean isD11On() { + if (isDigitalEnabled(11)) { + return isDigitalOn(11); + } + + return null; + } + + public Boolean isD12On() { + if (isDigitalEnabled(12)) { + return isDigitalOn(12); + } + + return null; + } + + /** + * If digital I/O line (DIO0) is enabled: returns true if digital 0 is HIGH (ON); false if it is LOW (OFF). + * If digital I/O line is not enabled this method returns null as it has no value. + *

+ * Important: the pin number corresponds to the logical pin (e.g. D4), not the physical pin number. + *

+ * Digital I/O pins seem to report high when open circuit (unconnected) + * + * @return + */ + public Boolean isDigitalOn(int pin) { + if (this.isDigitalEnabled(pin)) { + if (pin >=0 && pin <= 7) { + return ByteUtils.getBit(dioLsb, pin + 1); + } else if (pin >=10 && pin <= 12) { + return ByteUtils.getBit(dioMsb, pin - 7); + } + } + + return null; + } + + /** + * Returns true if this sample contains data from digital inputs + * + * See manual page 68 for byte bit mapping + * + * @return + */ + public boolean containsDigital() { + return this.getDigitalChannelMaskMsb() > 0 || this.getDigitalChannelMaskLsb() > 0; + } + + /** + * Returns true if this sample contains data from analog inputs or supply voltage + * + * How does supply voltage get enabled?? + * + * See manual page 68 for byte bit mapping + * + * @return + */ + public boolean containsAnalog() { + return this.getAnalogChannelMask() > 0; + } + + /** + * Returns the DIO MSB, only if sample contains digital; null otherwise + * + * @return + */ + public Integer getDioMsb() { + return dioMsb; + } + + private void setDioMsb(Integer dioMsb) { + this.dioMsb = dioMsb; + } + + /** + * Returns the DIO LSB, only if sample contains digital; null otherwise + * + * @return + */ + public Integer getDioLsb() { + return dioLsb; + } + + private void setDioLsb(Integer dioLsb) { + this.dioLsb = dioLsb; + } + + /** + * Consider using getAnalog(pin) instead + * + * @return + */ + public Integer getAnalog0() { + return analog[0]; + } + + public void setAnalog0(Integer analog0) { + analog[0] = analog0; + } + + public Integer getAnalog1() { + return analog[1]; + } + + public void setAnalog1(Integer analog1) { + analog[1] = analog1; + } + + public Integer getAnalog2() { + return analog[2]; + } + + public void setAnalog2(Integer analog2) { + analog[2] = analog2; + } + + public Integer getAnalog3() { + return analog[3]; + } + + public void setAnalog3(Integer analog3) { + analog[3] = analog3; + } + + /** + * Returns a 10 bit value of ADC line 0, if enabled. + * Returns null if ADC line 0 is not enabled. + *

+ * The range of Digi XBee series 2 ADC is 0 - 1.2V and although I couldn't find this in the spec + * a few google searches seems to confirm. When I connected 3.3V to just one of the ADC pins, it + * displayed its displeasure by reporting all ADC pins at 1023. + *

+ * Analog pins seem to float around 512 when open circuit + *

+ * The reason this returns null is to prevent bugs in the event that you thought you were reading the + * actual value when the pin is not enabled. + * + * @return + */ + public Integer getAnalog(int pin) { + if (this.isAnalogEnabled(pin)) { + return analog[pin]; + } + + return null; + } + +// public Integer getAnalog(int pin) { +// // analog starts 19 bytes after MSB length, if no dio enabled +// int startIndex = 18; +// +// if (!isAnalogEnabled(pin)) { +// // this pin is not turned on +// return null; +// } +// +// if (this.containsDigital()) { +// // make room for digital i/o +// startIndex+=2; +// } +// +// // start depends on how many pins before this pin are enabled +// for (int i = 0; i < pin; i++) { +// if (isAnalogEnabled(i)) { +// startIndex+=2; +// } +// } +// +// return (this.getProcessedPacketBytes()[startIndex] << 8) + this.getProcessedPacketBytes()[startIndex + 1]; +// } + + public Integer getSupplyVoltage() { + return analog[SUPPLY_VOLTAGE_INDEX]; + } + + public void setSupplyVoltage(Integer supplyVoltage) { + analog[SUPPLY_VOLTAGE_INDEX] = supplyVoltage; + } + + public String toString() { + StringBuilder builder = new StringBuilder(); + + builder.append(super.toString()); + + if (this.containsDigital()) { + for (int i = 0; i <= 7; i++) { + if (this.isDigitalEnabled(i)) { + builder.append(",digital[" + i + "]=" + (this.isDigitalOn(i) ? "high" : "low")); + } + } + + for (int i = 10; i <= 12; i++) { + if (this.isDigitalEnabled(i)) { + builder.append(",digital[" + i + "]=" + (this.isDigitalOn(i) ? "high" : "low")); + } + } + } + + if (this.containsAnalog()) { + for (int i = 0; i <= 3; i++) { + if (this.isAnalogEnabled(i)) { + builder.append(",analog[" + i + "]=" + this.getAnalog(i)); + } + } + + if (this.isSupplyVoltageEnabled()) { + builder.append(",supplyVoltage=" + this.getSupplyVoltage()); + } + } + + return builder.toString(); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/zigbee/ZNetRxResponse.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxResponse.java similarity index 92% rename from src/com/rapplogic/xbee/api/zigbee/ZNetRxResponse.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxResponse.java index 0db24cb..f09d66e 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZNetRxResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetRxResponse.java @@ -1,63 +1,65 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.io.IOException; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.NoRequestResponse; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Series 2 XBee. This packet is received when - * a remote XBee sends a ZNetTxRequest - *

- * API ID: 0x90 - *

- * @author andrew - * - */ -public class ZNetRxResponse extends ZNetRxBaseResponse implements NoRequestResponse { - - private int[] data; - - public ZNetRxResponse() { - super(); - } - - public int[] getData() { - return data; - } - - public void setData(int[] data) { - this.data = data; - } - - public void parse(IPacketParser parser) throws IOException { - this.parseAddress(parser); - this.parseOption(parser); - this.setData(parser.readRemainingBytes()); - } - - public String toString() { - return super.toString() + - ",data=" + ByteUtils.toBase16(this.data); - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.io.IOException; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.responses.NoRequestResponse; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Series 2 XBee. This packet is received when + * a remote XBee sends a ZNetTxRequest + *

+ * API ID: 0x90 + *

+ * @author andrew + * + */ +public class ZNetRxResponse extends ZNetRxBaseResponse implements NoRequestResponse { + + private static final long serialVersionUID = 4719910421796674035L; + + private int[] data; + + public ZNetRxResponse() { + super(); + } + + public int[] getData() { + return data; + } + + public void setData(int[] data) { + this.data = data; + } + + public void parse(IPacketParser parser) throws IOException { + this.parseAddress(parser); + this.parseOption(parser); + this.setData(parser.readRemainingBytes()); + } + + public String toString() { + return super.toString() + + ",data=" + ByteUtils.toBase16(this.data); + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/api/zigbee/ZNetTxRequest.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetTxRequest.java similarity index 96% rename from src/com/rapplogic/xbee/api/zigbee/ZNetTxRequest.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZNetTxRequest.java index 93ee444..a0636b9 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZNetTxRequest.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetTxRequest.java @@ -1,241 +1,243 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeRequest; -import com.rapplogic.xbee.util.ByteUtils; -import com.rapplogic.xbee.util.IntArrayOutputStream; - -/** - * Series 2 XBee. Sends a packet to a remote radio. The remote radio - * receives the data as a ZNetRxResponse packet. - *

- * API ID: 0x10 - *

- * @author andrew - * - */ -public class ZNetTxRequest extends XBeeRequest { - - // 10/28/08 the datasheet states 72 is maximum payload size but I was able to push 75 through successfully, - // even with all bytes as escape bytes (a total post-escape packet size of 169!). - - /** - * This is the maximum payload size for ZNet firmware, as specified in the datasheet. - * This value is provided for reference only and is not enforced by this software unless - * max size unless specified in the setMaxPayloadSize(int) method. - * Note: this size refers to the packet size prior to escaping the control bytes. - * Note: ZB Pro firmware provides the ATNP command to determine max payload size. - * For ZB Pro firmware, the TX Status will return a PAYLOAD_TOO_LARGE (0x74) delivery status - * if the payload size is exceeded - */ - public final static int ZNET_MAX_PAYLOAD_SIZE = 72; - public final static int DEFAULT_BROADCAST_RADIUS = 0; - - private XBeeAddress64 destAddr64; - private XBeeAddress16 destAddr16; - private int broadcastRadius; - private Option option; - private int[] payload; - private int maxPayloadSize; - - //TODO frameId should go last in all Request constructors since it is not specific to any one request - - public enum Option { - - // TODO handle new options. option needs to be an int so you can do Option.UNICAST | Option.DISABLE_RETRIES | Option.USE_EXTENDED_TIMEOUT etc - -// 0x01 - Disable retries and route repair -// 0x20 - Enable APS encryption (if EE=1) -// 0x40 - Use the extended transmission timeout - - UNICAST (0), - BROADCAST (8), - DISABLE_RETRIES (1), - ENABLE_APS_ENCRYPTION (0x20), - USE_EXTENDED_TIMEOUT (0x40); - - private static final Map lookup = new HashMap(); - - static { - for(Option s : EnumSet.allOf(Option.class)) { - lookup.put(s.getValue(), s); - } - } - - public static Option get(int value) { - return lookup.get(value); - } - - private final int value; - - Option(int value) { - this.value = value; - } - - public int getValue() { - return value; - } - } - - /** - * From manual p. 33: - * The ZigBee Transmit Request API frame specifies the 64-bit Address and the network address (if - * known) that the packet should be sent to. By supplying both addresses, the module will forego - * network address Discovery and immediately attempt to route the data packet to the remote. If the - * network address of a particular remote changes, network address and route discovery will take - * place to establish a new route to the correct node. Upon successful - * - * Key points: - * - always specify the 64-bit address and also specify the 16-bit address, if known. Set - * the 16-bit network address to 0xfffe if not known. - * - check the 16-bit address of the tx status response frame as it may change. - * - keep a hash table mapping of 64-bit address to 16-bit network address. - * - * - * @param frameId - * @param dest64 - * @param dest16 - * @param broadcastRadius - * @param option - * @param payload - */ - public ZNetTxRequest(int frameId, XBeeAddress64 dest64, XBeeAddress16 dest16, int broadcastRadius, Option option, int[] payload) { - this.setFrameId(frameId); - this.destAddr64 = dest64; - this.destAddr16 = dest16; - this.broadcastRadius = broadcastRadius; - this.option = option; - this.payload = payload; - } - - /** - * Abbreviated constructor for sending a unicast TX packet - * - * @param dest64 - * @param payload - */ - public ZNetTxRequest(XBeeAddress64 dest64, int[] payload) { - this(XBeeRequest.DEFAULT_FRAME_ID, dest64, XBeeAddress16.ZNET_BROADCAST, ZNetTxRequest.DEFAULT_BROADCAST_RADIUS, Option.UNICAST, payload); - } - - protected IntArrayOutputStream getFrameDataAsIntArrayOutputStream() { - - if (this.getMaxPayloadSize() > 0 && payload.length > this.getMaxPayloadSize()) { - throw new IllegalArgumentException("Payload exceeds user-defined maximum payload size of " + this.getMaxPayloadSize() + " bytes. Please package into multiple packets"); - } - - IntArrayOutputStream out = new IntArrayOutputStream(); - - // api id - out.write(this.getApiId().getValue()); - - // frame id (arbitrary byte that will be sent back with ack) - out.write(this.getFrameId()); - - // add 64-bit dest address - out.write(destAddr64.getAddress()); - - // add 16-bit dest address - out.write(destAddr16.getAddress()); - - // write broadcast radius - out.write(broadcastRadius); - - // write options byte - out.write(option.getValue()); - - out.write(payload); - - return out; - } - - public int[] getFrameData() { - return this.getFrameDataAsIntArrayOutputStream().getIntArray(); - } - - public ApiId getApiId() { - return ApiId.ZNET_TX_REQUEST; - } - - public XBeeAddress64 getDestAddr64() { - return destAddr64; - } - - public void setDestAddr64(XBeeAddress64 destAddr64) { - this.destAddr64 = destAddr64; - } - - public XBeeAddress16 getDestAddr16() { - return destAddr16; - } - - public void setDestAddr16(XBeeAddress16 destAddr16) { - this.destAddr16 = destAddr16; - } - - public int getBroadcastRadius() { - return broadcastRadius; - } - - public void setBroadcastRadius(int broadcastRadius) { - this.broadcastRadius = broadcastRadius; - } - - public Option getOption() { - return option; - } - - public void setOption(Option option) { - this.option = option; - } - - public int[] getPayload() { - return payload; - } - - public void setPayload(int[] payload) { - this.payload = payload; - } - - public String toString() { - return super.toString() + - ",destAddr64=" + this.destAddr64 + - ",destAddr16=" + this.destAddr16 + - ",broadcastRadius=" + this.broadcastRadius + - ",option=" + this.option + - ",payload=" + ByteUtils.toBase16(this.payload); - } - - public int getMaxPayloadSize() { - return maxPayloadSize; - } - - public void setMaxPayloadSize(int maxPayloadSize) { - this.maxPayloadSize = maxPayloadSize; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeRequest; +import com.rapplogic.xbee.util.ByteUtils; +import com.rapplogic.xbee.util.IntArrayOutputStream; + +/** + * Series 2 XBee. Sends a packet to a remote radio. The remote radio + * receives the data as a ZNetRxResponse packet. + *

+ * API ID: 0x10 + *

+ * @author andrew + * + */ +public class ZNetTxRequest extends XBeeRequest { + + private static final long serialVersionUID = -5391715539731414314L; + + // 10/28/08 the datasheet states 72 is maximum payload size but I was able to push 75 through successfully, + // even with all bytes as escape bytes (a total post-escape packet size of 169!). + + /** + * This is the maximum payload size for ZNet firmware, as specified in the datasheet. + * This value is provided for reference only and is not enforced by this software unless + * max size unless specified in the setMaxPayloadSize(int) method. + * Note: this size refers to the packet size prior to escaping the control bytes. + * Note: ZB Pro firmware provides the ATNP command to determine max payload size. + * For ZB Pro firmware, the TX Status will return a PAYLOAD_TOO_LARGE (0x74) delivery status + * if the payload size is exceeded + */ + public final static int ZNET_MAX_PAYLOAD_SIZE = 72; + public final static int DEFAULT_BROADCAST_RADIUS = 0; + + private XBeeAddress64 destAddr64; + private XBeeAddress16 destAddr16; + private int broadcastRadius; + private Option option; + private int[] payload; + private int maxPayloadSize; + + //TODO frameId should go last in all Request constructors since it is not specific to any one request + + public enum Option { + + // TODO handle new options. option needs to be an int so you can do Option.UNICAST | Option.DISABLE_RETRIES | Option.USE_EXTENDED_TIMEOUT etc + +// 0x01 - Disable retries and route repair +// 0x20 - Enable APS encryption (if EE=1) +// 0x40 - Use the extended transmission timeout + + UNICAST (0), + BROADCAST (8), + DISABLE_RETRIES (1), + ENABLE_APS_ENCRYPTION (0x20), + USE_EXTENDED_TIMEOUT (0x40); + + private static final Map lookup = new HashMap(); + + static { + for(Option s : EnumSet.allOf(Option.class)) { + lookup.put(s.getValue(), s); + } + } + + public static Option get(int value) { + return lookup.get(value); + } + + private final int value; + + Option(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + } + + /** + * From manual p. 33: + * The ZigBee Transmit Request API frame specifies the 64-bit Address and the network address (if + * known) that the packet should be sent to. By supplying both addresses, the module will forego + * network address Discovery and immediately attempt to route the data packet to the remote. If the + * network address of a particular remote changes, network address and route discovery will take + * place to establish a new route to the correct node. Upon successful + * + * Key points: + * - always specify the 64-bit address and also specify the 16-bit address, if known. Set + * the 16-bit network address to 0xfffe if not known. + * - check the 16-bit address of the tx status response frame as it may change. + * - keep a hash table mapping of 64-bit address to 16-bit network address. + * + * + * @param frameId + * @param dest64 + * @param dest16 + * @param broadcastRadius + * @param option + * @param payload + */ + public ZNetTxRequest(int frameId, XBeeAddress64 dest64, XBeeAddress16 dest16, int broadcastRadius, Option option, int[] payload) { + this.setFrameId(frameId); + this.destAddr64 = dest64; + this.destAddr16 = dest16; + this.broadcastRadius = broadcastRadius; + this.option = option; + this.payload = payload; + } + + /** + * Abbreviated constructor for sending a unicast TX packet + * + * @param dest64 + * @param payload + */ + public ZNetTxRequest(XBeeAddress64 dest64, int[] payload) { + this(XBeeRequest.DEFAULT_FRAME_ID, dest64, XBeeAddress16.ZNET_BROADCAST, ZNetTxRequest.DEFAULT_BROADCAST_RADIUS, Option.UNICAST, payload); + } + + protected IntArrayOutputStream getFrameDataAsIntArrayOutputStream() { + + if (this.getMaxPayloadSize() > 0 && payload.length > this.getMaxPayloadSize()) { + throw new IllegalArgumentException("Payload exceeds user-defined maximum payload size of " + this.getMaxPayloadSize() + " bytes. Please package into multiple packets"); + } + + IntArrayOutputStream out = new IntArrayOutputStream(); + + // api id + out.write(this.getApiId().getValue()); + + // frame id (arbitrary byte that will be sent back with ack) + out.write(this.getFrameId()); + + // add 64-bit dest address + out.write(destAddr64.getAddress()); + + // add 16-bit dest address + out.write(destAddr16.getAddress()); + + // write broadcast radius + out.write(broadcastRadius); + + // write options byte + out.write(option.getValue()); + + out.write(payload); + + return out; + } + + public int[] getFrameData() { + return this.getFrameDataAsIntArrayOutputStream().getIntArray(); + } + + public ApiId getApiId() { + return ApiId.ZNET_TX_REQUEST; + } + + public XBeeAddress64 getDestAddr64() { + return destAddr64; + } + + public void setDestAddr64(XBeeAddress64 destAddr64) { + this.destAddr64 = destAddr64; + } + + public XBeeAddress16 getDestAddr16() { + return destAddr16; + } + + public void setDestAddr16(XBeeAddress16 destAddr16) { + this.destAddr16 = destAddr16; + } + + public int getBroadcastRadius() { + return broadcastRadius; + } + + public void setBroadcastRadius(int broadcastRadius) { + this.broadcastRadius = broadcastRadius; + } + + public Option getOption() { + return option; + } + + public void setOption(Option option) { + this.option = option; + } + + public int[] getPayload() { + return payload; + } + + public void setPayload(int[] payload) { + this.payload = payload; + } + + public String toString() { + return super.toString() + + ",destAddr64=" + this.destAddr64 + + ",destAddr16=" + this.destAddr16 + + ",broadcastRadius=" + this.broadcastRadius + + ",option=" + this.option + + ",payload=" + ByteUtils.toBase16(this.payload); + } + + public int getMaxPayloadSize() { + return maxPayloadSize; + } + + public void setMaxPayloadSize(int maxPayloadSize) { + this.maxPayloadSize = maxPayloadSize; + } +} diff --git a/src/com/rapplogic/xbee/api/zigbee/ZNetTxStatusResponse.java b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetTxStatusResponse.java similarity index 95% rename from src/com/rapplogic/xbee/api/zigbee/ZNetTxStatusResponse.java rename to src/main/java/com/rapplogic/xbee/api/zigbee/ZNetTxStatusResponse.java index ae1eeb5..be39d73 100644 --- a/src/com/rapplogic/xbee/api/zigbee/ZNetTxStatusResponse.java +++ b/src/main/java/com/rapplogic/xbee/api/zigbee/ZNetTxStatusResponse.java @@ -1,236 +1,238 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.api.zigbee; - -import java.io.IOException; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.Map; - -import org.apache.log4j.Logger; - -import com.rapplogic.xbee.api.IPacketParser; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeFrameIdResponse; - -/** - * Series 2 XBee. This is sent out the UART of the transmitting XBee immediately following - * a Transmit packet. Indicates if the Transmit packet (ZNetTxRequest) - * was successful. - *

- * API ID: 0x8b - *

- * @author andrew - */ -public class ZNetTxStatusResponse extends XBeeFrameIdResponse { - - private final static Logger log = Logger.getLogger(ZNetTxStatusResponse.class); - - public enum DeliveryStatus { -// 0x00 = Success -// 0x01 = MAC ACK Failure -// 0x02 = CCA Failure -// 0x15 = Invalid destination -// endpoint -// 0x21 = Network ACK Failure -// 0x22 = Not Joined to Network -// 0x23 = Self-addressed -// 0x24 = Address Not Found -// 0x25 = Route Not Found -// 0x26 = Broadcast source failed to hear a neighbor relay -// the message -// 0x2B = Invalid binding table index -// 0x2C = Resource error lack of free buffers, timers, etc. -// 0x2D = Attempted broadcast with APS transmission -// 0x2E = Attempted unicast with APS transmission, but -// EE=0 -// 0x32 = Resource error lack of free -// 0x74 = Data payload too large - - SUCCESS (0), - MAC_FAILURE (1), - CCA_FAILURE (0x02), - INVALID_DESTINATION_ENDPOINT (0x15), - NETWORK_ACK_FAILURE (0x21), - NOT_JOINED_TO_NETWORK (0x22), - SELF_ADDRESSED (0x23), - ADDRESS_NOT_FOUND (0x24), - ROUTE_NOT_FOUND (0x25), - BROADCAST_SOURCE_NEIGHBOR_FAILURE (0x26), - INVALID_BINDING_TABLE_INDEX (0x2B), - RESOURCE_ERROR_LACK_FREE_BUFFERS (0x2C), - ATTEMPTED_BROADCAST_WITH_APS_TX (0x2D), - ATTEMPTED_UNICAST_WITH_APS_TX_EE_ZERO (0x2E), - RESOURCE_ERROR_LACK_FREE_BUFFERS_0x32 (0x32), // WUT, SAME AS 2C - PAYLOAD_TOO_LARGE(0x74), // ZB Pro firmware only - UNKNOWN(-1); - - private static final Map lookup = new HashMap(); - - static { - for(DeliveryStatus s : EnumSet.allOf(DeliveryStatus.class)) { - lookup.put(s.getValue(), s); - } - } - - private final int value; - - DeliveryStatus(int value) { - this.value = value; - } - - public static DeliveryStatus get(int value) { - return lookup.get(value); - } - - public int getValue() { - return value; - } - } - - public enum DiscoveryStatus { -// 0x00 = No Discovery Overhead -// 0x01 = Address Discovery -// 0x02 = Route Discovery -// 0x03 = Address and Route -// 0x40 = Extended Timeout Discovery - - // NOTE 0x40 IS A bit field so going to be painful with enums - - NO_DISCOVERY (0), - ADDRESS_DISCOVERY (1), - ROUTE_DISCOVERY (2), - ADDRESS_AND_ROUTE_DISCOVERY (3), - EXTENDED_TIMEOUT_DISCOVERY (0x40), - EXTENDED_TIMEOUT_DISCOVERY_0x41 (0x41), - EXTENDED_TIMEOUT_DISCOVERY_0x42 (0x42), - EXTENDED_TIMEOUT_DISCOVERY_0x43 (0x43), - UNKNOWN(-1); - - private static final Map lookup = new HashMap(); - - static { - for(DiscoveryStatus s : EnumSet.allOf(DiscoveryStatus.class)) { - lookup.put(s.getValue(), s); - } - } - - private final int value; - - DiscoveryStatus(int value) { - this.value = value; - } - - public static DiscoveryStatus get(int value) { - return lookup.get(value); - } - - public int getValue() { - return value; - } - } - - private XBeeAddress16 remoteAddress16; - private int retryCount; - private DeliveryStatus deliveryStatus; - private DiscoveryStatus discoveryStatus; - - - public ZNetTxStatusResponse() { - - } - - public XBeeAddress16 getRemoteAddress16() { - return remoteAddress16; - } - - - public void setRemoteAddress16(XBeeAddress16 remoteAddress) { - this.remoteAddress16 = remoteAddress; - } - - - public int getRetryCount() { - return retryCount; - } - - - public void setRetryCount(int retryCount) { - this.retryCount = retryCount; - } - - public DeliveryStatus getDeliveryStatus() { - return deliveryStatus; - } - - public void setDeliveryStatus(DeliveryStatus deliveryStatus) { - this.deliveryStatus = deliveryStatus; - } - - public DiscoveryStatus getDiscoveryStatus() { - return discoveryStatus; - } - - public void setDiscoveryStatus(DiscoveryStatus discoveryStatus) { - this.discoveryStatus = discoveryStatus; - } - - /** - * Returns true if the delivery status is SUCCESS - * - * @return - */ - public boolean isSuccess() { - return this.getDeliveryStatus() == DeliveryStatus.SUCCESS; - } - - public void parse(IPacketParser parser) throws IOException { - this.setFrameId(parser.read("ZNet Tx Status Frame Id")); - - this.setRemoteAddress16(parser.parseAddress16()); - this.setRetryCount(parser.read("ZNet Tx Status Tx Count")); - - int deliveryStatus = parser.read("ZNet Tx Status Delivery Status"); - - if (DeliveryStatus.get(deliveryStatus) != null) { - this.setDeliveryStatus(DeliveryStatus.get(deliveryStatus)); - } else { - log.warn("Unknown delivery status " + deliveryStatus); - this.setDeliveryStatus(DeliveryStatus.UNKNOWN); - } - - int discoveryStatus = parser.read("ZNet Tx Status Discovery Status"); - - if (DiscoveryStatus.get(discoveryStatus) != null) { - this.setDiscoveryStatus(DiscoveryStatus.get(discoveryStatus)); - } else { - log.warn("Unknown discovery status " + discoveryStatus); - this.setDiscoveryStatus(DiscoveryStatus.UNKNOWN); - } - } - - public String toString() { - return super.toString() + - ",remoteAddress16=" + this.remoteAddress16 + - ",retryCount=" + this.retryCount + - ",deliveryStatus=" + this.deliveryStatus + - ",discoveryStatus=" + this.discoveryStatus; - } +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.api.zigbee; + +import java.io.IOException; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.Map; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.IPacketParser; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.responses.XBeeFrameIdResponse; + +/** + * Series 2 XBee. This is sent out the UART of the transmitting XBee immediately following + * a Transmit packet. Indicates if the Transmit packet (ZNetTxRequest) + * was successful. + *

+ * API ID: 0x8b + *

+ * @author andrew + */ +public class ZNetTxStatusResponse extends XBeeFrameIdResponse { + + private static final long serialVersionUID = 6572415977878338714L; + + private final static Logger log = Logger.getLogger(ZNetTxStatusResponse.class); + + public enum DeliveryStatus { +// 0x00 = Success +// 0x01 = MAC ACK Failure +// 0x02 = CCA Failure +// 0x15 = Invalid destination +// endpoint +// 0x21 = Network ACK Failure +// 0x22 = Not Joined to Network +// 0x23 = Self-addressed +// 0x24 = Address Not Found +// 0x25 = Route Not Found +// 0x26 = Broadcast source failed to hear a neighbor relay +// the message +// 0x2B = Invalid binding table index +// 0x2C = Resource error lack of free buffers, timers, etc. +// 0x2D = Attempted broadcast with APS transmission +// 0x2E = Attempted unicast with APS transmission, but +// EE=0 +// 0x32 = Resource error lack of free +// 0x74 = Data payload too large + + SUCCESS (0), + MAC_FAILURE (1), + CCA_FAILURE (0x02), + INVALID_DESTINATION_ENDPOINT (0x15), + NETWORK_ACK_FAILURE (0x21), + NOT_JOINED_TO_NETWORK (0x22), + SELF_ADDRESSED (0x23), + ADDRESS_NOT_FOUND (0x24), + ROUTE_NOT_FOUND (0x25), + BROADCAST_SOURCE_NEIGHBOR_FAILURE (0x26), + INVALID_BINDING_TABLE_INDEX (0x2B), + RESOURCE_ERROR_LACK_FREE_BUFFERS (0x2C), + ATTEMPTED_BROADCAST_WITH_APS_TX (0x2D), + ATTEMPTED_UNICAST_WITH_APS_TX_EE_ZERO (0x2E), + RESOURCE_ERROR_LACK_FREE_BUFFERS_0x32 (0x32), // WUT, SAME AS 2C + PAYLOAD_TOO_LARGE(0x74), // ZB Pro firmware only + UNKNOWN(-1); + + private static final Map lookup = new HashMap(); + + static { + for(DeliveryStatus s : EnumSet.allOf(DeliveryStatus.class)) { + lookup.put(s.getValue(), s); + } + } + + private final int value; + + DeliveryStatus(int value) { + this.value = value; + } + + public static DeliveryStatus get(int value) { + return lookup.get(value); + } + + public int getValue() { + return value; + } + } + + public enum DiscoveryStatus { +// 0x00 = No Discovery Overhead +// 0x01 = Address Discovery +// 0x02 = Route Discovery +// 0x03 = Address and Route +// 0x40 = Extended Timeout Discovery + + // NOTE 0x40 IS A bit field so going to be painful with enums + + NO_DISCOVERY (0), + ADDRESS_DISCOVERY (1), + ROUTE_DISCOVERY (2), + ADDRESS_AND_ROUTE_DISCOVERY (3), + EXTENDED_TIMEOUT_DISCOVERY (0x40), + EXTENDED_TIMEOUT_DISCOVERY_0x41 (0x41), + EXTENDED_TIMEOUT_DISCOVERY_0x42 (0x42), + EXTENDED_TIMEOUT_DISCOVERY_0x43 (0x43), + UNKNOWN(-1); + + private static final Map lookup = new HashMap(); + + static { + for(DiscoveryStatus s : EnumSet.allOf(DiscoveryStatus.class)) { + lookup.put(s.getValue(), s); + } + } + + private final int value; + + DiscoveryStatus(int value) { + this.value = value; + } + + public static DiscoveryStatus get(int value) { + return lookup.get(value); + } + + public int getValue() { + return value; + } + } + + private XBeeAddress16 remoteAddress16; + private int retryCount; + private DeliveryStatus deliveryStatus; + private DiscoveryStatus discoveryStatus; + + + public ZNetTxStatusResponse() { + + } + + public XBeeAddress16 getRemoteAddress16() { + return remoteAddress16; + } + + + public void setRemoteAddress16(XBeeAddress16 remoteAddress) { + this.remoteAddress16 = remoteAddress; + } + + + public int getRetryCount() { + return retryCount; + } + + + public void setRetryCount(int retryCount) { + this.retryCount = retryCount; + } + + public DeliveryStatus getDeliveryStatus() { + return deliveryStatus; + } + + public void setDeliveryStatus(DeliveryStatus deliveryStatus) { + this.deliveryStatus = deliveryStatus; + } + + public DiscoveryStatus getDiscoveryStatus() { + return discoveryStatus; + } + + public void setDiscoveryStatus(DiscoveryStatus discoveryStatus) { + this.discoveryStatus = discoveryStatus; + } + + /** + * Returns true if the delivery status is SUCCESS + * + * @return + */ + public boolean isSuccess() { + return this.getDeliveryStatus() == DeliveryStatus.SUCCESS; + } + + public void parse(IPacketParser parser) throws IOException { + this.setFrameId(parser.read("ZNet Tx Status Frame Id")); + + this.setRemoteAddress16(parser.parseAddress16()); + this.setRetryCount(parser.read("ZNet Tx Status Tx Count")); + + int deliveryStatus = parser.read("ZNet Tx Status Delivery Status"); + + if (DeliveryStatus.get(deliveryStatus) != null) { + this.setDeliveryStatus(DeliveryStatus.get(deliveryStatus)); + } else { + log.warn("Unknown delivery status " + deliveryStatus); + this.setDeliveryStatus(DeliveryStatus.UNKNOWN); + } + + int discoveryStatus = parser.read("ZNet Tx Status Discovery Status"); + + if (DiscoveryStatus.get(discoveryStatus) != null) { + this.setDiscoveryStatus(DiscoveryStatus.get(discoveryStatus)); + } else { + log.warn("Unknown discovery status " + discoveryStatus); + this.setDiscoveryStatus(DiscoveryStatus.UNKNOWN); + } + } + + public String toString() { + return super.toString() + + ",remoteAddress16=" + this.remoteAddress16 + + ",retryCount=" + this.retryCount + + ",deliveryStatus=" + this.deliveryStatus + + ",discoveryStatus=" + this.discoveryStatus; + } } \ No newline at end of file diff --git a/src/com/rapplogic/xbee/AbstractXBeeConnection.java b/src/main/java/com/rapplogic/xbee/connections/AbstractXBeeConnection.java similarity index 97% rename from src/com/rapplogic/xbee/AbstractXBeeConnection.java rename to src/main/java/com/rapplogic/xbee/connections/AbstractXBeeConnection.java index f83810b..cbf0de7 100644 --- a/src/com/rapplogic/xbee/AbstractXBeeConnection.java +++ b/src/main/java/com/rapplogic/xbee/connections/AbstractXBeeConnection.java @@ -1,4 +1,4 @@ -package com.rapplogic.xbee; +package com.rapplogic.xbee.connections; import java.io.IOException; import java.io.InputStream; diff --git a/src/main/java/com/rapplogic/xbee/connections/SerialPortConnection.java b/src/main/java/com/rapplogic/xbee/connections/SerialPortConnection.java new file mode 100644 index 0000000..ca690e1 --- /dev/null +++ b/src/main/java/com/rapplogic/xbee/connections/SerialPortConnection.java @@ -0,0 +1,165 @@ +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.connections; + +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.TooManyListenersException; + +import jssc.SerialPort; +import jssc.SerialPortEvent; +import jssc.SerialPortEventListener; +import jssc.SerialPortException; +import jssc.SerialPortList; +import jssc.SerialPortTimeoutException; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.XBeeException; + +/** + * This class encapsulates a RXTX serial port, providing access to input/output streams, + * and notifying the subclass of new data events via the handleSerialData method. + * + * @author andrew + * + */ +public class SerialPortConnection implements XBeeConnection, SerialPortEventListener { + + private final static Logger log = Logger.getLogger(SerialPortConnection.class); + + private static final int DEFAULT_TIMEOUT = 5000; + + private SerialPort serialPort; + + private int timeout; + + private long lastDataReceiveTime = 0; + + private long lastDataSendTime = 0; + + public SerialPortConnection() { + + } + + public void openSerialPort(String port, int baudRate) throws TooManyListenersException, IOException, XBeeException, SerialPortException { + this.openSerialPort(port, "XBee", DEFAULT_TIMEOUT, baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, SerialPort.FLOWCONTROL_NONE); + } + + public void openSerialPort(String port, String appName, int timeout, int baudRate) throws TooManyListenersException, IOException, XBeeException, SerialPortException { + this.openSerialPort(port, appName, timeout, baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE, SerialPort.FLOWCONTROL_NONE); + } + + public void openSerialPort(String port, String appName, int timeout, int baudRate, int dataBits, int stopBits, int parity, int flowControl) throws TooManyListenersException, IOException, XBeeException, SerialPortException { + // Apparently you can't query for a specific port, but instead must iterate + Set serialPorts = new HashSet(Arrays.asList(SerialPortList.getPortNames())); + + if (!serialPorts.contains(port)) { + throw new XBeeException("Could not find port: " + port); + } + + this.timeout = timeout; + + serialPort = new SerialPort(port); + serialPort.openPort(); + + serialPort.setParams(baudRate, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE); + serialPort.setFlowControlMode(SerialPort.FLOWCONTROL_NONE); + + serialPort.addEventListener(this); + } + + /** + * Shuts down RXTX + */ + public void close() throws IOException { + try { + serialPort.closePort(); + } catch (SerialPortException e) { + throw new IOException(e); + } + } + + public void serialEvent(SerialPortEvent event) { + try { + if (serialPort.getInputBufferBytesCount() > 0) { + try { + log.debug("serialEvent: " + serialPort.getInputBufferBytesCount() + " bytes available"); + + synchronized (this) { + this.notify(); + } + } catch (Exception e) { + log.error("Error in handleSerialData method", e); + } + } else { + log.warn("We were notified of new data but available() is returning 0"); + } + } catch (SerialPortException ex) { + // it's best not to throw the exception because the RXTX thread may not be prepared to handle + log.error("RXTX error in serialEvent method", ex); + } + } + + public int getByte() throws IOException { + try { + int data = serialPort.readBytes(1, timeout)[0] & 0xFF; + lastDataReceiveTime = System.currentTimeMillis(); + return data; + } catch (SerialPortException e) { + throw new IOException(e); + } catch (SerialPortTimeoutException e) { + throw new IOException(e); + } + } + + public boolean hasData() throws IOException { + try { + return serialPort.getInputBufferBytesCount() > 0; + } catch (SerialPortException e) { + throw new IOException(e); + } + } + + public void writeIntArray(int[] packet) throws IOException { + try { + serialPort.writeIntArray(packet); + lastDataSendTime = System.currentTimeMillis(); + } catch (SerialPortException e) { + throw new IOException(e); + } + } + + public boolean isConnected() { + return serialPort != null && serialPort.isOpened(); + } + + @Override + public long getLastDataReceiveTime() { + return lastDataReceiveTime; + } + + @Override + public long getLastDataSendTime() { + return lastDataSendTime; + } +} \ No newline at end of file diff --git a/src/com/rapplogic/xbee/XBeeConnection.java b/src/main/java/com/rapplogic/xbee/connections/XBeeConnection.java similarity index 62% rename from src/com/rapplogic/xbee/XBeeConnection.java rename to src/main/java/com/rapplogic/xbee/connections/XBeeConnection.java index 4fc57a9..1e5f8d5 100644 --- a/src/com/rapplogic/xbee/XBeeConnection.java +++ b/src/main/java/com/rapplogic/xbee/connections/XBeeConnection.java @@ -1,8 +1,6 @@ -package com.rapplogic.xbee; +package com.rapplogic.xbee.connections; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; /** * Represents a protocol independent connection to a XBee radio (e.g. could be a serial connection, socket, xmpp etc.) @@ -19,7 +17,11 @@ * */ public interface XBeeConnection { - public OutputStream getOutputStream(); - public InputStream getInputStream(); - public void close() throws IOException; + public int getByte() throws IOException; + public boolean hasData() throws IOException; + public void close() throws IOException; + public void writeIntArray(int[] packet) throws IOException; + public boolean isConnected(); + public long getLastDataReceiveTime(); + public long getLastDataSendTime(); } diff --git a/src/main/java/com/rapplogic/xbee/connections/XBeeConnectionException.java b/src/main/java/com/rapplogic/xbee/connections/XBeeConnectionException.java new file mode 100644 index 0000000..cf18b8f --- /dev/null +++ b/src/main/java/com/rapplogic/xbee/connections/XBeeConnectionException.java @@ -0,0 +1,13 @@ +package com.rapplogic.xbee.connections; + +import com.rapplogic.xbee.api.XBeeException; + +public class XBeeConnectionException extends XBeeException { + + private static final long serialVersionUID = 8283447104282352813L; + + public XBeeConnectionException(String message, Exception e) { + super(message, e); + } + +} diff --git a/src/com/rapplogic/xbee/XBeePin.java b/src/main/java/com/rapplogic/xbee/connections/XBeePin.java similarity index 98% rename from src/com/rapplogic/xbee/XBeePin.java rename to src/main/java/com/rapplogic/xbee/connections/XBeePin.java index c6b410b..a347544 100644 --- a/src/com/rapplogic/xbee/XBeePin.java +++ b/src/main/java/com/rapplogic/xbee/connections/XBeePin.java @@ -17,7 +17,7 @@ * along with XBee-API. If not, see . */ -package com.rapplogic.xbee; +package com.rapplogic.xbee.connections; import java.util.ArrayList; import java.util.Collections; @@ -225,10 +225,11 @@ public void setAtPin(Integer atPin) { * @author andrew * */ - private static class PinSorter implements Comparator { - public int compare(Object o1, Object o2) { - return ((XBeePin)o1).getPin().compareTo(((XBeePin)o2).getPin()); - } + private static class PinSorter implements Comparator { + @Override + public int compare(XBeePin o1, XBeePin o2) { + return o1.getPin().compareTo(o2.getPin()); + } } public static List getZigBeePins() { diff --git a/src/main/java/com/rapplogic/xbee/connections/connectionprovider/IConnectionProvider.java b/src/main/java/com/rapplogic/xbee/connections/connectionprovider/IConnectionProvider.java new file mode 100644 index 0000000..81ddeaa --- /dev/null +++ b/src/main/java/com/rapplogic/xbee/connections/connectionprovider/IConnectionProvider.java @@ -0,0 +1,10 @@ +package com.rapplogic.xbee.connections.connectionprovider; + +import com.rapplogic.xbee.connections.XBeeConnection; +import com.rapplogic.xbee.connections.XBeeConnectionException; + +public interface IConnectionProvider { + + XBeeConnection open(String port, int baudRate) throws XBeeConnectionException; + +} diff --git a/src/main/java/com/rapplogic/xbee/connections/connectionprovider/SerialPortConnectionProvider.java b/src/main/java/com/rapplogic/xbee/connections/connectionprovider/SerialPortConnectionProvider.java new file mode 100644 index 0000000..2f7d45e --- /dev/null +++ b/src/main/java/com/rapplogic/xbee/connections/connectionprovider/SerialPortConnectionProvider.java @@ -0,0 +1,26 @@ +package com.rapplogic.xbee.connections.connectionprovider; + +import java.io.IOException; +import java.util.TooManyListenersException; + +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.connections.SerialPortConnection; +import com.rapplogic.xbee.connections.XBeeConnection; +import com.rapplogic.xbee.connections.XBeeConnectionException; + +import jssc.SerialPortException; + +public class SerialPortConnectionProvider implements IConnectionProvider { + + @Override + public XBeeConnection open(String port, int baudRate) throws XBeeConnectionException { + SerialPortConnection serial = new SerialPortConnection(); + try { + serial.openSerialPort(port, baudRate); + } catch (TooManyListenersException | IOException | XBeeException | SerialPortException e) { + throw new XBeeConnectionException("Failed to open connection", e); + } + return serial; + } + +} diff --git a/src/com/rapplogic/xbee/examples/ApiAtExample.java b/src/main/java/com/rapplogic/xbee/examples/ApiAtExample.java similarity index 92% rename from src/com/rapplogic/xbee/examples/ApiAtExample.java rename to src/main/java/com/rapplogic/xbee/examples/ApiAtExample.java index 3d6876a..2951db8 100644 --- a/src/com/rapplogic/xbee/examples/ApiAtExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/ApiAtExample.java @@ -1,78 +1,77 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.AtCommand; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeConfiguration; -import com.rapplogic.xbee.api.XBeeException; - -/** - * The AtCommand/AtCommandResponse classes are supported by both ZNet and WPAN XBees but certain - * commands are specific to ZNet or WPAN. - * - * Commands that are ZNet specific are located in the ZNetApiAtTest. - * - * Refer to the manual for more information on available commands - * - * @author andrew - * - */ -public class ApiAtExample { - -// TODO split class in to WPAN class - - private final static Logger log = Logger.getLogger(ApiAtExample.class); - - private XBee xbee = new XBee(new XBeeConfiguration().withStartupChecks(false)); - - public ApiAtExample() throws XBeeException { - - try { - // replace with port and baud rate of your XBee - xbee.open("/dev/tty.usbserial-A6005uPi", 9600); - -// // set D1 analog input -// this.sendCommand(new AtCommand("D1", 2)); -// // set D2 digital input -// this.sendCommand(new AtCommand("D2", 3)); -// // send sample every 5 seconds -// this.sendCommand(new AtCommand("IR", new int[] {0x13, 0x88})); - - log.info("MY is " + xbee.sendAtCommand(new AtCommand("MY"))); -// log.info("SH is " + xbee.sendAtCommand(new AtCommand("SH"))); -// log.info("SL is " + xbee.sendAtCommand(new AtCommand("SL"))); - } catch (Exception e) { - log.error("at command failed", e); - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws XBeeException { - PropertyConfigurator.configure("log4j.properties"); - new ApiAtExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeConfiguration; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.requests.AtCommand; + +/** + * The AtCommand/AtCommandResponse classes are supported by both ZNet and WPAN XBees but certain + * commands are specific to ZNet or WPAN. + * + * Commands that are ZNet specific are located in the ZNetApiAtTest. + * + * Refer to the manual for more information on available commands + * + * @author andrew + * + */ +public class ApiAtExample { + +// TODO split class in to WPAN class + + private final static Logger log = Logger.getLogger(ApiAtExample.class); + + private XBee xbee = new XBee(new XBeeConfiguration().withStartupChecks(false).withDefaultConnectionProvider()); + + public ApiAtExample() throws XBeeException { + + try { + // replace with port and baud rate of your XBee + xbee.open("/dev/tty.usbserial-A6005uPi", 9600); + +// // set D1 analog input +// this.sendCommand(new AtCommand("D1", 2)); +// // set D2 digital input +// this.sendCommand(new AtCommand("D2", 3)); +// // send sample every 5 seconds +// this.sendCommand(new AtCommand("IR", new int[] {0x13, 0x88})); + + log.info("MY is " + xbee.sendAtCommand(new AtCommand("MY"))); +// log.info("SH is " + xbee.sendAtCommand(new AtCommand("SH"))); +// log.info("SL is " + xbee.sendAtCommand(new AtCommand("SL"))); + } catch (Exception e) { + log.error("at command failed", e); + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws XBeeException { + new ApiAtExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/RemoteAtExample.java b/src/main/java/com/rapplogic/xbee/examples/RemoteAtExample.java similarity index 92% rename from src/com/rapplogic/xbee/examples/RemoteAtExample.java rename to src/main/java/com/rapplogic/xbee/examples/RemoteAtExample.java index 73e1579..4c62377 100644 --- a/src/com/rapplogic/xbee/examples/RemoteAtExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/RemoteAtExample.java @@ -1,106 +1,104 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.RemoteAtRequest; -import com.rapplogic.xbee.api.RemoteAtResponse; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeException; -import com.rapplogic.xbee.api.XBeeTimeoutException; - -/** - * This example uses Remote AT to turn on/off I/O pins. - * This example is more interesting if you connect a LED to pin 20 on your end device. - * Remember to use a resistor to limit the current flow. I used a 215 Ohm resistor. - *

- * Note: if your coordinator is powered on and receiving I/O samples, make sure you power off/on to drain - * the traffic before running this example. - * - * @author andrew - * - */ -public class RemoteAtExample { - - private final static Logger log = Logger.getLogger(RemoteAtExample.class); - - private RemoteAtExample() throws XBeeException, InterruptedException { - - XBee xbee = new XBee(); - - try { - // replace with your coordinator com/baud - xbee.open("/dev/tty.usbserial-A6005v5M", 9600); - // xbee.open("COM5", 9600); - - // replace with SH + SL of your end device - XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x0a, 0x3e, 0x02); - - // turn on end device (pin 20) D0 (Digital output high = 5) - //RemoteAtRequest request = new RemoteAtRequest(addr64, "D0", new int[] {5}); - //RemoteAtRequest request = new RemoteAtRequest(addr64, "IR", new int[] {0x7f, 0xff}); - //RemoteAtRequest request = new RemoteAtRequest(addr64, "D5", new int[] {3}); - //RemoteAtRequest request = new RemoteAtRequest(addr64, "D0", new int[] {2}); - //RemoteAtRequest request = new RemoteAtRequest(addr64, "P2", new int[] {3}); - RemoteAtRequest request = new RemoteAtRequest(addr64, "P0", new int[] {1}); - - RemoteAtResponse response = (RemoteAtResponse) xbee.sendSynchronous(request, 10000); - - if (response.isOk()) { - log.info("successfully turned on pin 20 (D0)"); - } else { - throw new RuntimeException("failed to turn on pin 20. status is " + response.getStatus()); - } - - System.exit(0); - - // wait a bit - Thread.sleep(5000); -// -// // now turn off end device D0 - request.setValue(new int[] {4}); - - response = (RemoteAtResponse) xbee.sendSynchronous(request, 10000); - - if (response.isOk()) { - log.info("successfully turned off pin 20 (D0)"); - } else { - throw new RuntimeException("failed to turn off pin 20. status is " + response.getStatus()); - } - - } catch (XBeeTimeoutException e) { - log.error("request timed out. make sure you remote XBee is configured and powered on"); - } catch (Exception e) { - log.error("unexpected error", e); - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws XBeeException, InterruptedException { - PropertyConfigurator.configure("log4j.properties"); - new RemoteAtExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.XBeeTimeoutException; +import com.rapplogic.xbee.api.requests.RemoteAtRequest; +import com.rapplogic.xbee.api.responses.RemoteAtResponse; + +/** + * This example uses Remote AT to turn on/off I/O pins. + * This example is more interesting if you connect a LED to pin 20 on your end device. + * Remember to use a resistor to limit the current flow. I used a 215 Ohm resistor. + *

+ * Note: if your coordinator is powered on and receiving I/O samples, make sure you power off/on to drain + * the traffic before running this example. + * + * @author andrew + * + */ +public class RemoteAtExample { + + private final static Logger log = Logger.getLogger(RemoteAtExample.class); + + private RemoteAtExample() throws XBeeException, InterruptedException { + + XBee xbee = new XBee(); + + try { + // replace with your coordinator com/baud + xbee.open("/dev/tty.usbserial-A6005v5M", 9600); + + // replace with SH + SL of your end device + XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x0a, 0x3e, 0x02); + + // turn on end device (pin 20) D0 (Digital output high = 5) + //RemoteAtRequest request = new RemoteAtRequest(addr64, "D0", new int[] {5}); + //RemoteAtRequest request = new RemoteAtRequest(addr64, "IR", new int[] {0x7f, 0xff}); + //RemoteAtRequest request = new RemoteAtRequest(addr64, "D5", new int[] {3}); + //RemoteAtRequest request = new RemoteAtRequest(addr64, "D0", new int[] {2}); + //RemoteAtRequest request = new RemoteAtRequest(addr64, "P2", new int[] {3}); + RemoteAtRequest request = new RemoteAtRequest(addr64, "P0", new int[] {1}); + + RemoteAtResponse response = (RemoteAtResponse) xbee.sendSynchronous(request, 10000); + + if (response.isOk()) { + log.info("successfully turned on pin 20 (D0)"); + } else { + throw new RuntimeException("failed to turn on pin 20. status is " + response.getStatus()); + } + + System.exit(0); + + // wait a bit + Thread.sleep(5000); +// +// // now turn off end device D0 + request.setValue(new int[] {4}); + + response = (RemoteAtResponse) xbee.sendSynchronous(request, 10000); + + if (response.isOk()) { + log.info("successfully turned off pin 20 (D0)"); + } else { + throw new RuntimeException("failed to turn off pin 20. status is " + response.getStatus()); + } + + } catch (XBeeTimeoutException e) { + log.error("request timed out. make sure you remote XBee is configured and powered on"); + } catch (Exception e) { + log.error("unexpected error", e); + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws XBeeException, InterruptedException { + new RemoteAtExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/ResponseHandlerExample.java b/src/main/java/com/rapplogic/xbee/examples/ResponseHandlerExample.java similarity index 100% rename from src/com/rapplogic/xbee/examples/ResponseHandlerExample.java rename to src/main/java/com/rapplogic/xbee/examples/ResponseHandlerExample.java diff --git a/src/com/rapplogic/xbee/examples/wpan/ApiReceiverExample.java b/src/main/java/com/rapplogic/xbee/examples/wpan/ApiReceiverExample.java similarity index 90% rename from src/com/rapplogic/xbee/examples/wpan/ApiReceiverExample.java rename to src/main/java/com/rapplogic/xbee/examples/wpan/ApiReceiverExample.java index b2de0eb..6cd65d8 100644 --- a/src/com/rapplogic/xbee/examples/wpan/ApiReceiverExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/wpan/ApiReceiverExample.java @@ -1,99 +1,94 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.wpan; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.ErrorResponse; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.wpan.RxResponse16; -import com.rapplogic.xbee.api.wpan.RxResponse64; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Receives IO samples from remote radio - * I have a photoresistor connected to analog0 and a thermistor is connected to analog1 - * Also there is a breadboard switch connected to digital2 with change detect configured - * - * @author andrew - * - */ -public class ApiReceiverExample { - - private final static Logger log = Logger.getLogger(ApiReceiverExample.class); - - private long last = System.currentTimeMillis(); - - private ApiReceiverExample() throws Exception { - XBee xbee = new XBee(); - - int count = 0; - int errors = 0; - - try { - // my end device - xbee.open("/dev/tty.usbserial-A6005v5M", 9600); - // my coordinator - //xbee.open("/dev/tty.usbserial-A4004Rim", 9600); - - while (true) { - - try { - XBeeResponse response = xbee.getResponse(); - count++; - - if (response.isError()) { - log.info("response contains errors", ((ErrorResponse)response).getException()); - errors++; - } - - for (int i = 0; i < response.getPacketBytes().length; i++) { - log.info("packet [" + i + "] " + ByteUtils.toBase16(response.getPacketBytes()[i])); - } - - if (response.getApiId() == ApiId.RX_16_RESPONSE) { - log.info("Received RX 16 packet " + ((RxResponse16)response)); - } else if (response.getApiId() == ApiId.RX_64_RESPONSE) { - log.info("Received RX 64 packet " + ((RxResponse64)response)); - } else { - log.info("Ignoring mystery packet " + response.toString()); - } - - log.debug("Received response: " + response.toString() + ", count is " + count + ", errors is " + errors); - } catch (Exception e) { - log.error(e); - } - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws Exception { - // init log4j - PropertyConfigurator.configure("log4j.properties"); - new ApiReceiverExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.wpan; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.responses.ErrorResponse; +import com.rapplogic.xbee.api.wpan.RxResponse16; +import com.rapplogic.xbee.api.wpan.RxResponse64; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Receives IO samples from remote radio + * I have a photoresistor connected to analog0 and a thermistor is connected to analog1 + * Also there is a breadboard switch connected to digital2 with change detect configured + * + * @author andrew + * + */ +public class ApiReceiverExample { + + private final static Logger log = Logger.getLogger(ApiReceiverExample.class); + + private ApiReceiverExample() throws Exception { + XBee xbee = new XBee(); + + int count = 0; + int errors = 0; + + try { + // my end device + xbee.open("/dev/tty.usbserial-A6005v5M", 9600); + // my coordinator + //xbee.open("/dev/tty.usbserial-A4004Rim", 9600); + + while (true) { + + try { + XBeeResponse response = xbee.getResponse(); + count++; + + if (response.isError()) { + log.info("response contains errors", ((ErrorResponse)response).getException()); + errors++; + } + + for (int i = 0; i < response.getPacketBytes().length; i++) { + log.info("packet [" + i + "] " + ByteUtils.toBase16(response.getPacketBytes()[i])); + } + + if (response.getApiId() == ApiId.RX_16_RESPONSE) { + log.info("Received RX 16 packet " + ((RxResponse16)response)); + } else if (response.getApiId() == ApiId.RX_64_RESPONSE) { + log.info("Received RX 64 packet " + ((RxResponse64)response)); + } else { + log.info("Ignoring mystery packet " + response.toString()); + } + + log.debug("Received response: " + response.toString() + ", count is " + count + ", errors is " + errors); + } catch (Exception e) { + log.error(e); + } + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws Exception { + new ApiReceiverExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/wpan/ApiSenderExample.java b/src/main/java/com/rapplogic/xbee/examples/wpan/ApiSenderExample.java similarity index 93% rename from src/com/rapplogic/xbee/examples/wpan/ApiSenderExample.java rename to src/main/java/com/rapplogic/xbee/examples/wpan/ApiSenderExample.java index 32dcd38..18b6228 100644 --- a/src/com/rapplogic/xbee/examples/wpan/ApiSenderExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/wpan/ApiSenderExample.java @@ -1,135 +1,132 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.wpan; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeePacket; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.wpan.TxRequest16; -import com.rapplogic.xbee.api.wpan.TxRequest64; -import com.rapplogic.xbee.api.wpan.TxStatusResponse; - -/** - * Sends a TX Request every 5000 ms and waits for TX status packet. - * If the radio is sending samples it will continue to wait for tx status. - * - * @author andrew - * - */ -public class ApiSenderExample { - - private final static Logger log = Logger.getLogger(ApiSenderExample.class); - - private ApiSenderExample() throws Exception { - - XBee xbee = new XBee(); - - final int sleep = 5000; - - int count = 0; - int errors = 0; - int ackErrors = 0; - int ccaErrors = 0; - int purgeErrors = 0; - - long now; - - try { - // replace with port and baud rate of your XBee - xbee.open("/dev/tty.usbserial-A6005uPi", 9600); - - while (true) { - - // log.debug("Sending count " + count); - // XBeeResponse response = xbee.sendTxRequest16(destination, 0x0a, payload); - - // int[] payload = new int[] {1,2,3,4,5,6,7,8}; - // to verify correct byte escaping, we'll send a start byte - int[] payload = new int[] { XBeePacket.SpecialByte.START_BYTE.getValue() }; - - // specify the remote XBee 16-bit MY address - XBeeAddress16 destination = new XBeeAddress16(0x18, 0x74); - TxRequest16 tx = new TxRequest16(destination, payload); - // or send a TX64 (same thing except we are addressing by SH+SL address) -// XBeeAddress64 destination = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x08, 0xb4, 0x8f); -// TxRequest64 tx2 = new TxRequest64(destination64, payload); - - now = System.currentTimeMillis(); - xbee.sendAsynchronous(tx); - - XBeeResponse response = null; - - while (true) { - // blocks until we get response - response = xbee.getResponse(); - - if (response.getApiId() != ApiId.TX_STATUS_RESPONSE) { - log.debug("expected tx status but received " + response); - } else { -// log.debug("got tx status"); - - if (((TxStatusResponse) response).getFrameId() != tx.getFrameId()) { - throw new RuntimeException("frame id does not match"); - } - - if (((TxStatusResponse) response).getStatus() != TxStatusResponse.Status.SUCCESS) { - errors++; - - if (((TxStatusResponse) response).isAckError()) { - ackErrors++; - } else if (((TxStatusResponse) response).isCcaError()) { - ccaErrors++; - } else if (((TxStatusResponse) response).isPurged()) { - purgeErrors++; - } - - log.debug("Tx status failure with status: " + ((TxStatusResponse) response).getStatus()); - } else { - // success - log.debug("Success. count is " + count + ", errors is " + errors + ", in " + (System.currentTimeMillis() - now) + ", ack errors " - + ackErrors + ", ccaErrors " + ccaErrors + ", purge errors " + purgeErrors); - } - - count++; - - break; - } - } - - Thread.sleep(sleep); - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws Exception { - // init log4j - PropertyConfigurator.configure("log4j.properties"); - new ApiSenderExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.wpan; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeePacket; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.wpan.TxRequest16; +import com.rapplogic.xbee.api.wpan.TxStatusResponse; + +/** + * Sends a TX Request every 5000 ms and waits for TX status packet. + * If the radio is sending samples it will continue to wait for tx status. + * + * @author andrew + * + */ +public class ApiSenderExample { + + private final static Logger log = Logger.getLogger(ApiSenderExample.class); + + private ApiSenderExample() throws Exception { + + XBee xbee = new XBee(); + + final int sleep = 5000; + + int count = 0; + int errors = 0; + int ackErrors = 0; + int ccaErrors = 0; + int purgeErrors = 0; + + long now; + + try { + // replace with port and baud rate of your XBee + xbee.open("/dev/tty.usbserial-A6005uPi", 9600); + //xbee.open("COM6", 38400); + + while (true) { + + // log.debug("Sending count " + count); + // XBeeResponse response = xbee.sendTxRequest16(destination, 0x0a, payload); + + // int[] payload = new int[] {1,2,3,4,5,6,7,8}; + // to verify correct byte escaping, we'll send a start byte + int[] payload = new int[] { XBeePacket.SpecialByte.START_BYTE.getValue() }; + + // specify the remote XBee 16-bit MY address + XBeeAddress16 destination = new XBeeAddress16(0x18, 0x74); + TxRequest16 tx = new TxRequest16(destination, payload); + // or send a TX64 (same thing except we are addressing by SH+SL address) +// XBeeAddress64 destination = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x08, 0xb4, 0x8f); +// TxRequest64 tx2 = new TxRequest64(destination64, payload); + + now = System.currentTimeMillis(); + xbee.sendAsynchronous(tx); + + XBeeResponse response = null; + + while (true) { + // blocks until we get response + response = xbee.getResponse(); + + if (response.getApiId() != ApiId.TX_STATUS_RESPONSE) { + log.debug("expected tx status but received " + response); + } else { +// log.debug("got tx status"); + + if (((TxStatusResponse) response).getFrameId() != tx.getFrameId()) { + throw new RuntimeException("frame id does not match"); + } + + if (((TxStatusResponse) response).getStatus() != TxStatusResponse.Status.SUCCESS) { + errors++; + + if (((TxStatusResponse) response).isAckError()) { + ackErrors++; + } else if (((TxStatusResponse) response).isCcaError()) { + ccaErrors++; + } else if (((TxStatusResponse) response).isPurged()) { + purgeErrors++; + } + + log.debug("Tx status failure with status: " + ((TxStatusResponse) response).getStatus()); + } else { + // success + log.debug("Success. count is " + count + ", errors is " + errors + ", in " + (System.currentTimeMillis() - now) + ", ack errors " + + ackErrors + ", ccaErrors " + ccaErrors + ", purge errors " + purgeErrors); + } + + count++; + + break; + } + } + + Thread.sleep(sleep); + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws Exception { + new ApiSenderExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/wpan/IoSamplesExample.java b/src/main/java/com/rapplogic/xbee/examples/wpan/IoSamplesExample.java similarity index 93% rename from src/com/rapplogic/xbee/examples/wpan/IoSamplesExample.java rename to src/main/java/com/rapplogic/xbee/examples/wpan/IoSamplesExample.java index f707c3e..7187999 100644 --- a/src/com/rapplogic/xbee/examples/wpan/IoSamplesExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/wpan/IoSamplesExample.java @@ -1,138 +1,135 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.wpan; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.ErrorResponse; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.wpan.IoSample; -import com.rapplogic.xbee.api.wpan.RxResponseIoSample; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Series 1 XBee -- receive IO samples from remote radio - * In this example we are going to set pin 20 to analog input, pins 11 and 12 to digital input, and configure change detect for pin 12. - * Change detect sends a sample whenever the remote XBee detects a change from or to ground; - * it does not detect the transition from open circuit to high or vice versa. - * - * Configuration: - * - * This assumes we are starting with the factory default settings and the XBee is in API mode (AP = 2) - * - * Remote radio: - * - * MY = 1 necessary? - * sets pin 20 to analog input - * D0 = 2 - * sets pin 11 to digital input - * D4 = 3 - * sets pin 12 to digital input for change detect - * D7 = 3 - * turn on change detect for D7. we need a bit mask of 10000000 (if you can't convert base 2 to hex in your head either, it's 0x80) - * why 10000000? we place a 1 in the position of each input we want to enable, so if you want to enable for D4 and D7 it would be 10010000 - * IC = 80 - * we want 1 sample per packet - * IT = 1 - * receive samples every 5 seconds - * IR = 1388 - * (coordinator address) necessary? doesn't it always send to coordinator? - * DL = 0 - * (save configuration) - * WR - * - * Coordinator: - * - * (set as coordinator) - * CE = 1 - * (set address) - * MY = 0 - * (end device) necessary? - * DL = 1 - * - * - * @author andrew - * - */ -public class IoSamplesExample { - - private final static Logger log = Logger.getLogger(IoSamplesExample.class); - - private IoSamplesExample() throws Exception { - XBee xbee = new XBee(); - - try { - xbee.open("/dev/tty.usbserial-A6005v5M", 9600); - - while (true) { - - try { - XBeeResponse response = xbee.getResponse(); - - log.info("Received i/o response: " + response); - log.info("packet bytes is " + ByteUtils.toBase16(response.getPacketBytes())); - - if (response.isError()) { - log.info("response contains errors", ((ErrorResponse)response).getException()); - continue; - } - - if (response.getApiId() == ApiId.RX_16_IO_RESPONSE) { - RxResponseIoSample ioSample = (RxResponseIoSample)response; - - log.info("Received I/O sample from " + ioSample.getSourceAddress()); - // optionally output the rssi strength - //log.info("rssi is " + ioSample.getRssi()); - - // loops just once since IT = 1 - for (IoSample sample: ioSample.getSamples()) { - if (ioSample.containsAnalog()) { - log.info("Analog pin 20 10-bit reading is " + sample.getAnalog0()); - log.info("Digital pin 11 is " + (sample.isD4On() ? "on" : "off")); - log.info("Digital pin 12 is " + (sample.isD7On() ? "on" : "off")); - } else { - // we know it's change detect since analog was not sent - log.info("Received change detect for Digital pin 12: " + (sample.isD7On() ? "on" : "off")); - } - } - } else { - // not what we expected - log.info("Ignoring mystery packet " + response.toString()); - } - } catch (Exception e) { - log.error(e); - } - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws Exception { - // init log4j - PropertyConfigurator.configure("log4j.properties"); - new IoSamplesExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.wpan; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.responses.ErrorResponse; +import com.rapplogic.xbee.api.wpan.IoSample; +import com.rapplogic.xbee.api.wpan.RxResponseIoSample; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Series 1 XBee -- receive IO samples from remote radio + * In this example we are going to set pin 20 to analog input, pins 11 and 12 to digital input, and configure change detect for pin 12. + * Change detect sends a sample whenever the remote XBee detects a change from or to ground; + * it does not detect the transition from open circuit to high or vice versa. + * + * Configuration: + * + * This assumes we are starting with the factory default settings and the XBee is in API mode (AP = 2) + * + * Remote radio: + * + * MY = 1 necessary? + * sets pin 20 to analog input + * D0 = 2 + * sets pin 11 to digital input + * D4 = 3 + * sets pin 12 to digital input for change detect + * D7 = 3 + * turn on change detect for D7. we need a bit mask of 10000000 (if you can't convert base 2 to hex in your head either, it's 0x80) + * why 10000000? we place a 1 in the position of each input we want to enable, so if you want to enable for D4 and D7 it would be 10010000 + * IC = 80 + * we want 1 sample per packet + * IT = 1 + * receive samples every 5 seconds + * IR = 1388 + * (coordinator address) necessary? doesn't it always send to coordinator? + * DL = 0 + * (save configuration) + * WR + * + * Coordinator: + * + * (set as coordinator) + * CE = 1 + * (set address) + * MY = 0 + * (end device) necessary? + * DL = 1 + * + * + * @author andrew + * + */ +public class IoSamplesExample { + + private final static Logger log = Logger.getLogger(IoSamplesExample.class); + + private IoSamplesExample() throws Exception { + XBee xbee = new XBee(); + + try { + xbee.open("/dev/tty.usbserial-A6005v5M", 9600); + + while (true) { + + try { + XBeeResponse response = xbee.getResponse(); + + log.info("Received i/o response: " + response); + log.info("packet bytes is " + ByteUtils.toBase16(response.getPacketBytes())); + + if (response.isError()) { + log.info("response contains errors", ((ErrorResponse)response).getException()); + continue; + } + + if (response.getApiId() == ApiId.RX_16_IO_RESPONSE) { + RxResponseIoSample ioSample = (RxResponseIoSample)response; + + log.info("Received I/O sample from " + ioSample.getSourceAddress()); + // optionally output the rssi strength + //log.info("rssi is " + ioSample.getRssi()); + + // loops just once since IT = 1 + for (IoSample sample: ioSample.getSamples()) { + if (ioSample.containsAnalog()) { + log.info("Analog pin 20 10-bit reading is " + sample.getAnalog0()); + log.info("Digital pin 11 is " + (sample.isD4On() ? "on" : "off")); + log.info("Digital pin 12 is " + (sample.isD7On() ? "on" : "off")); + } else { + // we know it's change detect since analog was not sent + log.info("Received change detect for Digital pin 12: " + (sample.isD7On() ? "on" : "off")); + } + } + } else { + // not what we expected + log.info("Ignoring mystery packet " + response.toString()); + } + } catch (Exception e) { + log.error(e); + } + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws Exception { + new IoSamplesExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/wpan/Processing.java b/src/main/java/com/rapplogic/xbee/examples/wpan/Processing.java similarity index 100% rename from src/com/rapplogic/xbee/examples/wpan/Processing.java rename to src/main/java/com/rapplogic/xbee/examples/wpan/Processing.java diff --git a/src/com/rapplogic/xbee/examples/wpan/WpanNodeDiscoverExample.java b/src/main/java/com/rapplogic/xbee/examples/wpan/WpanNodeDiscoverExample.java similarity index 94% rename from src/com/rapplogic/xbee/examples/wpan/WpanNodeDiscoverExample.java rename to src/main/java/com/rapplogic/xbee/examples/wpan/WpanNodeDiscoverExample.java index 6ca8727..54a7b89 100644 --- a/src/com/rapplogic/xbee/examples/wpan/WpanNodeDiscoverExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/wpan/WpanNodeDiscoverExample.java @@ -1,105 +1,105 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.wpan; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.AtCommand; -import com.rapplogic.xbee.api.AtCommandResponse; -import com.rapplogic.xbee.api.CollectTerminator; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeException; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.wpan.WpanNodeDiscover; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Example of performing a node discover for Series 1 XBees. - * You must connect to the coordinator to run this example and - * have one or more end devices that are associated. - * - * @author andrew - * - */ -public class WpanNodeDiscoverExample { - - private final static Logger log = Logger.getLogger(WpanNodeDiscoverExample.class); - - private XBee xbee = new XBee(); - - public WpanNodeDiscoverExample() throws XBeeException, InterruptedException { - - try { - // my coordinator com/baud - xbee.open("/dev/tty.usbserial-A4004Rim", 9600); - - // get the Node discovery timeout - xbee.sendAsynchronous(new AtCommand("NT")); - AtCommandResponse nodeTimeout = (AtCommandResponse) xbee.getResponse(); - - // default is 2.5 seconds for series 1 - int nodeDiscoveryTimeout = ByteUtils.convertMultiByteToInt(nodeTimeout.getValue()) * 100; - log.info("Node discovery timeout is " + nodeDiscoveryTimeout + " milliseconds"); - - xbee.sendAsynchronous(new AtCommand("ND")); - - // collect responses up to the timeout or until the terminating response is received, whichever occurs first - List responses = xbee.collectResponses(10000, new CollectTerminator() { - public boolean stop(XBeeResponse response) { - if (response instanceof AtCommandResponse) { - AtCommandResponse at = (AtCommandResponse) response; - if (at.getCommand().equals("ND") && at.getValue() != null && at.getValue().length == 0) { - log.debug("Found terminating response"); - return true; - } - } - return false; - } - }); - - //TODO check for terminating node - - log.info("Time is up! You should have heard back from all nodes by now. If not make sure all nodes are associated and/or try increasing the node timeout (NT)"); - - for (XBeeResponse response : responses) { - if (response instanceof AtCommandResponse) { - AtCommandResponse atResponse = (AtCommandResponse) response; - - if (atResponse.getCommand().equals("ND") && atResponse.getValue() != null && atResponse.getValue().length > 0) { - WpanNodeDiscover nd = WpanNodeDiscover.parse((AtCommandResponse)response); - log.info("Node Discover is " + nd); - } - } - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws XBeeException, InterruptedException { - PropertyConfigurator.configure("log4j.properties"); - new WpanNodeDiscoverExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.wpan; + +import java.util.List; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +import com.rapplogic.xbee.api.CollectTerminator; +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.requests.AtCommand; +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.api.wpan.WpanNodeDiscover; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Example of performing a node discover for Series 1 XBees. + * You must connect to the coordinator to run this example and + * have one or more end devices that are associated. + * + * @author andrew + * + */ +public class WpanNodeDiscoverExample { + + private final static Logger log = Logger.getLogger(WpanNodeDiscoverExample.class); + + private XBee xbee = new XBee(); + + public WpanNodeDiscoverExample() throws XBeeException, InterruptedException { + + try { + // my coordinator com/baud + xbee.open("/dev/tty.usbserial-A4004Rim", 9600); + + // get the Node discovery timeout + xbee.sendAsynchronous(new AtCommand("NT")); + AtCommandResponse nodeTimeout = (AtCommandResponse) xbee.getResponse(); + + // default is 2.5 seconds for series 1 + int nodeDiscoveryTimeout = ByteUtils.convertMultiByteToInt(nodeTimeout.getValue()) * 100; + log.info("Node discovery timeout is " + nodeDiscoveryTimeout + " milliseconds"); + + xbee.sendAsynchronous(new AtCommand("ND")); + + // collect responses up to the timeout or until the terminating response is received, whichever occurs first + List responses = xbee.collectResponses(10000, new CollectTerminator() { + public boolean stop(XBeeResponse response) { + if (response instanceof AtCommandResponse) { + AtCommandResponse at = (AtCommandResponse) response; + if (at.getCommand().equals("ND") && at.getValue() != null && at.getValue().length == 0) { + log.debug("Found terminating response"); + return true; + } + } + return false; + } + }); + + //TODO check for terminating node + + log.info("Time is up! You should have heard back from all nodes by now. If not make sure all nodes are associated and/or try increasing the node timeout (NT)"); + + for (XBeeResponse response : responses) { + if (response instanceof AtCommandResponse) { + AtCommandResponse atResponse = (AtCommandResponse) response; + + if (atResponse.getCommand().equals("ND") && atResponse.getValue() != null && atResponse.getValue().length > 0) { + WpanNodeDiscover nd = WpanNodeDiscover.parse((AtCommandResponse)response); + log.info("Node Discover is " + nd); + } + } + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws XBeeException, InterruptedException { + PropertyConfigurator.configure("log4j.properties"); + new WpanNodeDiscoverExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/BroadcastReceiverExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/BroadcastReceiverExample.java similarity index 91% rename from src/com/rapplogic/xbee/examples/zigbee/BroadcastReceiverExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/BroadcastReceiverExample.java index 61db559..b9a55b5 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/BroadcastReceiverExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/BroadcastReceiverExample.java @@ -1,59 +1,57 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeException; -import com.rapplogic.xbee.api.XBeeResponse; - -/** - * @author andrew - */ -public class BroadcastReceiverExample { - - private final static Logger log = Logger.getLogger(BroadcastReceiverExample.class); - - private BroadcastReceiverExample() throws XBeeException { - - XBee xbee = new XBee(); - - try { - // replace with your com port and baud rate. this is the com port of my coordinator - xbee.open("/dev/tty.usbserial-A6005uPi", 9600); - - while (true) { - XBeeResponse response = xbee.getResponse(); - log.info("received response " + response); - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws XBeeException, InterruptedException { - PropertyConfigurator.configure("log4j.properties"); - new BroadcastReceiverExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.XBeeResponse; + +/** + * @author andrew + */ +public class BroadcastReceiverExample { + + private final static Logger log = Logger.getLogger(BroadcastReceiverExample.class); + + private BroadcastReceiverExample() throws XBeeException { + + XBee xbee = new XBee(); + + try { + // replace with your com port and baud rate. this is the com port of my coordinator + xbee.open("/dev/tty.usbserial-A6005uPi", 9600); + + while (true) { + XBeeResponse response = xbee.getResponse(); + log.info("received response " + response); + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws XBeeException, InterruptedException { + new BroadcastReceiverExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/BroadcastSenderExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/BroadcastSenderExample.java similarity index 93% rename from src/com/rapplogic/xbee/examples/zigbee/BroadcastSenderExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/BroadcastSenderExample.java index 7d21e31..244c96b 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/BroadcastSenderExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/BroadcastSenderExample.java @@ -1,77 +1,75 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeException; -import com.rapplogic.xbee.api.zigbee.ZNetTxRequest; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * @author andrew - */ -public class BroadcastSenderExample { - - private final static Logger log = Logger.getLogger(BroadcastSenderExample.class); - - private BroadcastSenderExample() throws XBeeException { - - XBee xbee = new XBee(); - - try { - // replace with your com port and baud rate. this is the com port of my coordinator - xbee.open("/dev/ttyUSB0", 9600); - - while (true) { - // put some arbitrary data in the payload - int[] payload = ByteUtils.stringToIntArray("the\nquick\nbrown\nfox"); - - ZNetTxRequest request = new ZNetTxRequest(XBeeAddress64.BROADCAST, payload); - // make it a broadcast packet - request.setOption(ZNetTxRequest.Option.BROADCAST); - - log.info("request packet bytes (base 16) " + ByteUtils.toBase16(request.getXBeePacket().getPacket())); - - xbee.sendAsynchronous(request); - // we just assume it was sent. that's just the way it is with broadcast. - // no transmit status response is sent, so don't bother calling getResponse() - - try { - // wait a bit then send another packet - Thread.sleep(15000); - } catch (InterruptedException e) { - } - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws XBeeException, InterruptedException { - PropertyConfigurator.configure("log4j.properties"); - new BroadcastSenderExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.zigbee.ZNetTxRequest; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * @author andrew + */ +public class BroadcastSenderExample { + + private final static Logger log = Logger.getLogger(BroadcastSenderExample.class); + + private BroadcastSenderExample() throws XBeeException { + + XBee xbee = new XBee(); + + try { + // replace with your com port and baud rate. this is the com port of my coordinator + xbee.open("/dev/ttyUSB0", 9600); + + while (true) { + // put some arbitrary data in the payload + int[] payload = ByteUtils.stringToIntArray("the\nquick\nbrown\nfox"); + + ZNetTxRequest request = new ZNetTxRequest(XBeeAddress64.BROADCAST, payload); + // make it a broadcast packet + request.setOption(ZNetTxRequest.Option.BROADCAST); + + log.info("request packet bytes (base 16) " + ByteUtils.toBase16(request.getXBeePacket().getPacket())); + + xbee.sendAsynchronous(request); + // we just assume it was sent. that's just the way it is with broadcast. + // no transmit status response is sent, so don't bother calling getResponse() + + try { + // wait a bit then send another packet + Thread.sleep(15000); + } catch (InterruptedException e) { + } + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws XBeeException, InterruptedException { + new BroadcastSenderExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/SleepTestCoordinator.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/SleepTestCoordinator.java similarity index 93% rename from src/com/rapplogic/xbee/examples/zigbee/SleepTestCoordinator.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/SleepTestCoordinator.java index c21bff5..31edeab 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/SleepTestCoordinator.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/SleepTestCoordinator.java @@ -3,13 +3,13 @@ import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; -import com.rapplogic.xbee.api.RemoteAtRequest; -import com.rapplogic.xbee.api.RemoteAtResponse; import com.rapplogic.xbee.api.XBee; import com.rapplogic.xbee.api.XBeeAddress64; import com.rapplogic.xbee.api.XBeeConfiguration; import com.rapplogic.xbee.api.XBeeException; import com.rapplogic.xbee.api.XBeeTimeoutException; +import com.rapplogic.xbee.api.requests.RemoteAtRequest; +import com.rapplogic.xbee.api.responses.RemoteAtResponse; /** * The premise of this example is we have a end device configured in cyclic sleep. We'll send a command @@ -27,7 +27,7 @@ public SleepTestCoordinator(String args[]) throws XBeeTimeoutException, XBeeExce PropertyConfigurator.configure("log4j.properties"); - XBee xbee = new XBee(new XBeeConfiguration().withStartupChecks(false)); + XBee xbee = new XBee(new XBeeConfiguration().withStartupChecks(false).withDefaultConnectionProvider()); //coord xbee.open("/dev/tty.usbserial-A6005uRz", 9600); diff --git a/src/com/rapplogic/xbee/examples/zigbee/ZBForceSampleExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZBForceSampleExample.java similarity index 93% rename from src/com/rapplogic/xbee/examples/zigbee/ZBForceSampleExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/ZBForceSampleExample.java index 71e22eb..7f93363 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/ZBForceSampleExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZBForceSampleExample.java @@ -1,94 +1,92 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeRequest; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.XBeeTimeoutException; -import com.rapplogic.xbee.api.RemoteAtResponse; -import com.rapplogic.xbee.api.zigbee.ZBForceSampleRequest; -import com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse; - -/** - * To run this sample you will need to configure pin 19 (D1) to Analog input on the remote XBee: D1=2. - * To do this you can use X-CTU, the AtCommand [new AtCommand("D1", 2)] with your remote XBee connected to the serial port - * or with RemoteAtRequest and send the request through the coordinator. - * - * @author andrew - * - */ -public class ZBForceSampleExample { - - private final static Logger log = Logger.getLogger(ZBForceSampleExample.class); - - private ZBForceSampleExample() throws Exception { - XBee xbee = new XBee(); - - try { - // replace with the com port of your XBee coordinator - xbee.open("/dev/tty.usbserial-A6005v5M", 9600); - - while (true) { - // All XBees allow you to request an I/O sample on a local XBee (serial connected), however this is not very interesting. - // With ZNet/ZB Pro radios we can use Remote AT to force an I/O sample on an end device. - // The following code issues a force sample on a XBee end device and parses the io sample. - - // replace with your end device 64-bit address - XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x0a, 0x3e, 0x02); - - XBeeRequest request = new ZBForceSampleRequest(addr64); - - try { - XBeeResponse response = xbee.sendSynchronous(request, 6000); - RemoteAtResponse remoteAt = (RemoteAtResponse) response; - - if (remoteAt.isOk()) { - // extract the i/o sample - ZNetRxIoSampleResponse ioSample = ZNetRxIoSampleResponse.parseIsSample(remoteAt); - // make sure you configured the remote XBee to D1=2 (analog input) or you will get an error - log.info("10 bit analog1 sample is " + ioSample.getAnalog1()); - } else { - log.info("Remote AT request failed: " + response); - } - } catch (XBeeTimeoutException e) { - log.info("request timed out"); - } - - // wait a bit - Thread.sleep(2000); - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws Exception { - // init log4j - PropertyConfigurator.configure("log4j.properties"); - new ZBForceSampleExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeRequest; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.XBeeTimeoutException; +import com.rapplogic.xbee.api.responses.RemoteAtResponse; +import com.rapplogic.xbee.api.zigbee.ZBForceSampleRequest; +import com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse; + +/** + * To run this sample you will need to configure pin 19 (D1) to Analog input on the remote XBee: D1=2. + * To do this you can use X-CTU, the AtCommand [new AtCommand("D1", 2)] with your remote XBee connected to the serial port + * or with RemoteAtRequest and send the request through the coordinator. + * + * @author andrew + * + */ +public class ZBForceSampleExample { + + private final static Logger log = Logger.getLogger(ZBForceSampleExample.class); + + private ZBForceSampleExample() throws Exception { + XBee xbee = new XBee(); + + try { + // replace with the com port of your XBee coordinator + xbee.open("/dev/tty.usbserial-A6005v5M", 9600); + + while (true) { + // All XBees allow you to request an I/O sample on a local XBee (serial connected), however this is not very interesting. + // With ZNet/ZB Pro radios we can use Remote AT to force an I/O sample on an end device. + // The following code issues a force sample on a XBee end device and parses the io sample. + + // replace with your end device 64-bit address + XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x0a, 0x3e, 0x02); + + XBeeRequest request = new ZBForceSampleRequest(addr64); + + try { + XBeeResponse response = xbee.sendSynchronous(request, 6000); + RemoteAtResponse remoteAt = (RemoteAtResponse) response; + + if (remoteAt.isOk()) { + // extract the i/o sample + ZNetRxIoSampleResponse ioSample = ZNetRxIoSampleResponse.parseIsSample(remoteAt); + // make sure you configured the remote XBee to D1=2 (analog input) or you will get an error + log.info("10 bit analog1 sample is " + ioSample.getAnalog1()); + } else { + log.info("Remote AT request failed: " + response); + } + } catch (XBeeTimeoutException e) { + log.info("request timed out"); + } + + // wait a bit + Thread.sleep(2000); + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws Exception { + new ZBForceSampleExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/ZBNodeDiscoverExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZBNodeDiscoverExample.java similarity index 89% rename from src/com/rapplogic/xbee/examples/zigbee/ZBNodeDiscoverExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/ZBNodeDiscoverExample.java index ce94fb3..769c96b 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/ZBNodeDiscoverExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZBNodeDiscoverExample.java @@ -1,96 +1,92 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import java.util.List; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.AtCommand; -import com.rapplogic.xbee.api.AtCommandResponse; -import com.rapplogic.xbee.api.PacketListener; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeException; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.zigbee.ZBNodeDiscover; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * Example of performing a node discover for Series 2 XBees. - * You must connect to the coordinator to run this example and - * have one or more end device/routers that are associated. - * - * @author andrew - * - */ -public class ZBNodeDiscoverExample { - - private final static Logger log = Logger.getLogger(ZBNodeDiscoverExample.class); - - private XBee xbee = new XBee(); - - public ZBNodeDiscoverExample() throws XBeeException, InterruptedException { - - try { - // replace with your serial port - xbee.open("/dev/tty.usbserial-A6005v5M", 9600); - - - // get the Node discovery timeout - xbee.sendAsynchronous(new AtCommand("NT")); - AtCommandResponse nodeTimeout = (AtCommandResponse) xbee.getResponse(); - - // default is 6 seconds - int nodeDiscoveryTimeout = ByteUtils.convertMultiByteToInt(nodeTimeout.getValue()) * 100; - log.info("Node discovery timeout is " + nodeDiscoveryTimeout + " milliseconds"); - - log.info("Sending Node Discover command"); - xbee.sendAsynchronous(new AtCommand("ND")); - - // NOTE: increase NT if you are not seeing all your nodes reported - - List responses = xbee.collectResponses(nodeDiscoveryTimeout); - - log.info("Time is up! You should have heard back from all nodes by now. If not make sure all nodes are associated and/or try increasing the node timeout (NT)"); - - for (XBeeResponse response : responses) { - if (response instanceof AtCommandResponse) { - AtCommandResponse atResponse = (AtCommandResponse) response; - - if (atResponse.getCommand().equals("ND") && atResponse.getValue() != null && atResponse.getValue().length > 0) { - ZBNodeDiscover nd = ZBNodeDiscover.parse((AtCommandResponse)response); - log.info("Node Discover is " + nd); - } - } - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws XBeeException, InterruptedException { - PropertyConfigurator.configure("log4j.properties"); - new ZBNodeDiscoverExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import java.util.List; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.requests.AtCommand; +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.api.zigbee.ZBNodeDiscover; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * Example of performing a node discover for Series 2 XBees. + * You must connect to the coordinator to run this example and + * have one or more end device/routers that are associated. + * + * @author andrew + * + */ +public class ZBNodeDiscoverExample { + + private final static Logger log = Logger.getLogger(ZBNodeDiscoverExample.class); + + private XBee xbee = new XBee(); + + public ZBNodeDiscoverExample() throws XBeeException, InterruptedException { + + try { + // replace with your serial port + xbee.open("/dev/tty.usbserial-A6005v5M", 9600); + + + // get the Node discovery timeout + xbee.sendAsynchronous(new AtCommand("NT")); + AtCommandResponse nodeTimeout = (AtCommandResponse) xbee.getResponse(); + + // default is 6 seconds + int nodeDiscoveryTimeout = ByteUtils.convertMultiByteToInt(nodeTimeout.getValue()) * 100; + log.info("Node discovery timeout is " + nodeDiscoveryTimeout + " milliseconds"); + + log.info("Sending Node Discover command"); + xbee.sendAsynchronous(new AtCommand("ND")); + + // NOTE: increase NT if you are not seeing all your nodes reported + + List responses = xbee.collectResponses(nodeDiscoveryTimeout); + + log.info("Time is up! You should have heard back from all nodes by now. If not make sure all nodes are associated and/or try increasing the node timeout (NT)"); + + for (XBeeResponse response : responses) { + if (response instanceof AtCommandResponse) { + AtCommandResponse atResponse = (AtCommandResponse) response; + + if (atResponse.getCommand().equals("ND") && atResponse.getValue() != null && atResponse.getValue().length > 0) { + ZBNodeDiscover nd = ZBNodeDiscover.parse((AtCommandResponse)response); + log.info("Node Discover is " + nd); + } + } + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws XBeeException, InterruptedException { + new ZBNodeDiscoverExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/ZNetApiAtExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetApiAtExample.java old mode 100755 new mode 100644 similarity index 94% rename from src/com/rapplogic/xbee/examples/zigbee/ZNetApiAtExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetApiAtExample.java index f786936..567665f --- a/src/com/rapplogic/xbee/examples/zigbee/ZNetApiAtExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetApiAtExample.java @@ -1,171 +1,169 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.AtCommand; -import com.rapplogic.xbee.api.AtCommandResponse; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeException; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.zigbee.AssociationStatus; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * This class contains AtCommand examples that are specific to ZNet radios - * - * @author andrew - * - */ -public class ZNetApiAtExample { - - private final static Logger log = Logger.getLogger(ZNetApiAtExample.class); - - private XBee xbee = new XBee(); - - public ZNetApiAtExample() throws XBeeException { - try { - - // replace with port and baud rate of your XBee - xbee.open("COM6", 9600); - - // get the 8 byte SH/SL address - log.debug("SH is " + ByteUtils.toBase16(((AtCommandResponse)xbee.sendAtCommand(new AtCommand("SH"))).getValue())); - log.debug("SL is " + ByteUtils.toBase16(((AtCommandResponse)xbee.sendAtCommand(new AtCommand("SL"))).getValue())); - - // uncomment to run -// this.configureIOSamples(xbee); -// this.associationStatus(xbee); -// this.nodeDiscover(xbee); -// this.configureCoordinator(xbee); -// this.configureEndDevice(xbee); - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - private void associationStatus(XBee xbee) throws XBeeException { - // get association status - success indicates it is associated to another XBee - AtCommandResponse response = (AtCommandResponse) xbee.sendAtCommand(new AtCommand("AI")); - log.debug("Association Status is " + AssociationStatus.get(response)); - } - - private void configureEndDevice(XBee xbee) throws XBeeException { - - // basic end device configuration (assumes ZNet radio flashed with end device API firmware) - XBeeResponse response = null; - - // reset to factory settings - response = xbee.sendAtCommand(new AtCommand("RE")); - log.debug("RE is " + response); - - // set PAN id to arbitrary value - response = xbee.sendAtCommand(new AtCommand("ID", new int[] {0x1a, 0xaa})); - log.debug("ID is " + response); - - // set NI -- can be any arbitrary sequence of chars - response = xbee.sendAtCommand(new AtCommand("NI", new int[] {'E','N','D','_','D','E','V','I','C','E','_','2' })); - log.debug("NI is " + response); - - // set API mode to 2. factory setting is 1 - response = xbee.sendAtCommand(new AtCommand("AP", 2)); - log.debug("AP is " + response); - - // save to settings to survive power cycle - response = xbee.sendAtCommand(new AtCommand("WR")); - log.debug("WR is " + response); - - // software reset - response = xbee.sendAtCommand(new AtCommand("FR")); - log.debug("FR is " + response); - } - - private void configureCoordinator(XBee xbee) throws XBeeException { - // basic coordinator configuration (assumes ZNet radio flashed with COORDINATOR API firmware) - XBeeResponse response = null; - - // reset to factory settings - response = xbee.sendAtCommand(new AtCommand("RE")); - log.debug("RE is " + response); - - // set PAN id to arbitrary value - response = xbee.sendAtCommand(new AtCommand("ID", new int[] {0x1a, 0xaa})); - log.debug("RE is " + response); - - // set NI - response = xbee.sendAtCommand(new AtCommand("NI", new int[] {'C','O','O','R','D','I','N','A','T','O','R' })); - log.debug("NI is " + response); - - // set API mode to 2. factory setting is 1 - response = xbee.sendAtCommand(new AtCommand("AP", 2)); - log.debug("AP is " + response); - - // save to settings to survive power cycle - response = xbee.sendAtCommand(new AtCommand("WR")); - log.debug("WR is " + response); - - // software reset - response = xbee.sendAtCommand(new AtCommand("FR")); - log.debug("FR is " + response); - } - - /** - * This assumes an end device that is already has the configureEndDevice configuration - * Does not save configuration! -- use WR if you want this configure to survive power on/off. - * - * @param xbee - * @throws XBeeException - */ - private void configureIOSamples(XBee xbee) throws XBeeException { - // basic coordinator configuration (assumes ZNet radio flashed with COORDINATOR API firmware) - XBeeResponse response = null; - - // set IR to 1 sample every 10 seconds. Set to 0 to disable - response = xbee.sendAtCommand(new AtCommand("IR", new int[] {0x27, 0x10})); - log.debug("IR is " + response); - - // set pin 20 to monitor digital input - response = xbee.sendAtCommand(new AtCommand("DO", 0x3)); - log.debug("DO is " + response); - - // set pin 19 to monitor analog input - response = xbee.sendAtCommand(new AtCommand("D1", 0x2)); - log.debug("D1 is " + response); - - // set pin 18 to monitor analog input - response = xbee.sendAtCommand(new AtCommand("D2", 0x2)); - log.debug("D2 is " + response); - - // set pin 16 to monitor digital input - response = xbee.sendAtCommand(new AtCommand("D6", 0x3)); - log.debug("D6 is " + response); - - // optionally configure DH + DL; if set to zero (default), samples will be sent to coordinator - } - - public static void main(String[] args) throws XBeeException { - PropertyConfigurator.configure("log4j.properties"); - new ZNetApiAtExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.requests.AtCommand; +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.api.zigbee.AssociationStatus; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * This class contains AtCommand examples that are specific to ZNet radios + * + * @author andrew + * + */ +public class ZNetApiAtExample { + + private final static Logger log = Logger.getLogger(ZNetApiAtExample.class); + + private XBee xbee = new XBee(); + + public ZNetApiAtExample() throws XBeeException { + try { + + // replace with port and baud rate of your XBee + xbee.open("COM6", 9600); + + // get the 8 byte SH/SL address + log.debug("SH is " + ByteUtils.toBase16(((AtCommandResponse)xbee.sendAtCommand(new AtCommand("SH"))).getValue())); + log.debug("SL is " + ByteUtils.toBase16(((AtCommandResponse)xbee.sendAtCommand(new AtCommand("SL"))).getValue())); + + // uncomment to run +// this.configureIOSamples(xbee); +// this.associationStatus(xbee); +// this.nodeDiscover(xbee); +// this.configureCoordinator(xbee); +// this.configureEndDevice(xbee); + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + private void associationStatus(XBee xbee) throws XBeeException { + // get association status - success indicates it is associated to another XBee + AtCommandResponse response = (AtCommandResponse) xbee.sendAtCommand(new AtCommand("AI")); + log.debug("Association Status is " + AssociationStatus.get(response)); + } + + private void configureEndDevice(XBee xbee) throws XBeeException { + + // basic end device configuration (assumes ZNet radio flashed with end device API firmware) + XBeeResponse response = null; + + // reset to factory settings + response = xbee.sendAtCommand(new AtCommand("RE")); + log.debug("RE is " + response); + + // set PAN id to arbitrary value + response = xbee.sendAtCommand(new AtCommand("ID", new int[] {0x1a, 0xaa})); + log.debug("ID is " + response); + + // set NI -- can be any arbitrary sequence of chars + response = xbee.sendAtCommand(new AtCommand("NI", new int[] {'E','N','D','_','D','E','V','I','C','E','_','2' })); + log.debug("NI is " + response); + + // set API mode to 2. factory setting is 1 + response = xbee.sendAtCommand(new AtCommand("AP", 2)); + log.debug("AP is " + response); + + // save to settings to survive power cycle + response = xbee.sendAtCommand(new AtCommand("WR")); + log.debug("WR is " + response); + + // software reset + response = xbee.sendAtCommand(new AtCommand("FR")); + log.debug("FR is " + response); + } + + private void configureCoordinator(XBee xbee) throws XBeeException { + // basic coordinator configuration (assumes ZNet radio flashed with COORDINATOR API firmware) + XBeeResponse response = null; + + // reset to factory settings + response = xbee.sendAtCommand(new AtCommand("RE")); + log.debug("RE is " + response); + + // set PAN id to arbitrary value + response = xbee.sendAtCommand(new AtCommand("ID", new int[] {0x1a, 0xaa})); + log.debug("RE is " + response); + + // set NI + response = xbee.sendAtCommand(new AtCommand("NI", new int[] {'C','O','O','R','D','I','N','A','T','O','R' })); + log.debug("NI is " + response); + + // set API mode to 2. factory setting is 1 + response = xbee.sendAtCommand(new AtCommand("AP", 2)); + log.debug("AP is " + response); + + // save to settings to survive power cycle + response = xbee.sendAtCommand(new AtCommand("WR")); + log.debug("WR is " + response); + + // software reset + response = xbee.sendAtCommand(new AtCommand("FR")); + log.debug("FR is " + response); + } + + /** + * This assumes an end device that is already has the configureEndDevice configuration + * Does not save configuration! -- use WR if you want this configure to survive power on/off. + * + * @param xbee + * @throws XBeeException + */ + private void configureIOSamples(XBee xbee) throws XBeeException { + // basic coordinator configuration (assumes ZNet radio flashed with COORDINATOR API firmware) + XBeeResponse response = null; + + // set IR to 1 sample every 10 seconds. Set to 0 to disable + response = xbee.sendAtCommand(new AtCommand("IR", new int[] {0x27, 0x10})); + log.debug("IR is " + response); + + // set pin 20 to monitor digital input + response = xbee.sendAtCommand(new AtCommand("DO", 0x3)); + log.debug("DO is " + response); + + // set pin 19 to monitor analog input + response = xbee.sendAtCommand(new AtCommand("D1", 0x2)); + log.debug("D1 is " + response); + + // set pin 18 to monitor analog input + response = xbee.sendAtCommand(new AtCommand("D2", 0x2)); + log.debug("D2 is " + response); + + // set pin 16 to monitor digital input + response = xbee.sendAtCommand(new AtCommand("D6", 0x3)); + log.debug("D6 is " + response); + + // optionally configure DH + DL; if set to zero (default), samples will be sent to coordinator + } + + public static void main(String[] args) throws XBeeException { + new ZNetApiAtExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/ZNetExplicitReceiverExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetExplicitReceiverExample.java similarity index 91% rename from src/com/rapplogic/xbee/examples/zigbee/ZNetExplicitReceiverExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetExplicitReceiverExample.java index 93cf0e2..43e3ae2 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/ZNetExplicitReceiverExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetExplicitReceiverExample.java @@ -1,77 +1,74 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.zigbee.ZNetExplicitRxResponse; - -/** - * Set AO=1 for to enable explicit frames for this example - * - * @author andrew - * - */ -public class ZNetExplicitReceiverExample { - - private final static Logger log = Logger.getLogger(ZNetExplicitReceiverExample.class); - - private ZNetExplicitReceiverExample() throws Exception { - XBee xbee = new XBee(); - - try { - // replace with the com port or your receiving XBee - // this is the com port of my end device on my mac - xbee.open("/dev/tty.usbserial-A6005uRz", 9600); - - while (true) { - - try { - // we wait here until a packet is received. - XBeeResponse response = xbee.getResponse(); - - if (response.getApiId() == ApiId.ZNET_EXPLICIT_RX_RESPONSE) { - ZNetExplicitRxResponse rx = (ZNetExplicitRxResponse) response; - - log.info("received explicit packet response " + response.toString()); - } else { - log.debug("received unexpected packet " + response.toString()); - } - } catch (Exception e) { - log.error(e); - } - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws Exception { - // init log4j - PropertyConfigurator.configure("log4j.properties"); - new ZNetExplicitReceiverExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.zigbee.ZNetExplicitRxResponse; + +/** + * Set AO=1 for to enable explicit frames for this example + * + * @author andrew + * + */ +public class ZNetExplicitReceiverExample { + + private final static Logger log = Logger.getLogger(ZNetExplicitReceiverExample.class); + + private ZNetExplicitReceiverExample() throws Exception { + XBee xbee = new XBee(); + + try { + // replace with the com port or your receiving XBee + // this is the com port of my end device on my mac + xbee.open("/dev/tty.usbserial-A6005uRz", 9600); + + while (true) { + + try { + // we wait here until a packet is received. + XBeeResponse response = xbee.getResponse(); + + if (response.getApiId() == ApiId.ZNET_EXPLICIT_RX_RESPONSE) { + ZNetExplicitRxResponse rx = (ZNetExplicitRxResponse) response; + + log.info("received explicit packet response " + response.toString()); + } else { + log.debug("received unexpected packet " + response.toString()); + } + } catch (Exception e) { + log.error(e); + } + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws Exception { + new ZNetExplicitReceiverExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/ZNetExplicitSenderExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetExplicitSenderExample.java similarity index 94% rename from src/com/rapplogic/xbee/examples/zigbee/ZNetExplicitSenderExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetExplicitSenderExample.java index 5b99721..c5578e3 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/ZNetExplicitSenderExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetExplicitSenderExample.java @@ -1,98 +1,96 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeException; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.zigbee.ZNetExplicitTxRequest; -import com.rapplogic.xbee.api.zigbee.ZNetTxRequest; -import com.rapplogic.xbee.util.DoubleByte; - -/** - * Set AO=1 for to enable explicit frames for this example. - * Once set, you should use explicit tx/rx packets instead of plain vanilla tx requests (ZNetTxRequest). - * You can still send ZNetTxRequest requests but they will be received as explicit responses (ZNetExplicitRxResponse) - * - * @author andrew - * - */ -public class ZNetExplicitSenderExample { - - private final static Logger log = Logger.getLogger(ZNetExplicitSenderExample.class); - - private ZNetExplicitSenderExample() throws XBeeException { - - XBee xbee = new XBee(); - - try { - // replace with your com port and baud rate. this is the com port of my coordinator - //xbee.open("COM5", 9600); - xbee.open("/dev/tty.usbserial-A6005v5M", 9600); - - // replace with end device's 64-bit address (SH + SL) - XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x0a, 0x3e, 0x02); - - // create an array of arbitrary data to send - int[] payload = new int[] { 0, 0x66, 0xee }; - - // loopback test - int sourceEndpoint = 0; - int destinationEndpoint = ZNetExplicitTxRequest.Endpoint.DATA.getValue(); - - DoubleByte clusterId = new DoubleByte(0x0, ZNetExplicitTxRequest.ClusterId.SERIAL_LOOPBACK.getValue()); - //DoubleByte clusterId = new DoubleByte(0x0, ZNetExplicitTxRequest.ClusterId.TRANSPARENT_SERIAL.getValue()); - - // first request we just send 64-bit address. we get 16-bit network address with status response - ZNetExplicitTxRequest request = new ZNetExplicitTxRequest(0xff, addr64, XBeeAddress16.ZNET_BROADCAST, - ZNetTxRequest.DEFAULT_BROADCAST_RADIUS, ZNetTxRequest.Option.UNICAST, payload, sourceEndpoint, destinationEndpoint, clusterId, ZNetExplicitTxRequest.znetProfileId); - - log.info("sending explicit " + request.toString()); - - while (true) { - xbee.sendAsynchronous(request); - - XBeeResponse response = xbee.getResponse(); - - log.info("received response " + response.toString()); - - try { - // wait a bit then send another packet - Thread.sleep(5000); - } catch (InterruptedException e) { - } - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws XBeeException, InterruptedException { - PropertyConfigurator.configure("log4j.properties"); - new ZNetExplicitSenderExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.zigbee.ZNetExplicitTxRequest; +import com.rapplogic.xbee.api.zigbee.ZNetTxRequest; +import com.rapplogic.xbee.util.DoubleByte; + +/** + * Set AO=1 for to enable explicit frames for this example. + * Once set, you should use explicit tx/rx packets instead of plain vanilla tx requests (ZNetTxRequest). + * You can still send ZNetTxRequest requests but they will be received as explicit responses (ZNetExplicitRxResponse) + * + * @author andrew + * + */ +public class ZNetExplicitSenderExample { + + private final static Logger log = Logger.getLogger(ZNetExplicitSenderExample.class); + + private ZNetExplicitSenderExample() throws XBeeException { + + XBee xbee = new XBee(); + + try { + // replace with your com port and baud rate. this is the com port of my coordinator + //xbee.open("COM5", 9600); + xbee.open("/dev/tty.usbserial-A6005v5M", 9600); + + // replace with end device's 64-bit address (SH + SL) + XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x0a, 0x3e, 0x02); + + // create an array of arbitrary data to send + int[] payload = new int[] { 0, 0x66, 0xee }; + + // loopback test + int sourceEndpoint = 0; + int destinationEndpoint = ZNetExplicitTxRequest.Endpoint.DATA.getValue(); + + DoubleByte clusterId = new DoubleByte(0x0, ZNetExplicitTxRequest.ClusterId.SERIAL_LOOPBACK.getValue()); + //DoubleByte clusterId = new DoubleByte(0x0, ZNetExplicitTxRequest.ClusterId.TRANSPARENT_SERIAL.getValue()); + + // first request we just send 64-bit address. we get 16-bit network address with status response + ZNetExplicitTxRequest request = new ZNetExplicitTxRequest(0xff, addr64, XBeeAddress16.ZNET_BROADCAST, + ZNetTxRequest.DEFAULT_BROADCAST_RADIUS, ZNetTxRequest.Option.UNICAST, payload, sourceEndpoint, destinationEndpoint, clusterId, ZNetExplicitTxRequest.znetProfileId); + + log.info("sending explicit " + request.toString()); + + while (true) { + xbee.sendAsynchronous(request); + + XBeeResponse response = xbee.getResponse(); + + log.info("received response " + response.toString()); + + try { + // wait a bit then send another packet + Thread.sleep(5000); + } catch (InterruptedException e) { + } + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws XBeeException, InterruptedException { + new ZNetExplicitSenderExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/ZNetIoSampleExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetIoSampleExample.java similarity index 89% rename from src/com/rapplogic/xbee/examples/zigbee/ZNetIoSampleExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetIoSampleExample.java index fa498cb..84bcb66 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/ZNetIoSampleExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetIoSampleExample.java @@ -1,85 +1,80 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.PacketListener; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.wpan.IoSample; -import com.rapplogic.xbee.api.wpan.RxResponseIoSample; -import com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse; - -/** - * Series 2 XBees -- Example of receiving I/O samples. To configure your radio for this example, connect - * your end device to your serial connection and run the configureIOSamples() method - * in ZNetApiAtTest. - * - * @author andrew - * - */ -public class ZNetIoSampleExample implements PacketListener { - - private final static Logger log = Logger.getLogger(ZNetIoSampleExample.class); - - private ZNetIoSampleExample() throws Exception { - XBee xbee = new XBee(); - - try { - // replace with the com port of your XBee coordinator - xbee.open("/dev/tty.usbserial-A6005v5M", 9600); - xbee.addPacketListener(this); - - // wait forever - synchronized(this) { this.wait(); } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - /** - * Called by XBee API thread when a packet is received - */ - public void processResponse(XBeeResponse response) { - // This is a I/O sample response. You will only get this is you are connected to a Coordinator that is configured to - // receive I/O samples from a remote XBee. - - if (response.getApiId() == ApiId.ZNET_IO_SAMPLE_RESPONSE) { - ZNetRxIoSampleResponse ioSample = (ZNetRxIoSampleResponse) response; - - log.debug("received i/o sample packet. contains analog is " + ioSample.containsAnalog() + ", contains digital is " + ioSample.containsDigital()); - - // check the value of the input pins - log.debug("pin 20 (DO) digital is " + ioSample.isD0On()); - log.debug("pin 19 (D1) analog is " + ioSample.getAnalog1()); - } - } - - public static void main(String[] args) throws Exception { - // init log4j - PropertyConfigurator.configure("log4j.properties"); - new ZNetIoSampleExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.PacketListener; +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.zigbee.ZNetRxIoSampleResponse; + +/** + * Series 2 XBees -- Example of receiving I/O samples. To configure your radio for this example, connect + * your end device to your serial connection and run the configureIOSamples() method + * in ZNetApiAtTest. + * + * @author andrew + * + */ +public class ZNetIoSampleExample implements PacketListener { + + private final static Logger log = Logger.getLogger(ZNetIoSampleExample.class); + + private ZNetIoSampleExample() throws Exception { + XBee xbee = new XBee(); + + try { + // replace with the com port of your XBee coordinator + xbee.open("/dev/tty.usbserial-A6005v5M", 9600); + xbee.addPacketListener(this); + + // wait forever + synchronized(this) { this.wait(); } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + /** + * Called by XBee API thread when a packet is received + */ + public void processResponse(XBeeResponse response) { + // This is a I/O sample response. You will only get this is you are connected to a Coordinator that is configured to + // receive I/O samples from a remote XBee. + + if (response.getApiId() == ApiId.ZNET_IO_SAMPLE_RESPONSE) { + ZNetRxIoSampleResponse ioSample = (ZNetRxIoSampleResponse) response; + + log.debug("received i/o sample packet. contains analog is " + ioSample.containsAnalog() + ", contains digital is " + ioSample.containsDigital()); + + // check the value of the input pins + log.debug("pin 20 (DO) digital is " + ioSample.isD0On()); + log.debug("pin 19 (D1) analog is " + ioSample.getAnalog1()); + } + } + + public static void main(String[] args) throws Exception { + new ZNetIoSampleExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/ZNetReceiverExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetReceiverExample.java similarity index 91% rename from src/com/rapplogic/xbee/examples/zigbee/ZNetReceiverExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetReceiverExample.java index cf300da..5101b7f 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/ZNetReceiverExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetReceiverExample.java @@ -1,100 +1,97 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.ApiId; -import com.rapplogic.xbee.api.AtCommand; -import com.rapplogic.xbee.api.AtCommandResponse; -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeResponse; -import com.rapplogic.xbee.api.zigbee.ZNetRxResponse; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * This class is the companion to ZNetSenderTest.java, and as such, it receives packets sent by ZNetSenderTest.java - * See the ZNetSenderTest.java for information on how to configure your XBee for this demo - * - * You can start ZNetSenderTest.java and this class in any order but it's generally best to start this class first. - * - * @author andrew - * - */ -public class ZNetReceiverExample { - - private final static Logger log = Logger.getLogger(ZNetReceiverExample.class); - - private ZNetReceiverExample() throws Exception { - XBee xbee = new XBee(); - - try { - // replace with the com port of your receiving XBee (typically your end device) - // router - xbee.open("/dev/tty.usbserial-A6005uPi", 9600); - - while (true) { - - try { - // we wait here until a packet is received. - XBeeResponse response = xbee.getResponse(); - - log.info("received response " + response.toString()); - - if (response.getApiId() == ApiId.ZNET_RX_RESPONSE) { - // we received a packet from ZNetSenderTest.java - ZNetRxResponse rx = (ZNetRxResponse) response; - - log.info("Received RX packet, option is " + rx.getOption() + ", sender 64 address is " + ByteUtils.toBase16(rx.getRemoteAddress64().getAddress()) + ", remote 16-bit address is " + ByteUtils.toBase16(rx.getRemoteAddress16().getAddress()) + ", data is " + ByteUtils.toBase16(rx.getData())); - - // optionally we may want to get the signal strength (RSSI) of the last hop. - // keep in mind if you have routers in your network, this will be the signal of the last hop. - AtCommand at = new AtCommand("DB"); - xbee.sendAsynchronous(at); - XBeeResponse atResponse = xbee.getResponse(); - - if (atResponse.getApiId() == ApiId.AT_RESPONSE) { - // remember rssi is a negative db value - log.info("RSSI of last response is " + -((AtCommandResponse)atResponse).getValue()[0]); - } else { - // we didn't get an AT response - log.info("expected RSSI, but received " + atResponse.toString()); - } - } else { - log.debug("received unexpected packet " + response.toString()); - } - } catch (Exception e) { - log.error(e); - } - } - } finally { - if (xbee != null && xbee.isConnected()) { - xbee.close(); - } - } - } - - public static void main(String[] args) throws Exception { - // init log4j - PropertyConfigurator.configure("log4j.properties"); - new ZNetReceiverExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; + +import com.rapplogic.xbee.api.ApiId; +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeResponse; +import com.rapplogic.xbee.api.requests.AtCommand; +import com.rapplogic.xbee.api.responses.AtCommandResponse; +import com.rapplogic.xbee.api.zigbee.ZNetRxResponse; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * This class is the companion to ZNetSenderTest.java, and as such, it receives packets sent by ZNetSenderTest.java + * See the ZNetSenderTest.java for information on how to configure your XBee for this demo + * + * You can start ZNetSenderTest.java and this class in any order but it's generally best to start this class first. + * + * @author andrew + * + */ +public class ZNetReceiverExample { + + private final static Logger log = Logger.getLogger(ZNetReceiverExample.class); + + private ZNetReceiverExample() throws Exception { + XBee xbee = new XBee(); + + try { + // replace with the com port of your receiving XBee (typically your end device) + // router + xbee.open("/dev/tty.usbserial-A6005uPi", 9600); + + while (true) { + + try { + // we wait here until a packet is received. + XBeeResponse response = xbee.getResponse(); + + log.info("received response " + response.toString()); + + if (response.getApiId() == ApiId.ZNET_RX_RESPONSE) { + // we received a packet from ZNetSenderTest.java + ZNetRxResponse rx = (ZNetRxResponse) response; + + log.info("Received RX packet, option is " + rx.getOption() + ", sender 64 address is " + ByteUtils.toBase16(rx.getRemoteAddress64().getAddress()) + ", remote 16-bit address is " + ByteUtils.toBase16(rx.getRemoteAddress16().getAddress()) + ", data is " + ByteUtils.toBase16(rx.getData())); + + // optionally we may want to get the signal strength (RSSI) of the last hop. + // keep in mind if you have routers in your network, this will be the signal of the last hop. + AtCommand at = new AtCommand("DB"); + xbee.sendAsynchronous(at); + XBeeResponse atResponse = xbee.getResponse(); + + if (atResponse.getApiId() == ApiId.AT_RESPONSE) { + // remember rssi is a negative db value + log.info("RSSI of last response is " + -((AtCommandResponse)atResponse).getValue()[0]); + } else { + // we didn't get an AT response + log.info("expected RSSI, but received " + atResponse.toString()); + } + } else { + log.debug("received unexpected packet " + response.toString()); + } + } catch (Exception e) { + log.error(e); + } + } + } finally { + if (xbee != null && xbee.isConnected()) { + xbee.close(); + } + } + } + + public static void main(String[] args) throws Exception { + new ZNetReceiverExample(); + } +} diff --git a/src/com/rapplogic/xbee/examples/zigbee/ZNetSenderExample.java b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetSenderExample.java similarity index 97% rename from src/com/rapplogic/xbee/examples/zigbee/ZNetSenderExample.java rename to src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetSenderExample.java index a4d100b..370a9e7 100644 --- a/src/com/rapplogic/xbee/examples/zigbee/ZNetSenderExample.java +++ b/src/main/java/com/rapplogic/xbee/examples/zigbee/ZNetSenderExample.java @@ -1,182 +1,181 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.examples.zigbee; - -import org.apache.log4j.Logger; -import org.apache.log4j.PropertyConfigurator; - -import com.rapplogic.xbee.api.XBee; -import com.rapplogic.xbee.api.XBeeAddress16; -import com.rapplogic.xbee.api.XBeeAddress64; -import com.rapplogic.xbee.api.XBeeException; -import com.rapplogic.xbee.api.XBeeTimeoutException; -import com.rapplogic.xbee.api.zigbee.ZNetTxRequest; -import com.rapplogic.xbee.api.zigbee.ZNetTxStatusResponse; -import com.rapplogic.xbee.util.ByteUtils; - -/** - * To run this example you need to have at least two ZNet XBees powered up and configured to the same PAN ID (ATID) in API mode (2). - * This software requires the XBee to be configured in API mode; if your ZNet radios are flashed with the transparent (AT) firmware, - * you will need to re-flash with API firmware to run this software. - * - * I use the Digi X-CTU software to configure my XBee's, but if you don't have Windows (X-CTU only works on Windows), you can still use the configureCoordinator and - * configureEndDevice methods in ZNetApiAtTest.java. - * - * There are a few chicken and egg situations where you need to know some basic configuration before you can connect to the XBee. This - * includes the baud rate and the API mode. The default baud rate is 9600 and if you ever change it, you will want to remember the setting. - * If you can't connect at 9600 and you don't know the baud rate, try all possibilities until it works. Same with the API Mode: if you click - * Test/Query in X-CTU, try changing the API mode until it succeeds, then write it down somewhere for next time. - * - * Here's my setup configuration (assumes factory configuration): - * - * COORDINATOR config: - * - * - Reset to factory settings: - * ATRE - * - Put in API mode 2 - * ATAP 2 - * - Set PAN id to arbitrary value - * ATID 1AAA - * - Set the Node Identifier (give it a meaningful name) - * ATNI COORDINATOR - * - Save config - * ATWR - * - reboot - * ATFR - * - * The XBee network will assign the network 16-bit MY address. The coordinator MY address is always 0 - * - * X-CTU tells me my SH Address is 00 13 a2 00 and SL is 40 0a 3e 02 - * - * END DEVICE config: - * - * - Reset to factory settings: - * ATRE - * - Put in API mode 2 - * ATAP 2 - * - Set PAN id to arbitrary value - * ATID 1AAA - * - Set the Node Identifier (give it a meaningful name) - * ATNI END_DEVICE_1 - * - Save config - * ATWR - * - reboot - * ATFR - * - * Only one XBee needs to be connected to the computer (serial-usb); the other may be remote, but can also be connected to the computer. - * I use the XBee Explorer from SparkFun to connect my XBees to my computer as it makes it incredibly easy -- just drop in the XBee. - * - * For this example, I use my XBee COORDINATOR as my "sender" (runs this class) and the END DEVICE as my "receiver" XBee. - * You could alternatively use your END DEVICE as the sender -- it doesn't matter because any XBee, either configured as a COORDINATOR - * or END DEVICE, can both send and receive. - * - * How to find the COM port: - * - * Java is nice in that it runs on many platforms. I use mac/windows and linux (server) and the com port is different on all three. - * On the mac it appears as /dev/tty.usbserial-A6005v5M on my machine. I just plug in each XBee one at a time and check the /dev dir - * to match the XBee to the device name: ls -l /dev/tty.u (hit tab twice to see all entries) - * - * On Windows you can simply select Start->My Computer->Manage, select Device Manager and expand "Ports" - * - * For Linux I'm not exactly sure just yet although I found mine by trial and error to be /dev/ttyUSB0 I think it could easily be different - * for other distros. - * - * To run, simply right-click on the class, in the left pane, and select Run As->Java Application. Eclipse will let you run multiple - * processes in one IDE, but there is only one console and it will switch between the two processes as it is updated. - * - * If you are running the sender and receiver in the same eclipse, remember to hit the terminate button twice to kill both - * or you won't be able to start it again. If this situation occurs, simply restart eclipse. - * - * @author andrew - */ -public class ZNetSenderExample { - - private final static Logger log = Logger.getLogger(ZNetSenderExample.class); - - private ZNetSenderExample() throws XBeeException { - - XBee xbee = new XBee(); - - // replace with port and baud rate of your XBee. this is the com port of my coordinator - //coord - xbee.open("/dev/tty.usbserial-A6005uRz", 9600); - // coord (21A7) - //XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x8b, 0x98, 0xfe); - - // replace with end device's 64-bit address (SH + SL) - // router (firmware 23A7) - XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x8b, 0x98, 0xff); - - // create an array of arbitrary data to send - int[] payload = new int[] { 'X', 'B', 'e', 'e' }; - - // first request we just send 64-bit address. we get 16-bit network address with status response - ZNetTxRequest request = new ZNetTxRequest(addr64, payload); - - log.debug("zb request is " + request.getXBeePacket().getPacket()); - - log.info("sending tx " + request); - - while (true) { - log.info("request packet bytes (base 16) " + ByteUtils.toBase16(request.getXBeePacket().getPacket())); - - long start = System.currentTimeMillis(); - //log.info("sending tx packet: " + request.toString()); - - try { - ZNetTxStatusResponse response = (ZNetTxStatusResponse) xbee.sendSynchronous(request, 10000); - // update frame id for next request - request.setFrameId(xbee.getNextFrameId()); - - log.info("received response " + response); - - //log.debug("status response bytes:" + ByteUtils.toBase16(response.getPacketBytes())); - - if (response.getDeliveryStatus() == ZNetTxStatusResponse.DeliveryStatus.SUCCESS) { - // the packet was successfully delivered - if (response.getRemoteAddress16().equals(XBeeAddress16.ZNET_BROADCAST)) { - // specify 16-bit address for faster routing?.. really only need to do this when it changes - request.setDestAddr16(response.getRemoteAddress16()); - } - } else { - // packet failed. log error - // it's easy to create this error by unplugging/powering off your remote xbee. when doing so I get: packet failed due to error: ADDRESS_NOT_FOUND - log.error("packet failed due to error: " + response.getDeliveryStatus()); - } - - // I get the following message: Response in 75, Delivery status is SUCCESS, 16-bit address is 0x08 0xe5, retry count is 0, discovery status is SUCCESS - log.info("Response in " + (System.currentTimeMillis() - start) + ", Delivery status is " + response.getDeliveryStatus() + ", 16-bit address is " + ByteUtils.toBase16(response.getRemoteAddress16().getAddress()) + ", retry count is " + response.getRetryCount() + ", discovery status is " + response.getDeliveryStatus()); - } catch (XBeeTimeoutException e) { - log.warn("request timed out"); - } - - try { - // wait a bit then send another packet - Thread.sleep(10000); - } catch (InterruptedException e) { - } - } - } - - public static void main(String[] args) throws XBeeException, InterruptedException { - PropertyConfigurator.configure("log4j.properties"); - new ZNetSenderExample(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.examples.zigbee; + +import org.apache.log4j.Logger; +import org.apache.log4j.PropertyConfigurator; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeAddress16; +import com.rapplogic.xbee.api.XBeeAddress64; +import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.XBeeTimeoutException; +import com.rapplogic.xbee.api.zigbee.ZNetTxRequest; +import com.rapplogic.xbee.api.zigbee.ZNetTxStatusResponse; +import com.rapplogic.xbee.util.ByteUtils; + +/** + * To run this example you need to have at least two ZNet XBees powered up and configured to the same PAN ID (ATID) in API mode (2). + * This software requires the XBee to be configured in API mode; if your ZNet radios are flashed with the transparent (AT) firmware, + * you will need to re-flash with API firmware to run this software. + * + * I use the Digi X-CTU software to configure my XBee's, but if you don't have Windows (X-CTU only works on Windows), you can still use the configureCoordinator and + * configureEndDevice methods in ZNetApiAtTest.java. + * + * There are a few chicken and egg situations where you need to know some basic configuration before you can connect to the XBee. This + * includes the baud rate and the API mode. The default baud rate is 9600 and if you ever change it, you will want to remember the setting. + * If you can't connect at 9600 and you don't know the baud rate, try all possibilities until it works. Same with the API Mode: if you click + * Test/Query in X-CTU, try changing the API mode until it succeeds, then write it down somewhere for next time. + * + * Here's my setup configuration (assumes factory configuration): + * + * COORDINATOR config: + * + * - Reset to factory settings: + * ATRE + * - Put in API mode 2 + * ATAP 2 + * - Set PAN id to arbitrary value + * ATID 1AAA + * - Set the Node Identifier (give it a meaningful name) + * ATNI COORDINATOR + * - Save config + * ATWR + * - reboot + * ATFR + * + * The XBee network will assign the network 16-bit MY address. The coordinator MY address is always 0 + * + * X-CTU tells me my SH Address is 00 13 a2 00 and SL is 40 0a 3e 02 + * + * END DEVICE config: + * + * - Reset to factory settings: + * ATRE + * - Put in API mode 2 + * ATAP 2 + * - Set PAN id to arbitrary value + * ATID 1AAA + * - Set the Node Identifier (give it a meaningful name) + * ATNI END_DEVICE_1 + * - Save config + * ATWR + * - reboot + * ATFR + * + * Only one XBee needs to be connected to the computer (serial-usb); the other may be remote, but can also be connected to the computer. + * I use the XBee Explorer from SparkFun to connect my XBees to my computer as it makes it incredibly easy -- just drop in the XBee. + * + * For this example, I use my XBee COORDINATOR as my "sender" (runs this class) and the END DEVICE as my "receiver" XBee. + * You could alternatively use your END DEVICE as the sender -- it doesn't matter because any XBee, either configured as a COORDINATOR + * or END DEVICE, can both send and receive. + * + * How to find the COM port: + * + * Java is nice in that it runs on many platforms. I use mac/windows and linux (server) and the com port is different on all three. + * On the mac it appears as /dev/tty.usbserial-A6005v5M on my machine. I just plug in each XBee one at a time and check the /dev dir + * to match the XBee to the device name: ls -l /dev/tty.u (hit tab twice to see all entries) + * + * On Windows you can simply select Start->My Computer->Manage, select Device Manager and expand "Ports" + * + * For Linux I'm not exactly sure just yet although I found mine by trial and error to be /dev/ttyUSB0 I think it could easily be different + * for other distros. + * + * To run, simply right-click on the class, in the left pane, and select Run As->Java Application. Eclipse will let you run multiple + * processes in one IDE, but there is only one console and it will switch between the two processes as it is updated. + * + * If you are running the sender and receiver in the same eclipse, remember to hit the terminate button twice to kill both + * or you won't be able to start it again. If this situation occurs, simply restart eclipse. + * + * @author andrew + */ +public class ZNetSenderExample { + + private final static Logger log = Logger.getLogger(ZNetSenderExample.class); + + private ZNetSenderExample() throws XBeeException { + + XBee xbee = new XBee(); + + // replace with port and baud rate of your XBee. this is the com port of my coordinator + //coord + xbee.open("/dev/tty.usbserial-A6005uRz", 9600); + // coord (21A7) + //XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x8b, 0x98, 0xfe); + + // replace with end device's 64-bit address (SH + SL) + // router (firmware 23A7) + XBeeAddress64 addr64 = new XBeeAddress64(0, 0x13, 0xa2, 0, 0x40, 0x8b, 0x98, 0xff); + + // create an array of arbitrary data to send + int[] payload = new int[] { 'X', 'B', 'e', 'e' }; + + // first request we just send 64-bit address. we get 16-bit network address with status response + ZNetTxRequest request = new ZNetTxRequest(addr64, payload); + + log.debug("zb request is " + request.getXBeePacket().getPacket()); + + log.info("sending tx " + request); + + while (true) { + log.info("request packet bytes (base 16) " + ByteUtils.toBase16(request.getXBeePacket().getPacket())); + + long start = System.currentTimeMillis(); + //log.info("sending tx packet: " + request.toString()); + + try { + ZNetTxStatusResponse response = (ZNetTxStatusResponse) xbee.sendSynchronous(request, 10000); + // update frame id for next request + request.setFrameId(xbee.getNextFrameId()); + + log.info("received response " + response); + + //log.debug("status response bytes:" + ByteUtils.toBase16(response.getPacketBytes())); + + if (response.getDeliveryStatus() == ZNetTxStatusResponse.DeliveryStatus.SUCCESS) { + // the packet was successfully delivered + if (response.getRemoteAddress16().equals(XBeeAddress16.ZNET_BROADCAST)) { + // specify 16-bit address for faster routing?.. really only need to do this when it changes + request.setDestAddr16(response.getRemoteAddress16()); + } + } else { + // packet failed. log error + // it's easy to create this error by unplugging/powering off your remote xbee. when doing so I get: packet failed due to error: ADDRESS_NOT_FOUND + log.error("packet failed due to error: " + response.getDeliveryStatus()); + } + + // I get the following message: Response in 75, Delivery status is SUCCESS, 16-bit address is 0x08 0xe5, retry count is 0, discovery status is SUCCESS + log.info("Response in " + (System.currentTimeMillis() - start) + ", Delivery status is " + response.getDeliveryStatus() + ", 16-bit address is " + ByteUtils.toBase16(response.getRemoteAddress16().getAddress()) + ", retry count is " + response.getRetryCount() + ", discovery status is " + response.getDeliveryStatus()); + } catch (XBeeTimeoutException e) { + log.warn("request timed out"); + } + + try { + // wait a bit then send another packet + Thread.sleep(10000); + } catch (InterruptedException e) { + } + } + } + + public static void main(String[] args) throws XBeeException, InterruptedException { + new ZNetSenderExample(); + } +} diff --git a/src/com/rapplogic/xbee/test/OpenCloseConnectionsTest.java b/src/main/java/com/rapplogic/xbee/test/OpenCloseConnectionsTest.java similarity index 97% rename from src/com/rapplogic/xbee/test/OpenCloseConnectionsTest.java rename to src/main/java/com/rapplogic/xbee/test/OpenCloseConnectionsTest.java index e0776d9..31fcc21 100644 --- a/src/com/rapplogic/xbee/test/OpenCloseConnectionsTest.java +++ b/src/main/java/com/rapplogic/xbee/test/OpenCloseConnectionsTest.java @@ -3,9 +3,9 @@ import org.apache.log4j.Logger; import org.apache.log4j.PropertyConfigurator; -import com.rapplogic.xbee.api.AtCommand; import com.rapplogic.xbee.api.XBee; import com.rapplogic.xbee.api.XBeeException; +import com.rapplogic.xbee.api.requests.AtCommand; /** * Tests opening and closing connections to the radio diff --git a/src/com/rapplogic/xbee/util/ByteUtils.java b/src/main/java/com/rapplogic/xbee/util/ByteUtils.java similarity index 95% rename from src/com/rapplogic/xbee/util/ByteUtils.java rename to src/main/java/com/rapplogic/xbee/util/ByteUtils.java index 666e6ea..fd5090d 100644 --- a/src/com/rapplogic/xbee/util/ByteUtils.java +++ b/src/main/java/com/rapplogic/xbee/util/ByteUtils.java @@ -1,305 +1,305 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.util; - -import java.io.IOException; - -public class ByteUtils { - - // not to be instantiated - private ByteUtils() { - - } - - /** - * There is a slight problem with this method that you might have noticed; a Java int is signed, so we can't make - * use of the 32nd bit. This means this method does not support a four byte value with msb greater than 01111111 ((2^7-1) or 127) - * and will throw a runtime exception if it encounters this situation. - * - * TODO use long instead of int to support 4 bytes values. note that long assignments are not atomic. - * - * Not Used - */ - public static int convertMultiByteToInt(int[] bytes) { - - if (bytes.length > 4) { - throw new RuntimeException("too big"); - } else if (bytes.length == 4 && ((bytes[0] & 0x80) == 0x80)) { - // 0x80 == 10000000, 0x7e == 01111111 - throw new IllegalArgumentException("Java int can't support a four byte value with msb byte greater than 7e"); - } - - int val = 0; - - for (int i = 0; i < bytes.length; i++) { - - if (bytes[i] > 0xFF) { - throw new IllegalArgumentException("Values exceeds byte range: " + bytes[i]); - } - - if (i == (bytes.length - 1)) { - val+= bytes[i]; - } else { - val+= bytes[i] << ((bytes.length - i - 1) * 8); - } - } - - return val; - } - - /** - * Works for positive values only - * - * @param val - * @return - */ - public static int[] convertInttoMultiByte(int val) { - - if (val < 0) { - throw new IllegalArgumentException("Negative values are not supported"); - } - - // must decompose into a max of 4 bytes - // b1 b2 b3 b4 - // 01111111 11111111 11111111 11111111 - // 127 255 255 255 - - int size = 0; - - if ((val >> 24) > 0) { - size = 4; - } else if ((val >> 16) > 0) { - size = 3; - } else if ((val >> 8) > 0) { - size = 2; - } else { - size = 1; - } - - int[] data = new int[size]; - - for (int i = 0; i < size; i++) { - data[i] = (val >> (size - i - 1) * 8) & 0xFF; - } - - return data; - } - - public static String toBase16(int[] arr) { - return toBase16(arr, ","); - } - - public static String toBase16(int[] arr, String delimiter) { - - if (arr == null) { - return ""; - } - - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < arr.length; i++) { - sb.append(toBase16(arr[i])); - - if (i < arr.length - 1) { - sb.append(delimiter); - } - } - - return sb.toString(); - } - - public static String toBase2(int[] arr) { - - if (arr == null) { - return ""; - } - - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < arr.length; i++) { - sb.append(toBase2(arr[i])); - - if (i < arr.length - 1) { - sb.append(" "); - } - } - - return sb.toString(); - } - - public static String toBase10(int[] arr) { - - if (arr == null) { - return ""; - } - - StringBuffer sb = new StringBuffer(); - - for (int i = 0; i < arr.length; i++) { - sb.append((arr[i])); - - if (i < arr.length - 1) { - sb.append(" "); - } - } - - return sb.toString(); - } - - /** - * @deprecated use toString(int[] arr) - */ - public static String toChar(int[] arr) { - return toString(arr); - } - - /** - * Converts an int array to string. - * Note: this method does not validate that int values map - * to valid characters - * - * @param arr - * @return - */ - public static String toString(int[] arr) { - - if (arr == null) { - return ""; - } - - StringBuffer sb = new StringBuffer(); - - for (int anArr : arr) { - sb.append((char) anArr); - } - - return sb.toString(); - } - - private static String padBase2(String s) { - - for (int i = s.length(); i < 8; i++) { - s = "0" + s; - } - - return s; - } - -// /** -// * Determines the bit value of a single byte -// * -// * @param b -// * @return -// */ -// public static boolean[] parseBits(int b) { -// -// boolean[] results = new boolean[8]; -// -// for (int i = 0; i < 8; i++) { -// if (((b >> i) & 0x1) == 0x1) { -// results[i] = true; -// } else { -// results[i] = false; -// } -// } -// -// return results; -// } - - /** - * Returns true if the bit is on (1) at the specified position - * Position range: 1-8 - */ - public static boolean getBit(int b, int position) { - - if (position < 1 || position > 8) { - throw new IllegalArgumentException("Position is out of range"); - } - - if (b > 0xff) { - throw new IllegalArgumentException("input value [" + b + "] is larger than a byte"); - } - - return ((b >> (--position)) & 0x1) == 0x1; - - } - - public static String toBase16(int b) { - - if (b > 0xff) { - throw new IllegalArgumentException("input value [" + b + "] is larger than a byte"); - } - - if (b < 0x10) { - return "0x0" + Integer.toHexString(b); - } else { - return "0x" + Integer.toHexString(b); - } - } - - public static String toBase2(int b) { - - if (b > 0xff) { - throw new IllegalArgumentException("input value [" + b + "] is larger than a byte"); - } - - return padBase2(Integer.toBinaryString(b)); - } - - public static String formatByte(int b) { - return "base10=" + Integer.toString(b) + ",base16=" + toBase16(b) + ",base2=" + toBase2(b); - } - - public static int[] stringToIntArray(String s) { - int[] intArr = new int[s.length()]; - - for (int i = 0; i < s.length(); i++) { - intArr[i] = (char)s.charAt(i); - } - - return intArr; - } - - /** - * Parses a 10-bit analog value from the input stream - * - * @return - * @throws IOException - */ - public static int parse10BitAnalog(int msb, int lsb) throws IOException { - msb = msb & 0xff; - - // shift up bits 9 and 10 of the msb - msb = (msb & 0x3) << 8; - -// log.debug("shifted msb is " + msb); - - lsb = lsb & 0xff; - - return msb + lsb; - } - - public static int parse10BitAnalog(IIntInputStream in, int pos) throws IOException { - int adcMsb = in.read("Analog " + pos + " MSB"); - int adcLsb = in.read("Analog " + pos + " LSB"); - - return ByteUtils.parse10BitAnalog(adcMsb, adcLsb); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.util; + +import java.io.IOException; + +public class ByteUtils { + + // not to be instantiated + private ByteUtils() { + + } + + /** + * There is a slight problem with this method that you might have noticed; a Java int is signed, so we can't make + * use of the 32nd bit. This means this method does not support a four byte value with msb greater than 01111111 ((2^7-1) or 127) + * and will throw a runtime exception if it encounters this situation. + * + * TODO use long instead of int to support 4 bytes values. note that long assignments are not atomic. + * + * Not Used + */ + public static int convertMultiByteToInt(int[] bytes) { + + if (bytes.length > 4) { + throw new RuntimeException("too big"); + } else if (bytes.length == 4 && ((bytes[0] & 0x80) == 0x80)) { + // 0x80 == 10000000, 0x7e == 01111111 + throw new IllegalArgumentException("Java int can't support a four byte value with msb byte greater than 7e"); + } + + int val = 0; + + for (int i = 0; i < bytes.length; i++) { + + if (bytes[i] > 0xFF) { + throw new IllegalArgumentException("Values exceeds byte range: " + bytes[i]); + } + + if (i == (bytes.length - 1)) { + val+= bytes[i]; + } else { + val+= bytes[i] << ((bytes.length - i - 1) * 8); + } + } + + return val; + } + + /** + * Works for positive values only + * + * @param val + * @return + */ + public static int[] convertInttoMultiByte(int val) { + + if (val < 0) { + throw new IllegalArgumentException("Negative values are not supported"); + } + + // must decompose into a max of 4 bytes + // b1 b2 b3 b4 + // 01111111 11111111 11111111 11111111 + // 127 255 255 255 + + int size = 0; + + if ((val >> 24) > 0) { + size = 4; + } else if ((val >> 16) > 0) { + size = 3; + } else if ((val >> 8) > 0) { + size = 2; + } else { + size = 1; + } + + int[] data = new int[size]; + + for (int i = 0; i < size; i++) { + data[i] = (val >> (size - i - 1) * 8) & 0xFF; + } + + return data; + } + + public static String toBase16(int[] arr) { + return toBase16(arr, ","); + } + + public static String toBase16(int[] arr, String delimiter) { + + if (arr == null) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < arr.length; i++) { + sb.append(toBase16(arr[i])); + + if (i < arr.length - 1) { + sb.append(delimiter); + } + } + + return sb.toString(); + } + + public static String toBase2(int[] arr) { + + if (arr == null) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < arr.length; i++) { + sb.append(toBase2(arr[i])); + + if (i < arr.length - 1) { + sb.append(" "); + } + } + + return sb.toString(); + } + + public static String toBase10(int[] arr) { + + if (arr == null) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + + for (int i = 0; i < arr.length; i++) { + sb.append((arr[i])); + + if (i < arr.length - 1) { + sb.append(" "); + } + } + + return sb.toString(); + } + + /** + * @deprecated use toString(int[] arr) + */ + public static String toChar(int[] arr) { + return toString(arr); + } + + /** + * Converts an int array to string. + * Note: this method does not validate that int values map + * to valid characters + * + * @param arr + * @return + */ + public static String toString(int[] arr) { + + if (arr == null) { + return ""; + } + + StringBuffer sb = new StringBuffer(); + + for (int anArr : arr) { + sb.append((char) anArr); + } + + return sb.toString(); + } + + private static String padBase2(String s) { + + for (int i = s.length(); i < 8; i++) { + s = "0" + s; + } + + return s; + } + +// /** +// * Determines the bit value of a single byte +// * +// * @param b +// * @return +// */ +// public static boolean[] parseBits(int b) { +// +// boolean[] results = new boolean[8]; +// +// for (int i = 0; i < 8; i++) { +// if (((b >> i) & 0x1) == 0x1) { +// results[i] = true; +// } else { +// results[i] = false; +// } +// } +// +// return results; +// } + + /** + * Returns true if the bit is on (1) at the specified position + * Position range: 1-8 + */ + public static boolean getBit(int b, int position) { + + if (position < 1 || position > 8) { + throw new IllegalArgumentException("Position is out of range"); + } + + if (b > 0xff) { + throw new IllegalArgumentException("input value [" + b + "] is larger than a byte"); + } + + return ((b >> (--position)) & 0x1) == 0x1; + + } + + public static String toBase16(int b) { + + if (b > 0xff) { + throw new IllegalArgumentException("input value [" + b + "] is larger than a byte"); + } + + if (b < 0x10) { + return "0x0" + Integer.toHexString(b); + } else { + return "0x" + Integer.toHexString(b); + } + } + + public static String toBase2(int b) { + + if (b > 0xff) { + throw new IllegalArgumentException("input value [" + b + "] is larger than a byte"); + } + + return padBase2(Integer.toBinaryString(b)); + } + + public static String formatByte(int b) { + return "base10=" + Integer.toString(b) + ",base16=" + toBase16(b) + ",base2=" + toBase2(b); + } + + public static int[] stringToIntArray(String s) { + int[] intArr = new int[s.length()]; + + for (int i = 0; i < s.length(); i++) { + intArr[i] = (char)s.charAt(i); + } + + return intArr; + } + + /** + * Parses a 10-bit analog value from the input stream + * + * @return + * @throws IOException + */ + public static int parse10BitAnalog(int msb, int lsb) throws IOException { + msb = msb & 0xff; + + // shift up bits 9 and 10 of the msb + msb = (msb & 0x3) << 8; + +// log.debug("shifted msb is " + msb); + + lsb = lsb & 0xff; + + return msb + lsb; + } + + public static int parse10BitAnalog(IIntInputStream in, int pos) throws IOException { + int adcMsb = in.read("Analog " + pos + " MSB"); + int adcLsb = in.read("Analog " + pos + " LSB"); + + return ByteUtils.parse10BitAnalog(adcMsb, adcLsb); + } +} diff --git a/src/com/rapplogic/xbee/util/DoubleByte.java b/src/main/java/com/rapplogic/xbee/util/DoubleByte.java similarity index 95% rename from src/com/rapplogic/xbee/util/DoubleByte.java rename to src/main/java/com/rapplogic/xbee/util/DoubleByte.java index 0bfeb8d..4d1879d 100644 --- a/src/com/rapplogic/xbee/util/DoubleByte.java +++ b/src/main/java/com/rapplogic/xbee/util/DoubleByte.java @@ -1,105 +1,105 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.util; - -public class DoubleByte { - - private int msb; - private int lsb; - - public DoubleByte() { - - } - - /** - * Decomposes a 16bit int into high and low bytes - * - * @param val - */ - public DoubleByte(int val) { - if (val > 0xFFFF || val < 0) { - throw new IllegalArgumentException("value is out of range"); - } - - // split address into high and low bytes - msb = val >> 8; - lsb = val & 0xFF; - } - - /** - * Constructs a 16bit value from two bytes (high and low) - * - * @param msb - * @param lsb - */ - public DoubleByte(int msb, int lsb) { - - if (msb > 0xFF || lsb > 0xFF) { - throw new IllegalArgumentException("msb or lsb are out of range"); - } - - this.msb = msb; - this.lsb = lsb; - } - - public int getMsb() { - return msb; - } - - public int getLsb() { - return lsb; - } - - public int get16BitValue() { - return (this.msb << 8) + this.lsb; - } - - public void setMsb(int msb) { - this.msb = msb; - } - - public void setLsb(int lsb) { - this.lsb = lsb; - } - - public int[] getArray() { - return new int[] { this.msb, this.lsb }; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - DoubleByte that = (DoubleByte) o; - - if (lsb != that.lsb) return false; - if (msb != that.msb) return false; - - return true; - } - - @Override - public int hashCode() { - int result = msb; - result = 31 * result + lsb; - return result; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.util; + +public class DoubleByte { + + private int msb; + private int lsb; + + public DoubleByte() { + + } + + /** + * Decomposes a 16bit int into high and low bytes + * + * @param val + */ + public DoubleByte(int val) { + if (val > 0xFFFF || val < 0) { + throw new IllegalArgumentException("value is out of range"); + } + + // split address into high and low bytes + msb = val >> 8; + lsb = val & 0xFF; + } + + /** + * Constructs a 16bit value from two bytes (high and low) + * + * @param msb + * @param lsb + */ + public DoubleByte(int msb, int lsb) { + + if (msb > 0xFF || lsb > 0xFF) { + throw new IllegalArgumentException("msb or lsb are out of range"); + } + + this.msb = msb; + this.lsb = lsb; + } + + public int getMsb() { + return msb; + } + + public int getLsb() { + return lsb; + } + + public int get16BitValue() { + return (this.msb << 8) + this.lsb; + } + + public void setMsb(int msb) { + this.msb = msb; + } + + public void setLsb(int lsb) { + this.lsb = lsb; + } + + public int[] getArray() { + return new int[] { this.msb, this.lsb }; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + DoubleByte that = (DoubleByte) o; + + if (lsb != that.lsb) return false; + if (msb != that.msb) return false; + + return true; + } + + @Override + public int hashCode() { + int result = msb; + result = 31 * result + lsb; + return result; + } +} diff --git a/src/com/rapplogic/xbee/util/ExceptionHandler.java b/src/main/java/com/rapplogic/xbee/util/ExceptionHandler.java similarity index 100% rename from src/com/rapplogic/xbee/util/ExceptionHandler.java rename to src/main/java/com/rapplogic/xbee/util/ExceptionHandler.java diff --git a/src/com/rapplogic/xbee/util/IIntArray.java b/src/main/java/com/rapplogic/xbee/util/IIntArray.java similarity index 97% rename from src/com/rapplogic/xbee/util/IIntArray.java rename to src/main/java/com/rapplogic/xbee/util/IIntArray.java index 9eb0177..e539e3e 100644 --- a/src/com/rapplogic/xbee/util/IIntArray.java +++ b/src/main/java/com/rapplogic/xbee/util/IIntArray.java @@ -1,24 +1,24 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.util; - -public interface IIntArray { - public int[] getIntArray(); -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.util; + +public interface IIntArray { + public int[] getIntArray(); +} diff --git a/src/com/rapplogic/xbee/util/IIntInputStream.java b/src/main/java/com/rapplogic/xbee/util/IIntInputStream.java similarity index 97% rename from src/com/rapplogic/xbee/util/IIntInputStream.java rename to src/main/java/com/rapplogic/xbee/util/IIntInputStream.java index 145cee5..5d7bc5d 100644 --- a/src/com/rapplogic/xbee/util/IIntInputStream.java +++ b/src/main/java/com/rapplogic/xbee/util/IIntInputStream.java @@ -1,28 +1,28 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.util; - -import java.io.IOException; - -// TODO rename to IIntInputStream -public interface IIntInputStream { - public int read() throws IOException; - public int read(String s) throws IOException; -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.util; + +import java.io.IOException; + +// TODO rename to IIntInputStream +public interface IIntInputStream { + public int read() throws IOException; + public int read(String s) throws IOException; +} diff --git a/src/com/rapplogic/xbee/util/InputStreamWrapper.java b/src/main/java/com/rapplogic/xbee/util/InputStreamWrapper.java old mode 100755 new mode 100644 similarity index 100% rename from src/com/rapplogic/xbee/util/InputStreamWrapper.java rename to src/main/java/com/rapplogic/xbee/util/InputStreamWrapper.java diff --git a/src/com/rapplogic/xbee/util/IntArrayInputStream.java b/src/main/java/com/rapplogic/xbee/util/IntArrayInputStream.java similarity index 96% rename from src/com/rapplogic/xbee/util/IntArrayInputStream.java rename to src/main/java/com/rapplogic/xbee/util/IntArrayInputStream.java index 8108051..828482d 100644 --- a/src/com/rapplogic/xbee/util/IntArrayInputStream.java +++ b/src/main/java/com/rapplogic/xbee/util/IntArrayInputStream.java @@ -1,60 +1,60 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.util; - -/** - * //TODO replace with nio.IntBuffer - */ -public class IntArrayInputStream implements IIntInputStream { - - private int[] source; - private int pos; - - public IntArrayInputStream(int[] source) { - this.source = source; - } - - public int read() { - if (pos >= source.length) { - throw new IllegalStateException("end of input stream"); - } - - return source[pos++]; - } - - /** - * Reads size bytes from the input stream and returns the bytes in an array - * - * @param size - * @return - * Apr 13, 2009 - */ - public int[] read(int size) { - int[] block = new int[size]; - System.arraycopy(source, pos, block, 0, size); - // index pos - pos+=size; - return block; - } - - public int read(String s) { - return read(); - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.util; + +/** + * //TODO replace with nio.IntBuffer + */ +public class IntArrayInputStream implements IIntInputStream { + + private int[] source; + private int pos; + + public IntArrayInputStream(int[] source) { + this.source = source; + } + + public int read() { + if (pos >= source.length) { + throw new IllegalStateException("end of input stream"); + } + + return source[pos++]; + } + + /** + * Reads size bytes from the input stream and returns the bytes in an array + * + * @param size + * @return + * Apr 13, 2009 + */ + public int[] read(int size) { + int[] block = new int[size]; + System.arraycopy(source, pos, block, 0, size); + // index pos + pos+=size; + return block; + } + + public int read(String s) { + return read(); + } +} diff --git a/src/com/rapplogic/xbee/util/IntArrayOutputStream.java b/src/main/java/com/rapplogic/xbee/util/IntArrayOutputStream.java similarity index 96% rename from src/com/rapplogic/xbee/util/IntArrayOutputStream.java rename to src/main/java/com/rapplogic/xbee/util/IntArrayOutputStream.java index a856bbe..9f40279 100644 --- a/src/com/rapplogic/xbee/util/IntArrayOutputStream.java +++ b/src/main/java/com/rapplogic/xbee/util/IntArrayOutputStream.java @@ -1,63 +1,63 @@ -/** - * Copyright (c) 2008 Andrew Rapp. All rights reserved. - * - * This file is part of XBee-API. - * - * XBee-API is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * XBee-API is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with XBee-API. If not, see . - */ - -package com.rapplogic.xbee.util; - -import java.util.ArrayList; -import java.util.List; - -/** - * TODO replace with nio.IntBuffer - */ -public class IntArrayOutputStream implements IIntArray { - - private List intList = new ArrayList(); - - public IntArrayOutputStream() { - - } - - public void write (int val) { - intList.add(val); - } - - public void write(int[] val) { - for (int aVal : val) { - this.write(aVal); - } - } - - public int[] getIntArray() { - //int[] integer = (int[]) intList.toArray(new int[0]); - // TODO there has got to be a better way -- how to convert list to int[] array? - int[] intArr = new int[intList.size()]; - - int i = 0; - - for (Integer integer : intList) { - intArr[i++] = integer; - } - - return intArr; - } - - public List getInternalList() { - return intList; - } -} +/** + * Copyright (c) 2008 Andrew Rapp. All rights reserved. + * + * This file is part of XBee-API. + * + * XBee-API is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * XBee-API is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with XBee-API. If not, see . + */ + +package com.rapplogic.xbee.util; + +import java.util.ArrayList; +import java.util.List; + +/** + * TODO replace with nio.IntBuffer + */ +public class IntArrayOutputStream implements IIntArray { + + private List intList = new ArrayList(); + + public IntArrayOutputStream() { + + } + + public void write (int val) { + intList.add(val); + } + + public void write(int[] val) { + for (int aVal : val) { + this.write(aVal); + } + } + + public int[] getIntArray() { + //int[] integer = (int[]) intList.toArray(new int[0]); + // TODO there has got to be a better way -- how to convert list to int[] array? + int[] intArr = new int[intList.size()]; + + int i = 0; + + for (Integer integer : intList) { + intArr[i++] = integer; + } + + return intArr; + } + + public List getInternalList() { + return intList; + } +} diff --git a/log4j.properties b/src/main/resources/log4j.properties similarity index 100% rename from log4j.properties rename to src/main/resources/log4j.properties diff --git a/src/test/java/com/rapplogic/xbee/SimpleSeries2Test.java b/src/test/java/com/rapplogic/xbee/SimpleSeries2Test.java new file mode 100644 index 0000000..62c73f3 --- /dev/null +++ b/src/test/java/com/rapplogic/xbee/SimpleSeries2Test.java @@ -0,0 +1,29 @@ +package com.rapplogic.xbee; + +import static org.assertj.core.api.Assertions.assertThat; +import org.testng.annotations.Test; + +import com.rapplogic.xbee.api.XBee; +import com.rapplogic.xbee.api.XBeeConfiguration; +import com.rapplogic.xbee.api.XBeeException; + +public class SimpleSeries2Test { + + //TODO: Add series2 tests to get easy example of how it could be done and how to abstract the HW. + + @Test + public void createXBee() { + XBee xbee = getDefaultXBee(); + assertThat(xbee).isNotNull(); + } + + @Test(expectedExceptions=XBeeException.class) + public void createXBeeAndOpenConnectionWithInvalidConnectionProvider() throws XBeeException { + XBee xbee = getDefaultXBee(); + xbee.open("foobar", 12345); + } + + private XBee getDefaultXBee() { + return new XBee(new XBeeConfiguration().withMaxQueueSize(100).withStartupChecks(true).withConnectionProvider(new TestConnectionProvider())); + } +} diff --git a/src/test/java/com/rapplogic/xbee/TestConnectionProvider.java b/src/test/java/com/rapplogic/xbee/TestConnectionProvider.java new file mode 100644 index 0000000..be34cb6 --- /dev/null +++ b/src/test/java/com/rapplogic/xbee/TestConnectionProvider.java @@ -0,0 +1,15 @@ +package com.rapplogic.xbee; + +import com.rapplogic.xbee.connections.XBeeConnection; +import com.rapplogic.xbee.connections.XBeeConnectionException; +import com.rapplogic.xbee.connections.connectionprovider.IConnectionProvider; +import com.rapplogic.xbee.mocks.Series2Mock; + +public class TestConnectionProvider implements IConnectionProvider { + + @Override + public XBeeConnection open(String port, int baudRate) throws XBeeConnectionException { + return new Series2Mock(); + } + +} diff --git a/src/test/java/com/rapplogic/xbee/mocks/Series2Mock.java b/src/test/java/com/rapplogic/xbee/mocks/Series2Mock.java new file mode 100644 index 0000000..a93b8cc --- /dev/null +++ b/src/test/java/com/rapplogic/xbee/mocks/Series2Mock.java @@ -0,0 +1,51 @@ +package com.rapplogic.xbee.mocks; + +import java.io.IOException; + +import com.rapplogic.xbee.connections.XBeeConnection; + +public class Series2Mock implements XBeeConnection { + + @Override + public int getByte() throws IOException { + // TODO Auto-generated method stub + return 0; + } + + @Override + public boolean hasData() throws IOException { + // TODO Auto-generated method stub + return false; + } + + @Override + public void close() throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public void writeIntArray(int[] packet) throws IOException { + // TODO Auto-generated method stub + + } + + @Override + public boolean isConnected() { + // TODO Auto-generated method stub + return false; + } + + @Override + public long getLastDataReceiveTime() { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long getLastDataSendTime() { + // TODO Auto-generated method stub + return 0; + } + +}