protected override bool InitCommunicateKernel(IO_SERVER server, IO_COMMUNICATION communication, List <IO_DEVICE> ioDevices, SCADA_DRIVER driver) { if (IsCreateControl) { CommunicationControl = new Modbus_Serial_Ctrl(); if (communication != null) { CommunicationControl.SetUIParameter(communication.IO_COMM_PARASTRING); } } Serial_PARA = new Modbus_Serial_PARA(); if (communication != null) { comParaPack = new ParaPack(communication.IO_COMM_PARASTRING); Serial_PARA.BaudRate = Convert.ToInt32(comParaPack.GetValue("波特率")); Serial_PARA.CollectFaultsInternal = Convert.ToInt32(comParaPack.GetValue("重试间隔")); Serial_PARA.CollectFaultsNumber = Convert.ToInt32(comParaPack.GetValue("重试次数")); Serial_PARA.ContinueCollect = comParaPack.GetValue("连续采集") == "1" ? true : false; Serial_PARA.DataBits = Convert.ToInt32(comParaPack.GetValue("数据位")); Serial_PARA.ModbusType = (ModbusType)Enum.Parse(typeof(ModbusType), comParaPack.GetValue("MODBUS类型")); Serial_PARA.OffsetInterval = Convert.ToInt32(comParaPack.GetValue("偏移间隔")); Serial_PARA.PackMaxSize = Convert.ToInt32(comParaPack.GetValue("包最大长度")); Serial_PARA.ReadTimeout = Convert.ToInt32(comParaPack.GetValue("读超时时间")); Serial_PARA.RSTSendPreKeeyTime = Convert.ToInt32(comParaPack.GetValue("发送前RTS保持时间")); Serial_PARA.RTSSendAfterKeeyTime = Convert.ToInt32(comParaPack.GetValue("发送后RTS保持时间")); Serial_PARA.RTSEnable = comParaPack.GetValue("RTS") == "1" ? true : false; Serial_PARA.SerialCheck = (SerialCheck)Enum.Parse(typeof(SerialCheck), comParaPack.GetValue("校验")); Serial_PARA.SerialPort = comParaPack.GetValue("串口"); Serial_PARA.SimulatorSerialPort = comParaPack.GetValue("模拟器串口"); Serial_PARA.SixCommmand = comParaPack.GetValue("支持6号命令") == "1" ? true : false; Serial_PARA.SixteenCommmand = comParaPack.GetValue("支持16号命令") == "1" ? true : false;; Serial_PARA.StopBits = (StopBits)Enum.Parse(typeof(StopBits), comParaPack.GetValue("停止位")); Serial_PARA.WriteTimeout = Convert.ToInt32(comParaPack.GetValue("写超时时间")); //构造获取数据命令的字节数组,Modbus for (int i = 0; i < this.IODevices.Count; i++) { object fragment = new ModbusFragmentStore(); RealData mRealData = new RealData(); mRealData.Device = this.IODevices[i]; ScadaDeviceKernel driverDll = DeviceDrives.Find(x => x.DeviceDriverID == this.IODevices[i].DEVICE_DRIVER_ID); if (driverDll != null) { driverDll.InitKernel(IOServer, IOCommunication, this.IODevices[i], null, this.IODevices[i].DriverInfo); //IO_DEVICE_ADDRESS中存储的是DTU编号 mRealData.SlaveId = this.IODevices[i].IO_DEVICE_ADDRESS; //数据库中系统编号 mRealData.DEVICEID = this.IODevices[i].IO_DEVICE_ID; //获取下发命令的参数,注意此次要进心分段存储,因为modbus一次不能超过123个寄存器地址 mRealData.Fragment = (ModbusFragmentStore)fragment; RealDevices.Add(mRealData); } } } return(true); }
//由于此处Para里面设置的可能是不同命令的IO参数,所以需要返回不同命令的实时获取的数据,此处不需要返回Byte字节数组 public List <byte[]> GetDataCommandBytes(IO_SERVER server, IO_COMMUNICATION Communication, IO_DEVICE device, List <IO_PARA> paras, IO_PARA currentpara, ref object sender) { List <byte[]> cmmdBytes = new List <byte[]>(); //必须Read的IO参数 List <ModbusFragmentStore> modbusCodes = new List <ModbusFragmentStore>(); for (int i = 0; i < paras.Count; i++) { ParaPack paraPack = new ParaPack(paras[i].IO_PARASTRING); if (!modbusCodes.Exists(x => x.StoredCode == paraPack.GetValue("内存区")) && paraPack.GetValue("内存区") != "") { ModbusFragmentStore stored = new ModbusFragmentStore(); stored.StoredCode = paraPack.GetValue("内存区"); stored.Fragments = new List <ModbusFragment>(); stored.Units = new List <ushort>(); modbusCodes.Add(stored); } paraPack.Dispose(); paraPack = null; } for (int i = 0; i < paras.Count; i++) { ParaPack paraPack = new ParaPack(paras[i].IO_PARASTRING); if (paraPack.GetValue("内存区") != "") { if (modbusCodes.Exists(x => x.StoredCode == paraPack.GetValue("内存区")) && paraPack.GetValue("内存区") != "") { ModbusFragmentStore stored = modbusCodes.Find(x => x.StoredCode == paraPack.GetValue("内存区")); if (paraPack.GetValue("偏置") != "") { ushort offset = 0; if (ushort.TryParse(paraPack.GetValue("偏置"), out offset)) { if (!stored.Units.Contains(offset)) { stored.Units.Add(offset); } } } } } } ModbusFragmentStore mainStored = new ModbusFragmentStore(); //由于modbus获取寄存器最大数量是124个,所以要进行分段,最大线圈数量是1999个 foreach (ModbusFragmentStore stored in modbusCodes) { stored.MakeFragment(); mainStored.Fragments.AddRange(stored.Fragments); } //获取要解析的命令 sender = mainStored; return(cmmdBytes); }
protected override bool InitCommunicateKernel(IO_SERVER server, IO_COMMUNICATION communication, List <IO_DEVICE> ioDevices, SCADA_DRIVER driver) { if (IsCreateControl) { CommunicationControl = new Modbus_UDP_Ctrl(); if (communication != null) { CommunicationControl.SetUIParameter(communication.IO_COMM_PARASTRING); } } Udp_PARA = new Modbus_TCP_PARA(); if (communication != null) { TcpParaPack = new ParaPack(communication.IO_COMM_PARASTRING); Udp_PARA.CollectFaultsInternal = Convert.ToInt32(TcpParaPack.GetValue("重试间隔")); Udp_PARA.CollectFaultsNumber = Convert.ToInt32(TcpParaPack.GetValue("重试次数")); Udp_PARA.ContinueCollect = TcpParaPack.GetValue("重试") == "1" ? true : false; Udp_PARA.LocalTCP_Port = TcpParaPack.GetValue("本地端口"); Udp_PARA.LocalTCP_IP = TcpParaPack.GetValue("本地IP"); Udp_PARA.SimulatorTCP_Port = TcpParaPack.GetValue("模拟设备端口"); Udp_PARA.SimulatorTCP_IP = TcpParaPack.GetValue("模拟设备IP"); Udp_PARA.WriteTimeout = int.Parse(TcpParaPack.GetValue("写超时时间")); Udp_PARA.ReadTimeout = int.Parse(TcpParaPack.GetValue("读超时时间")); Udp_PARA.WriteBufferSize = int.Parse(TcpParaPack.GetValue("写缓存")); Udp_PARA.ReadBufferSize = int.Parse(TcpParaPack.GetValue("读缓存")); //构造获取数据命令的字节数组,Modbus for (int i = 0; i < this.IODevices.Count; i++) { object fragment = new ModbusFragmentStore(); RealData mRealData = new RealData(); mRealData.Device = this.IODevices[i]; ScadaDeviceKernel driverDll = DeviceDrives.Find(x => x.DeviceDriverID == this.IODevices[i].DEVICE_DRIVER_ID); if (driverDll != null) { driverDll.InitKernel(IOServer, IOCommunication, this.IODevices[i], null, this.IODevices[i].DriverInfo); //IO_DEVICE_ADDRESS中存储的是DTU编号 mRealData.SlaveId = this.IODevices[i].IO_DEVICE_ADDRESS; //数据库中系统编号 mRealData.DEVICEID = this.IODevices[i].IO_DEVICE_ID; //获取下发命令的参数,注意此次要进心分段存储,因为modbus一次不能超过123个寄存器地址 //mRealData.ReadSendByte = driverDll.GetDataCommandBytes(this.IOServer, this.IOCommunication, this.IODevices[i], this.IODevices[i].IOParas, null, ref fragment); } mRealData.Fragment = (ModbusFragmentStore)fragment; RealDevices.Add(mRealData); } } return(true); }
private bool RequestData(IO_DEVICE device, RealData realData, out string error, ModbusFragmentStore fragmentstore) { error = ""; try { if (udpClient != null) { //分段读取数据,如果是读取整个寄存器的话,一次只能最多读取123个, //如果是读取线圈的话最大只能读取1999个,因此要分段进行数据的读取 List <byte> allbytes = new List <byte>(); try { for (int i = 0; i < fragmentstore.Fragments.Count; i++) { ModbusFragment fragment = fragmentstore.Fragments[i]; switch (fragment.Code) { case "01": // 01和05是一个码 可写可读 { //返回的线圈状态,由于线圈是按位操作,转换也是按位转换 Task <bool[]> result = master.ReadCoilsAsync(byte.Parse(device.IO_DEVICE_ADDRESS), fragment.StartRegister, fragment.RegisterNum); byte[] bytes = ModbusConvert.BoolToByte(result.Result); fragment.StartIndex = allbytes.Count; fragment.Length = bytes.Length; allbytes.AddRange(bytes); } break; case "02": //只读属性 { //返回的线圈状态 Task <bool[]> result = master.ReadInputsAsync(byte.Parse(device.IO_DEVICE_ADDRESS), fragment.StartRegister, fragment.RegisterNum); byte[] bytes = ModbusConvert.BoolToByte(result.Result); fragment.StartIndex = allbytes.Count; fragment.Length = bytes.Length; allbytes.AddRange(bytes); } break; case "03": //HR保持寄存器,可写可读 { //返回的数据全部是ushort 需要将ushort 转换为byte在进行传递 Task <ushort[]> result = master.ReadHoldingRegistersAsync(byte.Parse(device.IO_DEVICE_ADDRESS), fragment.StartRegister, fragment.RegisterNum); byte[] bytes = ModbusConvert.Ushorts2Bytes(result.Result); fragment.StartIndex = allbytes.Count; fragment.Length = bytes.Length; allbytes.AddRange(bytes); } break; case "04": //只读属性 { //返回的数据全部是ushort 需要将ushort 转换为byte在进行传递 Task <ushort[]> result = master.ReadInputRegistersAsync(byte.Parse(device.IO_DEVICE_ADDRESS), fragment.StartRegister, fragment.RegisterNum); byte[] bytes = ModbusConvert.Ushorts2Bytes(result.Result); fragment.StartIndex = allbytes.Count; fragment.Length = bytes.Length; allbytes.AddRange(bytes); } break; } } } catch { //读取异常处理 this.DeviceStatus(this.IOServer, this.IOCommunication, device, null, "0");//tag为1表示上线,如果为0表示下线 } //将数据返回到采集客户端 if (allbytes.Count > 0) { device.IO_DEVICE_STATUS = 1; ReceiveData(this.IOServer, this.IOCommunication, device, allbytes.ToArray(), DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), fragmentstore); //设置设备状态 this.DeviceStatus(this.IOServer, this.IOCommunication, device, null, "1");//tag为1表示上线,如果为0表示下线 } else { device.IO_DEVICE_STATUS = 0; //设置设备状态 this.DeviceStatus(this.IOServer, this.IOCommunication, device, null, "0");//tag为1表示上线,如果为0表示下线 } } return(true); } catch { return(false); } }
/// <summary> /// 解析数据 /// </summary> /// <param name="server"></param> /// <param name="Communication"></param> /// <param name="device"></param> /// <param name="para"></param> /// <param name="datas"></param> /// <param name="datatime"></param> /// <param name="sender"></param> /// <returns></returns> protected override IOData Analysis(IO_SERVER server, IO_COMMUNICATION Communication, IO_DEVICE device, IO_PARA para, byte[] datas, DateTime datatime, object sender) { if (datas.Length > 0 && sender != null && para != null) { ParaPack paraPack = new ParaPack(para.IO_PARASTRING); ModbusFragmentStore modbusStore = (ModbusFragmentStore)sender; IOData data = new IOData(); data.CommunicationID = Communication.IO_COMM_ID; data.ID = device.IO_DEVICE_ADDRESS; data.ParaName = para.IO_NAME; data.ServerID = server.SERVER_ID; data.Date = DateTime.Now; Modbus_Type dataType = (Modbus_Type)Enum.Parse(typeof(Modbus_Type), paraPack.GetValue("数据类型")); switch (dataType) { case Modbus_Type.单精度浮点数32位: data.DataType = typeof(float); break; case Modbus_Type.双精度浮点数64位: data.DataType = typeof(double); break; case Modbus_Type.字符型: data.DataType = typeof(string); break; case Modbus_Type.无符号整数16位: data.DataType = typeof(UInt16); break; case Modbus_Type.无符号整数32位: data.DataType = typeof(UInt32); break; case Modbus_Type.无符号整数8位: data.DataType = typeof(byte); break; case Modbus_Type.符号整数16位: data.DataType = typeof(Int16); break; case Modbus_Type.符号整数8位: data.DataType = typeof(sbyte); break; case Modbus_Type.符号整数32位: data.DataType = typeof(int); break; } data.datas = datas; data.ParaString = para.IO_PARASTRING; //获取数据值高八位,低八位 int startaddr = int.Parse(paraPack.GetValue("偏置")); int charsize = int.Parse(paraPack.GetValue("字节长度")); string code = paraPack.GetValue("内存区"); bool bitSave = paraPack.GetValue("按位存取") == "1" ? true : false; bool ishigh = paraPack.GetValue("存储位置") == "高八位" ? true : false; ModbusFragment fragment = modbusStore.Fragments.Find(x => x.Code == code && startaddr >= x.StartRegister && startaddr <= x.StartRegister + x.RegisterNum); if (fragment != null) { switch (code) { case "01": //线圈 { byte[] vdatas = new byte[fragment.Length]; Array.Copy(datas, fragment.StartIndex, vdatas, 0, fragment.Length); data.ParaValue = vdatas[startaddr].ToString(); } break; case "02": //线圈只读 { byte[] vdatas = new byte[fragment.Length]; Array.Copy(datas, fragment.StartIndex, vdatas, 0, fragment.Length); data.ParaValue = vdatas[startaddr].ToString(); } break; case "03": //寄存器可读可写 { //注意是否按位读取, byte[] vdatas = new byte[fragment.Length]; Array.Copy(datas, fragment.StartIndex, vdatas, 0, fragment.Length); ushort[] vals = ModbusConvert.Bytes2Ushorts(vdatas); //将字节数组转为ushort switch (dataType) { case Modbus_Type.单精度浮点数32位: { data.ParaValue = ModbusConvert.GetReal(vals, 0).ToString(); } break; case Modbus_Type.双精度浮点数64位: { data.ParaValue = ModbusConvert.GetDouble(vals, 0).ToString(); } break; case Modbus_Type.字符型: { data.ParaValue = ModbusConvert.GetString(vals, 0, charsize).ToString(); } break; case Modbus_Type.无符号整数16位: { data.ParaValue = ModbusConvert.GetUShort(vals, 0).ToString(); } break; case Modbus_Type.无符号整数32位: { data.ParaValue = ModbusConvert.GetUInt(vals, 0).ToString(); } break; case Modbus_Type.无符号整数8位: { data.ParaValue = ModbusConvert.GetSByte(vals, 0, ishigh).ToString(); } break; case Modbus_Type.符号整数16位: { data.ParaValue = ModbusConvert.GetShort(vals, 0).ToString(); } break; case Modbus_Type.符号整数8位: { data.ParaValue = ModbusConvert.GetByte(vals, 0, ishigh).ToString(); } break; case Modbus_Type.符号整数32位: { data.ParaValue = ModbusConvert.GetInt(vals, 0).ToString(); } break; } } break; case "04": //寄存器只读 { //注意是否按位读取, byte[] vdatas = new byte[fragment.Length]; Array.Copy(datas, fragment.StartIndex, vdatas, 0, fragment.Length); ushort[] vals = ModbusConvert.Bytes2Ushorts(vdatas); //将字节数组转为ushort switch (dataType) { case Modbus_Type.单精度浮点数32位: { data.ParaValue = ModbusConvert.GetReal(vals, 0).ToString(); } break; case Modbus_Type.双精度浮点数64位: { data.ParaValue = ModbusConvert.GetDouble(vals, 0).ToString(); } break; case Modbus_Type.字符型: { data.ParaValue = ModbusConvert.GetString(vals, 0, charsize).ToString(); } break; case Modbus_Type.无符号整数16位: { data.ParaValue = ModbusConvert.GetUShort(vals, 0).ToString(); } break; case Modbus_Type.无符号整数32位: { data.ParaValue = ModbusConvert.GetUInt(vals, 0).ToString(); } break; case Modbus_Type.无符号整数8位: { data.ParaValue = ModbusConvert.GetSByte(vals, 0, ishigh).ToString(); } break; case Modbus_Type.符号整数16位: { data.ParaValue = ModbusConvert.GetShort(vals, 0).ToString(); } break; case Modbus_Type.符号整数8位: { data.ParaValue = ModbusConvert.GetByte(vals, 0, ishigh).ToString(); } break; case Modbus_Type.符号整数32位: { data.ParaValue = ModbusConvert.GetInt(vals, 0).ToString(); } break; } } break; } } } return(null); }