|
|
@@ -0,0 +1,726 @@
|
|
|
+using System.Collections.Concurrent;
|
|
|
+using YSAI.Core.communication.net.tcp.client;
|
|
|
+using YSAI.Core.subscription;
|
|
|
+using YSAI.Core.virtualAddress;
|
|
|
+using YSAI.Model.data;
|
|
|
+using YSAI.Model.@enum;
|
|
|
+using YSAI.Model.@interface;
|
|
|
+using YSAI.Model.tool;
|
|
|
+using YSAI.Unility;
|
|
|
+
|
|
|
+namespace YSAI.GE
|
|
|
+{
|
|
|
+ /// <summary>
|
|
|
+ /// 通用电气 PLC通信
|
|
|
+ /// </summary>
|
|
|
+ public sealed class GEOperate : IBaseAbstract, IDaq
|
|
|
+ {
|
|
|
+ protected override string TAG => "GEOperate";
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 锁
|
|
|
+ /// </summary>
|
|
|
+ private static readonly object Lock = new object();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 自身对象集合
|
|
|
+ /// </summary>
|
|
|
+ private static List<GEOperate> ThisObjList = new List<GEOperate>(); //自身对象集合
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 单例模式
|
|
|
+ /// </summary>
|
|
|
+ /// <returns></returns>
|
|
|
+ public static GEOperate Instance(GEData.Basics basics)
|
|
|
+ {
|
|
|
+ if (ThisObjList.Count >= MaxInstanceCount)
|
|
|
+ {
|
|
|
+ throw new Exception(ExceedMaxInstanceCountTips);
|
|
|
+ }
|
|
|
+ GEOperate? exp = ThisObjList.FirstOrDefault(c => c.basics.Comparer(basics).result);
|
|
|
+ if (exp == null)
|
|
|
+ {
|
|
|
+ lock (Lock)
|
|
|
+ {
|
|
|
+ if (ThisObjList.Count(c => c.basics.Comparer(basics).result) > 0)
|
|
|
+ {
|
|
|
+ return ThisObjList.First(c => c.basics.Comparer(basics).result);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ GEOperate exp2 = new GEOperate(basics);
|
|
|
+ ThisObjList.Add(exp2);
|
|
|
+ return exp2;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return exp;
|
|
|
+ }
|
|
|
+ /// <summary>
|
|
|
+ /// 构造函数
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="basics">基础数据</param>
|
|
|
+ public GEOperate(GEData.Basics basics)
|
|
|
+ {
|
|
|
+ this.basics = basics;
|
|
|
+ }
|
|
|
+
|
|
|
+ public GEOperate()
|
|
|
+ { }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 基础数据
|
|
|
+ /// </summary>
|
|
|
+ private GEData.Basics basics;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ ///SOCKET TCP Client
|
|
|
+ /// </summary>
|
|
|
+ private TcpClientOperate tcpClientOperate;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 虚拟地址
|
|
|
+ /// </summary>
|
|
|
+ private VirtualAddressManage VAM = new VirtualAddressManage();
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 实现订阅功能
|
|
|
+ /// </summary>
|
|
|
+ private SubscribeOperate subscribeOperate;
|
|
|
+
|
|
|
+ public void Dispose()
|
|
|
+ {
|
|
|
+ Off();
|
|
|
+ GC.Collect();
|
|
|
+ GC.SuppressFinalize(this);
|
|
|
+ ThisObjList.Remove(this);
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult GetStatus()
|
|
|
+ {
|
|
|
+ string SN = Depart("GetStatus");
|
|
|
+ if (tcpClientOperate == null)
|
|
|
+ {
|
|
|
+ return Break(SN, false, "未连接", OutputLog: false);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return Break(SN, tcpClientOperate.GetStatus().State, tcpClientOperate.GetStatus().State ? "已连接" : "未连接", OutputLog: false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> GetStatusAsync()
|
|
|
+ {
|
|
|
+ return Task.Run(() => GetStatus());
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult GetParam()
|
|
|
+ {
|
|
|
+ string SN = Depart("GetParam");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //名称
|
|
|
+ string name = TAG.Replace("Operate", string.Empty).Replace("Client", string.Empty);
|
|
|
+ //命名空间
|
|
|
+ string nameSpace = "YSAI.GE.GEOperate";
|
|
|
+ //对象实例
|
|
|
+ GEData.Basics basics = new GEData.Basics();
|
|
|
+ //参数处理
|
|
|
+ OperateResult operateResult = ParamTool.Get(new GEData.Basics(), name, Properties: new List<ParamStructure.propertie>
|
|
|
+ {
|
|
|
+ new ParamStructure.propertie
|
|
|
+ {
|
|
|
+ PropertyName = "ServiceName",
|
|
|
+ Description = "命名空间",
|
|
|
+ Show = false,
|
|
|
+ Use = false,
|
|
|
+ Default = nameSpace,
|
|
|
+ DataCate = null
|
|
|
+ }
|
|
|
+ });
|
|
|
+ return Break(SN, operateResult);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return Break(SN, false, ex.Message, Exception: ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> GetParamAsync()
|
|
|
+ {
|
|
|
+ return Task.Run(() => GetParam());
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult CreateInstance<T>(T Basics)
|
|
|
+ {
|
|
|
+ string SN = Depart("CreateInstance");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ //先判断对象类型是否一致
|
|
|
+ if (typeof(T).FullName.Equals(typeof(GEData.Basics).FullName))
|
|
|
+ {
|
|
|
+ return Break(SN, true, RData: Instance(Basics as GEData.Basics));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return Break(SN, false, "对象类型错误,无法创建实例");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return Break(SN, false, ex.Message, Exception: ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> CreateInstanceAsync<T>(T Basics)
|
|
|
+ {
|
|
|
+ return Task.Run(() => CreateInstance(Basics));
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult Subscribe(Address address)
|
|
|
+ {
|
|
|
+ string SN = Depart("Subscribe");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (subscribeOperate == null)
|
|
|
+ {
|
|
|
+ subscribeOperate = SubscribeOperate.Instance(new SubscribeData.Basics()
|
|
|
+ {
|
|
|
+ Address = address,
|
|
|
+ ChangeOut = basics.ChangeOut,
|
|
|
+ Function = Read,
|
|
|
+ AllOut = basics.AllOut,
|
|
|
+ HandleInterval = basics.HandleInterval,
|
|
|
+ SN = basics.SN,
|
|
|
+ TaskHandleInterval = basics.TaskHandleInterval,
|
|
|
+ TaskNumber = basics.TaskNumber
|
|
|
+ });
|
|
|
+ subscribeOperate.OnEvent += OnEventHandler;
|
|
|
+ OperateResult operateResult = subscribeOperate.On();
|
|
|
+ return Break(SN, operateResult.State, operateResult.Message);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ OperateResult operateResult = subscribeOperate.Subscribe(address);
|
|
|
+ return Break(SN, operateResult.State, operateResult.Message);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return Break(SN, false, ex.Message, Exception: ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> SubscribeAsync(Address address)
|
|
|
+ {
|
|
|
+ return Task.Run(() => Subscribe(address));
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult UnSubscribe(Address address)
|
|
|
+ {
|
|
|
+ string SN = Depart("UnSubscribe");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (subscribeOperate != null)
|
|
|
+ {
|
|
|
+ OperateResult operateResult = subscribeOperate.UnSubscribe(address);
|
|
|
+ return Break(SN, operateResult.State, operateResult.Message);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ return Break(SN, false, "当前尚未订阅");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return Break(SN, false, ex.Message, Exception: ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> UnSubscribeAsync(Address address)
|
|
|
+ {
|
|
|
+ return Task.Run(() => UnSubscribe(address));
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult Off()
|
|
|
+ {
|
|
|
+ string SN = Depart("Off");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (tcpClientOperate == null || !tcpClientOperate.GetStatus().State)
|
|
|
+ {
|
|
|
+ return Break(SN, false, "未连接");
|
|
|
+ }
|
|
|
+ if (subscribeOperate != null)
|
|
|
+ {
|
|
|
+ OperateResult operateResult = subscribeOperate.Off();
|
|
|
+ if (!operateResult.State)
|
|
|
+ {
|
|
|
+ return Break(SN, false, operateResult.Message);
|
|
|
+ }
|
|
|
+ subscribeOperate = null;
|
|
|
+ }
|
|
|
+ tcpClientOperate.Dispose();
|
|
|
+ tcpClientOperate = null;
|
|
|
+ return Break(SN, true);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return Break(SN, false, ex.Message, Exception: ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> OffAsync()
|
|
|
+ {
|
|
|
+ return Task.Run(() => Off());
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult On()
|
|
|
+ {
|
|
|
+ string SN = Depart("On");
|
|
|
+ try
|
|
|
+ {
|
|
|
+ if (tcpClientOperate != null && tcpClientOperate.GetStatus().State)
|
|
|
+ {
|
|
|
+ return Break(SN, false, "已连接");
|
|
|
+ }
|
|
|
+ if (tcpClientOperate != null && !tcpClientOperate.GetStatus().State)
|
|
|
+ {
|
|
|
+ tcpClientOperate.Dispose();
|
|
|
+ }
|
|
|
+ //先实例化底层 socket 通信
|
|
|
+ tcpClientOperate = TcpClientOperate.Instance(new TcpClientData.Basics
|
|
|
+ {
|
|
|
+ InterruptReconnection = basics.InterruptReconnection,
|
|
|
+ Ip = basics.Ip,
|
|
|
+ Port = basics.Port,
|
|
|
+ ReconnectionInterval = basics.ReconnectionInterval,
|
|
|
+ SN = basics.SN,
|
|
|
+ Timeout = basics.Timeout,
|
|
|
+ SendWait = true,
|
|
|
+ SendWaitInterval = basics.Timeout
|
|
|
+ });
|
|
|
+ OperateResult operateResult = tcpClientOperate.On();
|
|
|
+ if (operateResult.State)
|
|
|
+ {
|
|
|
+ //发送基础命令
|
|
|
+ operateResult = tcpClientOperate.SendWait(msg_init);
|
|
|
+ if (operateResult.State)
|
|
|
+ {
|
|
|
+ byte[]? bytes = operateResult.GetRData<byte[]>();
|
|
|
+ if (bytes != null)
|
|
|
+ {
|
|
|
+ if (bytes[0] == 0x01)
|
|
|
+ {
|
|
|
+ return Break(SN, true);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ tcpClientOperate.Off();
|
|
|
+ return Break(SN, false, operateResult.Message);
|
|
|
+ }
|
|
|
+ catch (Exception ex)
|
|
|
+ {
|
|
|
+ return Break(SN, false, ex.Message, Exception: ex);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> OnAsync()
|
|
|
+ {
|
|
|
+ return Task.Run(() => On());
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult Read(Address address)
|
|
|
+ {
|
|
|
+ throw new NotImplementedException();
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> ReadAsync(Address address)
|
|
|
+ {
|
|
|
+ throw new NotImplementedException();
|
|
|
+ }
|
|
|
+
|
|
|
+ public OperateResult Write<V>(ConcurrentDictionary<string, V> Values)
|
|
|
+ {
|
|
|
+ throw new NotImplementedException();
|
|
|
+ }
|
|
|
+
|
|
|
+ public Task<OperateResult> WriteAsync<V>(ConcurrentDictionary<string, V> Values)
|
|
|
+ {
|
|
|
+ throw new NotImplementedException();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ #region 基础
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 先发送56字节,给PLC;
|
|
|
+ /// 它将响应:0x01 0x00...
|
|
|
+ /// </summary>
|
|
|
+ private byte[] msg_init = new byte[56];
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 这是标准的消息格式,你需要更新;
|
|
|
+ /// 发送前的一些字段;
|
|
|
+ /// PC发送请求开始:0x02 0x00…;
|
|
|
+ /// PLC响应消息:0x03 0x00…;
|
|
|
+ /// </summary>
|
|
|
+ private byte[] msg_base = {
|
|
|
+ 0x02, // 00 - Type (x03:=ReceiveOK, x02:=Transmit, x08:=Something just after msg_init - maybe kind of exception interruption?)
|
|
|
+ 0x00, // 01 - Unknown
|
|
|
+ 0x00, // 02 - Seq Number (x00 works, x06 also works, x05 also according referenced document)
|
|
|
+ 0x00, // 03 - Unknown
|
|
|
+ 0x00, // 04 - Text Length
|
|
|
+ 0x00, // 05 - Unknown / Text character?
|
|
|
+ 0x00, // 06 - Unknown / Text character?
|
|
|
+ 0x00, // 07 - Unknown / Text character?
|
|
|
+ 0x00, // 08 - Unknown / Text character?
|
|
|
+ 0x01, // 09 - Unknown / Text character?
|
|
|
+ 0x00, // 10 - Unknown / Text character?
|
|
|
+ 0x00, // 11 - Unknown / Text character?
|
|
|
+ 0x00, // 12 - Unknown / Text character?
|
|
|
+ 0x00, // 13 - Unknown / Text character?
|
|
|
+ 0x00, // 14 - Unknown / Text character?
|
|
|
+ 0x00, // 15 - Unknown / Text character?
|
|
|
+ 0x00, // 16 - Unknown / Text character?
|
|
|
+ 0x01, // 17 - Unknown / Always x01
|
|
|
+ 0x00, // 18 - Unknown
|
|
|
+ 0x00, // 19 - Unknown
|
|
|
+ 0x00, // 20 - Unknown
|
|
|
+ 0x00, // 21 - Unknown
|
|
|
+ 0x00, // 22 - Unknown
|
|
|
+ 0x00, // 23 - Unknown
|
|
|
+ 0x00, // 24 - Unknown
|
|
|
+ 0x00, // 25 - Unknown
|
|
|
+ 0x00, // 26 - Time Seconds
|
|
|
+ 0x00, // 27 - Time Minutes
|
|
|
+ 0x00, // 28 - Time Hours
|
|
|
+ 0x00, // 29 - Reserved / Always x01
|
|
|
+ 0x06, // 30 - Seq Number (Repeated) (0x06) - meaning in responces from PLC
|
|
|
+ 0xc0, // 31 - Message Type
|
|
|
+ 0x00, // 32 - Mailbox Source
|
|
|
+ 0x00, // 33 - Mailbox Source
|
|
|
+ 0x00, // 34 - Mailbox Source
|
|
|
+ 0x00, // 35 - Mailbox Source
|
|
|
+ 0x10, // 36 - Mailbox Destination // dec: 3600
|
|
|
+ 0x0e, // 37 - Mailbox Destination
|
|
|
+ 0x00, // 38 - Mailbox Destination
|
|
|
+ 0x00, // 39 - Mailbox Destination
|
|
|
+ 0x01, // 40 - Packet Number // to check
|
|
|
+ 0x01, // 41 - Total Packet Number
|
|
|
+ 0x00, // 42 - Service Request Code - (Operation Type SERVICE_REQUEST_CODE)
|
|
|
+ 0x00, // 43 - Request Dependent Space (Ex. MEMORY_TYPE_CODE)
|
|
|
+ 0x00, // 44 - Request Dependent Space (Ex. Address:LSB)
|
|
|
+ 0x00, // 45 - Request Dependent Space (Ex. Address:MSB)
|
|
|
+ 0x00, // 46 - Request Dependent Space (Ex. Data Size Words:LSB)
|
|
|
+ 0x00, // 47 - Request Dependent Space (Ex. Data Size Words:MSB)
|
|
|
+ 0x00, // 48 - Request Dependent Space (Ex. Write Value:LSB)
|
|
|
+ 0x00, // 49 - Request Dependent Space (Ex. Write Value:MSB)
|
|
|
+ 0x00, // 50 - Request Dependent Space (Ex. Write Value Part 2 for LONG:LSB)
|
|
|
+ 0x00, // 51 - Request Dependent Space (Ex. Write Value Part 2 for LONG:MSB)
|
|
|
+ 0x00, // 52 - Dependent of "Data Size" - byte 46, 47 / PLC status in other Service Request
|
|
|
+ 0x00, // 53 - Dependent of "Data Size" - byte 46, 47 / PLC status in other Service Request
|
|
|
+ 0x00, // 54 - Dependent of "Data Size" - byte 46, 47 / PLC status in other Service Request
|
|
|
+ 0x00 // 55 - Dependent of "Data Size" - byte 46, 47 / PLC status in other Service Request
|
|
|
+ };
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 功能码
|
|
|
+ /// </summary>
|
|
|
+ private enum FCode
|
|
|
+ {
|
|
|
+ R,
|
|
|
+ AI,
|
|
|
+ AQ,
|
|
|
+ I,
|
|
|
+ Q,
|
|
|
+ T,
|
|
|
+ M,
|
|
|
+ SA,
|
|
|
+ SB,
|
|
|
+ SC,
|
|
|
+ G
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 解析地址,返回功能码与下标
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="address">地址</param>
|
|
|
+ /// <param name="isBit">是否是bit</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private (FCode fc, byte fCode, int index) ParseAddress(string address, bool isBit = false)
|
|
|
+ {
|
|
|
+ byte retCode = 0x00;
|
|
|
+ string code = string.Empty;
|
|
|
+ string[] rStrs = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", };
|
|
|
+ foreach (string str in rStrs)
|
|
|
+ {
|
|
|
+ code = address.Replace(str, string.Empty);
|
|
|
+ }
|
|
|
+ int retIndex = int.Parse(address.Replace(code, string.Empty));
|
|
|
+ FCode retFc = (FCode)Enum.Parse(typeof(FCode), code);
|
|
|
+ if (!isBit)
|
|
|
+ {
|
|
|
+ switch (code)
|
|
|
+ {
|
|
|
+ case "R":
|
|
|
+ retCode = 0x08;
|
|
|
+ break;
|
|
|
+ case "AI":
|
|
|
+ retCode = 0x0a;
|
|
|
+ break;
|
|
|
+ case "AQ":
|
|
|
+ retCode = 0x0c;
|
|
|
+ break;
|
|
|
+ case "I":
|
|
|
+ retCode = 0x10;
|
|
|
+ break;
|
|
|
+ case "Q":
|
|
|
+ retCode = 0x12;
|
|
|
+ break;
|
|
|
+ case "T":
|
|
|
+ retCode = 0x14;
|
|
|
+ break;
|
|
|
+ case "M":
|
|
|
+ retCode = 0x16;
|
|
|
+ break;
|
|
|
+ case "SA":
|
|
|
+ retCode = 0x18;
|
|
|
+ break;
|
|
|
+ case "SB":
|
|
|
+ retCode = 0x20;
|
|
|
+ break;
|
|
|
+ case "SC":
|
|
|
+ retCode = 0x22;
|
|
|
+ break;
|
|
|
+ case "G":
|
|
|
+ retCode = 0x38;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ switch (code)
|
|
|
+ {
|
|
|
+ case "I":
|
|
|
+ retCode = 0x46;
|
|
|
+ break;
|
|
|
+ case "Q":
|
|
|
+ retCode = 0x48;
|
|
|
+ break;
|
|
|
+ case "T":
|
|
|
+ retCode = 0x4a;
|
|
|
+ break;
|
|
|
+ case "M":
|
|
|
+ retCode = 0x4c;
|
|
|
+ break;
|
|
|
+ case "SA":
|
|
|
+ retCode = 0x4e;
|
|
|
+ break;
|
|
|
+ case "SB":
|
|
|
+ retCode = 0x50;
|
|
|
+ break;
|
|
|
+ case "SC":
|
|
|
+ retCode = 0x52;
|
|
|
+ break;
|
|
|
+ case "G":
|
|
|
+ retCode = 0x56;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return (retFc, retCode, retIndex);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 解析读取的包头数据
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="address"></param>
|
|
|
+ /// <param name=""></param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private byte[] R(string address, DataType dataType)
|
|
|
+ {
|
|
|
+ byte[] msg_send = new byte[56];
|
|
|
+ byte[] msg_read = new byte[512];
|
|
|
+ this.msg_base.CopyTo(msg_send, 0);
|
|
|
+ (FCode fc, byte fCode, int index) pa = ParseAddress(address);
|
|
|
+ switch (dataType)
|
|
|
+ {
|
|
|
+ case DataType.Byte:
|
|
|
+ switch (pa.fc)
|
|
|
+ {
|
|
|
+ case FCode.R:
|
|
|
+ msg_send[42] = 0x04; //请求类型
|
|
|
+ msg_send[43] = pa.fCode; //功能码
|
|
|
+ byte[] byteArrayAddress = BitConverter.GetBytes((Int16)(pa.index / 8));
|
|
|
+ msg_send[44] = byteArrayAddress[0];
|
|
|
+ msg_send[45] = byteArrayAddress[1];
|
|
|
+ msg_send[46] = 0x01;
|
|
|
+ break;
|
|
|
+ case FCode.AI:
|
|
|
+ break;
|
|
|
+ case FCode.AQ:
|
|
|
+ break;
|
|
|
+ case FCode.I:
|
|
|
+ break;
|
|
|
+ case FCode.Q:
|
|
|
+ break;
|
|
|
+ case FCode.T:
|
|
|
+ break;
|
|
|
+ case FCode.M:
|
|
|
+ break;
|
|
|
+ case FCode.SA:
|
|
|
+ break;
|
|
|
+ case FCode.SB:
|
|
|
+ break;
|
|
|
+ case FCode.SC:
|
|
|
+ break;
|
|
|
+ case FCode.G:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case DataType.Bool:
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ break;
|
|
|
+ case DataType.Short:
|
|
|
+ case DataType.Int16:
|
|
|
+ switch (pa.fc)
|
|
|
+ {
|
|
|
+ case FCode.R:
|
|
|
+ msg_send[42] = 0x04; //请求类型
|
|
|
+ msg_send[43] = pa.fCode; //功能码
|
|
|
+ msg_send[44] = (byte)(pa.index & 0xFF);
|
|
|
+ msg_send[45] = (byte)(pa.index >> 8);
|
|
|
+ msg_send[46] = 0x01;
|
|
|
+ break;
|
|
|
+ case FCode.AI:
|
|
|
+ break;
|
|
|
+ case FCode.AQ:
|
|
|
+ break;
|
|
|
+ case FCode.I:
|
|
|
+ break;
|
|
|
+ case FCode.Q:
|
|
|
+ break;
|
|
|
+ case FCode.T:
|
|
|
+ break;
|
|
|
+ case FCode.M:
|
|
|
+ break;
|
|
|
+ case FCode.SA:
|
|
|
+ break;
|
|
|
+ case FCode.SB:
|
|
|
+ break;
|
|
|
+ case FCode.SC:
|
|
|
+ break;
|
|
|
+ case FCode.G:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case DataType.Ushort:
|
|
|
+ case DataType.UInt16:
|
|
|
+
|
|
|
+ break;
|
|
|
+ case DataType.Int:
|
|
|
+ case DataType.Int32:
|
|
|
+ switch (pa.fc)
|
|
|
+ {
|
|
|
+ case FCode.R:
|
|
|
+ msg_send[42] = 0x04; //请求类型
|
|
|
+ msg_send[43] = pa.fCode; //功能码
|
|
|
+ int ad = pa.index - 1;
|
|
|
+ msg_send[44] = (byte)(ad & 0xFF);
|
|
|
+ msg_send[45] = (byte)(ad >> 8);
|
|
|
+ msg_send[46] = 0x02;
|
|
|
+ break;
|
|
|
+ case FCode.AI:
|
|
|
+ break;
|
|
|
+ case FCode.AQ:
|
|
|
+ break;
|
|
|
+ case FCode.I:
|
|
|
+ break;
|
|
|
+ case FCode.Q:
|
|
|
+ break;
|
|
|
+ case FCode.T:
|
|
|
+ break;
|
|
|
+ case FCode.M:
|
|
|
+ break;
|
|
|
+ case FCode.SA:
|
|
|
+ break;
|
|
|
+ case FCode.SB:
|
|
|
+ break;
|
|
|
+ case FCode.SC:
|
|
|
+ break;
|
|
|
+ case FCode.G:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case DataType.Uint:
|
|
|
+ case DataType.UInt32:
|
|
|
+
|
|
|
+ break;
|
|
|
+ case DataType.Long:
|
|
|
+ case DataType.Int64:
|
|
|
+
|
|
|
+ break;
|
|
|
+ case DataType.Ulong:
|
|
|
+ case DataType.UInt64:
|
|
|
+
|
|
|
+ break;
|
|
|
+ case DataType.Double:
|
|
|
+
|
|
|
+ break;
|
|
|
+ case DataType.Float:
|
|
|
+ switch (pa.fc)
|
|
|
+ {
|
|
|
+ case FCode.R:
|
|
|
+ msg_send[42] = 0x04; //请求类型
|
|
|
+ msg_send[43] = pa.fCode; //功能码
|
|
|
+ int ad = pa.index - 1;
|
|
|
+ msg_send[44] = (byte)(ad & 0xFF);
|
|
|
+ msg_send[45] = (byte)(ad >> 8);
|
|
|
+ msg_send[46] = 0x02;
|
|
|
+ break;
|
|
|
+ case FCode.AI:
|
|
|
+ break;
|
|
|
+ case FCode.AQ:
|
|
|
+ break;
|
|
|
+ case FCode.I:
|
|
|
+ break;
|
|
|
+ case FCode.Q:
|
|
|
+ break;
|
|
|
+ case FCode.T:
|
|
|
+ break;
|
|
|
+ case FCode.M:
|
|
|
+ break;
|
|
|
+ case FCode.SA:
|
|
|
+ break;
|
|
|
+ case FCode.SB:
|
|
|
+ break;
|
|
|
+ case FCode.SC:
|
|
|
+ break;
|
|
|
+ case FCode.G:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// 解析写入的包头数据
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="address">地址</param>
|
|
|
+ /// <param name="value">值</param>
|
|
|
+ /// <returns></returns>
|
|
|
+ private byte[] W(string address, object value)
|
|
|
+ {
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
+ }
|
|
|
+}
|