IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Déterminer les ports COM présents


Sujet :

Langage C++

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 27
    Points : 19
    Points
    19
    Par défaut Déterminer les ports COM présents
    Bonjour,

    Je suis à la recherche d'un moyen de connaître la totalité des ports COM présents sur un ordinateur.

    J'ai trouvé un code me permettant d'ouvrir un port COM et de pouvoir écrire dessus, de là, j'ai élaboré le début d'une classe me permettant de gérer plus facilement ces différents ports.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #ifndef HEADER_SERIALPORT
    #define HEADER_SERIALPORT
    #include <Windows.h>
    #include <string>
    #include <sstream>
     
    class SerialPort
    {
    public:
    	SerialPort();
    	~SerialPort();
    	/* Exception possible de type std::string*/
    	void Open(std::string port="COM3",unsigned int baudrate=9600,int timeout=-1);
    	/* Exception possible de type std::string*/
    	void Close();
    	std::string getPortName() const;
    	unsigned int getBaudrate() const;
    	void setBaudrate(unsigned int baudrate);
    	int getTimeout() const;
    	void setTimeout(int timeout);
    	void WriteComFile(std::string File);
    	std::string ReadComFile();
    	std::string WriteAndReadComFile(std::string File);
        static bool CheckForPort(int i);
    protected:
    	std::string portName;
    	unsigned int baudrate;
    	int timeout;
    	char szBuffer[80];
    	DCB dcb;
    	DWORD dwRead, dwWritten;
    	HANDLE hComm;
    	OVERLAPPED ovlr, ovlw;
    	COMMTIMEOUTS cto;
    	#define intimeout 1000//ms (attente entre chaque caratère --> attente a la fin de transmission)
    	//pour une application à 9600 bauds, 2ms sont suffisantes pour détécter la fin (1,04 ms entre chaque octet).
        //10bits par octet (stop + start)
    };
    #endif
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    #include "SerialPort.h"
    using namespace std;
     
    /* Constructeur
     * Initialise les paramètres
     */
    SerialPort::SerialPort(): dcb(),ovlr(),ovlw(),cto(),portName(""),baudrate(0),timeout(0){
    }
     
    /* Destructeur
     * referme le port si nécéssaire
     */
    SerialPort::~SerialPort(){
    	if(GetCommState(hComm,&dcb))CloseHandle(hComm);
    }
     
    /* Ouvre le port voulu
     * Defaut :
     * COM3 (modem)
     * 9600 bauds
     * pas de timeout
     * Exception possible de type std::string
     */
    void SerialPort::Open(string portName,unsigned int baudrate, int timeout){
    	if(!GetCommState(hComm, &dcb)){ //si pas deja ouvert
    		this->portName=portName;
    		this->baudrate=baudrate;
    		this->timeout=timeout;
    		ovlr.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    		ovlw.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
    		hComm = CreateFileA(this->portName.c_str(), GENERIC_READ | GENERIC_WRITE,
    		0, NULL, OPEN_EXISTING,
    		FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
    		if(!GetCommState(hComm, &dcb)){
    		throw string("Error : Unable to open "+this->portName);
    		}
    		dcb.BaudRate = this->baudrate;
    		SetCommState(hComm, &dcb);
    		// Set the timeout parameters nonsensically
    		cto.ReadIntervalTimeout = intimeout; //entre chaque caract
    		cto.ReadTotalTimeoutConstant =this->timeout;
    		cto.ReadTotalTimeoutMultiplier = 1;
    		cto.WriteTotalTimeoutConstant = -1; //pas de tm pour le moment
    		cto.WriteTotalTimeoutMultiplier = -1;
    		SetCommTimeouts(hComm, &cto);
    	}
    	else throw string("Warning : "+this->portName+" is already opened");
    }
     
    /* Ferme le port
     * Exception possible de type std::string
     */
    void SerialPort::Close(){
    	if(GetCommState(hComm, &dcb)){ //si pas deja ouvert
    	CloseHandle(hComm);
    	}
    	else throw string("Warning : "+this->portName+" is already closed"); //port deja fermé
    }
     
    /*
     *Getter & setter
     */
    std::string SerialPort::getPortName() const{
    	return this->portName;
    	}
     
    unsigned int SerialPort::getBaudrate()const{
    	return this->baudrate;
    	}
     
    void SerialPort::setBaudrate(unsigned int baudrate){
    	this->baudrate=baudrate;
    	dcb.BaudRate=this->baudrate;
    	SetCommState(hComm, &dcb);
    }
     
    int SerialPort::getTimeout() const{
    	return this->timeout;
    }
     
    /* Modifie le timeout [ms] (en lecture uniquement)
     * -1 = pas de timeout général (mais tjs le interval timeout des la reception d'un char)
     */
    void SerialPort::setTimeout(int timeout){
    	this->timeout=timeout;
    	cto.ReadTotalTimeoutConstant = this->timeout;
    	SetCommTimeouts(hComm, &cto);
    }
     
    /*
     * Ecriture sur le port
     */
    void SerialPort::WriteComFile(string File){
    	WriteFile(hComm, File.c_str(), strlen(File.c_str()), &dwWritten, &ovlw);
    }
     
    /*
     * Lecture sur le port
     */
    string SerialPort::ReadComFile(){
    	ReadFile (hComm, szBuffer, sizeof(szBuffer), &dwRead, &ovlr);
    	GetOverlappedResult(hComm, &ovlr, &dwRead, true);
    	szBuffer[dwRead] = 0;
    	return szBuffer;
    }
     
    /*
     * Ecrire et attendre une lecture juste après
     */
    string SerialPort::WriteAndReadComFile(string File){
    	WriteComFile(File);
    	return ReadComFile();
    }
     
    /*
     * Vérifier les ports disponnibles non ouverts
     */
    bool SerialPort::CheckForPort(int i){
        bool state(false);
    SerialPort S;
    std::ostringstream oss;
    oss << i;
    std::string ComNumber = oss.str();
    try{
        S.Open("COM"+ComNumber);
        S.Close();
        state=true;
        }
       catch(...){ //nothing to do ..
        }
        return state;
    }
    Dernièrement, pour une application que l'on m'a demandée de réaliser, je dois pouvoir déterminer les différents ports COM présents sur la machine même si ceux-ci sont déjà ouverts !

    Or, dans la classe ci-dessus, la méthode que j'ai essayé d'implémenter pour faire cela (la dernière fonction) ne me renvoi que les ports disponibles fermés.

    Par expérience, je sais qu'avec les windows form on à accès à la fonction static array<String^>^ GetPortNames() présente dans la classe SerialPort du namespace System::IO::Ports qui réalise exactement ce que je cherche et que donc cette opération est possible.

    Néanmoins, dans mon application je n'utilise pas les windows form ni visual studio et je n'ai donc visiblement pas accès à cette classe.

    Est-ce que vous auriez une solution simple à implémenter pour faire ce que je souhaite ?
    Je précise que je ne suis pas informaticien et que je maîtrise assez mal l'API windows (notamment au niveau des HANDLE). Mais mon but premier n'est pas la compréhension de chaque ligne de code non plus.
    Je vous remercie !!

  2. #2
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 27
    Points : 19
    Points
    19
    Par défaut
    Voila, je pense avoir trouvé comment faire.

    Quand j'utilise la fonction GetCommState, si le port est fermé ou s'il n'existe pas, la fonction retourne la valeur booléenne 0.
    Ensuite l'appel de la fonction GetLastError m'a permis de voir que le code d'erreur est différent lorsqu'il s'agit d'un port fermé ou d'un port inexistant.
    Lors d'un port inexistant, le code d'erreur est le code numéro 6.
    Lors d'un port fermé, le code d'erreur est le code numéro 1.

    Edit :

    Le code d'erreur 1 signifie ERROR_INVALID_FUNCTION
    Le code d'erreur 6 signifie ERROR_INVALID_HANDLE
    (source)

    Selon moi, le mieux pour voir si le port existe est donc de tester si le code d'erreur est le numéro 6. Dans ce cas, le handle est invalide et donc le port demandé n'est pas présent sur l'ordinateur.

    Désolé d'avoir mis cette discussion et d'y avoir répondu par moi même après de plus amples recherches, néanmoins je pense qu'elle pourra servir pour d'autres .

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 27
    Points : 19
    Points
    19
    Par défaut
    Désolé je déterre ce topic car finalement ma solution ne convient pas.
    Après plusieurs jours d'utilisation de l'application il s'avère que même si les ports sont utilisés (ouverts) le code d'erreur renvoyé est le numéro 6 : ERROR_INVALID_HANDLE.

    Quelqu'un à une idée à proposer ?
    Merci !

  4. #4
    Membre à l'essai
    Profil pro
    Inscrit en
    Octobre 2009
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : Belgique

    Informations forums :
    Inscription : Octobre 2009
    Messages : 27
    Points : 19
    Points
    19
    Par défaut
    Après avoir lu plus en détail la documentation Microsoft j'ai finalement trouvé la réponse à mon problème (écrite noir sur blanc ..).

    La fonction GetLastError renvoie le code d'erreur 2 (ERROR_FILE_NOT_FOUND) si le handle créé à partir de la fonction CreateFile n'existe pas.
    Dans tous les autres cas (port ouvert, fermé, indisponible, ...) le code d'"erreur" est différent.
    (source)

    Voici donc ce que devient la fonction implémentée (static) pour savoir si un port existe :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    bool SerialPort::IsExistingPort(string portName){
        HANDLE hComm = CreateFileA(portName.c_str(), GENERIC_READ | GENERIC_WRITE,
        0, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL);
        if(GetLastError()==ERROR_FILE_NOT_FOUND)
            return false;
        CloseHandle(hComm);
        return true;
    }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. les port coms
    Par hamster. dans le forum Général Java
    Réponses: 3
    Dernier message: 03/04/2008, 13h34
  2. [reseaux] Dialogue avec les ports COM
    Par EricBisca dans le forum Programmation et administration système
    Réponses: 1
    Dernier message: 05/11/2006, 18h08
  3. [C#] Comment utiliser tous les ports COM ?
    Par Seb.26 dans le forum C#
    Réponses: 2
    Dernier message: 10/01/2006, 16h34
  4. Enumérer les ports COM ...
    Par Marco85 dans le forum Windows
    Réponses: 3
    Dernier message: 13/10/2005, 14h30
  5. Lister les ports com disponible
    Par dyason dans le forum Général Python
    Réponses: 1
    Dernier message: 16/08/2004, 10h35

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo