001/** 002 * Copyright 2017, Digi International Inc. 003 * 004 * This Source Code Form is subject to the terms of the Mozilla Public 005 * License, v. 2.0. If a copy of the MPL was not distributed with this 006 * file, you can obtain one at http://mozilla.org/MPL/2.0/. 007 * 008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 015 */ 016package com.digi.xbee.api.packet; 017 018import java.io.ByteArrayOutputStream; 019import java.io.IOException; 020import java.util.Arrays; 021import java.util.LinkedHashMap; 022 023import org.slf4j.Logger; 024import org.slf4j.LoggerFactory; 025 026import com.digi.xbee.api.utils.HexUtils; 027 028/** 029 * This class represents a basic and unknown XBee packet where the payload is 030 * set as a byte array without a defined structure. 031 * 032 * @see XBeeAPIPacket 033 */ 034public class UnknownXBeePacket extends XBeeAPIPacket { 035 036 // Constants. 037 private static final int MIN_API_PAYLOAD_LENGTH = 1; // 1 (Frame type) 038 039 // Variables 040 protected byte[] rfData; 041 042 private Logger logger; 043 044 /** 045 * Creates a new {@code UnknownXBeePacket} from the given payload. 046 * 047 * @param payload The API frame payload. The first byte will be the frame 048 * type. 049 * The byte array must be in {@code OperatingMode.API} mode. 050 * 051 * @return Parsed Unknown packet. 052 * 053 * @throws IllegalArgumentException if {@code payload.length < }{@value #MIN_API_PAYLOAD_LENGTH}. 054 * @throws NullPointerException if {@code payload == null}. 055 */ 056 public static UnknownXBeePacket createPacket(byte[] payload) { 057 if (payload == null) 058 throw new NullPointerException("Unknown packet payload cannot be null."); 059 060 // 1 (Frame type) 061 if (payload.length < MIN_API_PAYLOAD_LENGTH) 062 throw new IllegalArgumentException("Incomplete Unknown packet."); 063 064 // payload[0] is the frame type. 065 int apiID = payload[0] & 0xFF; 066 int index = 1; 067 068 byte[] commandData = null; 069 if (index < payload.length) 070 commandData = Arrays.copyOfRange(payload, index, payload.length); 071 072 return new UnknownXBeePacket(apiID, commandData); 073 } 074 075 /** 076 * Class constructor. Instantiates an XBee packet with the given packet 077 * data. 078 * 079 * @param apiIDValue The XBee API integer value of the packet. 080 * @param rfData The XBee RF Data. 081 * 082 * @throws IllegalArgumentException if {@code apiIDValue < 0} or 083 * if {@code apiIDValue > 255}. 084 */ 085 public UnknownXBeePacket(int apiIDValue, byte[] rfData) { 086 super(apiIDValue); 087 this.rfData = rfData; 088 this.logger = LoggerFactory.getLogger(UnknownXBeePacket.class); 089 } 090 091 /* 092 * (non-Javadoc) 093 * @see com.digi.xbee.api.packet.XBeeAPIPacket#getAPIPacketSpecificData() 094 */ 095 @Override 096 protected byte[] getAPIPacketSpecificData() { 097 ByteArrayOutputStream data = new ByteArrayOutputStream(); 098 try { 099 if (rfData != null) 100 data.write(rfData); 101 } catch (IOException e) { 102 logger.error(e.getMessage(), e); 103 } 104 return data.toByteArray(); 105 } 106 107 /* 108 * (non-Javadoc) 109 * @see com.digi.xbee.api.packet.XBeeAPIPacket#needsAPIFrameID() 110 */ 111 @Override 112 public boolean needsAPIFrameID() { 113 return false; 114 } 115 116 /** 117 * Sets the XBee RF Data. 118 * 119 * @param rfData The new XBee RF Data. 120 */ 121 public void setRFData(byte[] rfData) { 122 if (rfData == null) 123 this.rfData = null; 124 else 125 this.rfData = Arrays.copyOf(rfData, rfData.length); 126 } 127 128 /** 129 * Returns the XBee RF Data of the packet. 130 * 131 * @return The RF Data. 132 */ 133 public byte[] getRFData() { 134 if (rfData == null) 135 return null; 136 return Arrays.copyOf(rfData, rfData.length); 137 } 138 139 /* 140 * (non-Javadoc) 141 * @see com.digi.xbee.api.packet.XBeeAPIPacket#isBroadcast() 142 */ 143 @Override 144 public boolean isBroadcast() { 145 return false; 146 } 147 148 /* 149 * (non-Javadoc) 150 * @see com.digi.xbee.api.packet.XBeeAPIPacket#getAPIPacketParameters() 151 */ 152 @Override 153 protected LinkedHashMap<String, String> getAPIPacketParameters() { 154 LinkedHashMap<String, String> parameters = new LinkedHashMap<String, String>(); 155 if (rfData != null) 156 parameters.put("RF Data", HexUtils.prettyHexString(HexUtils.byteArrayToHexString(rfData))); 157 return parameters; 158 } 159}