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