package ch.hevs.isi.field; import com.serotonin.modbus4j.ModbusFactory; import com.serotonin.modbus4j.ModbusMaster; import com.serotonin.modbus4j.code.DataType; import com.serotonin.modbus4j.exception.ErrorResponseException; import com.serotonin.modbus4j.exception.ModbusInitException; import com.serotonin.modbus4j.exception.ModbusTransportException; import com.serotonin.modbus4j.ip.IpParameters; import com.serotonin.modbus4j.ip.tcp.TcpMaster; import com.serotonin.modbus4j.locator.BaseLocator; public class ModbusAccessor { private static ModbusAccessor mySelf = null; //instance of the class private ModbusMaster master = null; //instance of the modbus master /** * private constructor * */ private ModbusAccessor(){ } /** * static method to create a singleton pattern of the class * checks if an instance of the class is already made * if not, it creates an instance of the class ModbusAccessor * @return instance of ModbusAccessor */ public static ModbusAccessor getMySelf(){ if (mySelf == null){ //if no instance is created mySelf = new ModbusAccessor(); //create a new instance of the class } return mySelf; //if there is already an instance, return the existing instance } /** * this method creates a ModbusFactory and a TCPMaster * it also initialize the Master * @param ipAddress IP-address of the server * @param port port of the server */ public void connect(String ipAddress, int port){ ModbusFactory MF = new ModbusFactory(); //create a modbus factory IpParameters IpParams = new IpParameters(); //create the ip parameters IpParams.setHost(ipAddress); //set the server ip-address IpParams.setPort(port); //set the server port //create the TCPMaster with the correct IP parameters and keep it alive this.master = MF.createTcpMaster(IpParams, true); try { this.master.init(); //initialize the master } catch(ModbusInitException e) { e.printStackTrace(); } } //methods to write /** * method to write a boolean value in the correct modbus register * @param register address of the register * @param value the desired boolean value * @throws ModbusTransportException * @throws ErrorResponseException */ public void writeBoolean (int register, boolean value) throws ModbusTransportException, ErrorResponseException{ //first parameter = slaveID = always 1 because we only have one //second parameter = register address ==> it is named offset because it starts with 0 and goes to the desired address this.master.setValue(BaseLocator.coilStatus(1,register), value); //set the desired value in the correct register } /** * method to write a float value in the correct modbus register * @param register address of the register * @param value the desired float value * @throws ModbusTransportException * @throws ErrorResponseException */ public void writeFloat (int register, float value) throws ModbusTransportException, ErrorResponseException{ //first parameter = slaveID = always 1 because we only have one //second parameter = register address ==> it is named offset because it starts with 0 and goes to the desired address //third parameter = DataType of the value. The max value is 3 Byte Float, but the class DataType has only 2 or 4 byte this.master.setValue(BaseLocator.holdingRegister(1,register,DataType.FOUR_BYTE_FLOAT), value); } //methods to read /** * method to read a boolean value in the correct modbus register * get the coil status of the register. * @param register address of register * @return boolean value of the desired register * @throws ModbusTransportException * @throws ErrorResponseException */ public boolean readBoolean(int register) throws ModbusTransportException, ErrorResponseException { //first parameter = slaveID = always 1 because we only have one //second parameter = register address ==> it is named offset because it starts with 0 and goes to the desired address boolean booleanValue = this.master.getValue(BaseLocator.coilStatus(1,register)); return booleanValue; } /** * method to read a boolean value in the correct modbus register * get the value from the holding register * @param register address of the register * @return float value of the desired register * @throws ModbusTransportException * @throws ErrorResponseException */ public float readFloat(int register)throws ModbusTransportException, ErrorResponseException{ //first parameter = slaveID = always 1 because we only have one //second parameter = register address ==> it is named offset because it starts with 0 and goes to the desired address //third parameter = DataType of the value. The max value is 3 Byte Float, but the class DataType has only 2 or 4 byte float floatValue = (float) this.master.getValue(BaseLocator.holdingRegister(1,register, DataType.FOUR_BYTE_FLOAT)); return floatValue; } /** * this main method is only for testing the ModbusAccessor class * @param args */ public static void main(String[] args) { //create an instance of ModbusAccessor and connect it with the server ModbusAccessor test = ModbusAccessor.getMySelf(); test.connect("LocalHost", 1502); //do this all the time while(true){ try{ //get a boolean value => solar SetPoint boolean solar_connect_st = test.readBoolean(609); //SOLAR_CONNECT_ST //get a float value => factory SetPoint float factory_st = test.readFloat(605); //FACTORY_ST //write a float value to the Remote_Factory_SP test.writeFloat(205,0.56F); //REMOTE_FACTORY_SP //write a boolean value to the Remote_Solar_SW test.writeBoolean(401,false); //REMOTE_SOLAR_SW //check the factory SetPoint System.out.println("Factory Setpoint is: " + factory_st); //check the solar SetPoint if(solar_connect_st){ System.out.println("Solar is connected"); }else{ System.out.println("Solar is disconnected"); } }catch (ModbusTransportException e){ }catch (ErrorResponseException e){ } } } }