All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ro.ciprianpascu.sbus.util.ModbusUtil Maven / Gradle / Ivy

Go to download

jamod is an object oriented implementation of the S-Bus protocol, realized 100% in Java. It allows to quickly realize master and slave applications in various transport flavors (IP and serial).

The newest version!
/**
 * 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 ro.ciprianpascu.sbus.util;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import ro.ciprianpascu.sbus.Modbus;
import ro.ciprianpascu.sbus.io.BytesOutputStream;
import ro.ciprianpascu.sbus.msg.ModbusMessage;

/**
 * Helper class that provides utility methods.
 *
 * @author Dieter Wimberger
 * @author Ciprian Pascu

 * @author John Charlton
 * @version %I% (%G%)
 */
public final class ModbusUtil {

    private static BytesOutputStream m_ByteOut = new BytesOutputStream(Modbus.MAX_MESSAGE_LENGTH);

    /**
     * Converts a {@link ModbusMessage} instance into
     * a hex encoded string representation.
     *
     * @param msg the message to be converted.
     * @return the converted hex encoded string representation of the message.
     */
    public static final String toHex(ModbusMessage msg) {
        String ret = "-1";
        try {
            synchronized (m_ByteOut) {
                msg.writeTo(m_ByteOut);
                ret = toHex(m_ByteOut.getBuffer(), 0, m_ByteOut.size());
                m_ByteOut.reset();
            }
        } catch (IOException ex) {
        }
        return ret;
    }// toHex

    /**
     * Returns the given byte[] as hex encoded string.
     *
     * @param data a byte[] array.
     * @return a hex encoded String.
     */
    public static final String toHex(byte[] data) {
        return toHex(data, 0, data.length);
    }// toHex

    /**
     * Returns a {@link String} containing unsigned hexadecimal
     * numbers as digits.
     * The {@link String} will coontain two hex digit characters
     * for each byte from the passed in {@link byte[]}.
* The bytes will be separated by a space character. * * * @param data the array of bytes to be converted into a hex-string. * @param off the offset to start converting from. * @param length the number of bytes to be converted. * * @return the generated hexadecimal representation as String. */ public static final String toHex(byte[] data, int off, int length) { // double size, two bytes (hex range) for one byte StringBuffer buf = new StringBuffer(data.length * 2); for (int i = off; i < length; i++) { // don't forget the second hex digit if ((data[i] & 0xff) < 0x10) { buf.append("0"); } buf.append(Long.toString(data[i] & 0xff, 16)); if (i < data.length - 1) { buf.append(" "); } } return buf.toString(); }// toHex /** * Returns a {@link byte[]} containing the given * byte as unsigned hexadecimal number digits. * * * @param i the int to be converted into a hex string. * @return the generated hexadecimal representation as byte[]. */ public static final byte[] toHex(int i) { StringBuffer buf = new StringBuffer(2); // don't forget the second hex digit if ((i & 0xff) < 0x10) { buf.append("0"); } buf.append(Long.toString(i & 0xff, 16).toUpperCase()); return buf.toString().getBytes(); }// toHex /** * Converts the register (a 16 bit value) into an unsigned short. * The value returned is: * * *
     * (((a & 0xff) << 8) | (b & 0xff))
     * 
     * 
* * This conversion has been taken from the documentation of * the {@link DataInput} interface. * * @param bytes a register as byte[2]. * @return the unsigned short value as {@link int}. * @see java.io.DataInput */ public static final int registerToUnsignedShort(byte[] bytes) { return ((bytes[0] & 0xff) << 8 | (bytes[1] & 0xff)); }// registerToUnsignedShort /** * Converts the given unsigned short into a register * (2 bytes). * The byte values in the register, in the order * shown, are: * * *
     * 
     * (byte)(0xff & (v >> 8))
     * (byte)(0xff & v)
     * 
     * 
* * This conversion has been taken from the documentation of * the {@link DataOutput} interface. * * @param v * @return the register as byte[2]. * @see java.io.DataOutput */ public static final byte[] unsignedShortToRegister(int v) { byte[] register = new byte[2]; register[0] = (byte) (0xff & (v >> 8)); register[1] = (byte) (0xff & v); return register; }// unsignedShortToRegister /** * Converts the given register (16-bit value) into * a {@link short}. * The value returned is: * * *
     * 
     * (short)((a << 8) | (b & 0xff))
     * 
     * 
* * This conversion has been taken from the documentation of * the {@link DataInput} interface. * * @param bytes bytes a register as byte[2]. * @return the signed short as short. */ public static final short registerToShort(byte[] bytes) { return (short) ((bytes[0] << 8) | (bytes[1] & 0xff)); }// registerToShort /** * Converts the register (16-bit value) at the given index * into a {@link short}. * The value returned is: * * *
     * 
     * (short)((a << 8) | (b & 0xff))
     * 
     * 
* * This conversion has been taken from the documentation of * the {@link DataInput} interface. * * @param bytes a {@link byte[]} containing a short value. * @param idx an offset into the given byte[]. * @return the signed short as short. */ public static final short registerToShort(byte[] bytes, int idx) { return (short) ((bytes[idx] << 8) | (bytes[idx + 1] & 0xff)); }// registerToShort /** * Converts the given {@link short} into a register * (2 bytes). * The byte values in the register, in the order * shown, are: * * *
     * 
     * (byte)(0xff & (v >> 8))
     * (byte)(0xff & v)
     * 
     * 
* * @param s * @return a register containing the given short value. */ public static final byte[] shortToRegister(short s) { byte[] register = new byte[2]; register[0] = (byte) (0xff & (s >> 8)); register[1] = (byte) (0xff & s); return register; }// shortToRegister /** * Converts a byte[4] binary int value to a primitive int.
* The value returned is: * * *
     * 
     * (((a & 0xff) << 24) | ((b & 0xff) << 16) |
     *  ((c & 0xff) << 8) | (d & 0xff))
     * 
     * 
* * @param bytes registers as byte[4]. * @return the integer contained in the given register bytes. */ public static final int registersToInt(byte[] bytes) { return (((bytes[0] & 0xff) << 24) | ((bytes[1] & 0xff) << 16) | ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff)); }// registersToInt /** * Converts an int value to a byte[4] array. * * @param v the value to be converted. * @return a byte[4] containing the value. */ public static final byte[] intToRegisters(int v) { byte[] registers = new byte[4]; registers[0] = (byte) (0xff & (v >> 24)); registers[1] = (byte) (0xff & (v >> 16)); registers[2] = (byte) (0xff & (v >> 8)); registers[3] = (byte) (0xff & v); return registers; }// intToRegisters /** * Converts a byte[8] binary long value into a long * primitive. * * @param bytes a byte[8] containing a long value. * @return a long value. */ public static final long registersToLong(byte[] bytes) { return ((((long) (bytes[0] & 0xff) << 56) | ((long) (bytes[1] & 0xff) << 48) | ((long) (bytes[2] & 0xff) << 40) | ((long) (bytes[3] & 0xff) << 32) | ((long) (bytes[4] & 0xff) << 24) | ((long) (bytes[5] & 0xff) << 16) | ((long) (bytes[6] & 0xff) << 8) | (bytes[7] & 0xff))); }// registersToLong /** * Converts a long value to a byte[8]. * * @param v the value to be converted. * @return a byte[8] containing the long value. */ public static final byte[] longToRegisters(long v) { byte[] registers = new byte[8]; registers[0] = (byte) (0xff & (v >> 56)); registers[1] = (byte) (0xff & (v >> 48)); registers[2] = (byte) (0xff & (v >> 40)); registers[3] = (byte) (0xff & (v >> 32)); registers[4] = (byte) (0xff & (v >> 24)); registers[5] = (byte) (0xff & (v >> 16)); registers[6] = (byte) (0xff & (v >> 8)); registers[7] = (byte) (0xff & v); return registers; }// longToRegisters /** * Converts a byte[4] binary float value to a float primitive. * * @param bytes the byte[4] containing the float value. * @return a float value. */ public static final float registersToFloat(byte[] bytes) { return Float.intBitsToFloat( (((bytes[0] & 0xff) << 24) | ((bytes[1] & 0xff) << 16) | ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff))); }// registersToFloat /** * Converts a float value to a byte[4] binary float value. * * @param f the float to be converted. * @return a byte[4] containing the float value. */ public static final byte[] floatToRegisters(float f) { return intToRegisters(Float.floatToIntBits(f)); }// floatToRegisters /** * Converts a byte[8] binary double value into a double primitive. * * @param bytes a byte[8] to be converted. * @return a double value. */ public static final double registersToDouble(byte[] bytes) { return Double.longBitsToDouble(((((long) (bytes[0] & 0xff) << 56) | ((long) (bytes[1] & 0xff) << 48) | ((long) (bytes[2] & 0xff) << 40) | ((long) (bytes[3] & 0xff) << 32) | ((long) (bytes[4] & 0xff) << 24) | ((long) (bytes[5] & 0xff) << 16) | ((long) (bytes[6] & 0xff) << 8) | (bytes[7] & 0xff)))); }// registersToDouble /** * Converts a double value to a byte[8]. * * @param d the double to be converted. * @return a byte[8]. */ public static final byte[] doubleToRegisters(double d) { return longToRegisters(Double.doubleToLongBits(d)); }// doubleToRegisters /** * Converts an unsigned byte to an integer. * * @param b the byte to be converted. * @return an integer containing the unsigned byte value. */ public static final int unsignedByteToInt(byte b) { return b & 0xFF; }// unsignedByteToInt /** * Returns the broadcast address for the subnet of the host the code * is executed on. * * @return the broadcast address as {@link InetAddress}. * * public static final InetAddress getBroadcastAddress() { * byte[] addr = new byte[4]; * try { * addr = InetAddress.getLocalHost().getAddress(); * addr[3] = -1; * return getAddressFromBytes(addr); * } catch (Exception ex) { * ex.printStackTrace(); * return null; * } * }//getBroadcastAddress */ /* * public static final InetAddress getAddressFromBytes(byte[] addr) throws Exception { * StringBuffer sbuf = new StringBuffer(); * for (int i = 0; i < addr.length; i++) { * if (addr[i] < 0) { * sbuf.append(256 + addr[i]); * } else { * sbuf.append(addr[i]); * } * if (i < (addr.length - 1)) { * sbuf.append('.'); * } * } * //DEBUG:System.out.println(sbuf.toString()); * return InetAddress.getByName(sbuf.toString()); * }//getAddressFromBytes */ // TODO: John description. /** * Returs the low byte of an integer word. * * @param wd * @return the low byte. */ public static final byte lowByte(int wd) { return (new Integer(0xff & wd).byteValue()); }// lowByte // TODO: John description. /** * * @param wd * @return the hi byte. */ public static final byte hiByte(int wd) { return (new Integer(0xff & (wd >> 8)).byteValue()); }// hiByte // TODO: John description. /** * * @param hibyte * @param lowbyte * @return a word. */ public static final int makeWord(int hibyte, int lowbyte) { int hi = 0xFF & hibyte; int low = 0xFF & lowbyte; return ((hi << 8) | low); }// makeWord public static final byte[] calculateCRC(byte[] data, int len) { short shortCRC=0; byte bytTMP=0; short shortIndexOfBuf=0; byte byteIndex_Of_CRCTable=0; byte[] crc = { 1, 1 }; while (len!=0) { bytTMP= (byte) (shortCRC >> 8) ; //>>: right move bit shortCRC=(short) (shortCRC << 8); //<<: left move bit byteIndex_Of_CRCTable=(byte) (bytTMP ^ data[shortIndexOfBuf]); shortCRC=(short) (shortCRC ^ mbufintCRCTable[(byteIndex_Of_CRCTable & 0xFF)]); //^: xor shortIndexOfBuf=(short) (shortIndexOfBuf+1); len=(short) (len-1); }; crc[0]=(byte) (shortCRC >> 8); crc[1]=(byte) (shortCRC & 0x00FF); return crc; }// calculateCRC /* * Check the UDP packets is correct or not by checking CRC */ public static boolean checkCRC(byte[] data,int intlength) { short shortCRC=0; byte bytTMP=0; short shortIndexOfBuf=0; byte byteIndex_Of_CRCTable=0; while (intlength!=0) { bytTMP= (byte) (shortCRC >> 8) ; //>>: right move bit shortCRC=(short) (shortCRC << 8); //<<: left move bit byteIndex_Of_CRCTable=(byte) (bytTMP ^ data[shortIndexOfBuf]); shortCRC=(short) (shortCRC ^ mbufintCRCTable[(byteIndex_Of_CRCTable & 0xFF)]); //^: xor shortIndexOfBuf=(short) (shortIndexOfBuf+1); intlength=(short) (intlength-1); }; return (data[shortIndexOfBuf]==(shortCRC >> 8) && data[shortIndexOfBuf+1]==(short)(shortCRC & 0xFF)); } /* CRCtable */ private static final int[] mbufintCRCTable ={ 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d, 0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4, 0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc, 0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823, 0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b, 0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12, 0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a, 0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41, 0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49, 0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70, 0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78, 0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f, 0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067, 0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e, 0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256, 0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d, 0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405, 0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c, 0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634, 0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab, 0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3, 0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a, 0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92, 0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9, 0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0 }; }// class ModBusUtil




© 2015 - 2024 Weber Informatics LLC | Privacy Policy