Home www.visualprog.cz

 

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ář

 

Click on of the PayPal button to donate money to PPC CAN Project

 

 

 

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

 Email Kontakt

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;
	};

}