001/*
002 * Copyright 2017-2019, 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;
017
018import java.net.Inet6Address;
019
020import com.digi.xbee.api.connection.IConnectionInterface;
021import com.digi.xbee.api.connection.serial.SerialPortParameters;
022import com.digi.xbee.api.exceptions.InterfaceNotOpenException;
023import com.digi.xbee.api.exceptions.OperationNotSupportedException;
024import com.digi.xbee.api.exceptions.TimeoutException;
025import com.digi.xbee.api.exceptions.XBeeDeviceException;
026import com.digi.xbee.api.exceptions.XBeeException;
027import com.digi.xbee.api.models.AssociationIndicationStatus;
028import com.digi.xbee.api.models.XBee16BitAddress;
029import com.digi.xbee.api.models.XBee64BitAddress;
030import com.digi.xbee.api.models.XBeeProtocol;
031import com.digi.xbee.api.models.XBeeTransmitOptions;
032import com.digi.xbee.api.packet.XBeePacket;
033import com.digi.xbee.api.packet.raw.TX16Packet;
034import com.digi.xbee.api.utils.HexUtils;
035
036/**
037 * This class represents a local 802.15.4 device.
038 * 
039 * @see CellularDevice
040 * @see DigiPointDevice
041 * @see DigiMeshDevice
042 * @see ThreadDevice
043 * @see WiFiDevice
044 * @see XBeeDevice
045 * @see ZigBeeDevice
046 */
047public class Raw802Device extends XBeeDevice {
048
049        // Constants
050        private static final String OPERATION_EXCEPTION = "Operation not supported in 802.15.4 protocol.";
051        
052        /**
053         * Class constructor. Instantiates a new {@code Raw802Device} object in the 
054         * given port name and baud rate.
055         * 
056         * @param port Serial port name where 802.15.4 device is attached to.
057         * @param baudRate Serial port baud rate to communicate with the device. 
058         *                 Other connection parameters will be set as default (8 
059         *                 data bits, 1 stop bit, no parity, no flow control).
060         * 
061         * @throws IllegalArgumentException if {@code baudRate < 0}.
062         * @throws NullPointerException if {@code port == null}.
063         * 
064         * @see #Raw802Device(IConnectionInterface)
065         * @see #Raw802Device(String, SerialPortParameters)
066         * @see #Raw802Device(String, int, int, int, int, int)
067         */
068        public Raw802Device(String port, int baudRate) {
069                this(XBee.createConnectiontionInterface(port, baudRate));
070        }
071        
072        /**
073         * Class constructor. Instantiates a new {@code Raw802Device} object in the 
074         * given serial port name and settings.
075         * 
076         * @param port Serial port name where 802.15.4 device is attached to.
077         * @param baudRate Serial port baud rate to communicate with the device.
078         * @param dataBits Serial port data bits.
079         * @param stopBits Serial port data bits.
080         * @param parity Serial port data bits.
081         * @param flowControl Serial port data bits.
082         * 
083         * @throws IllegalArgumentException if {@code baudRate < 0} or
084         *                                  if {@code dataBits < 0} or
085         *                                  if {@code stopBits < 0} or
086         *                                  if {@code parity < 0} or
087         *                                  if {@code flowControl < 0}.
088         * @throws NullPointerException if {@code port == null}.
089         * 
090         * @see #Raw802Device(IConnectionInterface)
091         * @see #Raw802Device(String, int)
092         * @see #Raw802Device(String, SerialPortParameters)
093         */
094        public Raw802Device(String port, int baudRate, int dataBits, int stopBits, int parity, int flowControl) {
095                this(port, new SerialPortParameters(baudRate, dataBits, stopBits, parity, flowControl));
096        }
097        
098        /**
099         * Class constructor. Instantiates a new {@code Raw802Device} object in the 
100         * given serial port name and parameters.
101         * 
102         * @param port Serial port name where 802.15.4 device is attached to.
103         * @param serialPortParameters Object containing the serial port parameters.
104         * 
105         * @throws NullPointerException if {@code port == null} or
106         *                              if {@code serialPortParameters == null}.
107         * 
108         * @see #Raw802Device(IConnectionInterface)
109         * @see #Raw802Device(String, int)
110         * @see #Raw802Device(String, int, int, int, int, int)
111         * @see com.digi.xbee.api.connection.serial.SerialPortParameters
112         */
113        public Raw802Device(String port, SerialPortParameters serialPortParameters) {
114                this(XBee.createConnectiontionInterface(port, serialPortParameters));
115        }
116        
117        /**
118         * Class constructor. Instantiates a new {@code Raw802Device} object with the 
119         * given connection interface.
120         * 
121         * @param connectionInterface The connection interface with the physical 
122         *                            802.15.4 device.
123         * 
124         * @throws NullPointerException if {@code connectionInterface == null}
125         * 
126         * @see #Raw802Device(String, int)
127         * @see #Raw802Device(String, SerialPortParameters)
128         * @see #Raw802Device(String, int, int, int, int, int)
129         * @see com.digi.xbee.api.connection.IConnectionInterface
130         */
131        public Raw802Device(IConnectionInterface connectionInterface) {
132                super(connectionInterface);
133        }
134        
135        /*
136         * (non-Javadoc)
137         * @see com.digi.xbee.api.XBeeDevice#open()
138         */
139        @Override
140        public void open() throws XBeeException {
141                super.open();
142                if (isRemote())
143                        return;
144                if (xbeeProtocol != XBeeProtocol.RAW_802_15_4)
145                        throw new XBeeDeviceException("XBee device is not a " + getXBeeProtocol().getDescription() + " device, it is a " + xbeeProtocol.getDescription() + " device.");
146        }
147        
148        /*
149         * (non-Javadoc)
150         * @see com.digi.xbee.api.XBeeDevice#getNetwork()
151         */
152        @Override
153        public XBeeNetwork getNetwork() {
154                if (!isOpen())
155                        throw new InterfaceNotOpenException();
156                
157                if (network == null)
158                        network = new Raw802Network(this);
159                return network;
160        }
161        
162        /*
163         * (non-Javadoc)
164         * @see com.digi.xbee.api.XBeeDevice#getXBeeProtocol()
165         */
166        @Override
167        public XBeeProtocol getXBeeProtocol() {
168                return XBeeProtocol.RAW_802_15_4;
169        }
170        
171        /*
172         * (non-Javadoc)
173         * @see com.digi.xbee.api.XBeeDevice#sendDataAsync(com.digi.xbee.api.models.XBee64BitAddress, byte[])
174         */
175        @Override
176        public void sendDataAsync(XBee64BitAddress address, byte[] data) throws XBeeException {
177                super.sendDataAsync(address, data);
178        }
179        
180        /**
181         * Sends the provided data to the XBee device of the network corresponding 
182         * to the given 16-bit address asynchronously.
183         * 
184         * <p>Asynchronous transmissions do not wait for answer from the remote 
185         * device or for transmit status packet</p>
186         * 
187         * @param address The 16-bit address of the XBee that will receive the data.
188         * @param data Byte array containing data to be sent.
189         * 
190         * @throws InterfaceNotOpenException if the device is not open.
191         * @throws NullPointerException if {@code address == null} or 
192         *                              if {@code data == null}.
193         * @throws XBeeException if there is any XBee related exception.
194         * 
195         * @see com.digi.xbee.api.models.XBee16BitAddress
196         * @see #sendData(RemoteXBeeDevice, byte[])
197         * @see #sendData(XBee16BitAddress, byte[])
198         * @see #sendData(XBee64BitAddress, byte[])
199         * @see #sendDataAsync(RemoteXBeeDevice, byte[])
200         * @see #sendDataAsync(XBee64BitAddress, byte[])
201         */
202        public void sendDataAsync(XBee16BitAddress address, byte[] data) throws XBeeException {
203                // Verify the parameters are not null, if they are null, throw an exception.
204                if (address == null)
205                        throw new NullPointerException("Address cannot be null");
206                if (data == null)
207                        throw new NullPointerException("Data cannot be null");
208                
209                // Check if device is remote.
210                if (isRemote())
211                        throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device.");
212                
213                logger.info(toString() + "Sending data asynchronously to {} >> {}.", address, HexUtils.prettyHexString(data));
214                
215                XBeePacket xbeePacket = new TX16Packet(getNextFrameID(), address, XBeeTransmitOptions.NONE, data);
216                sendAndCheckXBeePacket(xbeePacket, true);
217        }
218        
219        /*
220         * (non-Javadoc)
221         * @see com.digi.xbee.api.XBeeDevice#sendData(com.digi.xbee.api.models.XBee64BitAddress, byte[])
222         */
223        @Override
224        public void sendData(XBee64BitAddress address, byte[] data) throws TimeoutException, XBeeException {
225                super.sendData(address, data);
226        }
227        
228        /**
229         * Sends the provided data to the XBee device of the network corresponding 
230         * to the given 16-bit address.
231         * 
232         * <p>This method blocks until a success or error response arrives or the 
233         * configured receive timeout expires.</p>
234         * 
235         * <p>The received timeout is configured using the {@code setReceiveTimeout}
236         * method and can be consulted with {@code getReceiveTimeout} method.</p>
237         * 
238         * <p>For non-blocking operations use the method 
239         * {@link #sendData(XBee16BitAddress, byte[])}.</p>
240         * 
241         * @param address The 16-bit address of the XBee that will receive the data.
242         * @param data Byte array containing data to be sent.
243         * 
244         * @throws InterfaceNotOpenException if the device is not open.
245         * @throws NullPointerException if {@code address == null} or 
246         *                              if {@code data == null}.
247         * @throws TimeoutException if there is a timeout sending the data.
248         * @throws XBeeException if there is any other XBee related exception.
249         * 
250         * @see com.digi.xbee.api.models.XBee16BitAddress
251         * @see XBeeDevice#getReceiveTimeout()
252         * @see XBeeDevice#setReceiveTimeout(int)
253         * @see #sendData(RemoteXBeeDevice, byte[])
254         * @see #sendData(XBee64BitAddress, byte[])
255         * @see #sendDataAsync(RemoteXBeeDevice, byte[])
256         * @see #sendDataAsync(XBee16BitAddress, byte[])
257         * @see #sendDataAsync(XBee64BitAddress, byte[])
258         */
259        public void sendData(XBee16BitAddress address, byte[] data) throws TimeoutException, XBeeException {
260                // Verify the parameters are not null, if they are null, throw an exception.
261                if (address == null)
262                        throw new NullPointerException("Address cannot be null");
263                if (data == null)
264                        throw new NullPointerException("Data cannot be null");
265                
266                // Check if device is remote.
267                if (isRemote())
268                        throw new OperationNotSupportedException("Cannot send data to a remote device from a remote device.");
269                
270                logger.info(toString() + "Sending data to {} >> {}.", address, HexUtils.prettyHexString(data));
271                
272                XBeePacket xbeePacket = new TX16Packet(getNextFrameID(), address, XBeeTransmitOptions.NONE, data);
273                sendAndCheckXBeePacket(xbeePacket, false);
274        }
275        
276        /*
277         * (non-Javadoc)
278         * @see com.digi.xbee.api.AbstractXBeeDevice#set16BitAddress(com.digi.xbee.api.models.XBee16BitAddress)
279         */
280        @Override
281        public void set16BitAddress(XBee16BitAddress xbee16BitAddress) throws TimeoutException, XBeeException {
282                super.set16BitAddress(xbee16BitAddress);
283        }
284        
285        /*
286         * (non-Javadoc)
287         * @see com.digi.xbee.api.AbstractXBeeDevice#getAssociationIndicationStatus()
288         */
289        @Override
290        public AssociationIndicationStatus getAssociationIndicationStatus() throws TimeoutException, XBeeException {
291                return super.getAssociationIndicationStatus();
292        }
293        
294        /**
295         * @deprecated 802.15.4 protocol does not have an associated IPv6 address.
296         */
297        @Override
298        public Inet6Address getIPv6Address() {
299                // 802.15.4 protocol does not have IPv6 address.
300                return null;
301        }
302        
303        /**
304         * @deprecated Operation not supported in 802.15.4 protocol. This method
305         *             will raise an {@link UnsupportedOperationException}.
306         */
307        @Override
308        public Inet6Address getIPv6DestinationAddress()
309                        throws TimeoutException, XBeeException {
310                // Not supported in 802.15.4.
311                throw new UnsupportedOperationException(OPERATION_EXCEPTION);
312        }
313        
314        /**
315         * @deprecated Operation not supported in 802.15.4 protocol. This method
316         *             will raise an {@link UnsupportedOperationException}.
317         */
318        @Override
319        public void setIPv6DestinationAddress(Inet6Address ipv6Address)
320                        throws TimeoutException, XBeeException {
321                // Not supported in 802.15.4.
322                throw new UnsupportedOperationException(OPERATION_EXCEPTION);
323        }
324}