Aiuto per implementazione di una libreria per porta seriale

di il
7 risposte

Aiuto per implementazione di una libreria per porta seriale

Cerco un programmatore che mi aiuti nello sviluppare una libreria per la gestione della porta seriale in C++ (insomma dei volontari).
Tale libreria poi sarà rilasciata con licenza open source (da decidersi quale).

Informazioni: la libreria deve essere facile da utilizzare e deve essere sviluppata con tecniche moderne o per intenderci meglio più c++11 c'è meglio è. vi posto una bozza dell'interfaccia:

#ifndef SERIALX_H
#define SERIALX_H

#include <boost/thread/future.hpp>
#include <string>
#include <vector>

namespace serialx {

class Baudrate;
class CharSize;
class Parity;
class StopBits;
class FlowControl;

template< typename T >
using Buffer< T > = std::vector< T >;

template< typename ResultType >
using Future< ResultType > = boost::unique_future< ResultType >;

class SerialX
{
public:
    // SerialX s( "/dev/ttyUSB0", BaudRate( 115200 ) );
    SerialX(
            const std::string& device,
            const Baudrate& baudrate /* = Baudrate( 115200 ) */
            );

    // s.option( BaudRate( 9600 ) )
    // s.option( FlowControl( FlowControl::HARDWARE ) );
    // s.option( CharSize( 7 ) );
    template< typename Option >
    void option( const Option& opt );

    // auto baudrate = s.option< Baudrate >().value();
    // auto flowcontrol = s.option< FlowControl >().value();
    template< typename Option >
    Option option() const;


    // std::vector< int > buffer;
    // s.send( begin( buffer ), end( buffer ) );
    template< typename RAIter >
    Future< int > send( RAIter first, RAIter last );

    // auto readBuffer = s.read< int >.get();
    // auto readBuffer = s.read< char >.get();
    template< typename T >
    Future< Buffer< T > > read();

    /*
     * sp1.send().then( [&sp1] ( Future< int > f )
     * {
     *      LOG( trace ) << "sent " << f.get() << " bytes\n";
     *
     *      sp1.read().then( [] ( Future< Buffer< T > > res )
     *      {
     *          auto readData = res.get();
     *
     *          LOG( trace ) << "read " << readData.size() << " bytes\n";
     *          for( const auto& v : readData )
     *              LOG( trace ) << v;
     *      })
     * });
     */
};

} // serialx

#endif // SERIALX_H
Se trovo dei volontari il progetto verrà caricato su github.

7 Risposte

  • Re: Aiuto per implementazione di una libreria per porta seriale

    Ometti un particolare piuttosto importante: su quale sistema operativo?
    Inoltre, sei proprio sicuro che più c++11 c'è e meglio è? Secondo me una libreria per la seriale non dovrebbe avere bisogno di costrutti particolari e, proprio perchè si tratta di una libreria, più semplice è meglio è, anche più portabile verso diversi compilatori/sistemi operativi.
  • Re: Aiuto per implementazione di una libreria per porta seriale

    Di librerie per la seriale ne trovi a bizzeffe in rete.
    Basta che cerchi con le paroline magiche: "serial port", "UART" "RS232"

    Una per tutte:

    http://www.boost.org/doc/libs/1_40_0/doc/html/boost_asio/overview/serial_ports.html

    Se non conosci Boost, e' il caso di studiarla.
  • Re: Aiuto per implementazione di una libreria per porta seriale

    La libreria l'avrei basata su boost.asio.
    Come sistemi operativi mi limitavo almeno a linux Mac e windows.
    Nell'esempio l'approccio di utilizzo non mi sembrava per niente complicato, faccio un esempio su come vorrei che si utilizzasse:
    
    SerialX s1( "/dev/ttyS0", Baudrate( 115200 ) );
    
    // configurazione
    s1.option( CharSize( 8 ) );
    s1.option( FlowControl( FlowControl::NONE ) );
    s1.option( Parity( Parity::NONE ) );
    
    // lettura e scrittura sono asincroni e restituiscono dei future. Uso boost::future in quanto 
    // come PPL permetton la continuazione.
    
    // Caso1: scrittura 
    std::vector< int > b= {1, 2, 3, 4, 5, 6, 7, 8, 9 };
    auto res = sp1.send( begin( b ), end( b ) );
    
    // esegui altra roba in parallelo
    doOtherTask();
    
    // aspetta che i dati siano stati inviati
    cout << "spediti " << res.get() << " bytes" << endl;
    
    // Caso2: scrittura con continuazione
    sp1.send( begin( b ), end( b ) ).then( [ &sp1, &b, &cout ] ( boost::future< int > f
    {
        // aspetta che i dati siano stati inviati
        cout << "spediti " << f.get() << " bytes" << endl;
    });
    
    // stessa cosa per la lettura. La lettura dovrebbe restiuire un future con il Buffer letto
    auto res3 = sp1.read();
    
    auto read = res3.get();
    // ...
    

    L'utilizzo del C++11 (almeno per quanto riguarda l'implementazione) vorebbe essere solo come strumento di semplificazione.
  • Re: Aiuto per implementazione di una libreria per porta seriale

    Secondo me è troppo complicato!
    Io da una libreria seriale mi aspetterei 4/5 funzioni (in C)
    - open
    - close
    - write
    - read
    - eventualmente setoption
    Se vuoi puoi farne una classe in C++.
    Tutto il resto, eventualmente, lo costruisci sopra questa base.
    aggiunta successiva: mi sono dimenticato di scrivere che per me i buffer spediti e ricevuti dovrebbero essere, di base, array di char.
  • Re: Aiuto per implementazione di una libreria per porta seriale

    Spesso capita che le comunicazioni siano asincrono e che il wrapper non è di facile implementazione. Nel metodo descritto restituendo dei future uno può o continuare a utilizzare la libreria nel classico metodo oppure in modo asincrono senza nessuna complessità aggiunta o l'utilizzo di funzioni di callback che rendeono il codice sia pià difficile da leggere che più difficile da mantenere.

    Per quanto riguarda i buffer la penserei anche io come array di char o meglio ancora array di byte, però non vorrei chiudere la porta ad altri tipi.

    Beh se non c'è nessuno proverò comunque da solo a vedere come viene.
  • Re: Aiuto per implementazione di una libreria per porta seriale

    Per il sincrono/asincrono: la funzione read() ti ritornerà il numero di caratteri presenti nella 'coda' di ricezione che devi eventualmente implementare, niente di più semplice; se non ci sono ancora dati ti ritornerà 0.
    Per i buffer, non hanno senso altri tipi oltre ai byte (char o unsigned char): se ti è mai capitato di interfacciarti con un'apparecchiatura seriale capirai il perchè!
  • Re: Aiuto per implementazione di una libreria per porta seriale

    Terrò a mente i consigli. Ho lavorato spesso con le porte seriali per implementazioni di vari tipi di portocollo( ccTalk, BillToBill e propietari). Il mio primo approccio alla porta serial è stato esattamente implementare una class con poche funzionalità:
    read per leggere un determinato numero di byte in un timeout precisato
    readSome per leggere al volo i dati disponibili
    read_n per leggere esattamente n byte: restituisce un vector< byte >
    send per spedire.

    Ho usato Boost.Asio per vedere come era implementato. ma non mi è piacito il sistema a callback

    Questo in effetti vorebbe più essere un esperimento a vedere se un approccio diverso potrebbe eventualmente semplificare la vita ulteriormente.

    Appena avrò una prima versione funzionante la post sul sito per avere maggiori feedback.

    Grazie a tutti dei preziosi consigli
Devi accedere o registrarti per scrivere nel forum
7 risposte