public string GetParament() { ParaPack para = new ParaPack(); if (cbo_functioncode.SelectedItem != null) { ModbusFunctionCode funCode = (ModbusFunctionCode)cbo_functioncode.SelectedItem; para.AddItem("内存区", funCode.Code); } para.AddItem("偏置", this.ndOffset.Text.Trim()); if (cbo_StoreType.SelectedItem != null) { ModbusDataType datatype = (ModbusDataType)cbo_StoreType.SelectedItem; para.AddItem("数据类型", datatype.DataType.ToString()); } if (cbo_datatype.SelectedItem != null) { string datatype = (string)cbo_datatype.SelectedItem; para.AddItem("存储位置", datatype.ToString()); } para.AddItem("字节长度", this.ndCharSize.Text.Trim() == ""?"0": this.ndCharSize.Text.Trim()); para.AddItem("按位存取", this.cbPosition.Checked?"1":"0"); para.AddItem("数据位", this.ndPosition.Text.Trim() == ""?"0": this.ndPosition.Text.Trim()); return(para.ToString()); }
internal static DataStoreEventArgs CreateDataStoreEventArgs <T>(ushort startAddress, ModbusDataType modbusDataType, IEnumerable <T> data) { if (data == null) { throw new ArgumentNullException("data"); } DataStoreEventArgs eventArgs; if (typeof(T) == typeof(bool)) { var a = new ReadOnlyCollection <bool>(data.Cast <bool>().ToArray()); eventArgs = new DataStoreEventArgs(startAddress, modbusDataType) { Data = DiscriminatedUnion <ReadOnlyCollection <bool>, ReadOnlyCollection <ushort> > .CreateA(a) }; } else if (typeof(T) == typeof(ushort)) { var b = new ReadOnlyCollection <ushort>(data.Cast <ushort>().ToArray()); eventArgs = new DataStoreEventArgs(startAddress, modbusDataType) { Data = DiscriminatedUnion <ReadOnlyCollection <bool>, ReadOnlyCollection <ushort> > .CreateB(b) }; } else { throw new ArgumentException("Generic type T should be of type bool or ushort"); } return(eventArgs); }
public static string MergeComplexValue(byte[] values, ModbusDataType valueType, bool endianSwap = false, bool midEndianSwap = false) { //In case of adding new value type, modify endian handling logic if (midEndianSwap && (valueType == ModbusDataType.Float || valueType == ModbusDataType.Int32)) { //Mid endian swap logic Array.Reverse(values, 0, 2); Array.Reverse(values, 2, 2); } if (endianSwap) { Array.Reverse(values); } switch (valueType) { case ModbusDataType.Float: return(String.Format("{0:F3}", BitConverter.ToSingle(values))); case ModbusDataType.Int32: return(BitConverter.ToInt32(values).ToString()); default: return("Uknown value type"); } }
public void Store(ModbusDataType modbusData, ushort startAddress, IEnumerable <ushort> datas) { if (modbusData == ModbusDataType.InputRegister) { Array.Copy(datas.ToArray(), 0, Inputs, startAddress, datas.Count()); } else if (modbusData == ModbusDataType.HoldingRegister) { Array.Copy(datas.ToArray(), 0, Outputs, startAddress, datas.Count()); } else { throw new NotFiniteNumberException(); } Debug.WriteLine(modbusData); Debug.WriteLine(string.Format("{0}~:{1} >>{2}...", startAddress, datas.Count(), string.Join(" ", datas.Take(3)))); }
/// <summary> /// 数据转换,string到byte[] /// </summary> /// <param name="dataType"></param> /// <param name="value"></param> /// <returns></returns> public static BllResult <byte[]> TransferStringToBuffer(ModbusDataType dataType, string value) { try { switch (dataType) { case ModbusDataType.Bool: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(Convert.ToBoolean(value)))); case ModbusDataType.Short: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(new Int16[] { Convert.ToInt16(value) }))); case ModbusDataType.UShort: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(new UInt16[] { Convert.ToUInt16(value) }))); case ModbusDataType.Int: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(new Int32[] { Convert.ToInt32(value) }))); case ModbusDataType.UInt: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(new UInt32[] { Convert.ToUInt32(value) }))); case ModbusDataType.Long: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(new Int64[] { Convert.ToInt64(value) }))); case ModbusDataType.ULong: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(new UInt64[] { Convert.ToUInt64(value) }))); case ModbusDataType.Float: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(new Single[] { Convert.ToSingle(value) }))); case ModbusDataType.Double: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(new Double[] { Convert.ToDouble(value) }))); case ModbusDataType.String: return(BllResultFactory <byte[]> .Sucess(reverseBytesTransform.TransByte(value.PadRight(20, ' '), Encoding.ASCII))); default: return(BllResultFactory <byte[]> .Error("未识别的数据类型")); } } catch (Exception ex) { return(BllResultFactory <byte[]> .Error("转换出现问题:" + ex.Message)); } }
public void SetParament(string parastr) { ParaPack para = new ParaPack(parastr); if (para.Count > 0) { ///内存区 for (int i = 0; i < cbo_functioncode.Items.Count; i++) { ModbusFunctionCode funCode = (ModbusFunctionCode)cbo_functioncode.Items[i]; if (funCode.Code == para.GetValue("内存区")) { cbo_functioncode.SelectedIndex = i; break; } } //数据类型 for (int i = 0; i < cbo_StoreType.Items.Count; i++) { ModbusDataType datatype = (ModbusDataType)cbo_StoreType.Items[i]; if (datatype.ToString() == para.GetValue("数据类型")) { cbo_StoreType.SelectedIndex = i; break; } } //偏置 this.ndOffset.Value = para.GetValue("偏置") == "" ? 0: Convert.ToDecimal(para.GetValue("偏置")); this.ndCharSize.Value = para.GetValue("字节长度") == "" ? 0 : Convert.ToDecimal(para.GetValue("字节长度")); this.ndPosition.Value = para.GetValue("数据位") == "" ? 0 : Convert.ToDecimal(para.GetValue("数据位")); //存储位置 for (int i = 0; i < cbo_datatype.Items.Count; i++) { string datatype = (string)cbo_datatype.Items[i]; if (datatype.ToString() == para.GetValue("存储位置")) { cbo_datatype.SelectedIndex = i; break; } } //按位存取 this.cbPosition.Checked = para.GetValue("按位存取") == "1" ? true : false; } }
private void Cbo_StoreType_SelectedIndexChanged(object sender, EventArgs e) { if (cbo_StoreType.SelectedItem != null) { cbo_datatype.Visible = false; this.labelbytesize.Visible = false; this.ndCharSize.Visible = false; groupposition.Visible = false; ModbusDataType dataType = (ModbusDataType)cbo_StoreType.SelectedItem; labelStoredDesc.Text = dataType.Description; switch (dataType.DataType) { case Modbus_Type.无符号整数8位: cbo_datatype.Visible = true; break; case Modbus_Type.符号整数8位: cbo_datatype.Visible = true; break; case Modbus_Type.字符型: cbo_datatype.Visible = false; this.labelbytesize.Visible = true; this.ndCharSize.Visible = true; break; case Modbus_Type.无符号整数16位: this.groupposition.Visible = true; break; case Modbus_Type.符号整数16位: this.groupposition.Visible = true; break; default: cbo_datatype.Visible = false; this.labelbytesize.Visible = false; ndCharSize.Visible = false; this.groupposition.Visible = false; break; } } }
public static IModbusDataDecoder CreateDecoder(FunctionCode functionCode, ModbusDataType dataType) { switch (dataType) { case var _ when functionCode == FunctionCode.ReadCoils || functionCode == FunctionCode.ReadInputs: return(new DiscreteBoolDecoder()); case ModbusDataType.Int16: return(new Int16Decoder()); case ModbusDataType.Int32: return(new Int32Decoder()); case ModbusDataType.Float: return(new FloatDecoder()); default: throw new ArgumentOutOfRangeException(nameof(dataType), dataType, null); } }
private void Decode() { try { ModbusMessageMode mode = radioButtonMaster.Checked ? ModbusMessageMode.Master : ModbusMessageMode.Slave; ModbusDataType dataType = ModbusDataType.Float; if (radioButtonInts.Checked) { dataType = ModbusDataType.Integer; } else if (radioButtonLongInts.Checked) { dataType = ModbusDataType.LongInt; } MdbusMessage mdbusMessage = MdbusMessage.Decode(txtInput.Text, checkBoxModiconFormat.Checked, mode, dataType); resultBox.Text = mdbusMessage.ToString(true) + resultBox.Text; } catch (Exception e) { MessageBox.Show("Error decoding input string. Message:" + Environment.NewLine + e.Message, "Decoding Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }
/// <summary> /// 根据数据类型获取其对应的字节长度 /// </summary> /// <param name="type"></param> /// <returns></returns> public static ushort GetByteSize(ModbusDataType type) { switch (type) { case ModbusDataType.Bool: //一个寄存器是16位,可以包含16个Bool量,所以Bool类型占用2个字节 return(2); case ModbusDataType.Short: return(2); case ModbusDataType.UShort: return(2); case ModbusDataType.Int: return(4); case ModbusDataType.UInt: return(4); case ModbusDataType.Long: return(8); case ModbusDataType.ULong: return(8); case ModbusDataType.Float: return(4); case ModbusDataType.Double: return(8); case ModbusDataType.String: return(1); default: return(2); } }
private void cbDataType_SelectedIndexChanged(object sender, EventArgs e) { switch (cbDataType.SelectedIndex) { case 0: cbbTxtVar.Items.Clear(); cbbTxtVar.Items.AddRange(new object[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39}); modbusDataType = ModbusDataType.SignedInt; break; case 1: cbbTxtVar.Items.Clear(); cbbTxtVar.Items.AddRange(new object[] { 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79 }); modbusDataType = ModbusDataType.Float; break; case 2: cbbTxtVar.Items.Clear(); cbbTxtVar.Items.AddRange(new object[] { 0 }); modbusDataType = ModbusDataType.UnsignedShort; break; default: break; } }
private static Int16[] SplitComplexValue(string value, ModbusDataType valueType) { byte[] bf; //float f = float.Parse(value); switch (valueType) { case ModbusDataType.Float: bf = BitConverter.GetBytes(float.Parse(value)); break; case ModbusDataType.Int32: bf = BitConverter.GetBytes(Convert.ToInt32(value)); break; default: return(null); } //At this point all complex values used need only 2 registries (2 Int16) var p1 = BitConverter.ToInt16(bf.SubArray(0, 2), 0); var p2 = BitConverter.ToInt16(bf.SubArray(2, 2), 0); return(new Int16[] { p1, p2 }); }
public static Int16[] SplitComplexValue(float value, ModbusDataType valueType) { throw new NotImplementedException(); }
public static MdbusMessage Decode(string message, bool useModiconFormat, ModbusMessageMode mode, ModbusDataType dataType) { MdbusMessage mdbusMessage = new MdbusMessage(); mdbusMessage.DecodeMessage(message, useModiconFormat, mode, dataType); return(mdbusMessage); }
/// <summary> /// Decodes a message string from Mdbus.exe (Calta Software) /// </summary> /// <param name="message">Message string from Mdbus Monitor logging, starting with the Slave ID</param> /// <param name="useModiconFormat">True if Modicon format for Float or LongInt are used (the least significant bytes are sent in the first register and the most significant bytes in the second register of a pair)</param> /// <param name="mode">Set the mode to Master or Slave. Used to distinguish between request and response when decoding</param> /// <param name="dataType">Set the data type to decode, either float, int or long int (default is float)</param> /// <example> /// /// Example responses: /// /// 3 (0x03) Read Holding Registers /// SlaveID=1, FC=0x03, ByteCount=0x10 (16), values: 60 3A 46 .... /// 01 03 10 60 3A 46 33 69 89 44 57 33 CE 43 06 8B 59 3B 72 C4 8E /// /// 4 (0x04) Read Input Registers /// SlaveID=1, FC=0x04, ByteCount=0x10 (16), values: 60 3A 46 .... /// 01 04 10 60 3A 46 33 69 89 44 57 33 CE 43 06 8B 59 3B 72 C4 8E /// /// 16 (0x10) Write Multiple Registers /// SlaveID=1, FC=0x10 (16), StartAddr=0x0064 (100), Registers=0x0032 (50), ByteCount=0x64 (100), Values:48 9C 1C ... /// 01 10 00 64 00 32 64 48 9C 1C B6 48 94 27 C8 48 98 95 47 48 87 F7 BD 42 AC 07 2B 42 AE 57 91 42 AC 89 5E 42 AF DE 29 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 45 C9 F0 4D 45 CA 95 4D 45 C9 23 FE 45 C9 64 DF 42 0A 66 66 42 0C CC CD 42 13 33 33 42 11 33 33 42 9E CC CD 9D A4 /// </example> /// <returns></returns> /// private void DecodeMessage(string message, bool useModiconFormat, ModbusMessageMode mode, ModbusDataType dataType) { if (!message.Contains(' ')) { // TODO: create string array from text without spaces. throw new ArgumentException("Given message string does not contain spaces. Must use a valid string from Mdbus Monitor log"); } OriginalMessageString = message; UseModiconFormat = useModiconFormat; MessageMode = mode; DataType = dataType; // Check if there are RX or TX in beginning MessageType = ModbusMessageType.Unknown; if (message.Trim().StartsWith("RX")) { MessageType = ModbusMessageType.Receive; message = message.Replace("RX", ""); } else if (message.Trim().StartsWith("TX")) { MessageType = ModbusMessageType.Transmit; message = message.Replace("TX", ""); } // If we are slave then a TX would be a request (from master) and RX would be a response // If we are master, then a TX would be a request (from us) and RX would be a response // By default we want to decode as response (we are slave and RX message is important) MessageRole = ModbusMessageRole.Response; if (MessageMode == ModbusMessageMode.Master && MessageType == ModbusMessageType.Transmit) { MessageRole = ModbusMessageRole.Request; } else if (MessageMode == ModbusMessageMode.Slave && MessageType == ModbusMessageType.Receive) { MessageRole = ModbusMessageRole.Request; } string[] hexValuesSplit = message.Trim().Split(' '); if (hexValuesSplit.Length > 0) { SlaveId = Convert.ToInt32(hexValuesSplit[0], 16); } if (hexValuesSplit.Length > 1) { var byteValue = Convert.ToInt16(hexValuesSplit[1], 16); FunctionCode = byteValue & 0x7F; // Ignore the first (error) bit ModbusException = ((byteValue & 0x80) == 0x80); // Use the first (error) bit if (ModbusException && (hexValuesSplit.Length > 2)) { ExceptionCode = Convert.ToInt16(hexValuesSplit[2], 16); } } if (hexValuesSplit.Length > 1) { Checksum = hexValuesSplit[hexValuesSplit.Length - 2] + hexValuesSplit[hexValuesSplit.Length - 1]; ChecksumOk = ModbusUtility.CheckModbusCRC(hexValuesSplit); } int startByte = 0; bool hasDataValues = false; switch (FunctionCode) { case 1: case 2: if (MessageRole == ModbusMessageRole.Request) { StartAddress = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 2, 2); CoilCount = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 4, 2); } else { ByteCount = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 2, 1); startByte = 3; } break; case 3: case 4: // Request and response differs (we are slave): // RX 01 03 00 00 00 2C 44 17 // TX 01 03 58 01 14 00 00 46 81 38 00 45 48 40 00 44 F1 80 00 42 47 99 9A 47 26 C9 00 47 1D 38 00 47 1D 3A 00 47 27 F8 00 43 82 F3 33 3F B3 33 33 43 2C 66 66 00 00 00 00 00 00 00 00 00 00 00 00 45 34 50 00 00 00 00 00 00 00 00 00 00 00 00 00 43 C9 80 00 41 49 99 9A 41 48 00 00 60 34 if (MessageRole == ModbusMessageRole.Response) { ByteCount = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 2, 1); startByte = 3; hasDataValues = true; } else { StartAddress = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 2, 2); RegisterCount = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 4, 2); } break; case 6: // Request and response are the same: // RX 01 06 00 00 02 FD 49 2B // TX 01 06 00 00 02 FD 49 2B StartAddress = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 2, 2); SingleRegisterValue = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 4, 2); startByte = 6; hasDataValues = true; break; case 16: // Request and response differs (we are slave): // RX 01 10 00 5B 00 10 20 00 00 3F 80 00 00 3F 80 CC CD 42 0C CC CD 41 DC 51 EC 41 2C 1E B8 40 B5 CC CD 40 F4 E1 48 40 FA FB DB // TX 01 10 00 5B 00 10 B0 16 StartAddress = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 2, 2); RegisterCount = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 4, 2); // Only request has byte count if (MessageRole == ModbusMessageRole.Request) { ByteCount = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, 6, 1); startByte = 7; hasDataValues = true; } break; default: break; } if (((FunctionCode == 1) || (FunctionCode == 2)) && (MessageRole == ModbusMessageRole.Response)) { for (int i = startByte; (i - startByte < ByteCount) && (i < hexValuesSplit.Length - 2); i++) { var byteValue = ModbusUtility.ConvertHexStringToInt(hexValuesSplit, i, 1); if (byteValue.HasValue) { Coils.Add(byteValue.Value); } } } if (hasDataValues) { switch (DataType) { case ModbusDataType.Float: // convert all float values from hex string ConvertDataToFloats(useModiconFormat, hexValuesSplit, startByte); break; case ModbusDataType.Integer: // convert all integer values from hex string ConvertDataToIntegers(hexValuesSplit, startByte); break; case ModbusDataType.LongInt: // convert all integer values from hex string ConvertDataToLongInts(useModiconFormat, hexValuesSplit, startByte); break; default: break; } } }
private DataStoreEventArgs(ushort startAddress, ModbusDataType modbusDataType) { this.StartAddress = startAddress; this.ModbusDataType = modbusDataType; }
internal static ushort GetCountForValueType(ModbusDataType valueType) { return(RegistryCountsForValue.GetValueOrDefault(valueType)); }