当前位置:网站首页>Écrire La Bibliothèque de communication Modbus TCP

Écrire La Bibliothèque de communication Modbus TCP

2022-01-15 02:11:35 La lave de Rodinia

using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using MS_Entity;
using thinger.cn.DataConvertHelper;

namespace MS_UI
{
    
    public class ModbusTCPTask1
    {
    
        //Définir un objet de classe de port série
        private Socket tcpclient = null; //Définir un objet de classe de port série

        private CancellationTokenSource cts = new CancellationTokenSource();//Activer les bits de drapeau multithreadés

        public static int a;
        //Adresse de départ
        int StartAddress = 0;
        //Nombre d'erreurs
        int ErrorTimer = 0;
        //0x Liste des variables pour la zone 
        public List<Variable_Modbus> List_0x = new List<Variable_Modbus>();
        //1x Liste des variables pour la zone 
        public List<Variable_Modbus> List_1x = new List<Variable_Modbus>();
        //3x Liste des variables pour la zone 
        public List<Variable_Modbus> List_3x = new List<Variable_Modbus>();
        //4x Liste des variables pour la zone 
        public List<Variable_Modbus> List_4x = new List<Variable_Modbus>();// Pour stocker des données en temps réel 


        #region Ouverture et fermetureSocket
        /// <summary>
        /// Ouvre.TCP
        /// </summary>
        /// <param name="ip">IPAdresse</param>
        /// <param name="port">Numéro de port</param>
        /// <returns></returns>

        public bool Connect(string ip, int port)
        {
    
            tcpclient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
    
                //ParamètresSocket
                IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ip), Convert.ToInt32(port));
                tcpclient.Connect(ie);// Ouverture du port réseau 
            }
            catch (Exception)
            {
    
                return false;
            }
            Task.Run(() =>
            {
    
                Communication();
            }, cts.Token);
            return true;
        }

        #region Communication en temps réel
        private void Communication()
        {
    
            while (true)
            {
    
               foreach (StoreArea item in CommonMethods.StoreAreaList)//item:StoreType,StartReg,Length
                {
    
                    byte[] Res = null;
                    int Start = item.StartReg;//Offset StartReg="0" 
                    List<byte> ByteList = null;
                    //int Start = Convert.ToInt32(this.txt_Address.Text.Trim());
                    //int Length = Convert.ToInt32(this.txt_Length.Text.Trim());
                    switch (item.StoreType)
                    {
    
                        case "01 Coil Status(0x)":
                            Res = ReadOutputStatus(Start, item.Length);
                            if (Res != null)
                            {
    
                                ErrorTimer = 0;
                                ByteList.AddRange(Res);

                            }
                            //Analyse
                            int length = item.Length % 8 == 0 ? item.Length / 8 : item.Length / 8 + 1;
                            if (ByteList.Count == length)
                            {
    
                                AnalyseData_0x(ByteList);
                            }
                            break;


                        case "03 Holding Register(4x)":
                            ByteList = new List<byte>();
                            Res = ReadKeepReg(Start, item.Length);
                            if (Res != null)
                            {
    
                                ErrorTimer = 0;
                                ByteList.AddRange(Res);//232Octets
                            }
                            else
                            {
    
                                ErrorTimer += 1;
                            }

                            a = ByteList.Count;
                            if (ByteList.Count == item.Length * 2)//Point d'arrêt
                            {
    
                                AnalyseData_4x(ByteList);//ByteList:232Octets
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
 
        }
        #endregion

        

        /// <summary>
        /// FermerSocket
        /// </summary>
        /// <returns></returns>
        public bool Disconnect()
        {
    
            if (cts!=null)
            {
    
                cts.Cancel();
            }
            if (tcpclient != null)
            {
    
                tcpclient.Close();
                return true;
            }
            else
            {
    
                return false;
            }

        }
        #endregion

        #region  La partition se résout en entier et en virgule flottante 


        private void AnalyseData_0x(List<byte> ByteList)
        {
    
            if (ByteList != null && ByteList.Count > 0)
            {
    
                foreach (Variable_Modbus item in this.List_0x)
                {
    
                    int totalIndex = int.Parse(item.Address) - StartAddress;
                    int ByteIndex = totalIndex / 8;
                    int BitIndex = totalIndex % 8;
                    switch (item.DataType)
                    {
    
                        case "Bool":
                            string ByteStr = Convert.ToInt32(Convert.ToString(Convert.ToInt32(ByteList[ByteIndex]), 2)).ToString("0#######");
                            CommonMethods.CurrentValue[item.VarName] = ByteStr.Substring(7 - BitIndex, 1);
                            break;
                        default:
                            break;
                    }
                }
            }

        }

        private void AnalyseData_4x(List<byte> ByteList)
        {
    
            int StartByte;
            byte[] Res = null;
            if (ByteList != null && ByteList.Count > 0)//ByteList Pour toutes les variables 232Octets
            {
    
                //List_4x PourStoreAreaPour"04 Input Register(3x)", C'est l'équivalent du filtrage 
                foreach (Variable_Modbus item in this.List_4x)
                {
    
                    switch (item.DataType)
                    {
    
                        case "Float":
                            //AddressL'offset estVariable_ModbusMoyenne,Filtré,4 Les variables de zone sont stockées dans List_4x
                            StartByte = int.Parse(item.Address) * 2;
                            //Res = new byte[4] { ByteList[StartByte], ByteList[StartByte + 1], ByteList[StartByte + 2], ByteList[StartByte + 3] };
                            //CommonMethods.CurrentValue[item.VarName] = Convert.ToDouble(MS_Entity.Double.BytetoFloatByPoint(Res)).ToString("f1");

                            byte[] bytelib = ByteList.ToArray();
                            float floatlib = FloatLib.GetFloatFromByteArray(bytelib, StartByte);
                            CommonMethods.CurrentValue[item.VarName] = Convert.ToDouble(floatlib).ToString("f1"); //floatlib.ToString();
                            break;
                        case "Unsigned":
                            StartByte = int.Parse(item.Address) * 2;
                            Res = new byte[2] {
     ByteList[StartByte], ByteList[StartByte + 1] };
                            CommonMethods.CurrentValue[item.VarName] = MS_Entity.Int.FromByteArray(Res).ToString();
                            break;
                        default:
                            break;
                    }
                }
            }
        }
        #endregion


        #region TCPExplication détaillée du message



        //TCP Aucun événement reçu 
        /* TCPFormat du message pour: Demande: byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7] byte[8] byte[9] byte[10] byte[11] 12Octets byte[0] byte[1]: Numéro du message---------N'importe quoi., Les deux premiers mots des données retournées par le serveur sont les mêmes que celui - ci  byte[2] byte[3]:modbusIdentification,Obligatoire0C'est tout. byte[4] byte[5]: Les indications sont rangées dans byte[5] Nombre de tous les octets suivants , C'est la longueur totale  6 byte[6]:Numéro de la station,PourTCPEn termes d'accord,, Certaines situations n'ont pas d'importance , Vous pouvez spécifier ,PourrtuEtasciiDis, Vous devez sélectionner le numéro de station de l'appareil . byte[7]:Code de fonction byte[8] byte[9]:Adresse de départ byte[10] byte[11]: Spécifiez la longueur des données à lire  Envoyer:  L'heure de réception des données ,Ignorer automatiquement,Donc les données retournées sont 00 00 00 00 00 04 FF 01 01 00 Total général10Données en octets byte[0] byte[1] : Numéro du message, Quand on a écrit les instructions d'envoi ,Combien?, C'est combien? . byte[2] byte[3]:  Tout doit être 0,Ça veut dire que c'estmodbus Communications byte[4] byte[5]:Indicationsbyte[5] Tous les octets suivants , Vous comptez pour voir si 4- Oui.?Donc voici00 04, S'il y a un 100- Oui.,Alors c'est ici. 00 64 byte[6]:Numéro de la station, On a écrit FF, Donc ici, c'est FF byte[7]:Code de fonction, On a déjà écrit 01Code de fonction pour,Ici aussi.01, Conformément aux instructions que nous avons envoyées  byte[8]: Indicationsbyte[8] Nombre d'octets suivis , Parce que suivre byte[8] Ce qui suit sont des données réelles , Le résultat final que nous voulons est byte[8]Derrière byte[9]:Données réelles, Ça doit être ce qu'on veut vraiment ,Nous en connaissons un.byteOui.8Bits,  Mais nous n'avons lu qu'un seul bit de données , Toutes les valeurs valides ici sont juste byte[9]Le plus bas de,Le binaire est 0000 0000  On voit que le plus bas est 0, Donc l'adresse que nous avons finalement lue 0 La bobine est cassée . */
        #endregion

        #region Lire la bobine de sortie Fonction0x01
        /// <summary>
        /// Lire la bobine de sortie Fonction0x01
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        public byte[] ReadOutputStatus(int iAddress, int iLength)
        {
    
            byte[] Result = null;
            // Message d'envoi d'épissage 
            MS_Entity.ByteArray byteArray = new MS_Entity.ByteArray(12);
            byteArray.Add(new byte[]
            {
    
            0,0,0,0,0,6,1,1
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)((iLength - iLength % 256) / 256));
            byteArray.Add((byte)(iLength % 256));
            //Envoyer un message
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //Réception du message
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);

            // Message de jugement 
            int length = 0;
            if (iLength % 8 == 0)
            {
    
                length = iLength / 8;
            }
            else
            {
    
                length = iLength / 8 + 1;
            }
            if (length == data[8])
            {
    
                //Analyser le message
                Result = ByteMsgToRes(data, 9, length);
            }
            return Result;
        }
        #endregion

        #region  Bobine de sortie forcée  Code de fonction0x05
        /// <summary>
        ///  Bobine de sortie forcée  Code de fonction0x05
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="Value"></param>
        /// <returns></returns>
        public bool ForceOnOff(int iAddress, string Value)
        {
    
            byte[] Result = null;
            // Message d'envoi d'épissage 
            MS_Entity.ByteArray byteArray = new MS_Entity.ByteArray(12);
            byteArray.Add(new byte[]
            {
    
            0,0,0,0,0,6,1,5
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            if (Value == "1" | Value.ToUpper() == "TRUE")
            {
    
                byteArray.Add(0xFF);
            }
            else
            {
    
                byteArray.Add(0);
            }
            byteArray.Add(0);
            //Envoyer un message
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //Réception du message
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);
            //Analyser le message
            Result = ByteMsgToRes(data, 0, 12);
            // Message de jugement 
            if (Result.ToString() == byteArray.array.ToString())
            {
    
                return true;
            }
            else
            {
    
                return false;
            }
        }
        #endregion

        #region Lire le registre de conservation Code de fonction0x03
        /// <summary>
        /// Lire le registre de conservation Code de fonction0x03
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="iLength"></param>
        /// <returns></returns>
        public byte[] ReadKeepReg(int iAddress, int iLength)
        {
    
            //byte[] Result = null;
             Message d'envoi d'épissage  12Octets
            //ByteArray byteArray = new ByteArray(12);
            //byteArray.Add(new byte[]
            //{
    
            //0,0,0,0,0,6,1,3 // Le numéro de la station est 1,  Le Code de fonction est 3
            //});
            //byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            //byteArray.Add((byte)(iAddress % 256));
            //byteArray.Add((byte)((iLength - iLength % 256) / 256));
            //byteArray.Add((byte)(iLength % 256));
            Envoyer un message
            //tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            Réception du message 9Octets
            //byte[] data = new byte[512];
            //tcpclient.Receive(data, 512, SocketFlags.None);

             Message de jugement 
            //int length = iLength * 2;
            //if (length == data[8])
            //{
    
            // //Analyser le message
            // Result = ByteMsgToRes(data, 9, length);
            //}
            //return Result;

            //Message d'épissage
            List<byte> SendCommand = new List<byte>();
            SendCommand.AddRange(new byte[] {
     0, 0, 0, 0 });//Identificateur ,4Octets
            SendCommand.AddRange(new byte[] {
     0, 6 });//Longueur, 2Octets
            SendCommand.Add(1);//Numéro de station esclave,1Octets
            SendCommand.Add(0x03);//Code de fonction,1Octets
            SendCommand.Add((byte)((iAddress - iAddress % 256) / 256));//1Octets
            SendCommand.Add((byte)(iAddress % 256));//1Octets
            SendCommand.Add((byte)((iLength - iLength % 256) / 256));//1Octets
            SendCommand.Add((byte)(iLength % 256));//1Octets Total12Octets
            //Envoyer un message
            tcpclient.Send(SendCommand.ToArray(), SocketFlags.None);
            //Réception du message
            byte[] buffer = new byte[512];
            int count = tcpclient.Receive(buffer, SocketFlags.None);
            // Message de jugement 
            if (count == 2 * iLength + 9)
            {
    
                // Obtenir un vrai message ,  Capture d'un tableau d'octets 
                byte[] des = new byte[count];
                byte[] res = new byte[2 * iLength];
                Array.Copy(buffer, 0, des, 0, count);//DebufferCopier versdes, De0C'est parti., Copiercount- Oui.
                //Vérification secondaire
                if (des[7] == 0x03 && des[8] == 2 * iLength)//iLength Nombre de registres,2*iLengthNombre d'octets,Un registre2Octets
                {
    
                    // Capture de tableau d'octets 
                    Array.Copy(des, 9, res, 0, 2 * iLength);

                    // Ordre de rotation 
                    //List<ushort> result = new List<ushort>(); //ushort 16Bit entier non signé
                    //for (int i = 0; i < res.Length; i+=2)
                    //{
    
                    // result.Add(Convert.ToUInt16(res[i] * 256 + res[i + 1]));// Tourner haut et bas 
                    //} //Res[i] = Convert.ToByte(Result[i], 16) Méthode de référence
                    Dans des conditions normales, Réponse de l'esclave  Le format est Nombre d'octets, Registre haut de gamme , Statut du registre ,... Registre haut de gamme , Statut du registre ,
                    //ushort[] resu = new ushort[res.Length];
                    //for (int i = 0; i < res.Length; i++)
                    //{
    
                    // resu[i] = result[i];
                    //}

                    //byte[] res1 = Int.ToByteArray(Convert.ToInt16(resu));
                    //return res1;
                    //byte[] res1 = BitConverter.GetBytes(res.Length).Reverse().ToArray();
                }
                return res;
            }
            else
                return null;
        }
        #endregion

        #region  Preset Single Register  Code de fonction0x06
        /// <summary>
        ///  Preset Single Register  Code de fonction0x06
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="SetValue"></param>
        /// <returns></returns>
        public bool PreSetKeepReg(int iAddress, UInt16 SetValue)
        {
    
            byte[] Result = null;
            // Message d'envoi d'épissage 
            MS_Entity.ByteArray byteArray = new MS_Entity.ByteArray(12);
            byteArray.Add(new byte[]
            {
    
            0,0,0,0,0,6,1,6
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add((byte)((SetValue - SetValue % 256) / 256));
            byteArray.Add((byte)(SetValue % 256));

            //Envoyer un message
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //Réception du message
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);
            //Analyser le message
            Result = ByteMsgToRes(data, 0, 12);
            // Message de jugement 
            if (Result.ToString() == byteArray.array.ToString())
            {
    
                return true;
            }
            else
            {
    
                return false;
            }
        }
        #endregion

        #region  Preset double word Register  Code de fonction0x10
        /// <summary>
        ///  Preset double word Register  Code de fonction0x10
        /// </summary>
        /// <param name="iAddress"></param>
        /// <param name="SetValue"></param>
        /// <returns></returns>
        public bool PreSetFloatReg(int iAddress, float SetValue)
        {
    
            byte[] Result = null;
            // Message d'envoi d'épissage 
            MS_Entity.ByteArray byteArray = new MS_Entity.ByteArray(12);
            byteArray.Add(new byte[]
            {
    
            0,0,0,0,0,11,1,16
            });
            byteArray.Add((byte)((iAddress - iAddress % 256) / 256));
            byteArray.Add((byte)(iAddress % 256));
            byteArray.Add(new byte[]
            {
    
            0,2,4
            });
            byte[] bSetValue = new byte[4];
            bSetValue = BitConverter.GetBytes(SetValue);
            byteArray.Add(bSetValue[1]);
            byteArray.Add(bSetValue[0]);
            byteArray.Add(bSetValue[3]);
            byteArray.Add(bSetValue[2]);
            //Envoyer un message
            tcpclient.Send(byteArray.array, byteArray.array.Length, SocketFlags.None);
            //Réception du message
            byte[] data = new byte[512];
            tcpclient.Receive(data, 512, SocketFlags.None);
            //Analyser le message
            Result = ByteMsgToRes(data, 0, 12);
            byte[] SendRes = ByteMsgToRes(byteArray.array, 0, 12);
            SendRes[6] = 6;
            // Message de jugement 
            if (Result.ToString() == SendRes.ToString())
            {
    
                return true;
            }
            else
            {
    
                return false;
            }

        }
        #endregion

        #region  Capture de tableau d'octets 
        /// <summary>
        ///  Capture de tableau d'octets 
        /// </summary>
        /// <param name="MsgByte"></param>
        /// <param name="Start"></param>
        /// <param name="Length"></param>
        /// <returns></returns>
        public byte[] ByteMsgToRes(byte[] MsgByte, int Start, int Length)
        {
    
            byte[] Result = null;
            if (MsgByte != null && MsgByte.Length > 0)
            {
    
                Result = new byte[Length];
                for (int i = 0; i < Length; i++)
                {
    
                    Result[i] = MsgByte[i + Start];
                }
            }
            return Result;
        }
        #endregion


    }
}

版权声明
本文为[La lave de Rodinia]所创,转载请带上原文链接,感谢
https://chowdera.com/2022/01/202201080558307051.html

随机推荐