TCP/IP Socket komunikace
Protokol ModBus po RS232,485,...
na Pocket PC
(c)2002 Pavel Pindora
Email Kontakt Pro více informací je zde formulář

a k čemu je to dobré , je třeba si uvědomit, že socket je základem dalších aplikací jako telnet, ftp, můžeme s ním přenášet soubory, posílat SQL dotazy na socket server s příslušným softwarovým vybavením apod.
03.02.2002 Komunikace na lince RS232(485) mezi Pocket PC a Atmel 89C52 pomocí ModBus protokolu
29.9.2001 TCP/IP Socket komunikace v eVC 3.0, zdrojový kód
30.9.2001 Nastavení sítě pod Win.2000 pro připojení PDA pomocí seriového portu COM2
30.9.2001 Vlastní připojení PDA k PC s Win.2000
old Využití Poket PC pro komunikaci pomocí socket v projektu VisualProg
TCP/IP Socket komunikace v eVisualC++ 3.0, zdrojový kód
pro získání SocketKlient PDA (dle potřeby např. MIPS) případně i Server Socket (NT4.0 , Win2000) a to zcela zdarma k odzkoušení.

Inicializace pro komunikaci
![]()
void CSocketKlientDlg::OnButton4()
{
// TODO: Add your control notification handler code here
Inic_Socket();
}
BOOL CSocketKlientDlg::Inic_Socket()
{
TCHAR DText[1000];
char IPText[100];
// Initialize Winsocket
if (WSAStartup (MAKEWORD(1,1), &WSAData) != 0)
{
wsprintf (szError, TEXT("WSAStartup failed. Error: %d"),WSAGetLastError ());
MessageBox (szError, TEXT("Error"), MB_OK);
return FALSE;
};
// Create a TCP/IP socket that is bound to the server.
ServerSock = INVALID_SOCKET;
if ((ServerSock = socket (AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
{
wsprintf (szError, TEXT("Allocating socket failed. Error: %d"),WSAGetLastError ());
MessageBox (szError, TEXT("Error"), MB_OK);
return FALSE;
};
// Fill out the server socket's address information.
destination_sin.sin_family = AF_INET;
// Retrieve the host information corresponding to the host name.
phostent = NULL;
GetDlgItemText( IDC_EDIT2,DText,sizeof DText );UNICODE_to_Char( IPText,DText );
if ((phostent = gethostbyname(IPText)) == NULL)
{
wsprintf (szError, TEXT("Unable to get the host name. Error: %d"),WSAGetLastError ());
MessageBox (szError, TEXT("Error"), MB_OK);
closesocket (ServerSock);
return FALSE;
};
strcpy( name , phostent->h_name );
Char_to_UNICODE( szError,name );
SetDlgItemText( IDC_EDIT2,szError );
Char_to_UNICODE( szError,"PocketPC") ;SetDlgItemText( IDC_EDIT3,szError );
Char_to_UNICODE( szError,"PocketPC") ;SetDlgItemText( IDC_EDIT4,szError );
Char_to_UNICODE( szError,"KlientXX") ;SetDlgItemText( IDC_EDIT5,szError );
Char_to_UNICODE( szError,"Write" ) ;SetDlgItemText( IDC_EDIT6,szError );
Char_to_UNICODE( szError,"10.5" ) ;SetDlgItemText( IDC_EDIT7,szError );
// Assign the socket IP address.
memcpy ((char FAR *)&(destination_sin.sin_addr),phostent->h_addr,phostent->h_length);
// Convert to network ordering.
//PORTUN má přiřazenou hodnotu 1777 a záleží na Socket serveru kde poslouchádestination_sin.sin_port = htons (PORTNUM); return TRUE; }
Napojení na Server Socket běžící na Win2000
![]()
void CSocketKlientDlg::OnButton1() //Connect
{
// TODO: Add your control notification handler code here
if (connect (ServerSock,
(PSOCKADDR) &destination_sin,
sizeof (destination_sin)) == SOCKET_ERROR)
{
wsprintf (szError,TEXT("Connecting to the server failed. Error: %d"),WSAGetLastError ());
MessageBox (szError, TEXT("Error"), MB_OK);
closesocket (ServerSock);
return;
};
}
Vyslání Socket na Win2000
void CSocketKlientDlg::OnButton3()
{
char SocTx[10000];
SocTx[0] = NULL;
// Vyslání stringu SocTx na server,nejdříve ho musíme nějak naplnit.
if (send (ServerSock, SocTx, strlen (SocTx) + 1, 0) == SOCKET_ERROR)
{
wsprintf (szError,TEXT("Sending data to the server failed. Error: %d"),WSAGetLastError ());
MessageBox (szError, TEXT("Error"), MB_OK);
};
}
Ukončení spojení
![]()
void CSocketKlientDlg::OnButton2()
{
// TODO: Add your control notification handler code here
// Disable sending on ServerSock.
shutdown (ServerSock, 0x01);
// Disable receiving on ServerSock.
shutdown (ServerSock, 0x00);
// Close the socket.
closesocket (ServerSock);
WSACleanup ();
}
Nastavení sítě pod Windows 2000 Microsoft corp. pro připojení PDA pomocí seriového portu COM2
Nejdříve je třeba dodat, že se u dále uvedeného připojení nepředpokládá instalace Microsoft ActiveSync na PC pro synchronizaci dat mezi PDA . Pokud máme toto nainstalováno a funkční, Socket komunikaci lze zkoušet bez toho aby bylo nutné provádět dále popsaný způsob síťového připojení.
Pozor pokud je ActiveSync nainstalován, spouští se automaticky po startu a k uvedenému připojení nedojde.
Popis komunikace přes Internet ( pomocí GSM telefonu Nokia 5110 ) bude popsán také ale až po praktických aplikacích sběru dat s možností využití Socket Serveru napojeného na ODBC a vykonávající SQL příkazy.
Nejdříve z menu Start Nastavení Síťová a telefonická připojení zvolíme po dotázání, přímé připojení k jinému počítači pomocí seriového portu.

dále zvolíme hostitele ,protože budeme poskytovat služby pro PDA

Dále postupujeme dle požadavků ,
- navolíme port COM2

Vlastnosti portu zvolíme dle obrázků


- uživatele Pocket_PC což identifikace PDA na síti
Uživatel nemusí mít žádné heslo, protože se jedná o přímé připojení

Je nutné mít nainstalován protokol TCP/IP a nastaveny jeho vlastnosti dle následujícího obrázku

IP adresy jsou smyšlené, protože PC není připojeno na Internet.
Vlastní připojení PDA k Win2000
Důležitou věcí pro správnou komunikaci mezi Pocketem a serverem je správné příiřazení IP adresy serveru v registrech Pocket PC, následující obrázek ukazuje nastavenou IP adresu pro server evc-win2000 pojmenovaném na Pocketu jako ppp_peer ,jehož adresa je C0 93 2D 0A což je hexa výpis, zcela libovolně zvolené adresy z důvodu od okolního světa izolované sítě, 192.147.45.10

V Menu Programy spustíme Připojení .

*************************************************
Seriový port COM2 na PC má nastaveno rychlost 19200, kterou vybereme z nabídky v PDA a stiskneme tlačítko připojit.

*************************************************
Nyní již se provádí vlastní připojení.

*************************************************
Pokud máme vše správně nastaveno objeví se následující hlášení:

*************************************************
Následující složka změní příchozí připojení

na Neověřený uživatel

*************************************************
poklepáním na něho si můžeme prohlédnout vlastnosti


*************************************************
Dále zbývá jen spustit na PC Socket Server a na PDA klienta a můžeme komunikovat.
Pokud se na PDA zobrazí

tak ho ignorujeme, přepneme se na aplikaci SocketKlient a pokračujeme, komunikaci na PDA inicializujeme stiskem tlačítka Inic connect , spojení se servrem naváže tlačítko Připojit a tlačítkem Send vysíláme vlastní data, které můžem zapisovat do kolonek login, Heslo,... Spojení ukončíme tlačítkem Odpojit ale síť zůstane zachována.

*************************************************
Pocket PC a socket komunikace v projektu Visual Prog
Při vývoji software VisualProg vyvstal problém vytvořit pro Pocket PC aplikaci, která by umožňovala komunikaci mezi serverem a klienty pomocí socket protokolu. Na PC určeném jako server s instalovanými W2k Workstation, je spuštěna aplikace VisualProg s prvkem D_Srvsocket. Na server byly napojeny další PC s klienty pomocí sítě LAN s protokolem TCP/IP, současně na serveru přes seriovou linku probíhala socket komunikace s Pocketem a právě pro ladění této komunikace bylo potřeba vytvořit jednoduchou aplikaci Socket Server.exe, Socket klienty pro PC (Socket.exe) a Pocket PC (Socketklient.exe) tyto aplikace neprovádějí žádnou kontrolu, pracují dle dále uvedeného popisu a mohou být poskytnuty dalším zájemcům Email Kontakt. .
Prvkek D_Srvsocket pracuje dle principu znázorněném na následujícím obrázku.

Popis činnosti komunikačního kompletu Socket Server.exe, Socket.exe Socketklient.exe:
Spuštěním aplikace Socket Server.exe se čeká na připojení klientů

Na dalším PC se napojuje klient, jeho správné připojení je dáno vypsáním Welcome... po stisku tlačítka Connect.

Pocket PC je připojen přes seriový port COM2 a pomocí Microsoft ActiveSync spuštěném na serveru je navázána komunikace. Je však možné komunikovat i bez ActiveSync, vytvořením ppp kanálu tak jak je popsáno na našich stránkách v položce Pocket PC MIPS Správa TCP/IP. Spuštěním aplikace Socketklient.exe, navázáním spojení pomocí tlačítka Inic connect a Connect je navázáno spojení s serverem

což se projeví vypsáním dalšího klienta v okně aplikace Socket Server

Stiskem Send na Pocketu je vyslána zpráva jak serveru tak i dalším klientům, ta se skládá z obsahu zadávacích text boxů Login,Password,Target,Command, Data. Jedná se o spojené stringy v jeden, oddělené pomocí 0x0D 0x0A.
Obrázek klienta s přijatou zprávou od Pocket PC

Komunikace na lince RS232(485) mezi Pocket PC a Atmel 89C52
pomocí ModBus protokolu
Email Kontakt pro získání dll a exe aplikace zdarma,
za účelem otestováni ( jen funkce 1, nutno zadat zda pro MIPS,... )
Pro spojení Pocket PC a systémů na bázi jednočipu Atmel, případně Motorola 68HC711 vznikla potřeba jejich spojení po seriové lince. Jako komunikační protokol byl zvolen ModBus a tento byl naprogramován tak aby z výčtu funkcí byly podporovány tyto :
1 bitové čtení COIL STATUS
2 bitové čtení INPUT STATUS
3 celočíselné čtení HOLDING REGISTER
4 celočíselné čtení INPUT REGISTER
dále bitový zápis funkce 5 a celočíselný zápis 6
Aplikace byla naprogramována tak aby část uživatelská byla nezávislá na protokolu, tak se rozdělila obsluha seriové linky do samostatné DLL a uživatelský interface jako exe aplikace. Další bližší informace je možno získat u prvku D_ModB pro VisualProg.
Na následujícím obrázku vidíme uživatelskou část záložky Funkce 1 . Zde můžeme zvolit i funkci 2 v políčku Fnk.
Políčko Adres st. nám umožní adresovat na lince více stanic, např. máme v 8 pokojích teploměry s Atmely ( viz Aplikace s mikrořadičem Atmel 89C52 a 89C2052 volba Mikrokontrolery vedle New ...) a tak je můžeme všechny ovládat z PDA pomocí vhodného převodníku RS232/485 .
Políčko Adr mem představuje konkrétní paměťové místo v Atmelu

Nastavení seriového portu je možno změnit v záložce Set Serial

Vlastní Obsluha seriové linky je ponechána v DLL knihovně ( D_ModB_DLL.dll ) a je volána z uživatelské části pomocí zpřístupněných funkcí . Následující části zdrojových kódů vysvětlují jak tuto DLLku přilinkovat k vlastní aplikaci a mít tak možnost využívat ModBus i jinde pomoci PDA Pocket PC.
Programováno je pomocí MFC v Microsoft eMbedded Visual C++ 3.0
Funkce
OnInitDialog je volána při startu aplikace a
jsou zde vytvořeny záložky a přilinkována knihovna pomocí
DLLlibrary = LoadLibrary( _T("D_MODB_DLL.dll")
);
Dále
se volá nastavení seriového portu m_Tab_Serial.Set_Serial();
BOOL CD_ModBusDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
CenterWindow(GetDesktopWindow()); // center to the hpc screen
// TODO: Add extra initialization here
m_oPropSheet.AddPage( &m_Tab_Funkce1 );
m_oPropSheet.AddPage( &m_Tab_Funkce3 );
m_oPropSheet.AddPage( &m_Tab_Serial );
m_oPropSheet.Create( this,WS_CHILD | WS_VISIBLE | WS_TABSTOP,0 );
m_oPropSheet.ModifyStyleEx( 0,WS_EX_NODRAG);//WS_EX_CONTROLPARENT );
m_oPropSheet.SetWindowPos(
NULL,
5,
5,
50,
50,
SWP_NOZORDER | SWP_NOSIZE | SWP_NOACTIVATE
);
DLLlibrary = 0;
DLLlibrary = LoadLibrary( _T("D_MODB_DLL.dll") );
m_Tab_Funkce1.DLLlibrary = DLLlibrary;
m_Tab_Serial .DLLlibrary = DLLlibrary;
m_Tab_Serial.Set_Serial();
return TRUE; // return TRUE unless you set the focus to a control
}
Nastavení
seriového portu m_Tab_Serial.Set_Serial(); je
implementováno ve třídě Tab_Serial což je vlastní záložka a pracuje
zhruba následovně:
- Testuje se zda je
inicializována DLL knihovna if( DLLlibrary==NULL )...
- Najde se v DLL funkce pro
nastavení ser. linky
OpenCOMkanal = (FUNCopen)GetProcAddress(...
- přečtou se pomocí Serialize a CArchive ze
souboru parametry
- parametry se připraví pro DLL do daného formátu
parameter =
"[" + m_Baud
+ "]"...
- Otevře se komunikačni kanál a předají se
parametry, to vše v DLL
chyby_com = OpenCOMkanal( COMkanal,...
void Tab_Serial::Set_Serial()
{
unsigned short *pFileName = _T("\\Serial.txt");
CFile f;
if( DLLlibrary==NULL )
{
MessageBox( _T("DLL not existing"),MB_OK );
return ;
};
//OpenCOMkanal = (FUNCopen)GetProcAddress(DLLlibrary,_T("_OpenCOMkanal@16")); // PC
OpenCOMkanal = (FUNCopen)GetProcAddress(DLLlibrary,_T("OpenCOMkanal")); // Mips
if (OpenCOMkanal==NULL)
{
MessageBox( _T("OpenCOMkanal in DLL not found"),MB_OK );
return ;
};
char buf[512];
if( !f.Open( pFileName, CFile::modeRead ) )
{
f.Close();
MessageBox( _T("Unable to open file \\Serial.txt to read"),MB_OK );
return ;
}
CArchive ar( &f, CArchive::load, 512, buf );
Serialize(ar);
//f.Close();
if( errSer == 1 )
return ;
CString
parameter = "[" + m_Baud + "]" +
"[" + m_Data + "]" +
"[" + m_Parity + "]" +
"[" + m_Stop + "]" +
"[" + m_Timeout + "]";
LPCTSTR strLPCTSTR = m_COM.GetBuffer( m_COM.GetLength());
m_IDC_EDIT_ERR.SetWindowText( parameter+m_COM );
char charKanal[20];
m_CFunkce_App.LPCTSTR_to_Char( charKanal, strLPCTSTR,10);
COMkanal = atoi( charKanal );
chyby_com = OpenCOMkanal
(
COMkanal,
1,
parameter,
pole_dat // Ulozeni zpravy o chybach
);
if( chyby_com )
{
MessageBox( _T("Unable to set serial"),MB_OK );
return ;
}
m_IDC_EDIT_SPEED .SetWindowText( m_Baud );
m_IDC_EDIT_DATAB .SetWindowText( m_Data );
m_IDC_EDIT_PARITA .SetWindowText( m_Parity );
m_IDC_EDIT_STOP .SetWindowText( m_Stop );
m_IDC_EDIT_TIME .SetWindowText( m_Timeout );
m_IDC_EDIT_COM .SetWindowText( m_COM );
}
Vyslání dat na seriovou linku je v DLL knihovně implementováno ve funkci Cteni_bitovych_vystupu
a ta se volá stiskem tlačítka ve třídě Tab_Funkce1.
Opět se testuje správnost inicializace DLL knihovny pak se najde potřebná funkce
a provede se vlastní volání vyslání dat
unsigned int cbv = Cteni_bitovych_vystupu
(
COMkanal, //WORD adr_com, // ktery COM kanal
cisloSt[0], //int adresaSt, // Adesa stanice
200, //long cek_cyk, // jak dlouho cekat
...
void Tab_Funkce1::OnButtonSend1()
{
// TODO: Add your control notification handler code here
CString poleErr;
CString nazev = "DataF";
CFunkce_App Funkce_App;
unsigned short *polePoc;
unsigned short cisloSt[1],
cisloMem[1];
Funkce_App.GetULong( Adres_St .GetBuffer( Adres_St.GetLength()),(unsigned long*)cisloSt );
Funkce_App.GetULong( Adres_Mem.GetBuffer( Adres_St.GetLength()),(unsigned long*)cisloMem );
if( DLLlibrary==NULL )
{
MessageBox( _T("DLL not existing"),MB_OK );
return;
};
//Cteni_bitovych_vystupu = (FUNCcbv)GetProcAddress(DLLlibrary,_T("_Cteni_bitovych_vystupu@40")); // PC Debug
Cteni_bitovych_vystupu = (FUNCcbv)GetProcAddress(DLLlibrary,_T("Cteni_bitovych_vystupu")); // Mips
if (Cteni_bitovych_vystupu!=NULL)
{
unsigned int cbv = Cteni_bitovych_vystupu
(
COMkanal, //WORD adr_com, // ktery COM kanal
cisloSt[0], //int adresaSt, // Adesa stanice
200, //long cek_cyk, // jak dlouho cekat
cisloMem[0], //WORD pocAdr, // pocatecni adresa pole
32, //WORD pocetP, // pocet dat pole max 0-9999 (1-10000)
&poleErr, //char *pole_dat, // Ulozeni zpravy
parameter, //CString Parametr, "[9600][8][NONE][1][300]"
1, //CString PocetBitu,
Funkce1, //CString Naz_promprotokol,
dataf //float *Adr_promprotokol
);
Data_celkem++;
if( cbv==0 )
{
m_IDC_EDITERR.SetWindowText(poleErr);
Set_Static_F1( dataf );
Data_ok++;
}
else
{
Data_err++;
m_IDC_EDITERR.SetWindowText( poleErr );
};
poleErr.Format(_T("%d"),Data_celkem);
polePoc = poleErr.GetBuffer( poleErr.GetLength());
m_IDC_EDITPPO.SetWindowText( polePoc );
poleErr.Format(_T("%d"),Data_ok);
polePoc = poleErr.GetBuffer( poleErr.GetLength());
m_IDC_EDITPOK.SetWindowText( polePoc );
poleErr.Format(_T("%d"),Data_err);
polePoc = poleErr.GetBuffer( poleErr.GetLength());
m_IDC_EDITPER.SetWindowText( polePoc );
}
else
{
MessageBox( _T("Funkc 1(2) in DLL not found"),MB_OK );
return;
};
}