équivalence de vb6 en c# [Résolu]

j78330 10 Messages postés mardi 17 septembre 2013Date d'inscription 18 juillet 2016 Dernière intervention - 11 juil. 2016 à 09:26 - Dernière réponse : j78330 10 Messages postés mardi 17 septembre 2013Date d'inscription 18 juillet 2016 Dernière intervention
- 13 juil. 2016 à 11:41
Bonjour,
j'essais de recréer un programme qui était à l'origine en vb6 (visual basic ) en C # pouvez me dire
s'il est bon s'il vous plait ?
Pour communiquer avec mon appareil j'utilise le protocole de liaison suivant :
Protocol MODBUS/JBUS en mode RTU .(9600 Bds,1 bit start,8 bit de données, 1 bit stop, sans parité
(RS485). la liaison série n'étant pas la tâche la plus prioritaire de l'appareil le logiciel de liaison doit prévoir 3 essais de dialogue avant de conclure à un défaut de transmission. il est inutile et déconseillé d'interroger
l'appareil plus d'une fois toutes les 500 ms.
L'appareil peut renvoyer les 3 codes d'erreur suivant à une demande de données :
01 : Fonction non reconnue
02 : Adresse de données incorrecte
03 : Valeur des données incorrecte
Programme en vb6 :
Public Sub ModBus(c() As Byte)
    Dim Buffer
    Dim x(100) As Byte
    Dim Tentative, j As Integer
    Dim td As Double
    Dim delairep As Double
   On Error GoTo finProcedure
Err.Clear
    Tentative = 0
    Form1.MSComm1.InputLen = 0              'Lecture du buffer par 1
début:
    t = Timer
    While Abs(t - Timer) < 0.05
    Wend
    Tentative = Tentative + 1
    If Tentative > 3 Then                   'Si à la troisième interrogation la réponse est toujours erronée opération abandonnée
        Call MessageErreur(MessageMod(26), 1)
        CodeErreur = 0
        
        Exit Sub
    End If
    'test remote ADAC
    If (Fonction = 5 And AdataL = 7) Then
        x(0) = AdresADAC
    Else
        x(0) = AdresseModbus
    End If
    x(1) = Fonction
    x(2) = AdataH
    x(3) = AdataL
    x(4) = LdataH
    x(5) = LdataL
    For i = 0 To 5
        If x(i) < 0 Or x(i) > 255 Then
            CodeErreur = 2
            Exit Sub
        End If
    Next i
    Call CalculCRC(x(), 5, CrcH, CrcL)
    
    If Form1.MSComm1.PortOpen = False Then
        
        CodeErreur = 3
        Exit Sub
    End If
    Form1.MSComm1.InBufferCount = 0
    If ToxGain = True Then '???
        ToxGain = False
        Form1.MSComm1.Output = Chr(x(0)) + Chr(x(1)) + Chr(x(2)) + Chr(x(3)) + Chr(x(4)) + Chr(x(5)) + Chr(CrcL) + Chr(CrcH)
    Else
        Form1.MSComm1.Output = Chr(x(0)) + Chr(Fonction) + Chr(AdataH) + Chr(AdataL) + Chr(LdataH) + Chr(LdataL) + Chr(CrcL) + Chr(CrcH)
    End If
    
    td = Timer
    If Fonction = 3 Then
        Buffer = (2 * LdataL + 5)
    Else
        Buffer = 8
    End If
    
    Do Until Form1.MSComm1.InBufferCount >= Buffer   'Nous attendons d'avoir au moins 1 réponse
        'Debug.Print (Timer - td)
        delairep = 0.4
        If (x(2) = 0) Then
            If x(3) = 31 Then
                delairep = 4
            End If
        End If
        
        
        If (Timer - td) > delairep Then      'Si le temps de récupération des données dépasse 0.1 seconde nous sortons de la boucle
            Debug.Print "                           appel :"; AppelBloc; " inbuf= "; Form1.MSComm1.InBufferCount; "bufferdemande = "; Buffer
            DoEvents
            GoTo début
            
        End If
        If Form1.MSComm1.PortOpen = False Then  'L'utilisateur a décidé de couper la communication avec la sonde
            CodeErreur = 0
            Exit Sub
        End If
    Loop
    'Debug.Print "temps de réponse = "; (Timer - td)
     frmSequenceur.tmrMiseEnService.Enabled = True
    Buffer = Form1.MSComm1.Input
    For i = 0 To 2                              'Boucle pour récupérer les trois premiers caractères
        c(i) = AscB(MidB(Buffer, i + 1, 1))
    Next i
'Ce n'est pas la bonne adresse de l'appareil
    If Val(GetSetting(App.EXEName, "Général", "AdresseModBus", Setting)) <> AdresseModbus Then AdresseModbus = Val(GetSetting(App.EXEName, "Général", "AdresseModBus", Setting))
    If c(0) <> AdresseModbus Then
        Call MessageErreur(MessageMod(28) & AdresseModbus & MessageMod(99) & c(0), 1)
        GoTo début
    End If
'La sonde renvoi un code erreur
    If c(1) >= 128 Then
        Tentative = Tentative + 1
        If c(2) = 1 And Tentative > 3 Then Call MessageErreur(MessageMod(29), 1)
        If c(2) = 2 And Tentative > 3 Then Call MessageErreur(MessageMod(30), 1)
        If c(2) = 3 And Tentative > 3 Then Call MessageErreur(MessageMod(31), 1)
        Exit Sub
    End If
 
    On Error Resume Next
    If Fonction = 3 Then
        For j = 3 To (2 * LdataL + 4)
            c(j) = AscB(MidB(Buffer, j + 1, 1))
        Next j
        Call CalculCRC(c(), j - 3, CrcH, CrcL)
        If c(j - 1) <> CrcH Or c(j - 2) <> CrcL Then
            GoTo début
        End If
    End If
    If Fonction = 5 Or Fonction = 6 Then
        For j = 3 To 7
            c(j) = AscB(MidB(Buffer, j + 1, 1))
        Next j
        Call CalculCRC(c(), 5, CrcH, CrcL)
        If c(6) <> CrcL Or c(7) <> CrcH Then
            GoTo début
        End If
    End If
If Mid(Form1.lstInformations.List(Form1.lstInformations.ListIndex), 18, Len(Form1.lstInformations.List(Form1.lstInformations.ListIndex)) - 11) = MessageMod(26) Then
    Call MessageErreur(MessageMod(32), 0)
End If
CodeErreur = 1
Exit Sub
finProcedure:
If Err.Number <> 0 Then MsgBox "l'erreur n° " & Err.Number & " est sur venu (" & Err.Description & " ). ", vbCritical, "ERREUR !!"
Resume Next
Err.Clear
End Sub


et voici le programme qui j'ai fait en c# :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Diagnostics;
using System.Timers;
using System.Drawing;


namespace Test
{

    public static class Com
    {
        static byte[] c = new byte[100];
      public  static byte[] b = new byte[100];

        public static int AdresseModBus = 161;
        public static int Fonction;
        public static int AdataH;
        public static int AdataL;
        public static int LdataH;
        public static int LdataL;
        public static int ret = 0;
        public static int r = 0;
        public static int Demande;
 
        public static long CodeErreur;
………
……..
}
public static byte[] ModBus(byte[] c)
        {
           // byte[] b = new byte[100];
            int Tentative, j;
            double td, delairep;
            byte Buffer;
            int t;
             int crch, crcl;
           int[] crchcrcl = new int[2];

            Tentative = 0;
            Program.principale_.serialPort1.ReceivedBytesThreshold = 1;
       début:
            t = DateTime.Now.Millisecond + DateTime.Now.Millisecond;
      
            Console.Write(t - DateTime.Now.Millisecond);
         while ((t - DateTime.Now.Second) <0.05) { }
           Tentative++;
           if (Tentative > 3)
           {
               CodeErreur = 0;
               Program.principale_.Invoke(new messagecombobox(messageboxx), Program.principale_.Heure + " : Pas de réponse");

               Program.principale_.ledcom.BackColor = Color.Red;
               Application.Exit();
           }
            c[0] = (byte)AdresseModBus;
            c[1] = (byte)Fonction;
            c[2] = (byte)AdataH;
            c[3] = (byte)AdataL;
            c[4] = (byte)LdataH;
            c[5] = (byte)LdataL;
            c[6] = (byte)CalculCRC(c, 5)[1];
            c[7] = (byte)CalculCRC(c, 5)[0];
            for (int i = 0; i < 6; i++)
            {
                if (c[i] < 0 || c[i] > 255)
                    Application.Exit();
            }
            Program.principale_.serialPort1.DiscardInBuffer();
            Program.principale_.serialPort1.Write(c, 0, 8);

            if (Program.principale_.serialPort1.IsOpen == false)
            {
                CodeErreur = 3;
                Program.principale_.lstInformations.Text = Program.principale_.Heure + "Pas de réponse du boitier";
                Program.principale_.serialPort1.Close();
                Program.principale_.ledcom.BackColor = Color.Red;
                Application.Exit();
            }   
            for (int i = 0; i <=2*LdataL+5; i++)
            {
                try
                {
              x[i] = (byte)Program.principale_.serialPort1.ReadByte();             
                }
                catch { break; }
            }
            td = ((double)DateTime.Now.TimeOfDay.TotalSeconds);
           if (Fonction == 3)
           {
               Buffer = Convert.ToByte(2 * LdataL + 5);
           }
       else
           {
               Buffer = 8;
           }
           int nbreOctetsRecu;
           do
           {
               delairep = 1;
               if (c[2] == 0)
               {
                   if (c[3] == 98)
                       delairep = 4;
               }
               Console.WriteLine(((double)DateTime.Now.TimeOfDay.TotalSeconds) - td);
               if ((((double)DateTime.Now.TimeOfDay.TotalSeconds) - td) > delairep)
               {
                   Debug.Print("   inbuf = " + Program.principale_.serialPort1.BytesToRead + " bufferdemande = " + Buffer);
                   Application.DoEvents();
                   goto début;
               }
               if (Program.principale_.serialPort1.IsOpen == false)
               {
                   CodeErreur = 0;
                   Program.principale_.lstInformations.Text = "Vous avez coupez la communication";
                   Application.Exit();
               }
               nbreOctetsRecu = Program.principale_.serialPort1.BytesToRead;
           }
           while (nbreOctetsRecu < Buffer);
           Buffer = (byte)Program.principale_.serialPort1.ReadByte();

           for (int i = 0; i <= 2; i++)
           {
               c[i] = (byte)("" + Buffer).ElementAt(i + 1);
           }
           if (c[0] != AdresseModBus)
           {
             MessageBox.Show("Ce n'est pas la bonne addresse" + " " + AdresseModBus + " " + c[0]);
               goto début;
           }
           if (c[1] >= 128)
           {
               Tentative++;
               Program.principale_.lstInformations.Text = "Pas de réponse du boitier";
           }
           if (Fonction == 3) // permet de lire des mots 16 bits
           {
               for (j = 3; j <= (2 * LdataL + 4); j++)
                   x[j] = (byte)("" + Buffer).ElementAt(j + 1);
               crchcrcl = CalculCRC(x, j - 3);
               crch = crchcrcl[0];
               crcl = crchcrcl[1];

               if (x[j - 1] != crch || x[j - 2] != crcl)
               { goto début; }
           }

           if (Fonction == 6 || Fonction == 5)// la fonction 6 permet d'écrire des mots de 16 bits; la fonction 5 permet de forcer un bit de commande à 1 ou a 0
           {
               for (j = 3; j <= 7; j++)
                   x[j] = (byte)("" + Buffer).ElementAt(j + 1);
               crchcrcl = CalculCRC(x, j - 3);
               crch = crchcrcl[0];
               crcl = crchcrcl[1];

               if (x[j - 1] != crch || x[j - 2] != crcl)
               { goto début; }
           }
           return x;
        }


Je vous remercie d'avance pour vos réponse

EDIT : Ajout des balises de code (la coloration syntaxique).
Explications disponibles ICI

Merci d'y penser dans tes prochains messages.
Afficher la suite 

5 réponses

Répondre au sujet
Whismeril 11409 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 21 avril 2018 Dernière intervention - Modifié par Whismeril le 11/07/2016 à 13:26
0
Utile
1
Bonjour

et merci à Buno d'avoir mis de la couleur dans ton message.

Je n'ai pas regardé le code VB6 car se sont deux philosophies différentes et appliquer l'une dans l'autre donne des résultats boiteux.

Les goto sont à proscrire, c'éatiot déjà vrai en vb6 (vb1 même je pense).


L'idée de base avec la programmation objet, est qu'un objet a une tache/fonction.

Ca n'est pas à l'objet qui gére le port com d'afficher un message, ou un texte dans un label.
Il génère un événement, change une propriété, les deux... et l'objet qui gére l'ihm affiche un message.
Comme ça, si tu passes de console à Winform, puis de winform à wpf, ton objet port com ne change pas.

La boucle while pour tes tentatives, c'est bloquant, ton programme ne peut rien faire d'autre pendant ce temps.
Utilise un timer.

Il est plus simple de s'abonner à l'évènement DataRecieved, quand il se génère ça veut dire qu'il y a quelques chose à lire.

Quand tu veux affecter un entier à une variable, tu peux utiliser un enum, ça permet plus tard, en maintenance de ne pas se préoccuper de ce que codeerreur 3 veut dire, la valeur de l'enum sera CodeErreur.ValeurIncorrect. Plus lisible.

Pour calculer un temps d'exécution tu peux utiliser la classe stopwatch

Voilà déjà pour une première lecture rapide

Quand j'étais petit, la mer Morte n'était que malade.
George Burns
j78330 10 Messages postés mardi 17 septembre 2013Date d'inscription 18 juillet 2016 Dernière intervention - 11 juil. 2016 à 17:16
merci ta réponse
Commenter la réponse de Whismeril
NHenry 14132 Messages postés vendredi 14 mars 2003Date d'inscriptionModérateurStatut 21 avril 2018 Dernière intervention - 11 juil. 2016 à 21:08
0
Utile
1
De mon côté j'ajouterai 4 points :
Mets un peu plus de commentaires.
Ensuite,
t = DateTime.Now.Millisecond
Préfères peut être Environment.TickCount qui te retourne une valeur en millisecondes depuis le démarrage de la machine, un peu plus stable, je pense.

Evites de multiplier les instructions sur une ligne :
Debug.Print "                           appel :"; AppelBloc; " inbuf= "; Form1.MSComm1.InBufferCount; "bufferdemande = "; Buffer

Ca rend le code moins lisible.


Et UN énorme point :
Je vois :
"début:"
dans ton code, cela indique un GOTO, instruction à bannir sauf cas extrêmes. De plus, évites les noms de références (variables/fonctions/étiquettes/...) avec des accents.
2 solutions, utiliser les contrôles de boucles (comme break ou continue) ou découpes ta fonction en autres plus petites.

Whismeril 11409 Messages postés mardi 11 mars 2003Date d'inscriptionContributeurStatut 21 avril 2018 Dernière intervention - 11 juil. 2016 à 22:05
Il peut utiliser des else à ses if, ou un switch aussi.
Commenter la réponse de NHenry
j78330 10 Messages postés mardi 17 septembre 2013Date d'inscription 18 juillet 2016 Dernière intervention - 13 juil. 2016 à 11:41
0
Utile
merci pour vos réponses
Commenter la réponse de j78330

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.