Программа для чтения UDP сообщений от модема Enfora с использованием Indy компонента C++ Builder 6
Модем на основе модуля Enfora GSM0308
Программа для чтения UDP сообщений с исползованием компанента Indy C++ Builder
Управление модемом Enfora через СМС
Пишите автору сайта ganatol2000@mail.ru
Воспользуемся C++ Builder 6.
В него входят как раз нужный нам Indy компонент:
IdUDPServer.
В параметре DefaultPort компонента
IdUDPServer не забудьте выставить порт, который был
введен в модем командой AT$UDPAPI. У меня это 40000.
А также проверьте, чтобы свойство: Active имело значение
true Основное событие OnUDPRead, оно генерируется всякий раз в
момент приема UDP сообщения. Вот функция, которая
реализует обработку этого события
void __fastcall TForm1::IdUDPServer1UDPRead(TObject
*Sender,
TStream *AData, TIdSocketHandle *ABinding)
{
char My[200];
TDateTime DateMy;
TDateTime TimeMy;
AnsiString MyDump;
AData->ReadBuffer(My, AData->Size);
My[AData->Size]=0;
MyDump=Dump(My, AData->Size, 0, true, "");
DateMy = Date();
AnsiString strDate = DateToStr(DateMy);
TimeMy = Time(); // store the current date and time
AnsiString strTime = TimeToStr(TimeMy);
Memo1->Lines->Add(strDate+" "+strTime+":"+
"IP:"+ABinding->PeerIP+":"+"Port:"+ABinding->PeerPort+":"+"Size:"+AData->Size+":"+"Data:"+MyDump);
if(AData->Size==42)
{
int a= DataGrammAnalogValie(My).ToInt();
float b=a*0.001709;
Memo2->Lines->Add(DataGrammMessageID(My)+" "+DataGrammModemID(My)+" "+CurrToStr(b));
Series1->Add(b*koefficient, strTime, clRed);
FILE* MyAnalogValue;
char* h=" ";
char* u="U=";
MyAnalogValue=fopen("analog_value.log","a");
fprintf(MyAnalogValue,"%s %s %s %s %s %s %s %s %s %s \n",strDate.c_str(), h,
strTime.c_str(),
h, DataGrammMessageID(My).c_str(), h, DataGrammModemID(My).c_str(),
h, u, CurrToStr(b*koefficient).c_str());
fclose(MyAnalogValue);
}
else
{
Memo2->Lines->Add("The format of the datagram is not supported");
}
}
Здесь AData->ReadBuffer(My, AData->Size); считывает
принятую датаграмму в char My[200],
далее функцией Dump:
AnsiString __fastcall Dump(void *data, int size, int col,
bool hex, const AnsiString &pref)
{
AnsiString s;
for (int i = 0; i < size; ++i) {
if (!i)
s += pref;
else if (col && !(i % col)) {
s += "\n";
s += pref;
}
if (hex)
s += IntToHex(((unsigned char*)data)[i], 2) + " ";
else {
AnsiString s1 = int(((unsigned char*)data)[i]);
while (s1.Length() < 3)
s1 = " " + s1;
s += s1 + " ";
}
}
return s;
}
формируется дамп. Потом считывается дата и время и все эти данные отправляются в
компонент Memo1 для отображения.
Обратите внимания, что используя ABinding->PeerIP
и ABinding->PeerPort мы так же отображаем
IP адрес и порт откуда пришло
UDP сообщение.
Но сам дамп не очень информативен. Можно конечно используя таблицу
ASСII символов попытаться понять что же мы получили...
Но все-таки наверное следует обработать данные и отобразить в более приемлемом
для человека виде. Поэтому проверяем размер UDP
сообщения, который должен составлять в выбранном нами формате 42 байта. И если
размер сообщения совпадает с ожидаемым, то функциями:
AnsiString __fastcall DataGrammMessageID(char *data)
{
AnsiString s;
for (int i = 4; i < 14; ++i) {
s += AnsiString::StringOfChar(data[i], 1);
}
return s;
}
AnsiString __fastcall DataGrammModemID(char *data)
{
AnsiString s;
for (int i = 15; i < 36; ++i) {
s += AnsiString::StringOfChar(data[i], 1);
}
return s;
}
AnsiString __fastcall DataGrammAnalogValie(char *data)
{
AnsiString s;
for (int i = 37; i < 41; ++i) {
s += AnsiString::StringOfChar(data[i], 1);
}
return s;
}
разберем UDP сообщение на составляющие, и используя
коэффициент 0,001709 вычислим значение напряжения подаваемого на аналоговый
вход. Потом всю эту информацию подадим на компонент Memo2
для отображения. Также используя Series1->Add(b*koefficient, strTime, clRed);
выведем значение аналоговой величины на график(компонент
TChart), чтобы можно было наблюдать её изменение с течением
времени. Здесь koefficient
переменная
параметризации, записываемая кнопкой Save (функции
реализующие работу с переменной koefficient
найдете в исходниках программы или
придумаете сами). В заключении
расшифрованное UDP сообщение регистрируется в log
файле.