在C#和Java中利用反射处理S7协议读取西门子PLC的变量

发布时间:2022-12-12 10:35

在C#和java中,有开源通信库NetS7Plus和S7Connector提供后台与PLC的通信。由于这两个库都提供了连续读取的方法。

以java为例,按偏移量读取Db块中的数值:

package com.zg.mymes.myConnPLC.myS7.myS7entities;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.github.s7connector.api.annotation.S7Variable;
import com.github.s7connector.impl.utils.S7Type;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.format.annotation.DateTimeFormat;
import org.yaml.snakeyaml.scanner.Constant;
import java.util.Date;
/**
* @Auther: Zg
* @Date: 2022/11/23 - 11 - 23 - 17:13
* @Description: com.zg.mymes.myConnPLC.myS7.myS7entities
* @version: 1.0
* 可定制化的PLC值
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
//@PropertySource("classpath:myS7Db.properties")
public class MyS7Entity {
//    @TableId(type = IdType.AUTO)
//    private Integer id;
//
//    public static final Integer dbNum = 30;
//    //@Value("${myS7Db.offSet}")
//    public static final Integer offSet = 42;
//
//    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
//    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
//    private Date createTime;
//    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
//    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
//    private Date insertTime;
//必须为public 否则报错
@S7Variable(byteOffset = 0, type = S7Type.REAL)
public Double aBLineVoltage_PLC;
@S7Variable(byteOffset = 4, type = S7Type.REAL)
public Double bCLineVoltage_PLC;
@S7Variable(byteOffset = 8, type = S7Type.REAL)
public Double aCLineVoltage_PLC;
@S7Variable(byteOffset = 12, type = S7Type.REAL)
public Double aPhaseVoltage_PLC;
@S7Variable(byteOffset = 16, type = S7Type.REAL)
public Double bPhaseVoltage_PLC;
@S7Variable(byteOffset = 20, type = S7Type.REAL)
public Double cPhaseVoltage_PLC;
@S7Variable(byteOffset = 24, type = S7Type.REAL)
public Double aPhaseCurrent_PLC;
@S7Variable(byteOffset = 28, type = S7Type.REAL)
public Double bPhaseCurrent_PLC;
@S7Variable(byteOffset = 32, type = S7Type.REAL)
public Double cPhaseCurrent_PLC;
@S7Variable(byteOffset = 36, type = S7Type.REAL)
public Double allActivePower_PLC;
@S7Variable(byteOffset = 40, type = S7Type.REAL)
public Double aActivePower_PLC;
@S7Variable(byteOffset = 44, type = S7Type.REAL)
public Double bActivePower_PLC;
@S7Variable(byteOffset = 48, type = S7Type.REAL)
public Double cActivePower_PLC;
@S7Variable(byteOffset = 52, type = S7Type.REAL)
public Double allReactivePower_PLC;
@S7Variable(byteOffset = 56, type = S7Type.REAL)
public Double aReactivePower_PLC;
@S7Variable(byteOffset = 60, type = S7Type.REAL)
public Double bReactivePower_PLC;
@S7Variable(byteOffset = 64, type = S7Type.REAL)
public Double cReactivePower_PLC;
@S7Variable(byteOffset = 68, type = S7Type.REAL)
public Double allPowerFactor_PLC;
@S7Variable(byteOffset = 72, type = S7Type.REAL)
public Double aPowerFactor_PLC;
@S7Variable(byteOffset = 76, type = S7Type.REAL)
public Double bPowerFactor_PLC;
@S7Variable(byteOffset = 80, type = S7Type.REAL)
public Double cPowerFactor_PLC;
@S7Variable(byteOffset = 84, type = S7Type.REAL)
public Double aBLineVoltage_Power;
@S7Variable(byteOffset = 88, type = S7Type.REAL)
public Double bCLineVoltage_Power;
@S7Variable(byteOffset = 92, type = S7Type.REAL)
public Double aCLineVoltage_Power;
@S7Variable(byteOffset = 96, type = S7Type.REAL)
public Double aPhaseVoltage_Power;
@S7Variable(byteOffset = 100, type = S7Type.REAL)
public Double bPhaseVoltage_Power;
@S7Variable(byteOffset = 104, type = S7Type.REAL)
public Double cPhaseVoltage_Power;
@S7Variable(byteOffset = 108, type = S7Type.REAL)
public Double aPhaseCurrent_Power;
@S7Variable(byteOffset = 112, type = S7Type.REAL)
public Double bPhaseCurrent_Power;
@S7Variable(byteOffset = 116, type = S7Type.REAL)
public Double cPhaseCurrent_Power;
@S7Variable(byteOffset = 120, type = S7Type.REAL)
public Double allActivePower_Power;
@S7Variable(byteOffset = 124, type = S7Type.REAL)
public Double aActivePower_Power;
@S7Variable(byteOffset = 128, type = S7Type.REAL)
public Double bActivePower_Power;
@S7Variable(byteOffset = 132, type = S7Type.REAL)
public Double cActivePower_Power;
@S7Variable(byteOffset = 136, type = S7Type.REAL)
public Double allReactivePower_Power;
@S7Variable(byteOffset = 140, type = S7Type.REAL)
public Double aReactivePower_Power;
@S7Variable(byteOffset = 144, type = S7Type.REAL)
public Double bReactivePower_Power;
@S7Variable(byteOffset = 148, type = S7Type.REAL)
public Double cReactivePower_Power;
@S7Variable(byteOffset = 152, type = S7Type.REAL)
public Double allPowerFactor_Power;
@S7Variable(byteOffset = 156, type = S7Type.REAL)
public Double aPowerFactor_Power;
@S7Variable(byteOffset = 160, type = S7Type.REAL)
public Double bPowerFactor_Power;
@S7Variable(byteOffset = 164, type = S7Type.REAL)
public Double cPowerFactor_Power;
@S7Variable(byteOffset = 168, type = S7Type.REAL)
public Double testAlarm;
@S7Variable(byteOffset = 404, type = S7Type.WORD)
public Integer heartBeat;
@S7Variable(byteOffset = 606,size = 130, type = S7Type.STRING)
public String var100;
@S7Variable(byteOffset = 738,size = 130, type = S7Type.STRING)
public String var101;
/**
@S7Variable(byteOffset=0, type= S7Type.REAL) public double var1;
@S7Variable(byteOffset=4, type= S7Type.REAL) public double var2;
@S7Variable(byteOffset=8, type= S7Type.REAL) public double var3;
@S7Variable(byteOffset=144, type= S7Type.BOOL) public boolean STATE_P1;
@S7Variable(byteOffset=144, type= S7Type.BOOL,bitOffset = 1) public boolean STATE_P1;
*/
}

读取的变量为类中的字段,但是实际情况中,我们往往需要各个变量的采集时间,报警值,缩放比例,中文名等,例如

package com.zg.mymes.entities;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
/**
* @Auther: Zg
* @Date: 2022/11/23 - 11 - 23 - 14:26
* @Description: com.zg.mymes.entities
* @version: 1.0
*/
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public class ActualData {
@TableId(type = IdType.AUTO)
private Integer id;
private String name;
private String description;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
//    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
//    @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date createTime;
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private Date insertTime;
private String varAddress;
private String varType;
private String scale;
private String highAlarm;
private String highHighAlarm;
private String lowAlarm;
private String lowLowAlarm;
private String alarmDescription;
private String value;
}

这样的格式的变量,这时就需要我们把第一个类class MyS7Entity中的字段映射到class ActualData中,这时就可以利用反射特性快速映射:

    //S7
@Async
@Scheduled(cron = "*/1 * * * * *")
public void Listen(){
try {
s7ConnHelper.readPlcData(31, MyS7Entity.class, 0);
Map<String, Object> myMap = new HashMap<>();
Field[] fields = s7ConnHelper.getMyDbData().getClass().getFields();
for (Field f :fields
) {
//log.info(f.getType().toString());
if (f.get(s7ConnHelper.getMyDbData()) instanceof Double){
String format = String.format("%.3f", f.get(s7ConnHelper.getMyDbData()));
myMap.put(f.getName(),format);
}
else {
myMap.put(f.getName(),f.get(s7ConnHelper.getMyDbData()));
}
}
s7ConnHelper.setMyMap(myMap);
java.util.Date date = new Date();//获得当前时间
Timestamp t = new Timestamp(date.getTime());//将时间转换成Timestamp类型,这样便可以存入到Mysql数据库中
for (ActualData actualData:s7ConnHelper.getActualDatas()
) {
actualData.setCreateTime(t);
actualData.setValue(myMap.get(actualData.getName()).toString());
if (
actualData.getVarType().equals("Float")&&
actualData.getHighHighAlarm()!=null && actualData.getHighHighAlarm().length()!=0&&
actualData.getHighAlarm()!=null && actualData.getHighAlarm().length()!=0 &&
actualData.getLowLowAlarm()!=null && actualData.getLowLowAlarm().length()!=0 &&
actualData.getLowAlarm()!=null && actualData.getLowAlarm().length()!=0
){
if ((Double.parseDouble(actualData.getValue())>Double.parseDouble(actualData.getHighAlarm()))
&& (Double.parseDouble(actualData.getValue())<Double.parseDouble(actualData.getHighHighAlarm()))
){
actualData.setAlarmDescription("该变量高报警!");
actualData.setInsertTime(t);
actualDataService.save(actualData);
}
if (Double.parseDouble(actualData.getValue())>Double.parseDouble(actualData.getHighHighAlarm())){
actualData.setAlarmDescription("该变量高高报警!");
actualData.setInsertTime(t);
actualDataService.save(actualData);
}
if ((Double.parseDouble(actualData.getValue())<Double.parseDouble(actualData.getLowAlarm()))
&& (Double.parseDouble(actualData.getValue())>Double.parseDouble(actualData.getLowLowAlarm()))
){
actualData.setAlarmDescription("该变量低报警!");
actualData.setInsertTime(t);
actualDataService.save(actualData);
}
if (Double.parseDouble(actualData.getValue())<Double.parseDouble(actualData.getLowLowAlarm())){
actualData.setAlarmDescription("该变量低低报警!");
actualData.setInsertTime(t);
actualDataService.save(actualData);
}
}
}
s7ConnHelper.getActualDatas().forEach(actualData -> log.info(actualData.toString()));
catch (Exception ex){
log.info(ex.getMessage()+"=====");
s7ConnHelper.s7Connector=null;
s7ConnHelper.s7Serializer=null;
try {
s7ConnHelper.initConnect();
errorTimes=0;
} catch (IOException e) {
e.printStackTrace();
}
}
}

通信帮助类:

package com.zg.mymes.myConnPLC.myS7;
import com.github.s7connector.api.DaveArea;
import com.github.s7connector.api.S7Connector;
import com.github.s7connector.api.S7Serializer;
import com.github.s7connector.api.factory.S7ConnectorFactory;
import com.github.s7connector.api.factory.S7SerializerFactory;
import com.zg.mymes.entities.ActualData;
import com.zg.mymes.entities.MyConfig;
import com.zg.mymes.helper.MyJsonConfigTool;
import com.zg.mymes.myConnPLC.DataConvert;
import com.zg.mymes.myConnPLC.myS7.myS7entities.MyS7Entity;
import com.zg.mymes.myConnPLC.myS7.myS7entities.MyS7WriteEntity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.*;
/**
* @Auther: Zg
* @Date: 2022/11/23 - 11 - 23 - 17:14
* @Description: com.zg.mymes.myConnPLC.myS7
* @version: 1.0
*/
@Component
@Slf4j
@Builder
@Data
@AllArgsConstructor
@NoArgsConstructor
public class S7ConnHelper implements IS7ConnHelper {
private String Ip;
private Integer Port;
public S7Connector s7Connector;
public S7Serializer s7Serializer;
private List<ActualData> actualDatas = new ArrayList<ActualData>();
private MyS7Entity myDbData;
private List<Object> myDbDataList = new ArrayList<>();
private List<MyS7Entity> myDbDatas = new ArrayList<MyS7Entity>();
private Map<String,Object> myMap = new HashMap<>();
private Integer errorTimes = 0;
private Boolean isConnected = false;
private Boolean heart = false;
@Autowired
private MyJsonConfigTool configTool;
@Autowired
private DataConvert dataConvert;
@Override
public void initConnect() throws IOException {
MyConfig myConfig = configTool.ReadJson();
Ip = myConfig.getIp();
Port = 102;
actualDatas = myConfig.getActualDatas();
if (this.s7Connector==null){
this.s7Connector = S7ConnectorFactory.buildTCPConnector()
.withHost(Ip)
.withPort(Port)
.withTimeout(10000)
.withRack(0)//机架号
.withSlot(1)//插槽号
.build();
this.s7Serializer = S7SerializerFactory.buildSerializer(s7Connector);
this.isConnected = true;
}
}
/**
*
* @param dbNum DB号
* @param clazz 变量
* @param offSet 偏移量
*/
@Override
public MyS7Entity readPlcData(Integer dbNum, Class<?> clazz, int offSet){
//第一个参数:DaveArea.DB 表示读取PLC的地址区域为DB
//第二个参数:DB块地址,若plc中是DB1000,则填1000
//第三个参数:数据长度
//第四个参数:偏移量
//s7Connector.read(DaveArea.DB,)
//        this.clazz = clazz;
//        this.dbNum = dbNum;
//S7Serializer s7Serializer = S7SerializerFactory.buildSerializer(s7Connector);
//db号,偏移量
if (this.isConnected=true){
//            java.util.Date date = new Date();//获得当前时间
//            Timestamp t = new Timestamp(date.getTime());
this.myDbData = (MyS7Entity)this.s7Serializer.dispense(clazz, dbNum, offSet);
//this.myDbData.setCreateTime(t);
//心跳
if (heart==false){
this.myDbData.setHeartBeat(10);
heart=true;
}
else if (heart==true){
this.myDbData.setHeartBeat(20);
heart=false;
}
try {
this.s7Serializer.store(this.myDbData,dbNum,offSet);
}
//断线重连
catch (Exception ex){
log.info(ex.getMessage()+"Inner+=+=");
this.isConnected=false;
try {
this.s7Connector.close();
} catch (IOException e) {
e.printStackTrace();
}
this.s7Connector=null;
this.s7Serializer=null;
try {
this.initConnect();
errorTimes=0;
} catch (IOException e) {
e.printStackTrace();
}
}
this.myDbData = (MyS7Entity)this.s7Serializer.dispense(clazz, dbNum, offSet);
if (myDbDatas.size()<30){
myDbDatas.add(myDbData);
}
else {
myDbDatas.remove(0);
}
}
return myDbData;
}
@Override
public MyS7Entity readTheDbData(Integer dbNum, MyS7Entity clazz, int offSet) {
MyS7Entity myData = this.s7Serializer.dispense(clazz.getClass(), dbNum, offSet);
return myData;
}
@Override
public void writePlcData(Integer dbNum, MyS7WriteEntity clazz){
this.s7Serializer.store(clazz,dbNum,0);
}
//DB,DB号,偏移量,Byte数组
@Override
public void writePlcByte(byte[] bytes){
this.s7Connector.write(DaveArea.DB,31,0,bytes);
}
}
package com.zg.mymes.myConnPLC.myS7;
import com.zg.mymes.myConnPLC.myS7.myS7entities.MyS7Entity;
import com.zg.mymes.myConnPLC.myS7.myS7entities.MyS7WriteEntity;
import java.io.IOException;
/**
* @Auther: Zg
* @Date: 2022/11/23 - 11 - 23 - 17:10
* @Description: com.zg.mymes.myConnPLC.myS7
* @version: 1.0
*/
public interface IS7ConnHelper {
void initConnect() throws IOException;
MyS7Entity readPlcData(Integer dbNum, Class<?> clazz, int offSet);
MyS7Entity readTheDbData(Integer dbNum, MyS7Entity clazz, int offSet);
void writePlcData(Integer dbNum, MyS7WriteEntity clazz);
void writePlcByte(byte[] bytes);
}
package com.zg.mymes.helper;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zg.mymes.entities.MyConfig;
import org.springframework.stereotype.Service;
import java.io.*;
/**
* @Auther: Zg
* @Date: 2022/11/23 - 11 - 23 - 14:58
* @Description: com.zg.mymes.helper
* @version: 1.0
*/
@Service
public class MyJsonConfigTool {
public String jsonStr="D:\\s7cfg.json";
public void CreatJson( MyConfig config) throws IOException {
// 创建文件对象
File fileText = new File(jsonStr);
ObjectMapper mapper = new ObjectMapper();
// 向文件写入对象写入信息
FileWriter fileWriter = new FileWriter(fileText);
// 写文件
String jsonString = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(config);
fileWriter.write(jsonString);
// 关闭
fileWriter.close();
}
public MyConfig ReadJson() throws IOException {
ObjectMapper mapper = new ObjectMapper();
File file = new File(jsonStr);
String str = getStr(file);
MyConfig myConfig = mapper.readValue(str, MyConfig.class);
return myConfig;
}
public String getStr(File jsonFile){
String jsonStr = "";
try {
FileReader fileReader = new FileReader(jsonFile);
Reader reader = new InputStreamReader(new FileInputStream(jsonFile),"utf-8");
int ch = 0;
StringBuffer sb = new StringBuffer();
while ((ch = reader.read()) != -1) {
sb.append((char) ch);
}
fileReader.close();
reader.close();
jsonStr = sb.toString();
return jsonStr;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}

C#的对应代码:

using S7.Net.Types;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZgCsharp.Entities
{
public class MyS7Db
{
public float aBLineVoltage_PLC { get; set; }
public float bCLineVoltage_PLC { get; set; }
public float aCLineVoltage_PLC { get; set; }
public float aPhaseVoltage_PLC { get; set; }
public float bPhaseVoltage_PLC { get; set; }
public float cPhaseVoltage_PLC { get; set; }
public float aPhaseCurrent_PLC { get; set; }
public float bPhaseCurrent_PLC { get; set; }
public float cPhaseCurrent_PLC { get; set; }
public float allActivePower_PLC { get; set; }
public float aActivePower_PLC { get; set; }
public float bActivePower_PLC { get; set; }
public float cActivePower_PLC { get; set; }
public float allReactivePower_PLC { get; set; }
public float aReactivePower_PLC { get; set; }
public float bReactivePower_PLC { get; set; }
public float cReactivePower_PLC { get; set; }
public float allPowerFactor_PLC { get; set; }
public float aPowerFactor_PLC { get; set; }
public float bPowerFactor_PLC { get; set; }
public float cPowerFactor_PLC { get; set; }
public float aBLineVoltage_Power { get; set; }
public float bCLineVoltage_Power { get; set; }
public float aCLineVoltage_Power { get; set; }
public float aPhaseVoltage_Power { get; set; }
public float bPhaseVoltage_Power { get; set; }
public float cPhaseVoltage_Power { get; set; }
public float aPhaseCurrent_Power { get; set; }
public float bPhaseCurrent_Power { get; set; }
public float cPhaseCurrent_Power { get; set; }
public float allActivePower_Power { get; set; }
public float aActivePower_Power { get; set; }
public float bActivePower_Power { get; set; }
public float cActivePower_Power { get; set; }
public float allReactivePower_Power { get; set; }
public float aReactivePower_Power { get; set; }
public float bReactivePower_Power { get; set; }
public float cReactivePower_Power { get; set; }
public float allPowerFactor_Power { get; set; }
public float aPowerFactor_Power { get; set; }
public float bPowerFactor_Power { get; set; }
public float cPowerFactor_Power { get; set; }
public float testAlarm { get; set; }
//public ushort heartBeat { get; set; }
//[S7String(S7StringType.S7String, 130)]
//public string var100;
//public string Var100
//{
//    get { return var100; }
//    set { var100 = value; }
//}
//[S7String(S7StringType.S7String, 130)]
//public string var101;
//public string Var101
//{
//    get { return var101; }
//    set { var101 = value; }
//}
//public bool Bool1 { get; set; }
//public byte Byte1 { get; set; }
//public double Float1 { get; set; }
//public uint MD101 { get; set; }
}
}
using Newtonsoft.Json;
using S7.Net;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using ZgCsharp.Entities;
using ZgCsharp.SqlSugar.Repository.Impl;
namespace ZgCsharp.S7
{
/*
public enum CpuType
{
S7200 = 0,
Logo0BA8 = 1,
S7200Smart = 2,
S7300 = 10,
S7400 = 20,
S71200 = 30,
S71500 = 40
}
*/
public class MyS7Helper
{
public Plc myS7Master = null;
//配置文件地址
private string jsonfile = Application.StartupPath + "\\Config\\modbuscfg1.json";
private string str;
private CfgJson cfgJson;
private ModelRepository modelRepository;
private string ip;
private int port;
private string myCpuType;
private string s7DbNum;
private string s7StartByte;
private int strMax;
private MyS7Db myS7Db = new MyS7Db();
private List<ActualData> actualDatas = new List<ActualData>();
public List<ActualData> ActualDatas
{
get { return actualDatas; }
set { actualDatas = value; }
}
public MyS7Db MyS7Db
{
get { return myS7Db; }
set { myS7Db = value; }
}
private CancellationTokenSource cts = new CancellationTokenSource();
public MyS7Helper(ModelRepository modelRepository)
{
this.modelRepository = modelRepository;
str = File.ReadAllText(jsonfile);
cfgJson = JsonConvert.DeserializeObject<CfgJson>(str);
this.ip = cfgJson.Ip;
this.port = 102;
this.myCpuType = cfgJson.CPUType;
this.s7DbNum = cfgJson.S7DbNum;
this.s7StartByte = cfgJson.S7StartByte;
this.strMax = int.Parse(cfgJson.strMax);
this.actualDatas = cfgJson.ActualDatas;
this.Conn();
this.ReadPLCClass();
}
public bool Conn()
{
myS7Master = new Plc((CpuType)Enum.Parse(typeof(CpuType), this.myCpuType), this.ip, 0, 0);
try
{
myS7Master.Open();
}
catch (Exception ex)
{
return false;
}
return true;
}
public void DisConn()
{
myS7Master.Close();
}
public void ReadPLCClass()
{
Task.Run(async () =>
{
while (!cts.IsCancellationRequested)
{
if (myS7Master.IsConnected)
{
//int i = myS7Master.ReadClass(myS7Db, int.Parse(this.s7DbNum), int.Parse(this.s7StartByte));
myS7Db = myS7Master.ReadClass<MyS7Db>(int.Parse(this.s7DbNum), int.Parse(this.s7StartByte));
await Task.Delay(500);
System.Reflection.PropertyInfo[] fields = MyS7Db.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
//System.Reflection.FieldInfo[] fields = MyS7Db.GetType().GetFields(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Public);
foreach (var item in fields)
{
foreach (var i in this.actualDatas)
{
if (item.Name == i.Name)
{
i.Value = item.GetValue(MyS7Db).ToString();
}
}
}
}
}
}, cts.Token);
}
public void WritePLCClass(MyS7Db myS7DbData)
{
myS7Master.WriteClass(myS7DbData, int.Parse(this.s7DbNum), int.Parse(this.s7StartByte));
}
public void WriteStr(string str)
{
byte[] myBytes = Encoding.ASCII.GetBytes(str);
byte[] byte1 = { (byte)130, (byte)myBytes.Length };
byte[] b = byte1.Concat(myBytes).ToArray();
//myS7Master.WriteBytes(DataType.DataBlock, int.Parse(this.s7DbNum), int.Parse(this.s7StartByte), b);
myS7Master.WriteBytes(DataType.DataBlock, 32, 3696, b);
}   
public void WriteBadApple(byte[] bytes)
{
myS7Master.WriteBytes(DataType.DataBlock, 32, 0, bytes);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ZgCsharp.Entities
{
public class CfgJson
{
public string Ip { get; set; }
public string Port { get; set; }
public string SlaveNo { get; set; }
public string Address { get; set; }
public string VarNum { get; set; }
public string CPUType { get; set; }
public string S7DbNum { get; set; }
public string S7StartByte { get; set; }
public string strMax { get; set; }
public List<ActualData> ActualDatas { get; set; }
}
}

使用springboot当后端,layui+thyme leaf当前端:

在这里插入图片描述

文档下载:在C#和Java中利用反射处理S7协议读取西门子PLC的变量.doc文档

THE END
喜欢就支持一下吧