//License /*** * Java Modbus Library (jamod) * Copyright (c) 2002-2004, jamod development team * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS ``AS * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. ***/ package net.wimpi.modbus.facade; import net.wimpi.modbus.ModbusException; import net.wimpi.modbus.io.ModbusTCPTransaction; import net.wimpi.modbus.msg.*; import net.wimpi.modbus.net.TCPMasterConnection; import net.wimpi.modbus.procimg.InputRegister; import net.wimpi.modbus.procimg.Register; import net.wimpi.modbus.util.BitVector; import java.net.InetAddress; import java.net.UnknownHostException; /** * Modbus/TCP Master facade. * * @author Dieter Wimberger * @version 1.2rc2 (14/04/2014) */ public class ModbusTCPMaster { private TCPMasterConnection m_Connection; private InetAddress m_SlaveAddress; private ModbusTCPTransaction m_Transaction; private ReadCoilsRequest m_ReadCoilsRequest; private ReadInputDiscretesRequest m_ReadInputDiscretesRequest; private WriteCoilRequest m_WriteCoilRequest; private WriteMultipleCoilsRequest m_WriteMultipleCoilsRequest; private ReadInputRegistersRequest m_ReadInputRegistersRequest; private ReadMultipleRegistersRequest m_ReadMultipleRegistersRequest; private WriteSingleRegisterRequest m_WriteSingleRegisterRequest; private WriteMultipleRegistersRequest m_WriteMultipleRegistersRequest; private boolean m_Reconnecting = false; /** * Constructs a new master facade instance for communication * with a given slave. * * @param addr an internet address as resolvable IP name or IP number, * specifying the slave to communicate with. */ public ModbusTCPMaster(String addr) { try { m_SlaveAddress = InetAddress.getByName(addr); m_Connection = new TCPMasterConnection(m_SlaveAddress); m_ReadCoilsRequest = new ReadCoilsRequest(); m_ReadInputDiscretesRequest = new ReadInputDiscretesRequest(); m_WriteCoilRequest = new WriteCoilRequest(); m_WriteMultipleCoilsRequest = new WriteMultipleCoilsRequest(); m_ReadInputRegistersRequest = new ReadInputRegistersRequest(); m_ReadMultipleRegistersRequest = new ReadMultipleRegistersRequest(); m_WriteSingleRegisterRequest = new WriteSingleRegisterRequest(); m_WriteMultipleRegistersRequest = new WriteMultipleRegistersRequest(); } catch (UnknownHostException e) { throw new RuntimeException(e.getMessage()); } }//constructor /** * Constructs a new master facade instance for communication * with a given slave. * * @param addr an internet address as resolvable IP name or IP number, * specifying the slave to communicate with. * @param port the port the slave is listening to. */ public ModbusTCPMaster(String addr, int port) { this(addr); m_Connection.setPort(port); }//constructor /** * Connects this <tt>ModbusTCPMaster</tt> with the slave. * * @throws Exception if the connection cannot be established. */ public void connect() throws Exception { if (m_Connection != null && !m_Connection.isConnected()) { m_Connection.connect(); m_Transaction = new ModbusTCPTransaction(m_Connection); m_Transaction.setReconnecting(m_Reconnecting); } }//connect /** * Disconnects this <tt>ModbusTCPMaster</tt> from the slave. */ public void disconnect() { if (m_Connection != null && m_Connection.isConnected()) { m_Connection.close(); m_Transaction = null; } }//disconnect /** * Sets the flag that specifies whether to maintain a * constant connection or reconnect for every transaction. * * @param b true if a new connection should be established for each * transaction, false otherwise. */ public void setReconnecting(boolean b) { m_Reconnecting = b; if (m_Transaction != null) { m_Transaction.setReconnecting(b); } }//setReconnecting /** * Tests if a constant connection is maintained or if a new * connection is established for every transaction. * * @return true if a new connection should be established for each * transaction, false otherwise. */ public boolean isReconnecting() { return m_Reconnecting; }//isReconnecting /** * Reads a given number of coil states from the slave. * <p/> * Note that the number of bits in the bit vector will be * forced to the number originally requested. * * @param ref the offset of the coil to start reading from. * @param count the number of coil states to be read. * @return a <tt>BitVector</tt> instance holding the * received coil states. * @throws ModbusException if an I/O error, a slave exception or * a transaction error occurs. */ public synchronized BitVector readCoils(int ref, int count) throws ModbusException { m_ReadCoilsRequest.setReference(ref); m_ReadCoilsRequest.setBitCount(count); m_Transaction.setRequest(m_ReadCoilsRequest); m_Transaction.execute(); BitVector bv = ((ReadCoilsResponse) m_Transaction.getResponse()).getCoils(); bv.forceSize(count); return bv; }//readCoils /** * Writes a coil state to the slave. * * @param unitid the slave unit id. * @param ref the offset of the coil to be written. * @param state the coil state to be written. * @return the state of the coil as returned from the slave. * @throws ModbusException if an I/O error, a slave exception or * a transaction error occurs. */ public synchronized boolean writeCoil(int unitid, int ref, boolean state) throws ModbusException { m_WriteCoilRequest.setUnitID(unitid); m_WriteCoilRequest.setReference(ref); m_WriteCoilRequest.setCoil(state); m_Transaction.setRequest(m_WriteCoilRequest); m_Transaction.execute(); return ((WriteCoilResponse) m_Transaction.getResponse()).getCoil(); }//writeCoil /** * Writes a given number of coil states to the slave. * <p/> * Note that the number of coils to be written is given * implicitly, through {@link BitVector#size()}. * * @param ref the offset of the coil to start writing to. * @param coils a <tt>BitVector</tt> which holds the coil states to be written. * @throws ModbusException if an I/O error, a slave exception or * a transaction error occurs. */ public synchronized void writeMultipleCoils(int ref, BitVector coils) throws ModbusException { m_WriteMultipleCoilsRequest.setReference(ref); m_WriteMultipleCoilsRequest.setCoils(coils); m_Transaction.setRequest(m_WriteMultipleCoilsRequest); m_Transaction.execute(); }//writeMultipleCoils /** * Reads a given number of input discrete states from the slave. * <p/> * Note that the number of bits in the bit vector will be * forced to the number originally requested. * * @param ref the offset of the input discrete to start reading from. * @param count the number of input discrete states to be read. * @return a <tt>BitVector</tt> instance holding the received input discrete * states. * @throws ModbusException if an I/O error, a slave exception or * a transaction error occurs. */ public synchronized BitVector readInputDiscretes(int ref, int count) throws ModbusException { m_ReadInputDiscretesRequest.setReference(ref); m_ReadInputDiscretesRequest.setBitCount(count); m_Transaction.setRequest(m_ReadInputDiscretesRequest); m_Transaction.execute(); BitVector bv = ((ReadInputDiscretesResponse) m_Transaction.getResponse()).getDiscretes(); bv.forceSize(count); return bv; }//readInputDiscretes /** * Reads a given number of input registers from the slave. * <p/> * Note that the number of input registers returned (i.e. array length) * will be according to the number received in the slave response. * * @param ref the offset of the input register to start reading from. * @param count the number of input registers to be read. * @return a <tt>InputRegister[]</tt> with the received input registers. * @throws ModbusException if an I/O error, a slave exception or * a transaction error occurs. */ public synchronized InputRegister[] readInputRegisters(int ref, int count) throws ModbusException { m_ReadInputRegistersRequest.setReference(ref); m_ReadInputRegistersRequest.setWordCount(count); m_Transaction.setRequest(m_ReadInputRegistersRequest); m_Transaction.execute(); return ((ReadInputRegistersResponse) m_Transaction.getResponse()).getRegisters(); }//readInputRegisters /** * Reads a given number of registers from the slave. * <p/> * Note that the number of registers returned (i.e. array length) * will be according to the number received in the slave response. * * @param ref the offset of the register to start reading from. * @param count the number of registers to be read. * @return a <tt>Register[]</tt> holding the received registers. * @throws ModbusException if an I/O error, a slave exception or * a transaction error occurs. */ public synchronized Register[] readMultipleRegisters(int ref, int count) throws ModbusException { m_ReadMultipleRegistersRequest.setReference(ref); m_ReadMultipleRegistersRequest.setWordCount(count); m_Transaction.setRequest(m_ReadMultipleRegistersRequest); m_Transaction.execute(); return ((ReadMultipleRegistersResponse) m_Transaction.getResponse()).getRegisters(); }//readMultipleRegisters /** * Writes a single register to the slave. * * @param ref the offset of the register to be written. * @param register a <tt>Register</tt> holding the value of the register * to be written. * @throws ModbusException if an I/O error, a slave exception or * a transaction error occurs. */ public synchronized void writeSingleRegister(int ref, Register register) throws ModbusException { m_WriteSingleRegisterRequest.setReference(ref); m_WriteSingleRegisterRequest.setRegister(register); m_Transaction.setRequest(m_WriteSingleRegisterRequest); m_Transaction.execute(); }//writeSingleRegister /** * Writes a number of registers to the slave. * * @param ref the offset of the register to start writing to. * @param registers a <tt>Register[]</tt> holding the values of * the registers to be written. * @throws ModbusException if an I/O error, a slave exception or * a transaction error occurs. */ public synchronized void writeMultipleRegisters(int ref, Register[] registers) throws ModbusException { m_WriteMultipleRegistersRequest.setReference(ref); m_WriteMultipleRegistersRequest.setRegisters(registers); m_Transaction.setRequest(m_WriteMultipleRegistersRequest); m_Transaction.execute(); }//writeMultipleRegisters }//class ModbusTCPMaster