A
A
AlexSer2021-09-02 08:43:46
Qt
AlexSer, 2021-09-02 08:43:46

How to configure QT to communicate via SerialPort with a device using the ASTM E1381-95 protocol?

Protocol link:
ASTM protocol

Main points of the protocol:
613062002ce8b291241488.png

Here is my code for receiving and sending data to the device:

//Запуск чтения serial порт соединения с устройством
     FurunoCA270 *CA270;
        CA270=new FurunoCA270();
        CA270->serialPort=sPort5->serialPort;
        CA270->terminal=ui->terminal;
        CA270->Start(data);

void FurunoCA270::Start(QString msg){
    //записываем шаг итерации при принятий и отправке данных;
    QByteArray ACK="\x06";
    QByteArray ENQ="\x05";
    QByteArray EOT="\x04";
    QByteArray STX="\x02";
    QByteArray ETX="\x03";

    QByteArray byte;
    static QByteArray IpuByte;

    /*Схема запросов с IPU->HOST Порядок тестов Q [ALL или barcode];
     *  IPU  |-> ENQ ->  HOST
     *       <- ACK -|
     *       |-> H ->
     *       <- ACK -|
     *       |-> Q ->
     *       <- ACK -|
     *       |-> L ->
     *       <- ACK -|
     *       |->EOT ->
     * */
    byte+=msg;
//Если от устройства идет прием данных:
    if(!byte.contains(ACK)){
             IpuByte+=byte;
        if(byte.contains(ENQ)){
            serialPort->write(ACK);
        }
        if(!byte.contains(EOT)){

            if(byte.contains(LF)){
                serialPort->write(ACK);
                terminal->append("HOST=====>ACK");
            }
        }else{
              terminal->append("IPU=====>EOT");
        //определяю по записи Q в строке, это передача данных от устройства или запрос данных, если запрос данных то 
         отправляю сигнал ENQ.

            if(IpuByte.contains("Q")){
                serialPort->write(ENQ);
                terminal->append("HOST=====>ENQ");
            }else{
               //если это прием данных от устройства то отправляю на парсинг.
                   Parser(IpuByte); //
                   IpuByte.clear();
            }
        }
    }else{
          if(IpuByte.length()>0){
              //если приходят запросы от оборудования то передаю сообщения в устройство
              //условие на получение первого ACK;
              this->SendMsg(IpuByte);
              IpuByte.clear();
          }
    }






 }

void FurunoCA270::SendMsg(QByteArray byteArray){
    if(byteArray.contains("ALL")){
          this->ALL();

    }else{
              //код на по штучную вставку данных.

    }


}


void FurunoCA270::ALL(){
   QHash<int,QMap<QString,QStringList>> data=QsqlQueryData::WorkList("FurunoCA270");

   static QByteArray msg;

     QDateTime dt = QDateTime::currentDateTime();


  //   H+=STX+h+CR+ETX+CheckSum(h)+CR+LF;
   //  msg+=H;
     int N=1;

         QString h="H|\\^&|||HOST|||||||||"+dt.toString("yyyyMMddhhmmss");

          sendSerialMsg(h);
          for(int i=0; i<data.size(); i++){
                 QString p;
                 QString o;
                 QString c;
                 QString l;
                 QMap<QString,QStringList>::iterator it = data[i].begin();
                 for(;it != data[i].end(); ++it){
                     QString SID=QString::number(N);
                                      if(SID.length()==2){SID="0"+SID;}
                                      if(SID.length()==1){SID="00"+SID;}

                                  //+QsqlQueryData::InfoPacient(it.key())[0].toUtf8()+" "+QsqlQueryData::InfoPacient(it.key())[1][0].toUtf8()+" "+QsqlQueryData::InfoPacient(it.key())[2][0]+
                                   p="P|"+QString::number(N)+"|"+it.key()+"|||PACIENT UNK||"+QsqlQueryData::InfoPacient(it.key())[3]+"||Race1|||||"+QsqlQueryData::InfoPacient(it.key())[4]+"|1||||||||||";

                     QString tests;
                    for(int j=0; j<it.value().size(); j++){
                         if(IDTest(it.value()[j]).length()>0){
                              tests+="^^^"+IDTest(it.value()[j])+"\\";
                         }
                     }



                     tests.chop(1);
                      o="O|1|"+SID+"||"+tests+"||||||||||||01";
                      c="C|1|I|TestOrder1|G";

                 }


      sendSerialMsg(p);
      sendSerialMsg(o);
      sendSerialMsg(c);

             N++;
     }

    QString l="L|1";
    sendSerialMsg(l);

    QByteArray EOT="\x04";
    serialPort->write(EOT+LF);

}

int FurunoCA270::sendSerialMsg(QString msg){
    static int j=0;
     QByteArray Msg;
     if(msg.contains("H")){
        j=j+1;
     }
     Msg+=STX+QString::number(j)+msg+CR+ETX+CheckSum(QString::number(j)+msg)+CR+LF;
     serialPort->write(Msg);
     terminal->append(Msg);
      j=j+1;

      if(j==8){
        j=0;
    }
      if(msg.contains("L")){
         j=0;
      }
    return  j;
}

Problem:

The code does not work quite correctly, I would like to make it a separate class so as not to generate messages for the device as in this code. Maybe someone has a code example or someone who has dealt with this topic and can suggest the right solution?
Because in this code I do not take into account timeouts, I do not take into account the length of the message. Yes, the working code with the device is exchanging data, both transmitting and receiving, but I would like it to be logical and correct, and most importantly convenient.
PS: I haven't done much C++ programming so don't be judgmental.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question