All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.digi.xbee.api.io.IOSample Maven / Gradle / Ivy

There is a newer version: 1.3.2
Show newest version
/**
 * Copyright 2017, Digi International Inc.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, you can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
package com.digi.xbee.api.io;

import java.util.Arrays;
import java.util.HashMap;

import com.digi.xbee.api.exceptions.OperationNotSupportedException;
import com.digi.xbee.api.utils.ByteUtils;

/**
 * This class represents an IO Data Sample. The sample is built using the
 * the constructor. The sample contains an analog and digital mask indicating 
 * which IO lines are configured with that functionality.
 * 
 * 

Depending on the protocol the XBee device is executing, the digital and * analog masks are retrieved in separated bytes (2 bytes for the digital * mask and 1 for the analog mask) or merged (digital and analog masks are * contained in the same 2 bytes).

*
*

802.15.4 Protocol

*
*

Digital and analog channels masks

*

------------------------------------------------------------------

*

Indicates which digital and ADC IO lines are configured in the module. * Each bit corresponds to one digital or ADC IO line on the module:

*
*
*

bit 0 = DIO0

1 *

bit 1 = DIO1

0 *

bit 2 = DIO2

0 *

bit 3 = DIO3

1 *

bit 4 = DIO4

0 *

bit 5 = DIO5

1 *

bit 6 = DIO6

0 *

bit 7 = DIO7

0 *

bit 8 = DIO8

0 *

bit 9 = AD0

0 *

bit 10 = AD1

1 *

bit 11 = AD2

1 *

bit 12 = AD3

0 *

bit 13 = AD4

0 *

bit 14 = AD5

0 *

bit 15 = N/A

0 *
*

Example: mask of {@code 0x0C29} means DIO0, DIO3, DIO5, AD1 and * AD2 enabled.

*

0 0 0 0 1 1 0 0 0 0 1 0 1 0 0 1

*
*

*

Other Protocols

*
*

Digital Channel Mask

*

------------------------------------------------------------------

*

Indicates which digital IO lines are configured in the module. Each bit * corresponds to one digital IO line on the module:

*
*
*

bit 0 = DIO0/AD0

*

bit 1 = DIO1/AD1

*

bit 2 = DIO2/AD2

*

bit 3 = DIO3/AD3

*

bit 4 = DIO4/AD4

*

bit 5 = DIO5/AD5/ASSOC

*

bit 6 = DIO6/RTS

*

bit 7 = DIO7/CTS

*

bit 8 = DIO8/DTR/SLEEP_RQ

*

bit 9 = DIO9/ON_SLEEP

*

bit 10 = DIO10/PWM0/RSSI

*

bit 11 = DIO11/PWM1

*

bit 12 = DIO12/CD

*

bit 13 = DIO13

*

bit 14 = DIO14

*

bit 15 = N/A

*
*

Example: mask of {@code 0x040B} means DIO0, DIO1, DIO2, DIO3 and * DIO10 enabled.

*

0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1

*

*
*

Analog Channel Mask

*

-----------------------------------------------------------------------

*

Indicates which lines are configured as ADC. Each bit in the analog * channel mask corresponds to one ADC line on the module.

*
*
*

bit 0 = AD0/DIO0

*

bit 1 = AD1/DIO1

*

bit 2 = AD2/DIO2

*

bit 3 = AD3/DIO3

*

bit 4 = AD4/DIO4

*

bit 5 = AD5/DIO5/ASSOC

*

bit 6 = N/A

*

bit 7 = Supply Voltage Value

*
*

Example: mask of {@code 0x03} means AD0, and AD1 enabled.

*

0 0 0 0 0 0 1 1

*
*/ public class IOSample { // Variables. private final byte[] ioSamplePayload; private int digitalHSBMask; private int digitalLSBMask; private int digitalMask; private int analogMask; private int digitalHSBValues; private int digitalLSBValues; private int digitalValues; private int powerSupplyVoltage; private final HashMap analogValuesMap = new HashMap(); private final HashMap digitalValuesMap = new HashMap(); /** * Class constructor. Instantiates a new object of type {@code IOSample} * with the given IO sample payload. * * @param ioSamplePayload The payload corresponding to an IO sample. * * @throws IllegalArgumentException if {@code ioSamplePayload.length < 5}. * @throws NullPointerException if {@code ioSamplePayload == null}. */ public IOSample(byte[] ioSamplePayload) { if (ioSamplePayload == null) throw new NullPointerException("IO sample payload cannot be null."); if (ioSamplePayload.length < 5) throw new IllegalArgumentException("IO sample payload must be longer than 4."); this.ioSamplePayload = ioSamplePayload; if (ioSamplePayload.length % 2 != 0) parseRawIOSample(); else parseIOSample(); } /** * Parses the information contained in the IO sample bytes reading the * value of each configured DIO and ADC. */ private void parseRawIOSample() { int dataIndex = 3; // Obtain the digital mask. // Available digital IOs in 802.15.4 digitalHSBMask = ioSamplePayload[1] & 0x01; // 0 0 0 0 0 0 0 1 digitalLSBMask = ioSamplePayload[2] & 0xFF; // 1 1 1 1 1 1 1 1 // Combine the masks. digitalMask = (digitalHSBMask << 8) + digitalLSBMask; // Obtain the analog mask. // Available analog IOs in 802.15.4 analogMask = ((ioSamplePayload[1] << 8) + (ioSamplePayload[2] & 0xFF)) & 0x7E00; // 0 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 // Read the digital values (if any). There are 9 possible digital lines in // 802.15.4 protocol. The digital mask indicates if there is any digital // line enabled to read its value. If 0, no digital values are received. if (digitalMask > 0) { // Obtain the digital values. digitalHSBValues = ioSamplePayload[3] & 0x7F; digitalLSBValues = ioSamplePayload[4] & 0xFF; // Combine the values. digitalValues = (digitalHSBValues << 8) + digitalLSBValues; for (int i = 0; i < 16; i++) { if (!ByteUtils.isBitEnabled(digitalMask, i)) continue; if (ByteUtils.isBitEnabled(digitalValues, i)) digitalValuesMap.put(IOLine.getDIO(i), IOValue.HIGH); else digitalValuesMap.put(IOLine.getDIO(i), IOValue.LOW); } // Increase the data index to read the analog values. dataIndex += 2; } // Read the analog values (if any). There are 6 possible analog lines. // The analog mask indicates if there is any analog line enabled to read // its value. If 0, no analog values are received. int adcIndex = 9; while ((ioSamplePayload.length - dataIndex) > 1 && adcIndex < 16) { if (!ByteUtils.isBitEnabled(analogMask, adcIndex)) { adcIndex += 1; continue; } // 802.15.4 protocol does not provide power supply value, so get just the ADC data. analogValuesMap.put(IOLine.getDIO(adcIndex - 9), ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF)); // Increase the data index to read the next analog values. dataIndex += 2; adcIndex += 1; } } /** * Parses the information contained in the IO sample bytes reading the * value of each configured DIO and ADC. */ private void parseIOSample() { int dataIndex = 4; // Obtain the digital masks. // Available digital IOs digitalHSBMask = ioSamplePayload[1] & 0x7F; // 0 1 1 1 1 1 1 1 digitalLSBMask = ioSamplePayload[2] & 0xFF; // 1 1 1 1 1 1 1 1 // Combine the masks. digitalMask = (digitalHSBMask << 8) + digitalLSBMask; // Obtain the analog mask. // Available analog IOs analogMask = ioSamplePayload[3] & 0xBF; // 1 0 1 1 1 1 1 1 // Read the digital values (if any). There are 16 possible digital lines. // The digital mask indicates if there is any digital line enabled to read // its value. If 0, no digital values are received. if (digitalMask > 0) { // Obtain the digital values. digitalHSBValues = ioSamplePayload[4] & 0x7F; digitalLSBValues = ioSamplePayload[5] & 0xFF; // Combine the values. digitalValues = (digitalHSBValues << 8) + digitalLSBValues; for (int i = 0; i < 16; i++) { if (!ByteUtils.isBitEnabled(digitalMask, i)) continue; if (ByteUtils.isBitEnabled(digitalValues, i)) digitalValuesMap.put(IOLine.getDIO(i), IOValue.HIGH); else digitalValuesMap.put(IOLine.getDIO(i), IOValue.LOW); } // Increase the data index to read the analog values. dataIndex += 2; } // Read the analog values (if any). There are 6 possible analog lines. // The analog mask indicates if there is any analog line enabled to read // its value. If 0, no analog values are received. int adcIndex = 0; while ((ioSamplePayload.length - dataIndex) > 1 && adcIndex < 8) { if (!ByteUtils.isBitEnabled(analogMask, adcIndex)) { adcIndex += 1; continue; } // When analog index is 7, it means that the analog value corresponds to the power // supply voltage, therefore this value should be stored in a different value. if (adcIndex == 7) powerSupplyVoltage = ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF); else analogValuesMap.put(IOLine.getDIO(adcIndex), ((ioSamplePayload[dataIndex] & 0xFF) << 8) + (ioSamplePayload[dataIndex + 1] & 0xFF)); // Increase the data index to read the next analog values. dataIndex += 2; adcIndex += 1; } } /** * Returns the HSB of the digital mask. * * @return HSB of the digital mask. * * @see #getDigitalLSBMask() * @see #getDigitalMask() */ public int getDigitalHSBMask() { return digitalHSBMask; } /** * Returns the LSB of the digital mask. * * @return LSB of the digital mask. * * @see #getDigitalHSBMask() * @see #getDigitalMask() */ public int getDigitalLSBMask() { return digitalLSBMask; } /** * Returns the combined (HSB + LSB) digital mask. * * @return The combined digital mask. * * @see #getDigitalLSBMask() * @see #getDigitalHSBMask() */ public int getDigitalMask() { return digitalMask; } /** * Checks whether or not the {@code IOSample} has digital values. * * @return {@code true} if there are digital values, {@code false} * otherwise. */ public boolean hasDigitalValues() { return digitalValuesMap.size() > 0; } /** * Returns whether or not this IO sample contains a digital value for * the given IO line. * * @param ioLine The IO line to check if has a digital value. * * @return {@code true} if the given IO line has a digital value, * {@code false} otherwise. * * @see #hasDigitalValues() * @see IOLine */ public boolean hasDigitalValue(IOLine ioLine) { return digitalValuesMap.containsKey(ioLine); } /** * Returns the digital values map. * *

To verify if this sample contains a valid digital values, use the * method {@code hasDigitalValues()}.

* *
	 * {@code
	 * if (ioSample.hasDigitalValues()) {
	 *     HashMap values = ioSample.getDigitalValues();
	 *     ...
	 * } else {
	 *     ...
	 * }
	 * }
	 * 
* * @return {@code HashMap} with the digital value of each configured IO * line. * * @see #getDigitalValue(IOLine) * @see #hasDigitalValues() * @see IOLine * @see IOValue */ public HashMap getDigitalValues() { return (HashMap) digitalValuesMap.clone(); } /** * Returns the digital value of the provided IO line. * *

To verify if this sample contains a digital value for the given * {@code IOLine}, use the method {@code hasDigitalValue(IOLine)}.

* *
	 * {@code
	 * if (ioSample.hasDigitalValue(IOLine.DIO0_AD0)) {
	 *     IOValue value = ioSample.getDigitalValue(IOLine.DIO0_AD0);
	 *     ...
	 * } else {
	 *     ...
	 * }
	 * }
	 * 
* * @param ioLine The IO line to get its digital value. * * @return The {@code IOValue} of the given IO line or {@code null} if the * IO sample does not contain a digital value for the given IO line. * * @see #getDigitalValues() * @see #hasDigitalValues() * @see IOLine * @see IOValue */ public IOValue getDigitalValue(IOLine ioLine) { if (!digitalValuesMap.containsKey(ioLine)) return null; return digitalValuesMap.get(ioLine); } /** * Returns the analog mask. * * @return Analog mask. */ public int getAnalogMask() { return analogMask; } /** * Returns whether or not the {@code IOSample} has analog values. * * @return {@code true} if there are analog values, {@code false} otherwise. * * @see #getAnalogValue(IOLine) * @see #getAnalogValues() * @see #hasAnalogValue(IOLine) * @see IOLine */ public boolean hasAnalogValues() { return analogValuesMap.size() > 0; } /** * Returns whether or not the given IO line has an analog value. * * @param ioLine The IO line to check if has an analog value. * * @return {@code true} if the given IO line has an analog value, * {@code false} otherwise. * * @see #getAnalogValue(IOLine) * @see #getAnalogValues() * @see #hasAnalogValues() * @see IOLine */ public boolean hasAnalogValue(IOLine ioLine) { return analogValuesMap.containsKey(ioLine); } /** * Returns the analog values map. * *

To verify if this sample contains a valid analog values, use the * method {@code hasAnalogValues()}.

* *
	 * {@code
	 * if (ioSample.hasAnalogValues()) {
	 *     HashMap values = ioSample.getAnalogValues();
	 *     ...
	 * } else {
	 *     ...
	 * }
	 * }
	 * 
* * @return {@code HashMap} with the analog value of each configured IO * line. * * @see #getAnalogValue(IOLine) * @see #hasAnalogValue(IOLine) * @see #hasAnalogValues() * @see IOLine */ public HashMap getAnalogValues() { return (HashMap) analogValuesMap.clone(); } /** * Returns the analog value of the provided IO line. * *

To verify if this sample contains an analog value for the given * {@code IOLine}, use the method {@code hasAnalogValue(IOLine)}.

* *
	 * {@code
	 * if (ioSample.hasAnalogValue(IOLine.DIO0_AD0)) {
	 *     Integer value = ioSample.getAnalogValue(IOLine.DIO0_AD0);
	 *     ...
	 * } else {
	 *     ...
	 * }
	 * }
	 * 
* * @param ioLine The IO line to get its analog value. * * @return The analog value of the given IO line or {@code null} if the * IO sample does not contain an analog value for the given IO line. * * @see #getAnalogValues() * @see #hasAnalogValue(IOLine) * @see #hasAnalogValues() * @see IOLine */ public Integer getAnalogValue(IOLine ioLine) { if (!analogValuesMap.containsKey(ioLine)) return null; return analogValuesMap.get(ioLine); } /** * Returns whether or not the IOSample has power supply value. * * @return {@code true} if the IOSample has power supply value, * {@code false} otherwise. * * @see #getPowerSupplyValue() */ public boolean hasPowerSupplyValue() { return ByteUtils.isBitEnabled(analogMask, 7); } /** * Returns the value of the power supply voltage. * *

To verify if this sample contains the power supply voltage, use the * method {@code hasPowerSupplyValue()}.

* *
	 * {@code
	 * if (ioSample.hasPowerSupplyValue()) {
	 *     int value = ioSample.getPowerSupplyValue();
	 *     ...
	 * } else {
	 *     ...
	 * }
	 * }
	 * 
* * @return The value of the power supply voltage. * * @throws OperationNotSupportedException if the IOSample does not have * power supply value. * * @see #hasPowerSupplyValue() */ public int getPowerSupplyValue() throws OperationNotSupportedException { if (!ByteUtils.isBitEnabled(analogMask, 7)) throw new OperationNotSupportedException(); return powerSupplyVoltage; } /* * (non-Javadoc) * @see java.lang.Object#toString() */ @Override public String toString() { StringBuilder sb = new StringBuilder("{"); if (hasDigitalValues()) { for (IOLine line : digitalValuesMap.keySet()) { sb.append("[").append(line).append(": ").append(digitalValuesMap.get(line)).append("], "); } } if (hasAnalogValues()) { for (IOLine line : analogValuesMap.keySet()) { sb.append("[").append(line).append(": ").append(analogValuesMap.get(line)).append("], "); } } if (hasPowerSupplyValue()) { try { sb.append("[").append("Power supply voltage: ").append(getPowerSupplyValue()).append("], "); } catch (OperationNotSupportedException e) {} } String s = sb.toString(); if (s.endsWith(", ")) s = s.substring(0, s.length() - 2); return s + "}"; } /* * (non-Javadoc) * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { try { IOSample sample = (IOSample)obj; return Arrays.equals(ioSamplePayload, sample.ioSamplePayload); } catch (ClassCastException e) { return false; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy