TCP Client Software Device Plugin

General HouseBot discussion. Any issues that don't fit into any of the other topics belong here.
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

TCP Client Software Device Plugin

Post by Osler »

The title says it all. Find attached a software device to allow two-way communication with a TCP server. It is very basic and will need to have some sort of script associated with it that can parse the incoming data and clear the client buffer periodically. Questions, comments, feature requests...let me know. It was written using Visual Basic 2008 Express Edition and will require the HBDotNet.dll and the HBDotNetBridge.dll (both included in the download). See the ReadMe file that is included for set-up instructions.

Osler
Attachments
HB_TCP Client_02122010.zip
(106.16 KiB) Downloaded 579 times
Basi
Member
Posts: 15
Joined: Fri Apr 28, 2006 12:17 am

Re: TCP Client Software Device Plugin

Post by Basi »

Hi Osler,

Thank you for this. I downloaded the zip and read through the PDF file. I am wondering if this can work as an http listener?
It would be kind of nice to give HB a built in web server (so to speak). It wouldn't have to serve up html pages, but just respond
to simple HTTP GET requests. Anyway just a thought/comment.

Can you give some examples of the intended use of this plugin. It seams like one coud use it to access ethernet devices like network IP cameras?

Thanks, -Basi
Basi
Member
Posts: 15
Joined: Fri Apr 28, 2006 12:17 am

Re: TCP Client Software Device Plugin

Post by Basi »

Hi Osler,

Thank you for this. I downloaded the zip and read through the PDF file. I am wondering if this can work as an http listener?
It would be kind of nice to give HB a built in web server (so to speak). It wouldn't have to serve up html pages, but just respond
to simple HTTP GET requests. Anyway just a thought/comment.

Can you give some examples of the intended use of this plugin. It seams like one coud use it to access ethernet devices like network IP cameras?

Thanks, -Basi
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: TCP Client Software Device Plugin

Post by Osler »

Yes, I was looking at doing a listener as well since the code is not that much different. I am finishing up work on two other plugins and will take a look at doing a TCP listener when I am done.

For my particular purpose, I use a modified version to interface to my SageTV server to allow me to get recording details, guide data, and control media extenders around the house. Scott uses his one-way version to control MS Media Center. I made a generic version while writing the SageTV plugin because I know a few others had requested this functionality in the past.

For IP cameras and such you probably want to look at the web browser I wrote a while back that will allow you to integrate an IE window into your software remote.

Osler
roussell
Advanced Member
Posts: 268
Joined: Wed Dec 15, 2004 9:07 am
Location: Pelham, AL

Re: TCP Client Software Device Plugin

Post by roussell »

I'd love to try out your Sage plugin when it's ready.

Terry
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: TCP Client Software Device Plugin

Post by Osler »

@roussell:

You have PM.

Osler
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: TCP Client Software Device Plugin

Post by Osler »

Find below the source code for this project in case someone needs to modify it to meet their needs. It was coded in MS Visual Basic 2008 Express Edition. Don't forget to add a reference to HBDotNet. Many thanks to allanstevens for posting his source code for the weather.com plugin.

Osler

Code: Select all

Imports System
Imports System.Collections.Generic
Imports System.Text
Imports HBDotNet
Imports System.Net
Imports System.IO
Imports System.Net.Sockets

Namespace TCPClient
    <HBDevice("TCP Client")> _
    Public Class TCPClient
        Inherits HBDeviceBase

        Public Event onConnect()
        Public Event onerror(ByVal Description As String)
        Public Event onDataArrival(ByVal Data As String, ByVal TotalBytes As Integer)
        Public Event onDisconnect()
        Public Event onSendComplete(ByVal DataSize As Integer)

        Private Shared response As [String] = [String].Empty
        Private Shared port As Integer = 44
        Private Shared ipHostInfo As IPHostEntry = Dns.GetHostEntry("localhost")
        Private Shared ipAddress As IPAddress = ipHostInfo.AddressList(0)
        Private Shared client As New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
        Private Shared MyBuffer As New StringBuilder
        Public Overloads Overrides Function OnInit(ByVal enabled As Boolean) As Boolean
            If enabled Then
                enabled = OnEnable()
            End If
            MyBase.OnInit(enabled)
            Return True
        End Function
        Public Overloads Overrides Sub OnShutdown()
            Try
                client.Shutdown(SocketShutdown.Both)
            Catch
            End Try
            client.Close()
            MyBase.OnShutdown()
        End Sub
        Public Overloads Overrides Function OnEnable() As Boolean
            If Me.Connected = False Then
                If GetProperty("TCConnected") = "1" Then
                    If GetProperty("TCHostAddress") <> "<ENTER IP ADDRESS>" And GetProperty("TCHostPort") <> "<ENTER PORT NUMBER>" Then
                        Me.EstablishConnection(GetProperty("TCHostAddress"), CInt(GetProperty("TCHostPort")))
                    End If
                End If
            End If
            Return True
        End Function
        Public Overloads Overrides Function OnDisable() As Boolean
            If Me.Connected = True Then
                Me.BreakConnection()
            End If
            Return MyBase.OnDisable()
        End Function
        Public Overloads Overrides Sub OnAboutBox()
            MsgBox("This plugin is used to send and receive data from a TCP server.")
        End Sub
        Protected Overloads Overrides Function OnPropertyChangeRequest(ByVal hbProperty As HBDotNet.HBProperty, ByVal newValue As String) As Boolean
            HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, hbProperty.Name & " changed to " & newValue)
            If Me.Connected() = True Then
                If hbProperty.Name = "TCSendData" And newValue <> "" Then
                    Me.SendData(newValue & vbCr)
                End If
                If hbProperty.Name = "TCHostAddress" Or hbProperty.Name = "TCHostPort" Then
                    Me.BreakConnection()
                End If
                If hbProperty.Name = "TCConnected" And newValue = "0" Then
                    Me.BreakConnection()
                End If
            Else
                If hbProperty.Name = "TCConnected" And newValue = "1" Then
                    If GetProperty("TCHostAddress") <> "<ENTER IP ADDRESS>" And GetProperty("TCHostPort") <> "<ENTER PORT NUMBER>" Then
                        Me.EstablishConnection(GetProperty("TCHostAddress"), CInt(GetProperty("TCHostPort")))
                    Else
                        HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttError, "IP address or port are not valid.")
                    End If
                End If
            End If
            Return MyBase.OnPropertyChangeRequest(hbProperty, newValue)
        End Function
        Public Overloads Overrides Function OnRegisterProperties() As Boolean
            Properties.Add(New HBProperty("TCHostAddress", "TCHostAddress", False, "<ENTER IP ADDRESS>", eIOType.ioOutputOnly, True, _
             True, True, False, ePropertyType.ptAlpha, ""))
            Properties.Add(New HBProperty("TCHostPort", "TCHostPort", False, "<ENTER PORT NUMBER>", eIOType.ioOutputOnly, True, _
             True, True, False, ePropertyType.ptAlpha, ""))
            Properties.Add(New HBProperty("TCConnected", "TCConnected", True, "0", eIOType.ioInputAndOutput, True, _
             True, True, False, ePropertyType.ptBoolean, ""))
            Properties.Add(New HBProperty("TCClear", "TCClear", False, "0", eIOType.ioInputAndOutput, True, _
             True, True, False, ePropertyType.ptBoolean, ""))
            Properties.Add(New HBProperty("TCReceivedData", "TCReceivedData", False, "", eIOType.ioInputOnly, True, _
             True, True, False, ePropertyType.ptAlpha, ""))
            Properties.Add(New HBProperty("TCSendData", "TCSendData", False, "", eIOType.ioOutputOnly, True, _
             True, True, False, ePropertyType.ptAlpha, ""))
            Return MyBase.OnRegisterProperties()
        End Function
        Public Sub SetProperty(ByVal propertyName As String, ByVal propertyValue As String)
            Properties.GetPropertyByName(propertyName).CurrentValue = propertyValue
        End Sub
        Public Sub SetProperty(ByVal propertyName As String, ByVal propertyValue As Double)
            Properties.GetPropertyByName(propertyName).CurrentValue = propertyValue.ToString()
        End Sub
        Public Sub SetProperty(ByVal propertyName As String, ByVal propertyValue As Double, ByVal decimalPrecision As Integer)
            Properties.GetPropertyByName(propertyName).CurrentValue = propertyValue.ToString("F" & decimalPrecision.ToString())
        End Sub
        Public Function GetProperty(ByVal propertyName As String) As String
            Return Properties.GetPropertyByName(propertyName).CurrentValue
        End Function
        Private Sub EstablishConnection(ByVal RemoteHostName As String, ByVal RemotePort As Integer)
            Try
                client = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
                port = RemotePort
                ipHostInfo = Dns.GetHostEntry(RemoteHostName)
                ipAddress = ipHostInfo.AddressList(0)
                Dim remoteEP As New IPEndPoint(ipAddress, port)
                client.BeginConnect(remoteEP, AddressOf sockConnected, client)
                HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "Attempting connection to " & RemoteHostName & ":" & RemotePort.ToString & ".")
            Catch
                RaiseEvent onerror(Err.Description)
                Exit Sub
            End Try
        End Sub
        Private Sub SendData(ByVal Data As String)
            Try
                Dim byteData As Byte() = ASCIIEncoding.ASCII.GetBytes(Data)
                client.BeginSend(byteData, 0, byteData.Length, 0, AddressOf sockSendEnd, client)
                HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "Sending data (" & Data & ").")
            Catch
                RaiseEvent onerror(Err.Description)
                Exit Sub
            End Try
        End Sub
        Private Sub BreakConnection()
            Try
                client.Shutdown(SocketShutdown.Both)
                HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "Socket shutting down.")
            Catch
                HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "There was a problem shutting down the socket.")
            End Try
        End Sub
        Private Sub sockConnected(ByVal ar As IAsyncResult)
            Try
                If client.Connected = False Then RaiseEvent onerror("Connection refused.") : Exit Sub
                Dim state As New StateObject
                state.workSocket = client
                client.BeginReceive(state.buffer, 0, state.BufferSize, 0, AddressOf sockDataArrival, state)
                RaiseEvent onConnect()
            Catch
                RaiseEvent onerror(Err.Description)
                Exit Sub
            End Try
        End Sub
        Private Sub sockDataArrival(ByVal ar As IAsyncResult)
            Dim state As StateObject = CType(ar.AsyncState, StateObject)
            Dim client As Socket = state.workSocket
            Dim ReuseSocket As Boolean = True
            Dim bytesRead As Integer
            Try
                bytesRead = client.EndReceive(ar)
            Catch
                Exit Sub
            End Try
            System.Threading.Thread.CurrentThread.Sleep(500)
            Try
                Dim Data() As Byte = state.buffer
                If bytesRead = 0 Then
                    client.Disconnect(True)
                    HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "Socket closing.")
                    RaiseEvent onDisconnect()
                    Exit Sub
                End If
                ReDim state.buffer(32767)
                client.BeginReceive(state.buffer, 0, state.BufferSize, 0, AddressOf sockDataArrival, state)
                RaiseEvent onDataArrival(Replace(Replace(Replace(ASCIIEncoding.ASCII.GetString(Data), Chr(3), "<ETX>" & Chr(149)), Chr(2), "<STX>"), Chr(0), ""), bytesRead)
            Catch
                RaiseEvent onerror(Err.Description)
                Exit Sub
            End Try
        End Sub
        Private Sub sockSendEnd(ByVal ar As IAsyncResult)
            Try
                Dim client As Socket = CType(ar.AsyncState, Socket)
                Dim bytesSent As Integer = client.EndSend(ar)
                RaiseEvent onSendComplete(bytesSent)
            Catch
                RaiseEvent onerror(Err.Description)
                Exit Sub
            End Try
        End Sub
        Private Function Connected() As Boolean
            Try
                Return client.Connected
            Catch
                RaiseEvent onerror(Err.Description)
                Exit Function
            End Try
        End Function
        Private Sub ClearBuffer()
            Dim MyBufferLength As Integer = MyBuffer.Length
            MyBuffer.Remove(0, MyBufferLength)
            Me.SetProperty("TCClear", "0")
        End Sub
        Private Sub TCPSocket_onConnect() Handles Me.onConnect
            HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "Connection established.")
        End Sub
        Private Sub TCPSocket_onDataArrival(ByVal Data As String, ByVal TotalBytes As Integer) Handles Me.onDataArrival
            HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "Data (" & Data & ") arrived.")
            If Me.GetProperty("TCClear") = "1" Then
                Me.ClearBuffer()
            End If
            MyBuffer.Append(Data)
            Me.SetProperty("TCReceivedData", MyBuffer.ToString)
        End Sub
        Private Sub TCPSocket_onDisconnect() Handles Me.onDisconnect
            Me.SetProperty("TCConnected", "0")
            Me.ClearBuffer()
            HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "Socket disconnected.")
        End Sub
        Private Sub TCPSocket_onerror(ByVal Description As String) Handles Me.onerror
            HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttError, "TCP Socket Error: " & Description)
            Err.Clear()
        End Sub
        Private Sub TCPSocket_onSendComplete(ByVal DataSize As Integer) Handles Me.onSendComplete
            Me.SetProperty("TCSendData", "")
            HBModule.TraceDeviceMessage(_deviceHandle, TRC_TYPE.ttDebug, "Data sent.")
        End Sub
    End Class
    Public Class StateObject
        Public workSocket As Socket = Nothing
        Public BufferSize As Integer = 32767
        Public buffer(32767) As Byte
        Public sb As New StringBuilder()
    End Class
End Namespace
Autodomain
Member
Posts: 23
Joined: Sun Sep 27, 2009 6:41 am
Location: London GB

Re: TCP Client Software Device Plugin

Post by Autodomain »

Hi Osler,

I'm using your plugin to control a dreambox satellite receiver and it work fine, but when i try to install another instance of that plugin and set the property TCConnected to 1 then Housebot exit to windows . Can You advice me how to do that without problem ??

Here the dump file.
  • ====== Begin Dump - Sunday, May 30, 2010 14:49:26 ======
    Server Version = 3.30.02

    ==================================
    ======== House Server Thread =======
    ==================================
    Thread Type = Device Thread [TCP Client] - [rs485_serial]
    Thread ID = E14
    Exception code: C0000005 ACCESS_VIOLATION
    Fault address: 09CBCE59 79E883DF:2D21BDAB 0Í"

    Registers:
    EAX:0A496498
    EBX:07A921D4
    ECX:07AAEE10
    EDX:00000000
    ESI:07AAEE10
    EDI:00000000
    CS:EIP:001B:09CBCE59
    SS:ESP:0023:0CB1FBA8 EBP:0CB1FBBC
    DS:0023 ES:0023 FS:003B GS:0000
    Flags:00010202

    Call stack:
    Address Frame
    09CBCE59 0CB1FBBC 0000:00000000
    09CBA9EB 0CB1FBF0 0000:00000000
    09CBA7C6 0CB1FC00 0000:00000000
    09CBA780 0CB1FC20 0000:00000000
    79E821B9 0CB1FCA0 DllUnregisterServerInternal+619D
    79FC1F92 0CB1FCC0 StrongNameErrorInfo+53EE
    79FC214A 0CB1FDC8 StrongNameErrorInfo+55A6
    79FC226E 0CB1FEA0 StrongNameErrorInfo+56CA
    074335F8 0CB1FED0 0000:00000000
    078C344A 0CB1FF08 HBDeviceRun+1A
    00406E8C 0CB1FF74 CxIOFile::~CxIOFile+3F0C
    785432A3 0CB1FFAC endthread+52
    7854332B 0CB1FFB4 endthread+DA
    7C80B729 0CB1FFEC GetModuleFileNameA+1BA


    ====== End Dump ======
Here the screenshot.
screenshot.JPG
screenshot.JPG (79.84 KiB) Viewed 10898 times
Thanks in advance .
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: TCP Client Software Device Plugin

Post by Osler »

This is a problem I am currently attempting to find a solution for. For some reason you can't have multiple device instances. Hopefully I can get this fixed soon. How many of these devices do you need? If you have the capability you can use the code I posted in VB express and compile a new dll with a slightly different name for each device you need.

Osler
Autodomain
Member
Posts: 23
Joined: Sun Sep 27, 2009 6:41 am
Location: London GB

Re: TCP Client Software Device Plugin

Post by Autodomain »

Thanks for the quick response,
I need at least 4 TCP device, 2 satellite receiver and 2 rs232 over tcp.
I already tried to re-compile that dll, but I'm not an expert about visual basic and dll. I can try again if You drive me to the correct path, otherwise I will wait until You sort out the problem.

Thanks
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: TCP Client Software Device Plugin

Post by Osler »

There are others who say they are not seeing this problem when using the dotnetbridge so let me poke around. I am obviously doing something wrong, but it is unclear to me at this time exactly what that is.

Osler
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: TCP Client Software Device Plugin

Post by Osler »

roussell is looking at the source for the DotNetBridge and may have a solution.

If a solution is not forthcoming by this weekend, I will compile 4 separate dll files for you to use to bridge you until the DotNetBridge issue is resolved. :wink:

Osler
Autodomain
Member
Posts: 23
Joined: Sun Sep 27, 2009 6:41 am
Location: London GB

Re: TCP Client Software Device Plugin

Post by Autodomain »

Do not worry about that, I have found another solution.
I'm usnig Http request instead of a telnet connection, it is much faster than a telnet connection and is connectionless.

I use,

Code: Select all

"http://"192.168.1.122/web/getcurrent"
to get a xml code, and a vbs script to parse it.

But I will need Your plug-in after for the virtual serial port.

I want to say thanks to Osler and all other valuable members of this forum.
chrisrey
Member
Posts: 10
Joined: Wed Mar 17, 2010 10:57 am

Re: TCP Client Software Device Plugin

Post by chrisrey »

Hi Osler, I tried the plugin, no problem getting data, but unable to send data to the server, and each time I get data the TCConnected returns to 0, any idea? :?:
Osler
HouseBot Guru
Posts: 742
Joined: Fri Feb 03, 2006 11:18 pm

Re: TCP Client Software Device Plugin

Post by Osler »

What does the device log say?

Osler
Post Reply