通过S7Connector公共类创建连接PLC,读写各类型的点位信息

1.连接PLC

public static S7Connector initConnect(){
    S7Connector s7Connector;
    try {
        s7Connector = S7ConnectorFactory
                .buildTCPConnector()
                .withHost("xx.xx.xx.xx")//PLC对应的ip地址
                .withPort(102) //端口号,默认的是102
                .withRack(0) //机架号
                .withSlot(1) //槽位号
                .withTimeout(2000) //连接超时时间
                .build();
    }catch (Exception e){
        log.error("PLC连接失败,请检查");
        return null;
    }
    return s7Connector;
}
/**
 * 关闭plc连接
 */
public static void closeConnect(S7Connector connector){
    try {
        connector.close();
    }catch (Exception ex){
        log.error("plc关闭异常==={}",ex.getMessage());
    }
}

/**
 * 写入值
 * dbNum--DB编码,offset--偏移量,value--写入的值,length--写入值占用的字节长度
 * type:
 *  int(java--Integer类型):1
 *  Dint(java--Long类型):2
 *  Real(java--Double):3
 *  LReal(java--长浮点数,没有对应的类型):4
 */
public static void writeValue(int dbNum,int offset,int value,int type){
    //创建连接 initConnect() 对应的连接PLC方法
    S7Connector s7Connector = initConnect();
    //将参数转换成对应格式的byte数组
    byte[] bytes = getByte(value,0,type);
    //写入PLC
    //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
    //第二个参数:DB块地址,若plc中是DB1000,则填1000
    //第三个参数:偏移量
    //第四个参数:写入的数据 二进制数组byte[]
    s7Connector.write(DaveArea.DB,dbNum, offset,bytes);
    log.info("写入参数成功,offset--{},value--{}",offset,value);
    //关闭连接
    closeConnect(s7Connector);
}
public static void writeValue(int dbNum,int offset,double value,int type){
    //创建连接
    S7Connector s7Connector = initConnect();
    //将参数转换成对应格式的byte数组
    byte[] bytes = getByte(0,value,type);
    //写入PLC
    //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
    //第二个参数:DB块地址,若plc中是DB1000,则填1000
    //第三个参数:偏移量
    //第四个参数:写入的数据 二进制数组byte[]
    s7Connector.write(DaveArea.DB,dbNum, offset,bytes);
    log.info("写入参数成功,offset--{},value--{}",offset,value);
    //关闭连接
    closeConnect(s7Connector);
}

/**
 * 获取对应类型的byte[]数组
 * type:
 *  1-int
 *  2-Dint
 *  3-LReal
 *  4-Real
 */
public static byte[] getByte(int value1,double value2,int type){
    byte[] bytes = new byte[0];
    if ( type == 1 ){
        bytes = ByteBuffer.allocate(2).putShort((short)value1).array();
    }
    if ( type == 2 ){
        bytes = ByteBuffer.allocate(4).putInt(value1).array();
    }
    if ( type == 3 ){
        bytes = ByteBuffer.allocate(4).putFloat((float) value2).array();
    }
    if ( type == 4 ){
        bytes = ByteBuffer.allocate(8).putDouble(value2).array();
    }
    return bytes;
}


public static void writeValue(S7Connector s7Connector,int dbNum,int offset,int value,int length){
    //将参数转换成对应格式的byte数组
    byte[] bytes = ByteBuffer.allocate(length).putShort((short) value).array();
    //写入PLC
    //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
    //第二个参数:DB块地址,若plc中是DB1000,则填1000
    //第三个参数:偏移量
    //第四个参数:写入的数据 二进制数组byte[]
    s7Connector.write(DaveArea.DB,dbNum, offset,bytes);
    log.info("写入参数成功,offset--{},value--{}",offset,value);
}

//读取PLC中的int类型
public static Integer readInt(int dbNum,int offset){
    //创建连接
    S7Connector s7Connector = initConnect();
    //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
    //第二个参数:DB块地址,若plc中是DB1000,则填1000
    //第三个参数:数据长度
    //第四个参数:偏移量
    byte[] getBytes = s7Connector.read(DaveArea.DB, dbNum, 2, offset);
    S7Serializable converter = new IntegerConverter();
    Integer data = converter.extract(Integer.class, getBytes, 0, 0);
    closeConnect(s7Connector);
    return data;
}

//读取PLC中的Real类型
public static float readReal(int dbNum,int offset){
    //创建连接
    S7Connector s7Connector = initConnect();
    //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
    //第二个参数:DB块地址,若plc中是DB1000,则填1000
    //第三个参数:数据长度
    //第四个参数:偏移量
    byte[] getBytes = s7Connector.read(DaveArea.DB, dbNum, 4, offset);
    float getValue = ByteBuffer.wrap(getBytes).getFloat();
    closeConnect(s7Connector);
    return getValue;
}
//读取word类型,点位信息里面存储的是16进制数
public void testReadPlcDIntData() {
        S7Connector s7Connector = initConnect();
        //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数:DB块地址,若plc中是DB1000,则填1000
        //第三个参数:数据长度,这个长度为2,因为当前点位信息里面存储的是2位,相当于有4位16进制数,对应的是16位的二进制数
        //第四个参数:偏移量
        byte[] getBytes = s7Connector.read(DaveArea.DB, 63, 2, 4);
        //创建字符串,用于存储对应的每位上面的十六进制数
        StringBuilder sb = new StringBuilder();
        //遍历byte数组,解析出对应的16进制数
        for ( byte item : getBytes ){
             sb.append(Integer.toHexString((item & 0xFF) | 0x100),1,3);
        }
        //打印出读取到的点位信息数据,例如会读取出来0000,fe11的十六进制数
        //0000-转换成2进制就是0000 0000 0000 0000
        System.out.println(sb);
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
/**
 * 批量读取
 */
public void batchRead(){
    //连接PLC
    S7Connector s7Connector = initConnect();
    //PLC实例化
    S7Serializer s7Serializer = S7SerializerFactory.buildSerializer(s7Connector);
    //PlcDuo是对应映射出来的实体对象,相当于PLC里面对应的点位信息,101-是指读取的那个DB块,例如DB101,就写入101,0-相当于就是当前点位信息什么的第一个bit
    PlcDuo plcScanData = s7Serializer.dispense(PlcDuo.class, 101,0);
    //打印出实体
    System.out.println(plcScanData);
}
/**
 * 获取plc扫描过程中,获取的参数信息
 * S7Type.REAL--对应Double类型
 * S7Type.WORD--对应Integer类型
 * S7Type.BOOL--对应Boolean类型
 * type是这个点位在PLC中设置的类型,源码会解析其长度;
 * byteOffset对应PLC偏移量中的整数部分;
 * bitOffset指偏移量的小数部分,bitOffset指第几个bit.
 * byteOffset和bitOffset 也可理解为返回的byte[]中第byteOffset到bitOffset
 */

@Data
public class PlcDuo {

    @S7Variable(byteOffset = 218, type = S7Type.REAL)
    public Integer startScan;

    @S7Variable(byteOffset = 186, type = S7Type.REAL)
    public Double yInterval;   

    @S7Variable(byteOffset = 136,bitOffset = 0,type = S7Type.BOOL)
    public Boolean var1;

}
    /**
     * 批量写
     */
    @Test
    public void batchWrite(){
        //创建plc连接
        S7Connector s7Connector = initConnect();
        //PLC实例化
        S7Serializer s7Serializer = S7SerializerFactory.buildSerializer(s7Connector);
        //创建实体对象
        PlcDuo plcScanData = new PlcDuo();
        //给对象属性赋值,相当于点位信息赋值
        plcScanData.setVar1(true);
        //进行批量的写入,100-对应的DB块100
        s7Serializer.store(plcScanData,100,0);
    }
    /**
     * 读取PLC中的浮点型Double(8字节)数据
     * java float : plc Real 4 字节
     * java double : plc LReal 8 字节
     **/
    @Test
    public void testReadPlcLRealData() {

        S7Connector s7Connector = initConnect();
        //第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
        //第二个参数:DB块地址,若plc中是DB1000,则填1000
        //第三个参数:数据长度
        //第四个参数:偏移量
        byte[] getBytes = s7Connector.read(DaveArea.DB, 102, 4, 178);
        //读取LReal类型的必须进行特殊处理,不然读取到的小数会失去精度
        double getValue = ByteBuffer.wrap(getBytes).getDouble();
        NumberFormat nf = NumberFormat.getInstance();
        nf.setGroupingUsed(false);
        System.out.println("getDoubleData:"+nf.format(getValue));
        try {
            s7Connector.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

注意点:如果需要进行批量写入的话,需要将当前DB块儿上面所有的点位信息都要进行赋值,不然的话,没有赋值到的点位信息(对应的实体某个属性值),将会在批量写入之后变成默认值,int类型的会置0,boolean类型的会置为false。

批量读取的话,int,Real,Boolean都是可以批量读取的,但是LReal是不能进行批量读取的。而且单独读取的话,也必须将读取的byte数组进行特殊的处理,才能将读取到的数据不丢失精度。

其余的类型S7Connector中都内置了对应的转置方法,对应引用就行,例如读取int类型,就可以使用new IntegerConverter()内置方法来进行byte数组的处理。

S7Connector s7Connector = initConnect();
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:数据长度
//第四个参数:偏移量
byte[] getBytes = s7Connector.read(DaveArea.DB, 101, 2, 146);
//公共方法
S7Serializable converter = new IntegerConverter();
Integer data = converter.extract(Integer.class, getBytes, 0, 0);
System.out.println(data);

  • 12
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个Java通过S7Connector工具S7-1200 PLC读取数据的示例代码,并将数据整理后存储到MySQL数据库中: ```java import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.SQLException; import java.util.Map; import com.github.s7connector.api.DaveArea; import com.github.s7connector.api.S7Connector; import com.github.s7connector.api.S7ConnectorOptions; public class S7ConnectorExample { public static void main(String[] args) { // 连接PLC S7ConnectorOptions options = new S7ConnectorOptions(); options.setHost("192.168.0.1"); options.setRack(0); options.setSlot(1); S7Connector connector = S7Connector.newDefault(options); // 读取数据 Map<String, Object> data = connector.readAll(DaveArea.DB, 1, 0, 20); // 解析数据 int value1 = (int) data.get("DB1.DBX0.0"); int value2 = (int) data.get("DB1.DBW2"); float value3 = (float) data.get("DB1.DBD4"); // 存储数据到数据库 try (Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "password")) { PreparedStatement stmt = conn.prepareStatement("INSERT INTO mytable (value1, value2, value3) VALUES (?, ?, ?)"); stmt.setInt(1, value1); stmt.setInt(2, value2); stmt.setFloat(3, value3); stmt.executeUpdate(); } catch (SQLException e) { System.out.println("存储数据到数据库失败:" + e.getMessage()); } // 断开PLC连接 connector.close(); } } ``` 在以上示例代码中,我们首先使用S7Connector工具连接PLC,然后使用`readAll`方法读取指定DB块的数据。接着,我们解析数据,并将数据存储到MySQL数据库中。最后,我们断开与PLC连接。需要注意的是,以上示例代码仅供参考,实际应用中需要根据具体需求进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值