/*
* ============================================================================
* GNU General Public License
* ============================================================================
*
* Copyright (C) 2006-2011 Serotonin Software Technologies Inc. http://serotoninsoftware.com
* @author Matthew Lohbihler
*
* This program 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.
*
* This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
*
* When signing a commercial license with Serotonin Software Technologies Inc.,
* the following extension to GPL is made. A special exception to the GPL is
* included to allow you to distribute a combined work that includes BAcnet4J
* without being obliged to provide the source code for any proprietary components.
*/
package com.serotonin.bacnet4j.npdu;
import java.math.BigInteger;
import com.serotonin.bacnet4j.type.constructed.Address;
import org.free.bacnet4j.util.ByteQueue;
/**
* Network layer protocol control information. This class currently only implements the reading of information.
*
* @author mlohbihler
*/
public class NPCI {
private final int version;
private BigInteger control;
private int destinationNetwork;
private int destinationLength;
private byte[] destinationAddress;
private int sourceNetwork;
private int sourceLength;
private byte[] sourceAddress;
private int hopCount;
private int messageType;
private int vendorId;
/**
* For sending global broadcasts
*
* @param source
* optional source address
*/
public NPCI(Address source) {
version = 1;
control = BigInteger.valueOf(0);
control = control.setBit(5);
destinationNetwork = 0xFFFF;
hopCount = 0xFF;
setSourceAddress(source);
}
public NPCI(Address destination, Address source, boolean expectsReply) {
version = 1;
control = BigInteger.valueOf(0);
if (destination != null) {
control = control.setBit(5);
destinationNetwork = destination.getNetworkNumber().intValue();
destinationAddress = destination.getMacAddress().getBytes();
if (destinationAddress != null)
destinationLength = destinationAddress.length;
hopCount = 0xFF;
}
setSourceAddress(source);
if (expectsReply)
control = control.setBit(2);
}
public NPCI(Address destination, Address source, boolean expectsReply, int messageType, int vendorId) {
this(destination, source, expectsReply);
control = control.setBit(7);
this.messageType = messageType;
this.vendorId = vendorId;
}
private void setSourceAddress(Address source) {
if (source != null) {
control = control.setBit(3);
sourceNetwork = source.getNetworkNumber().intValue();
sourceAddress = source.getMacAddress().getBytes();
sourceLength = sourceAddress.length;
}
}
public NPCI(ByteQueue queue) {
version = queue.popU1B();
control = BigInteger.valueOf(queue.popU1B());
if (control.testBit(5)) {
destinationNetwork = queue.popU2B();
destinationLength = queue.popU1B();
if (destinationLength > 0) {
destinationAddress = new byte[destinationLength];
queue.pop(destinationAddress);
}
}
if (control.testBit(3)) {
sourceNetwork = queue.popU2B();
sourceLength = queue.popU1B();
sourceAddress = new byte[sourceLength];
queue.pop(sourceAddress);
}
if (control.testBit(5))
hopCount = queue.popU1B();
if (control.testBit(7)) {
messageType = queue.popU1B();
if (messageType >= 80)
vendorId = queue.popU2B();
}
}
public void write(ByteQueue queue) {
queue.push(version);
queue.push(control.intValue());
if (control.testBit(5)) {
queue.pushU2B(destinationNetwork);
queue.push(destinationLength);
if (destinationAddress != null)
queue.push(destinationAddress);
}
if (control.testBit(3)) {
queue.pushU2B(sourceNetwork);
queue.push(sourceLength);
queue.push(sourceAddress);
}
if (control.testBit(5))
queue.push(hopCount);
if (control.testBit(7)) {
queue.push(messageType);
if (messageType >= 80)
queue.pushU2B(vendorId);
}
}
public boolean hasDestinationInfo() {
return control.testBit(5);
}
public boolean isDestinationBroadcast() {
return destinationLength == 0;
}
public boolean hasSourceInfo() {
return control.testBit(3);
}
public boolean isExpectingReply() {
return control.testBit(2);
}
public boolean isNetworkMessage() {
return control.testBit(7);
}
public boolean isVendorSpecificNetworkMessage() {
return isNetworkMessage() && messageType >= 80;
}
public int getNetworkPriority() {
return (control.testBit(1) ? 2 : 0) | (control.testBit(0) ? 1 : 0);
}
public byte[] getDestinationAddress() {
return destinationAddress;
}
public int getDestinationLength() {
return destinationLength;
}
public int getDestinationNetwork() {
return destinationNetwork;
}
public int getHopCount() {
return hopCount;
}
public int getMessageType() {
return messageType;
}
public byte[] getSourceAddress() {
return sourceAddress;
}
public int getSourceLength() {
return sourceLength;
}
public int getSourceNetwork() {
return sourceNetwork;
}
public int getVendorId() {
return vendorId;
}
public int getVersion() {
return version;
}
//
// public static void main(String[] args) {
// byte[] b1 = {(byte)0x81,(byte)0xb,(byte)0x0,(byte)0x18};
// byte[] b2 = {(byte)0x1,(byte)0x8,(byte)0x0,(byte)0x64,(byte)0x1,
// (byte)0x2,(byte)0x10,(byte)0x0,(byte)0xc4,(byte)0x2,(byte)0x0,(byte)0x7,(byte)0xd0,(byte)0x22,
// (byte)0x1,(byte)0xe0,(byte)0x91,(byte)0x0,(byte)0x21,(byte)0x23};
// ByteQueue q = new ByteQueue(b2);
// new NPCI(q);
//
// }
}