Trimiterea sms-urilor ruse prin intermediul comenzilor at-uri (un exemplu pe java) - foaia de înșelăciune a programatorului

La un moment dat, într-unul dintre proiecte, a fost nevoie să se trimită programabil SMS-uri ruse prin GSM-modem prin intermediul comenzilor AT. Partea de server a proiectului este implementată în Java, astfel încât exemplul va fi în această limbă. Pentru cei care sunt interesați - bun venit la pisică.







Un pic de date de intrare: server cu COM port (RS232), GSM-modem Cinterion (Siemens) MC52i. Modemul funcționează cu comenzi AT.

Primul punct al soluției la această sarcină a fost să găsească o cale de a face Java un COM-port. Din fericire, căutarea în Google a emis aproape imediat o bibliotecă foarte convenabilă java-simple-serial-connector și documentația pentru aceasta. În consecință, descărcați biblioteca, conectați-o la proiect, creați o clasă care va funcționa cu modemul și scrieți în titlu


import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;

Biblioteca este conectată. Scriem o clasă pentru a lucra cu un modem


clasa publică SMSSender public SMSSender () <>

static serial SerialPort serialPort;

public static boolean smsSend (sms String, telefon String, JspWriter afară) aruncă IOException

// Transmiteți numele portului la constructor
serialPort = noul SerialPort ("COM1");
încercați // Deschideți portul
serialPort.openPort ();
// Setați parametrii
serialPort.setParams (SerialPort.BAUDRATE_9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
// Dacă trebuie să răspundeți la răspunsurile modemului - vom suspenda răspunsurile Listener și parsim. Voi omite acest lucru, cine are nevoie - documentația este documentată
//serialPort.addEventListener(new PortReader (), SerialPort.MASK_RXCHAR);

return true;
>
captură (SerialPortException ex) out.println (ex);
return false;
>

Așa că am deschis și am închis imediat conexiunea cu portul com. Acum direct cum să trimiteți SMS-uri rusești. Pentru a face acest lucru, trebuie să comunicați cu modemul într-un format PDU. În consecință, mai întâi modemul este configurat să funcționeze în acest mod:

Următorul ar trebui să meargă echipa

AT + CMGS =<тело смс><Символ CTRL+Z>

Acum, cum să compuneți acest SMS în format PDU. Când am căutat un răspuns, am fugit în următoarele surse, care explică titlul (Codul pe Delphi, dar totul este clar)

Ordinea și valoarea octeților antet sunt clare. Acum, hai să ne mișcăm cum să codificăm textul mesajului. Acesta trebuie trimis la modem în codare UCS2. De fapt, aceasta este o codificare inversă pe 7 biți. Funcția de conversie în format UCS2 pe JAVA:


String static privat StringToUSC2 (String text) aruncă String IOException str = "";

octet [] msgb = text.getBytes ("UTF-16");

String msgPacked = "";






pentru (int i = 2; i dacă (b.length () <2) msgPacked += "0";
msgPacked + = b;
>

String msglenPacked = Integer.toHexString (msgPacked.length () / 2);

dacă (msglenPacked.length () <2) str += "0";

str + = msglenPacked;
str + = msgPacked;

Ei bine, voi da un exemplu de clasă pentru trimiterea mesajelor ruse SMS cu explicații:

import jssc.SerialPort;
import jssc.SerialPortEvent;
import jssc.SerialPortEventListener;
import jssc.SerialPortException;

// Clasa pentru trimiterea de mesaje SMS

clasa publică SMSSender public SMSSender () <>

static serial SerialPort serialPort;

// Funcție pentru conversia textului SMS în format USC2 împreună cu lungimea mesajului (valoarea returnată <длина пакета><пакет>)

String static privat StringToUSC2 (String text) aruncă String IOException str = "";

octet [] msgb = text.getBytes ("UTF-16");
// Conversia SMS-ului în sine
String msgPacked = "";
pentru (int i = 2; i dacă (b.length () <2) msgPacked += "0";
msgPacked + = b;
>

// Lungimea pachetului rezultat în formatul dorit
String msglenPacked = Integer.toHexString (msgPacked.length () / 2);
// Dacă lungimea este ciudată - adăugați la sfârșitul 0
dacă (msglenPacked.length () <2) str += "0";

// Formăm un șir de lungime și corpul pachetului propriu-zis
str + = msglenPacked;
str + = msgPacked;

// Obțineți lungimea mesajului
static int int getSMSLength (String sms) întoarcere (sms.length () / 2 - 1);
>

public static boolean smsSend (sms String, telefon String, JspWriter afară) aruncă IOException

// Transmiteți numele portului la constructor
serialPort = noul SerialPort ("COM1");
încercați // Deschideți portul
serialPort.openPort ();
// Setați parametrii
serialPort.setParams (SerialPort.BAUDRATE_9600,
SerialPort.DATABITS_8,
SerialPort.STOPBITS_1,
SerialPort.PARITY_NONE);
//serialPort.addEventListener(new PortReader (), SerialPort.MASK_RXCHAR);

// Formați mesajul
Mesaj text = "0011000B91" + reversePhone (telefon) + "0008A7" + StringToUSC2 (sms);

// Trimiteți cererea către dispozitiv
char c = 0x0D; // Caracter retur de carriage CR
String str = "AT + CMGF = 0" + c;
serialPort.writeString (str);
Răsucire (500); // Teoretic, aici trebuie să așteptăm răspunsul modemului, dar ne vom limita să așteptăm doar o jumătate de secundă
// Goliți portul
serialPort.purgePort (serialPort.PURGE_RXCLEAR | serialPort.PURGE_TXCLEAR);
//out.println(str);
str = "AT + CMGS =" + getSMSLength (mesaj) + c;
serialPort.writeString (str);
Răsucire (500);
serialPort.purgePort (serialPort.PURGE_RXCLEAR | serialPort.PURGE_TXCLEAR);
//out.println(str);
c = 26; // caractere CTRL + Z
serialPort.writeString (mesaj + c);
Răsucire (1000);

return true;
>
captură (SerialPortException ex) out.println (ex);
return false;
> captură (InterruptedException e) //out.println(e);
return false;
>

// Clasa de citire a răspunsurilor. Am decis să o fac fără ea, dar în documentația pentru JSSC totul este 🙂
/ * clasa statică privată PortReader implementează SerialPortEventListener

public void serialEvent (eveniment SerialPortEvent) dacă (event.isRXCHAR () event.getEventValue ()> 0) try // Obțineți răspunsul de la dispozitiv, procesați datele etc.
Date de șir = serialPort.readString (event.getEventValue ());
// Și trimiteți din nou solicitarea
System.out.println ("răspuns:" + date);
>
captură (SerialPortException ex) System.out.println (ex);
>
>
>
> * /
>

P.S>
De asemenea, a fost utilizat modul PDU. Metoda reversPhone () poate fi reprezentată de linia a 4-a
String phonenumPDU = «»;
phonenum = phonenum + "F";
pentru (int i = 1; i<12;i=i+2) phonenumPDU = phonenumPDU + phonenum.charAt(i+1) + phonenum.charAt(i);
>

Sunt de acord 🙂 Această punere în aplicare este mai corect, dar eu când am scris - a fost un fior să-l înțeleagă cu un modem, astfel încât această metodă este implementată „vlobovuyu“.







Trimiteți-le prietenilor: