TCP/IP RSTP

HMG en Español

Moderator: Rathinagiri

User avatar
danielmaximiliano
Posts: 2632
Joined: Fri Apr 09, 2010 4:53 pm
Location: Argentina
Contact:

TCP/IP RSTP

Post by danielmaximiliano »

Hola a todos:
hace un tiempo compre 2 camaras IP PTZ las cuales vienen con software, una es para android (con muchas funciones) pero el software para windows (muy fea y pocas funciones) lo cual me tome el tiempo de investigar como funciona.
estas se conectan mediante TCP (conexión y envio de comandos RSTP) y sobre TCP (RTP los datos de video son devueltos)
todo esto lo veo mediante WIRESHARK analizando los paquetes en mi red interna.

mi pregunta es: Alguien trabajo con Harbour/HMG con TCP para decirme como empezar ya que necesito primer conectarme con el servidor RSTP
desde ya gracias
*´¨)
¸.·´¸.·*´¨) ¸.·*¨)
(¸.·´. (¸.·` *
.·`. Harbour/HMG : It's magic !
(¸.·``··*

Saludos / Regards
DaNiElMaXiMiLiAnO

Whatsapp. := +54901169026142
Telegram Name := DaNiElMaXiMiLiAnO
User avatar
mol
Posts: 3799
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: TCP/IP RSTP

Post by mol »

Hola Daniel!
I don't know if I understood your request.
I'm using TCPIP to connect with fiscal printer
Maybe some code will be useful for you

Code: Select all



CLASS DF_KOMUNIKATOR
	DATA	lTcpIP	INIT .F.
	DATA	oPort	INIT NIL
	//
	DATA	cIpAdress INIT ""
	DATA	nIpPort		INIT 0
	DATA	nTimeOut	INIT 5000  // 3 sekundy
	// dalej obsługa przez serial
	DATA	cDFPortName INIT "" // nazwa portu COM
	DATA	nPredkosc	INIT 9600
	DATA	nParzystosc	INIT NOPARITY
	DATA	nBitow		INIT 8
	DATA	nBitowStopu	INIT ONESTOPBIT
	// stan portu
	DATA	Open	INIT .F.
	//
	DATA	nProducent	INIT 1	// Novitus
	DATA	nCodePage	INIT 1	// Mazovia
	
	METHOD	INIT	SETGET
	METHOD	WRITE	SETGET
	METHOD	READ	SETGET
	METHOD	CLOSE	SETGET
ENDCLASS

*---------
METHOD Init(lTcpIp, cNazwaPortu, nPort, nPredkosc, nParzystosc, nBitow, nBitowStopu, nTimeout) CLASS DF_KOMUNIKATOR

	::lTcpIp := lTcpIp

	if ::lTcpIp
		if HB_PING(cNazwaPortu)<>0
			MsgStop("Drukarka fiskalna nie odpowiada na adresie: "+cNazwaPortu)
			return NIL
		endif
		
		if Empty( ::oPort := hb_socketOpen( HB_SOCKET_AF_INET, HB_SOCKET_PT_STREAM))	//, HB_SOCKET_IPPROTO_UDP ) )
			//MsgStop( "socket create error " + hb_ntos( hb_socketGetError() ) )
			MsgStop( "Błąd przy zestawieniu połączenia", "WYDRUK FISKALNY")
			return NIL
		endif

		if ! hb_socketConnect( ::oPort, { HB_SOCKET_AF_INET, cNazwaPortu, nPort } )
			//MsgStop( "socket connect error " + hb_ntos( hb_socketGetError() ) )
			MsgStop( "Błąd przy zestawieniu połączenia", "WYDRUK FISKALNY")
			return NIL
		endif
		::cIpAdress := cNazwaPortu
		::nIpPort := nPort
	
	else
	
		::cDFPortName	:= cNazwaPortu
		::nPredkosc		:= nPredkosc
		::nParzystosc	:= nParzystosc
		::nBitow		:= nBitow
		::nBitowStopu	:= nBitowStopu
		
		::oPort := win_com():Init(cNazwaPortu, nPredkosc, nParzystosc, nBitow, nBitowStopu)
		if !::oPort:Open

			MsgBox("Błąd otwarcia portu komunikacyjnego - BRAK POŁĄCZENIA Z DRUKARKĄ FISKALNĄ!", "WYDRUK FISKALNY" )
			::oPort := NIL
			return NIL
		else
			// "Open succeeded"
			::oPort:RTSFlow(.F.)
			::oPort:DTRFlow(.F.)       
			::oPort:XonXoffFlow(.t.)
			::oPort:SetDTR(.t.)
		endif
	endif
	
	// sprawdzamy, czy drukarka w ogóle jest podłączona
	if !::Write( DLE )	// < 1)
		MsgStop("Brak komunikacji z drukarką fiskalną", "WYDRUK FISKALNY" )
		return NIL
	endif
	
	::nTimeOut := nTimeout
	::Open := .t.
return SELF
*---------
METHOD Write(cDaneDoWyslania) CLASS	DF_KOMUNIKATOR
	local xLen := 0
	local lOK := .T.
	
	if ::lTcpIp
		hb_socketSend( ::oPort, cDaneDoWyslania )
	else
		xLen := ::oPort:Write(cDaneDoWyslania)
		if valtype(xLen) <> "N"
			lOK := .f.
		else
			lOK := (xLen == len(cDaneDoWyslania))
		endif
		if !lOK
			MsgStop("Operacja zakończona niepowodzeniem. Błąd komunikacji z durkarką fiskalną!", "WYDRUK FISKALNY" )
		endif
	endif
return lOK
*---------
METHOD Read(cOdpowiedz, n)  CLASS	DF_KOMUNIKATOR
	hb_default(@n,1)
	cOdpowiedz := space(n)
	if ::lTcpIp
		n := hb_socketRecv( ::oPort, @cOdpowiedz,,, ::nTimeOut )
		//debugmsg("odpowiedz", cOdpowiedz)
	else
		::oPort:Read(@cOdpowiedz, n)
	endif
return cOdpowiedz
*---------
METHOD Close CLASS	DF_KOMUNIKATOR
	if ::lTcpIp
		hb_socketShutdown( ::oPort )
		hb_socketClose( ::oPort )
	else	
		::oPort:Close()
	endif
	::oPort := NIL
return

User avatar
danielmaximiliano
Posts: 2632
Joined: Fri Apr 09, 2010 4:53 pm
Location: Argentina
Contact:

Re: TCP/IP RSTP

Post by danielmaximiliano »

Thanks Marek, it is an IP camera, it has RTSP (Real-Time Streaming Protocol) functions.
*´¨)
¸.·´¸.·*´¨) ¸.·*¨)
(¸.·´. (¸.·` *
.·`. Harbour/HMG : It's magic !
(¸.·``··*

Saludos / Regards
DaNiElMaXiMiLiAnO

Whatsapp. := +54901169026142
Telegram Name := DaNiElMaXiMiLiAnO
User avatar
danielmaximiliano
Posts: 2632
Joined: Fri Apr 09, 2010 4:53 pm
Location: Argentina
Contact:

Re: TCP/IP RSTP

Post by danielmaximiliano »

Hola a todos:
Con la ayuda de WireShark pude ver como es el inicio de sesion de la aplicacion de la camara sobre TCP/IP capturando los paquetes TCP en la red.
Pude crear el socket y sobre protocolo RSTP pude enviar las credenciales al servidor RSTP de la camara y que acepte mis peticiones.
Ahora en mas resolver los metodos SETUP y extraer la sessionID para completar el metodo PLAY

Code: Select all

#include <hmg.ch>
#include "hbsocket.ch"


FUNCTION Main()
   PUBLIC oSocket , cRequest
   PUBLIC cRtspDescribe    := Space( 1024 )
   PUBLIC cRtspSetup       := Space( 1024 )
   PUBLIC cRtspPlay        := Space( 1024 )
   PUBLIC nPos, nEnd, nSeq := 0
   PUBLIC cSession         := ""
   PUBLIC cServerIP        := "192.168.100.16"   // IP de la cámara
   PUBLIC nPort            := 554                // Puerto RTSP
   
   LOAD Window Main
   Center Window Main
   Activate Window Main
   
   FUNCTION Connect()
   oSocket    := hb_socketOpen()
   IF oSocket == NIL
      MSGINFO("Error al crear socket")
      RETURN
   ENDIF

   IF ! hb_socketConnect( oSocket, {HB_SOCKET_AF_INET, cServerIP, nPort } )
      MSGINFO("No se pudo conectar a:", cServerIP)
      hb_socketClose( oSocket )
      RETURN
   ENDIF

   // 1) DESCRIBE
      nSeq++
      cRequest := "DESCRIBE rtsp://192.168.100.16:554/22992e47b611dde40dde83b803ca1ab0_0 RTSP/1.0\r\n" + CRLF + ;
                  "CSeq: " + LTRIM( STR( nSeq ) ) + "\r\n"                                             + CRLF + ;
		          "User-Agent: HarbourClient/1.0\r\n"                                                  + CRLF + ;
                  "Accept: application/sdp\r\n"                                                        + CRLF + CRLF
   hb_socketSend( oSocket, cRequest       )
   hb_socketRecv( oSocket, @cRtspDescribe, LEN( cRtspDescribe )  )

   // 2) SETUP 
   nSeq++
   cRequest := "SETUP rtsp://192.168.100.16:554/22992e47b611dde40dde83b803ca1ab0_0/trackID=0 RTSP/1.0\r\n"  + CRLF + ;
               "CSeq: " + LTRIM( STR( nSeq ) ) + "\r\n"                                                     + CRLF + ;
		       "User-Agent: HarbourHMGClient/1.0\r\n"                                                       + CRLF + ;
               "Transport: RTP/AVP/TCP;unicast;interleaved=2\r\n"                                           + CRLF + CRLF
   hb_socketSend( oSocket, cRequest )
   hb_socketRecv( oSocket, @cRtspSetup )
   
   // Extraer Session ID
   PUBLIC nPos, nEnd, cSession := ""
   nPos := AT( "Session:", cRtspSetup )
   IF nPos > 0
      nEnd := AT( CRLF, SUBSTR( cRtspSetup, nPos ) )
      cSession:= ALLTRIM( SUBSTR( cRtspSetup, nPos + 8, nEnd-1 ) )
   ENDIF

   
   // 3) PLAY
   nSeq++
   cRequest := "PLAY rtsp://192.168.100.16:554/22992e47b611dde40dde83b803ca1ab0_0 RTSP/1.0\r\n" + CRLF + ;
        "CSeq: " + LTRIM(STR(nSeq))                                                            + CRLF + ;
        "Session: " + cSession                                                                  + CRLF + ;
        "Range: npt=0.000-\r\n"                                                                 + CRLF + CRLF   
   hb_socketSend( oSocket, cRequest )
   hb_socketRecv( oSocket, @cRtspPlay , LEN( cRtspPlay ))
   WAITWINDOW()
   hb_socketClose( oSocket )

RETURN
*´¨)
¸.·´¸.·*´¨) ¸.·*¨)
(¸.·´. (¸.·` *
.·`. Harbour/HMG : It's magic !
(¸.·``··*

Saludos / Regards
DaNiElMaXiMiLiAnO

Whatsapp. := +54901169026142
Telegram Name := DaNiElMaXiMiLiAnO
User avatar
serge_girard
Posts: 3336
Joined: Sun Nov 25, 2012 2:44 pm
DBs Used: 1 MySQL - MariaDB
2 DBF
Location: Belgium
Contact:

Re: TCP/IP RSTP

Post by serge_girard »

Great project!
There's nothing you can do that can't be done...
User avatar
mol
Posts: 3799
Joined: Thu Sep 11, 2008 5:31 am
Location: Myszków, Poland
Contact:

Re: TCP/IP RSTP

Post by mol »

Very iteresting!
Don't you need to send username and password for the camera?
franco
Posts: 887
Joined: Sat Nov 02, 2013 5:42 am
DBs Used: DBF
Location: Canada

Re: TCP/IP RSTP

Post by franco »

Nice work.
How long after taking picture does it arrive on computer. Or is this what it does.
Do you think this would work with a cell phone.
What size is the image when you receive it. What format ? jpg
All The Best,
Franco
Canada
User avatar
danielmaximiliano
Posts: 2632
Joined: Fri Apr 09, 2010 4:53 pm
Location: Argentina
Contact:

Re: TCP/IP RSTP

Post by danielmaximiliano »

mol wrote: Sun Sep 28, 2025 5:21 pm Very iteresting!
Don't you need to send username and password for the camera?
Hello Mol, sorry for the delay in answering your question.
On Android or PC, when installing the application it insists on adding the camera with its QR or Code that it has on a label. When you run the program or application, it only asks for the password and then recommends changing it. it never asks you to enter it again that's why I use the RTSP chain that I see in WIRESHARK.
I am studying how to recover the SessionID returned by the "SETUP" Method, which it is not returning with my program but in the case of the official application.
by the way I am encapsulating all the classes
However, with the method "OPTION" that I do not see that the official application uses through WireShark, it does return the SessionID that is required by other RTSP Methods
En Android o la PC, al instalar la aplicacion te insiste en agregar la camara con su QR o Codigo que tiene en una etiqueta. al ejecutar el programa o aplicacion te pide solamente el password y despues te recomienda cambiarlo. nunca ms te pide entrarlo por eso yo uso la cadena RTSP que veo en WIRESHARK.
estoy estudiando la forma de recuperar la SessionID que devuelve el Metodo "SETUP" al cual no est devolviendo con mi programa pero si en el caso de la aplicacion oficial.
de paso estoy encapsulando todo el Clases
sin embargo con el metodo "OPTION" que no veo que usa la aplicacion oficial mediante WireShark si devuelve la SessionID que es requerida por otros Metodos de RTSP
*´¨)
¸.·´¸.·*´¨) ¸.·*¨)
(¸.·´. (¸.·` *
.·`. Harbour/HMG : It's magic !
(¸.·``··*

Saludos / Regards
DaNiElMaXiMiLiAnO

Whatsapp. := +54901169026142
Telegram Name := DaNiElMaXiMiLiAnO
User avatar
danielmaximiliano
Posts: 2632
Joined: Fri Apr 09, 2010 4:53 pm
Location: Argentina
Contact:

Re: TCP/IP RSTP

Post by danielmaximiliano »

Hola a todos: despúes de luchar varios dias con encapsular en clases los métodos RTSP pude conectarme a la cámara IP PTZ y enviar
OPTION, DESCRIBE, SETUP, PLAY y TEARDOWN con hbsocket y la ayuda de WIRESHARK :D
ahora me queda recuperar los datos de VIDEO y AUDIO para mostrarlo en una VENTANA con ACTIVEX de VLC :mrgreen:
Captura de pantalla 2025-10-02 161830.jpg
Captura de pantalla 2025-10-02 161830.jpg (325.62 KiB) Viewed 423 times
les dejos el fuente aquí :arrow:
Camera.rar
(283.92 KiB) Downloaded 20 times
próximamente iré publicando las mejoras
*´¨)
¸.·´¸.·*´¨) ¸.·*¨)
(¸.·´. (¸.·` *
.·`. Harbour/HMG : It's magic !
(¸.·``··*

Saludos / Regards
DaNiElMaXiMiLiAnO

Whatsapp. := +54901169026142
Telegram Name := DaNiElMaXiMiLiAnO
Post Reply