QByteArray tel = "79123456789"; QString msg = QStringLiteral("Привет!!!"); QByteArray ret; ret.append( QByteArray::fromHex("000100") ); ret.append( static_cast(tel.count()) ); ret.append( QByteArray::fromHex("91") ); if (tel.count()%2 == 1) tel.append('F'); for (int i=0; imakeEncoder(QTextCodec::IgnoreHeader); QByteArray encodedString = encoder->fromUnicode(msg); delete encoder; ret.append( static_cast(encodedString.count()) ); ret.append( encodedString ); qDebug() << ret.toHex(); Это был первый вариант. Вот что я сейчас использую: //------------------------------------------------------------------------------ QByteArray GsmSMS::encodeToPDU(QByteArray tel, QString msg) { QByteArray ret; if (tel.startsWith('+')) tel=tel.right( tel.count()-1 ); //if (tel.count()==11) // Для России if (tel.count()<17) // Стандарт { msg.truncate(70); QByteArray encodedString = encodeUCS2(msg); ret.append( "000100" ); ret.append( byteToHex(static_cast(tel.count())) ); ret.append( "91"); ret.append( phoneToPDU(tel) ); ret.append( "0008" ); ret.append( byteToHex(static_cast(encodedString.count())) ); ret.append( encodedString.toHex() ); } return ret; } //------------------------------------------------------------------------------ QByteArray GsmSMS::byteToHex(quint8 ch) { QByteArray ret; ret.append(ch); return ret.toHex(); } //------------------------------------------------------------------------------ QByteArray GsmSMS::phoneToPDU(QByteArray data) { if (data.count()%2 == 1) data.append('F'); for (int i=0; imakeEncoder(QTextCodec::IgnoreHeader); QByteArray ret = encoder->fromUnicode(str); delete encoder; return ret; } //------------------------------------------------------------------------------ QString GsmSMS::decodeUCS2(QByteArray data) { QTextCodec *codec = QTextCodec::codecForName("UTF-16BE"); QTextDecoder *deencoder = codec->makeDecoder(QTextCodec::IgnoreHeader); QString ret = deencoder->toUnicode(data); delete deencoder; return ret; } //------------------------------------------------------------------------------ QByteArray GsmSMS::encodeGSM7bit(QByteArray data) { QByteArray ret; if (!data.isEmpty()) { quint16 d=0; quint8 j=0; for (qint16 i=0; i(d)); d>>=8; } if (d) ret.append( static_cast(d)); } return ret; } //------------------------------------------------------------------------------ QByteArray GsmSMS::decodeGSM7bit(QByteArray data) { QByteArray ret; if (!data.isEmpty()) { quint16 d = static_cast(data[0]); quint8 j=0; for (qint16 i=1; i(d) & 0x7f); d>>=7; quint16 b = static_cast(data[i]); b<<=++j; d|=b; if (j==7) { j=0; ret.append(static_cast(d) & 0x7f); d>>=7; } } if (d) ret.append(static_cast(d) & 0x7f); d>>=7; if (d) ret.append(static_cast(d)); } return ret; } //------------------------------------------------------------------------------ QDateTime GsmSMS::dateFromPDU(QByteArray data) { data = QByteArray("20") + phoneToPDU(data); //---------------------------------------------- // Timezone //---------------------------------------------- quint8 tz = data.mid(14, 2).toUShort(nullptr, 16); bool bNegative = tz & 0x80; tz = ((tz>>4) & 7)*10 + (tz & 0x0f); int offsetSeconds = ((tz >> 2)*60 + (tz & 3)*15) * 60; // (hour*60 + min)*60 if (bNegative) offsetSeconds = -offsetSeconds; //---------------------------------------------- data.chop(2); QDateTime dateTime = QDateTime::fromString(QString::fromLatin1(data), QStringLiteral("yyyyMMddhhmmss") ); dateTime.setTimeZone( QTimeZone(offsetSeconds) ); return dateTime; } //------------------------------------------------------------------------------ /* // Для проверки: QByteArray pdu(QByteArray::fromHex("07919781340310F10409D0D432BB2C030000124040610470210AD4F29C4E2FCFE92E10")); QByteArray phone; QDateTime dateTime; QString msg; qDebug() << GsmSMS::decodePDU(pdu, &phone, &dateTime, &msg); qDebug() << phone; qDebug() << dateTime; qDebug() << msg; */ bool GsmSMS::decodePDU(QByteArray pdu, QByteArray *phone, QDateTime *dateTime, QString *msg) { quint16 index = pdu[0]+1; quint8 TP_MTIandCo = pdu[index++]; // TP-MTI & Co if ( (TP_MTIandCo & 3) != 0 ) return false; // Раскодируем только сообщения вида SMS-DELIVER /* switch (TP_MTIandCo & 3){ // Message Type indicator (TP-MTI) case 0: qDebug("SMS-DELIVER"); break; case 1: qDebug("SMS-SUBMIT REPORT"); break; case 2: qDebug("SMS-STATUS REPORT"); break; } */ bool TP_UDHI = TP_MTIandCo & 0x40;// User Data header Indicator quint8 senderLenght = pdu[index++]; if (senderLenght & 1) senderLenght++; senderLenght>>=1; quint8 senderType = (pdu[index++] & 0x7f) >> 4; *phone = pdu.mid(index, senderLenght); index += senderLenght+1; if (senderType==1){ // Международный формат номера *phone = phoneFromPDU(phone->toHex()); } else if (senderType==5){ // Буквенно-цифровой, упакованый в 7 бит на символ *phone = decodeGSM7bit(*phone); }; quint8 TP_DCS = pdu[index++]; // Data coding scheme *dateTime = dateFromPDU( pdu.mid(index, 7).toHex() ); index+=7; quint8 TP_UDL = pdu[index++]; //User Data Length if ( (TP_DCS==0) || (TP_DCS==0x10) ) // Сообщение упаковано в 7 бит на символ { quint8 UDHL = 0; if (TP_UDHI) { UDHL = pdu[index]+1; // Длина блока UDH вместе с самим байтом блинны // Ниже эквивалент формулы UDHL = UDHL*8/7 с округлением вверх quint16 n = UDHL<<3; UDHL = ((n/7) + ((n%7) ? 1:0)); } // Ниже эквивалент формулы TP_UDL = TP_UDL*7/8 с округлением вверх quint16 n = TP_UDL * 7; TP_UDL = ((n>>3) + ((n%8) ? 1:0)); QByteArray data = decodeGSM7bit( pdu.mid(index, TP_UDL) ); if (UDHL) data = data.right(data.count() - UDHL); *msg = QString::fromLatin1(data); } else if ( (TP_DCS==8) || (TP_DCS==0x18) ) // Сообщение упаковано в кодировку UCS2 { if (TP_UDHI) // User Data header Indicator { quint8 UDHL = pdu[index]+1; // Длина блока UDH вместе с самим байтом блинны index += UDHL; TP_UDL -= UDHL; } *msg = decodeUCS2( pdu.mid(index, TP_UDL) ); } else return false; return true; }