/***
* Copyright 2002-2010 jamod development team
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
***/
package net.wimpi.modbus.msg;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import net.wimpi.modbus.Modbus;
import net.wimpi.modbus.util.ModbusUtil;
/**
* Abstract class implementing a <tt>ModbusMessage</tt>.
* This class provides specialised implementations with
* the functionality they have in common.
*
* @author Dieter Wimberger
* @version @version@ (@date@)
*/
public abstract class ModbusMessageImpl implements ModbusMessage {
// instance attributes
private int m_TransactionID = Modbus.DEFAULT_TRANSACTION_ID;
private int m_ProtocolID = Modbus.DEFAULT_PROTOCOL_ID;
private int m_DataLength;
private int m_UnitID = Modbus.DEFAULT_UNIT_ID;
private int m_FunctionCode;
private boolean m_Headless = false; // flag for headerless (serial) transport
/*** Header ******************************************/
/**
* Tests if this message instance is headless.
*
* @return true if headless, false otherwise.
*/
public boolean isHeadless() {
return m_Headless;
}// isHeadless
@Override
public void setHeadless() {
m_Headless = true;
}// setHeadless
/**
* Sets the headless flag of this message.
*
* @param b true if headless, false otherwise.
*/
protected void setHeadless(boolean b) {
m_Headless = b;
}// setHeadless
@Override
public int getTransactionID() {
return m_TransactionID;
}// getTransactionID
/**
* Sets the transaction identifier of this
* <tt>ModbusMessage</tt>.
* <p>
* The identifier should be a 2-byte (short) non negative
* integer value valid in the range of 0-65535.<br>
* <p>
*
* @param tid the transaction identifier as <tt>int</tt>.
*/
public void setTransactionID(int tid) {
m_TransactionID = tid;
// setChanged(true);
}// setTransactionID
@Override
public int getProtocolID() {
return m_ProtocolID;
}// getProtocolID
/**
* Sets the protocol identifier of this
* <tt>ModbusMessage</tt>.
* <p>
* The identifier should be a 2-byte (short) non negative
* integer value valid in the range of 0-65535.<br>
* <p>
*
* @param pid the protocol identifier as <tt>int</tt>.
*/
public void setProtocolID(int pid) {
m_ProtocolID = pid;
// setChanged(true);
}// setProtocolID
@Override
public int getDataLength() {
return m_DataLength;
}// getDataLength
/**
* Sets the length of the data appended
* after the protocol header.
* <p>
* Note that this library, a bit in contrast to the
* specification, counts the unit identifier and the
* function code to the header, because it is part
* of each and every message. Thus this message will
* append two (2) to the passed in integer value.
* <p>
*
* @param length the data length as <tt>int</tt>.
*/
public void setDataLength(int length) {
// should be below 255, check!
m_DataLength = length + 2;
}// setData
@Override
public int getUnitID() {
return m_UnitID;
}// getUnitID
/**
* Sets the unit identifier of this
* <tt>ModbusMessage</tt>.<br>
* The identifier should be a 1-byte non negative
* integer value valid in the range of 0-255.
*
* @param num the unit identifier number to be set.
*/
public void setUnitID(int num) {
m_UnitID = num;
// setChanged(true);
}// setUnitID
@Override
public int getFunctionCode() {
return m_FunctionCode;
}// getFunctionCode
/**
* Sets the function code of this <tt>ModbusMessage</tt>.<br>
* The function code should be a 1-byte non negative
* integer value valid in the range of 0-127.<br>
* Function codes are ordered in conformance
* classes their values are specified in
* <tt>net.wimpi.modbus.Modbus</tt>.
*
* @param code the code of the function to be set.
* @see net.wimpi.modbus.Modbus
*/
protected void setFunctionCode(int code) {
m_FunctionCode = code;
// setChanged(true);
}// setFunctionCode
/*** Data ********************************************/
/*** Transportable ***********************************/
/**
* Writes this message to the given <tt>DataOutput</tt>.
*
* @param dout a <tt>DataOutput</tt> instance.
* @throws IOException if an I/O related error occurs.
*/
@Override
public void writeTo(DataOutput dout) throws IOException {
if (!isHeadless()) {
dout.writeShort(getTransactionID());
dout.writeShort(getProtocolID());
dout.writeShort(getDataLength());
}
dout.writeByte(getUnitID());
dout.writeByte(getFunctionCode());
writeData(dout);
}// writeTo
/**
* Writes the subclass specific data to the given DataOutput.
*
* @param dout the DataOutput to be written to.
* @throws IOException if an I/O related error occurs.
*/
public abstract void writeData(DataOutput dout) throws IOException;
@Override
public void readFrom(DataInput din) throws IOException {
if (!isHeadless()) {
setTransactionID(din.readUnsignedShort());
setProtocolID(din.readUnsignedShort());
m_DataLength = din.readUnsignedShort();
}
setUnitID(din.readUnsignedByte());
setFunctionCode(din.readUnsignedByte());
readData(din);
}// readFrom
/**
* Reads the subclass specific data from the given DataInput instance.
*
* @param din the DataInput to read from.
* @throws IOException if an I/O related error occurs.
*/
public abstract void readData(DataInput din) throws IOException;
@Override
public int getOutputLength() {
int l = 2 + getDataLength();
if (!isHeadless()) {
l = l + 6;
}
return l;
}// getOutputLength
/*** END Transportable *******************************/
/**
* Returns the this message as hexadecimal string.
*
* @return the message as hex encoded string.
*/
@Override
public String getHexMessage() {
return ModbusUtil.toHex(this);
}// getHexMessage
}// class ModbusMessageImpl