郑州网站建设九零后,小程序推广话术案例,昌平网站开发公司,大学学风建设网站一、源码结构#xff1a; 二、运行效果#xff1a; 三、源码解析
1. 读取配置文件及创建变量信息#xff08;点位名称#xff0c;地址#xff0c;数据类型#xff08;bool/short/int/float/long/double#xff09;#xff09; 2. 异步任务处理#xff1a;读任务…一、源码结构 二、运行效果 三、源码解析
1. 读取配置文件及创建变量信息点位名称地址数据类型bool/short/int/float/long/double 2. 异步任务处理读任务写任务,将读到的数据存到字典中判断数据是否有发生变化如果数据有变化则事件广播通知 using HslCommunication;
using HslCommunication.Core;
using HslCommunication.ModBus;
using PLCEvent.Util;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using UtilHelper;namespace PLCEvent.Service
{public class PLCService{ public static Actionstring OnDataChange;public static ConcurrentDictionarystring, bool DicBoolData new ConcurrentDictionarystring, bool();public static ConcurrentDictionarystring, Word DicAllData new ConcurrentDictionarystring, Word();public static ConcurrentDictionarystring, Word DicChangeData new ConcurrentDictionarystring, Word();static ModbusTcpNet client null;static IByteTransform byteTransform;static ConcurrentQueuePLCModel queueWrite new ConcurrentQueuePLCModel();public static void DataChange(string address){OnDataChange?.Invoke(address);}/// summary/// 自定义控件内接收到数据变化事件根据传入address以及DataType查询监听地址所需要的监听范围40120_int 监听两个word40120 4012140130_long 监听四个word40130 40131 40132 40133判断是否属于本控件监听/// /summarypublic static Liststring RangeAddress(string address, int length){Liststring lstaddress new Liststring();if (0 length){lstaddress.Add(address);}else{for (int i 0; i length; i){lstaddress.Add(FillAddress((DataHelper.Obj2Int(address) i).ToString()));}}return lstaddress;}/// summary/// 读取时按位补充0/// /summarypublic static string FillAddress(string val, int length 5){return val.PadLeft(length, 0);}/// summary/// 写入时格式化地址如40101 - 101/// /summary public static string FormatAddress(string val){if (val.Length 5) return val;return val.Substring(1, val.Length - 1);}/// summary/// 初始化plc通信开启读写任务/// /summarypublic static void Init(){client new ModbusTcpNet(CommonMethods.PLCConfig.HostAddress, CommonMethods.PLCConfig.PortNumber);client.AddressStartWithZero false;client.DataFormat DataFormat.CDAB;byteTransform client.ByteTransform;TskPlcRead();TskPlcWrite();}/// summary/// 获取boolbool类型/// /summary/// param nameaddress/param/// returns/returnspublic static bool GetBool(string address){ try{bool exist DicBoolData.TryGetValue(address, out var value);// 字典存储if (!exist){Logger.Info($[Error] PLCService,GetBool,errmsg:查无点位数据({address}));}return value;}catch (Exception ex){Logger.Info([Error] PLCService,GetBool,errmsg: ex.Message);}return false;}/// summary/// 获取word1个word2个字节/// /summary static Word GetAddressWord(string address, int add){address FillAddress((Convert.ToInt32(address) add).ToString());bool exist DicAllData.TryGetValue(address, out var value);if (!exist){Logger.Info($[Error] PLCService,GetAddressWord,errmsg:查无点位数据({address}));}return value;}/// summary/// 拼接字节多个word/// /summary static byte[] JoinAddressWord(string address, DataType datatype){byte[] ret null;switch (datatype){ case DataType.Short:{ var buff GetAddressWord(address, 0);ret new byte[2] { buff.Byte1, buff.Byte2 };}break;case DataType.Int:case DataType.Float:{var buff1 GetAddressWord(address, 0);var buff2 GetAddressWord(address, 1);ret new byte[4] { buff1.Byte1, buff1.Byte2, buff2.Byte1, buff2.Byte2 };} break;case DataType.Long: case DataType.Double:{var buff1 GetAddressWord(address, 0);var buff2 GetAddressWord(address, 1);var buff3 GetAddressWord(address, 2);var buff4 GetAddressWord(address, 3);ret new byte[8] { buff1.Byte1, buff1.Byte2, buff2.Byte1, buff2.Byte2, buff3.Byte1, buff3.Byte2, buff4.Byte1, buff4.Byte2 };} break;}return ret;}public static ushort GetShort(string address){try{ var buff JoinAddressWord(address, DataType.Short);return byteTransform.TransUInt16(buff, 0); }catch (Exception ex){Logger.Info([Error] PLCService,GetShort,errmsg: ex.Message);}return 0;}public static uint GetInt(string address){try{var buff JoinAddressWord(address, DataType.Int);return byteTransform.TransUInt32(buff, 0);}catch (Exception ex){Logger.Info([Error] PLCService,GetInt,errmsg: ex.Message);}return 0;}public static float GetFloat(string address){try{var buff JoinAddressWord(address, DataType.Float);return byteTransform.TransSingle(buff, 0);}catch (Exception ex){Logger.Info([Error] PLCService,GetFloat,errmsg: ex.Message);}return 0;}public static ulong GetLong(string address){try{var buff JoinAddressWord(address, DataType.Long);return byteTransform.TransUInt64(buff, 0);}catch (Exception ex){Logger.Info([Error] PLCService,GetLong,errmsg: ex.Message);}return 0;}public static double GetDouble(string address){try{var buff JoinAddressWord(address, DataType.Double);return byteTransform.TransDouble(buff, 0);}catch (Exception ex){Logger.Info([Error] PLCService,GetDouble,errmsg: ex.Message);}return 0;}/// summary/// 定时读取/// /summarystatic void TskPlcRead(){Task.Factory.StartNew(async () {var start_c CommonMethods.PLCConfig.ReadStart_Coil;var start_h CommonMethods.PLCConfig.ReadStart_Holding;bool[] temp_c null; byte[] temp_h null;while (!CommonMethods.CTS.IsCancellationRequested){try{DicChangeData.Clear();var array_c (await client.ReadBoolAsync(start_c, (ushort)CommonMethods.PLCConfig.ReadCount_Coil)).Content;var array_h (await client.ReadAsync(start_h, (ushort)(CommonMethods.PLCConfig.ReadCount_Holding * 2))).Content;// ushort占两个字节if (null ! array_c){// bool类型只占1位数据有变化直接通知if (null temp_c) temp_c new bool[array_c.Length];CheckBoolChange(0, start_c, temp_c, array_c);Array.Copy(array_c, temp_c, array_c.Length);}if (null ! array_h){// word类型数据位(2,4,8)所以要先读取全部的数据再通知变化if (null temp_h) temp_h new byte[array_h.Length];CheckWordChange(4, start_h, temp_h, array_h);Array.Copy(array_h, temp_h, array_h.Length);if (DicChangeData.Count 0){foreach (var item in DicChangeData){DataChange(item.Key);}}} }catch (Exception ex){ Logger.Info([Error] PLCMgr,TskPlcRead,errmsg ex.Message);} await Task.Delay(100);}}, TaskCreationOptions.LongRunning);}/// summary/// 检查数据是否有变化bool类型/// /summary public static void CheckBoolChange(string flg, string start, bool[] oldbuffer, bool[] newbuffer){for (int i 0; i newbuffer.Length; i){string address flg FillAddress((i Convert.ToInt32(start)).ToString(), 4);// 00101bool value newbuffer[i];DicBoolData.AddOrUpdate1(address, value); if (oldbuffer[i] ! value){ OnDataChange(address);}}}/// summary/// 检查数据是否有变化word类型/// /summary public static void CheckWordChange(string flg, string start, byte[] oldbuffer, byte[] newbuffer){int index 0;for (int i 0; i newbuffer.Length; i i 2){string address flg FillAddress((index Convert.ToInt32(start)).ToString(), 4);// 40101index;byte byte1 newbuffer[i];byte byte2 newbuffer[i 1];Word buff new Word() { Byte1 byte1, Byte2 byte2 };DicAllData.AddOrUpdate1(address, buff);if (oldbuffer[i] ! byte1 || oldbuffer[i 1] ! byte2){DicChangeData.AddOrUpdate1(address, buff);}}}/// summary/// 添加写入值/// /summary public static void AddWriteVariable(string address, object value, DataType datatype){queueWrite.Enqueue(new PLCModel() { Address address, Value value, PLCDataType datatype });//加载值进队列} /// summary/// 定时写入/// /summarystatic void TskPlcWrite(){ Task.Factory.StartNew(async () {while (!CommonMethods.CTS.IsCancellationRequested){try{if (!queueWrite.IsEmpty){PLCModel model null; OperateResult result null;queueWrite.TryDequeue(out model);var dataype model.PLCDataType;switch (dataype){case DataType.Bool:result await client.WriteAsync(FormatAddress(model.Address), Convert.ToBoolean(model.Value));break;case DataType.Short:result await client.WriteAsync(FormatAddress(model.Address), Convert.ToUInt16(model.Value)); break;case DataType.Int:result await client.WriteAsync(FormatAddress(model.Address), Convert.ToUInt32(model.Value));break;case DataType.Float:result await client.WriteAsync(FormatAddress(model.Address), Convert.ToSingle(model.Value));break;case DataType.Long:result await client.WriteAsync(FormatAddress(model.Address), Convert.ToUInt64(model.Value));break;case DataType.Double:result await client.WriteAsync(FormatAddress(model.Address), Convert.ToDouble(model.Value));break;}if (!result.IsSuccess){Logger.Info([Error] PLCMgr,TskPlcWrite,errmsg:写入失败, result.Message);}}}catch (Exception ex){ Logger.Info([Error] PLCMgr,TskPlcWrite,errmsg: ex.Message);} await Task.Delay(100);}}, TaskCreationOptions.LongRunning);}}
} 3. 自定义控件绑定参数,绑定事件当收到数据变化事件通过属性get方式如果是bool类型直接取Bool字典的点位数据如果是Word类型根据数据类型拼装Word字典中的word数据得到对应数据类型的点位数据通过set方式加入到写队列。 注意点 1. 字典类型ConcurrentDictionarystring, bool DicBoolDataConcurrentDictionarystring, Word DicAllDataWordbyte1byte2 2. bool类型只占1位数据有变化直接通知 3. word类型数据位(short:2,int/float:4,long/double:8)所以要先读取全部的数据再通知变化 4. 自定义控件内接收到数据变化事件根据传入address以及DataType查询监听地址所需要的监听范围40120_int 监听两个word40120 4012140130_long 监听四个word40130 40131 40132 40133判断是否属于本控件监听 5. 自定义控件继承BaseParams类 PLCValue get:通过不同的数据类型获取字典中的word数据并拼接合成相应的数据类型;set:传入地址(写入时格式化地址如:40101-101)及类型 文章转载自: http://www.morning.jqmmf.cn.gov.cn.jqmmf.cn http://www.morning.lyrgp.cn.gov.cn.lyrgp.cn http://www.morning.clwhf.cn.gov.cn.clwhf.cn http://www.morning.jhzct.cn.gov.cn.jhzct.cn http://www.morning.nkyqh.cn.gov.cn.nkyqh.cn http://www.morning.jqcrf.cn.gov.cn.jqcrf.cn http://www.morning.tslfz.cn.gov.cn.tslfz.cn http://www.morning.qjfkz.cn.gov.cn.qjfkz.cn http://www.morning.rnht.cn.gov.cn.rnht.cn http://www.morning.sjsks.cn.gov.cn.sjsks.cn http://www.morning.jycr.cn.gov.cn.jycr.cn http://www.morning.hrypl.cn.gov.cn.hrypl.cn http://www.morning.wprxm.cn.gov.cn.wprxm.cn http://www.morning.cbvlus.cn.gov.cn.cbvlus.cn http://www.morning.xgzwj.cn.gov.cn.xgzwj.cn http://www.morning.xlndf.cn.gov.cn.xlndf.cn http://www.morning.qkbwd.cn.gov.cn.qkbwd.cn http://www.morning.fglxh.cn.gov.cn.fglxh.cn http://www.morning.mbzlg.cn.gov.cn.mbzlg.cn http://www.morning.hqxyt.cn.gov.cn.hqxyt.cn http://www.morning.nmlpp.cn.gov.cn.nmlpp.cn http://www.morning.mhsmj.cn.gov.cn.mhsmj.cn http://www.morning.grnhb.cn.gov.cn.grnhb.cn http://www.morning.yfmwg.cn.gov.cn.yfmwg.cn http://www.morning.psgbk.cn.gov.cn.psgbk.cn http://www.morning.bwnd.cn.gov.cn.bwnd.cn http://www.morning.kkrnm.cn.gov.cn.kkrnm.cn http://www.morning.rshijie.com.gov.cn.rshijie.com http://www.morning.qgmwt.cn.gov.cn.qgmwt.cn http://www.morning.jmwrj.cn.gov.cn.jmwrj.cn http://www.morning.gwjsm.cn.gov.cn.gwjsm.cn http://www.morning.wdshp.cn.gov.cn.wdshp.cn http://www.morning.rythy.cn.gov.cn.rythy.cn http://www.morning.dfojgo.cn.gov.cn.dfojgo.cn http://www.morning.weitao0415.cn.gov.cn.weitao0415.cn http://www.morning.rkqqf.cn.gov.cn.rkqqf.cn http://www.morning.jiuyungps.com.gov.cn.jiuyungps.com http://www.morning.rzcbk.cn.gov.cn.rzcbk.cn http://www.morning.wtcbl.cn.gov.cn.wtcbl.cn http://www.morning.spnky.cn.gov.cn.spnky.cn http://www.morning.jbztm.cn.gov.cn.jbztm.cn http://www.morning.spwln.cn.gov.cn.spwln.cn http://www.morning.4r5w91.cn.gov.cn.4r5w91.cn http://www.morning.yrbq.cn.gov.cn.yrbq.cn http://www.morning.fewhope.com.gov.cn.fewhope.com http://www.morning.qqnjr.cn.gov.cn.qqnjr.cn http://www.morning.rfzzw.com.gov.cn.rfzzw.com http://www.morning.pxdgy.cn.gov.cn.pxdgy.cn http://www.morning.xhlpn.cn.gov.cn.xhlpn.cn http://www.morning.pxwjp.cn.gov.cn.pxwjp.cn http://www.morning.zmpqh.cn.gov.cn.zmpqh.cn http://www.morning.krgjc.cn.gov.cn.krgjc.cn http://www.morning.nzsx.cn.gov.cn.nzsx.cn http://www.morning.xqxrm.cn.gov.cn.xqxrm.cn http://www.morning.xhhzn.cn.gov.cn.xhhzn.cn http://www.morning.wfzdh.cn.gov.cn.wfzdh.cn http://www.morning.xjmyq.com.gov.cn.xjmyq.com http://www.morning.nlkjq.cn.gov.cn.nlkjq.cn http://www.morning.hqgxz.cn.gov.cn.hqgxz.cn http://www.morning.shprz.cn.gov.cn.shprz.cn http://www.morning.jcwhk.cn.gov.cn.jcwhk.cn http://www.morning.ntqgz.cn.gov.cn.ntqgz.cn http://www.morning.lhldx.cn.gov.cn.lhldx.cn http://www.morning.lptjt.cn.gov.cn.lptjt.cn http://www.morning.rqxmz.cn.gov.cn.rqxmz.cn http://www.morning.lsgjf.cn.gov.cn.lsgjf.cn http://www.morning.kdhrf.cn.gov.cn.kdhrf.cn http://www.morning.rknsp.cn.gov.cn.rknsp.cn http://www.morning.bojkosvit.com.gov.cn.bojkosvit.com http://www.morning.sqtsl.cn.gov.cn.sqtsl.cn http://www.morning.zrjzc.cn.gov.cn.zrjzc.cn http://www.morning.qjxxc.cn.gov.cn.qjxxc.cn http://www.morning.yjmlg.cn.gov.cn.yjmlg.cn http://www.morning.spkw.cn.gov.cn.spkw.cn http://www.morning.qgwpx.cn.gov.cn.qgwpx.cn http://www.morning.jppdk.cn.gov.cn.jppdk.cn http://www.morning.smspc.cn.gov.cn.smspc.cn http://www.morning.nkqnn.cn.gov.cn.nkqnn.cn http://www.morning.mspqw.cn.gov.cn.mspqw.cn http://www.morning.nspzy.cn.gov.cn.nspzy.cn