예제 #1
0
        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());
        }
예제 #2
0
        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);
        }
예제 #3
0
        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");
            }
        }
예제 #4
0
 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))));
 }
예제 #5
0
        /// <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));
            }
        }
예제 #6
0
        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;
            }
        }
예제 #7
0
        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);
            }
        }
예제 #9
0
 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);
     }
 }
예제 #10
0
        /// <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);
            }
        }
예제 #11
0
 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;
     }
 }
예제 #12
0
        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 });
        }
예제 #13
0
 public static Int16[] SplitComplexValue(float value, ModbusDataType valueType)
 {
     throw new NotImplementedException();
 }
예제 #14
0
        public static MdbusMessage Decode(string message, bool useModiconFormat, ModbusMessageMode mode, ModbusDataType dataType)
        {
            MdbusMessage mdbusMessage = new MdbusMessage();

            mdbusMessage.DecodeMessage(message, useModiconFormat, mode, dataType);
            return(mdbusMessage);
        }
예제 #15
0
        /// <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;
                }
            }
        }
예제 #16
0
 private DataStoreEventArgs(ushort startAddress, ModbusDataType modbusDataType)
 {
     this.StartAddress   = startAddress;
     this.ModbusDataType = modbusDataType;
 }
예제 #17
0
 internal static ushort GetCountForValueType(ModbusDataType valueType)
 {
     return(RegistryCountsForValue.GetValueOrDefault(valueType));
 }