Imports System.IO
Imports System.IO.Ports
Imports System.Net
Imports System.Net.Sockets
Imports System.Text
Imports System.Threading

Public Class Terminal
    Public IPAdrs As String
    Public connectType As Integer
    Public PortName As String
    Public port As Integer
    Public ip As IPAddress
    Public client As TcpClient
    Public mStream As NetworkStream
    Public fReceive As Boolean = True
    Public serial As SerialPort

    Private SetTxt As New SetTxtDataDelegate(AddressOf SetTxtData)
    Delegate Sub SetTxtDataDelegate(ByVal str1 As String)
    Private Sub SetTxtData(ByVal str1 As String)
        ' データを設定
        TxtRecvData.Text = str1
    End Sub


    Private Sub Terminal_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        ' TCP/IP モード
        If (connectType = 0) Then
            ' IPアドレス
            ip = IPAddress.Parse(IPAdrs)
            ' ポート番号
            port = 5074

            ' クライアント
            client = New TcpClient(ip.ToString(), port)
            ' ストリ－ム
            mStream = client.GetStream()
            mStream.ReadTimeout = 10
            mStream.WriteTimeout = 1000

            ' 受信
            Task.Run(Sub()
                         ReceiveProc()
                     End Sub)

            ' COM モード
        ElseIf (connectType = 1) Then
            serial = New System.IO.Ports.SerialPort()
            ' ポート番号
            serial.PortName = PortName
            ' 転送速度
            serial.BaudRate = 9600
            ' データビット
            serial.DataBits = 8
            ' パリティ
            serial.Parity = System.IO.Ports.Parity.None
            ' ストップビット
            serial.StopBits = System.IO.Ports.StopBits.One
            ' フロー制御
            serial.Handshake = System.IO.Ports.Handshake.None
            ' タイムアウト
            serial.ReadTimeout = 5000
            serial.WriteTimeout = 5000
            ' RTS
            serial.RtsEnable = True
            ' 受信イベント
            AddHandler serial.DataReceived, AddressOf DataReceivedHandler

            ' ポートオープン
            serial.Open()
            serial.DiscardInBuffer()
            serial.DiscardOutBuffer()
        End If
    End Sub

    Private Sub BtnSend_Click(sender As Object, e As EventArgs) Handles BtnSend.Click
        ' TCP/IP モード
        If connectType = 0 Then
            ' データ送信
            writeCommand(mStream, Encoding.ASCII.GetBytes(TxtSendData.Text))

            ' COM モード
        ElseIf connectType = 1 Then
            ' データ送信
            serial.Write(TxtSendData.Text, 0, TxtSendData.Text.Length)
        End If
        ' 送信データクリア
        TxtSendData.Text = String.Empty
    End Sub

    Private Sub BtnRecvClear_Click(sender As Object, e As EventArgs) Handles BtnRecvClear.Click
        ' 受信データクリア
        TxtRecvData.Text = String.Empty
    End Sub

    Private Sub BtnDisConnect_Click(sender As Object, e As EventArgs) Handles BtnDisConnect.Click
        fReceive = False
        ' TCP/IP モード
        If (connectType = 0) Then
            ' ストリームクローズ
            mStream.Dispose()
            ' ソケットクローズ
            client.Dispose()

            ' COM モード
        ElseIf (connectType = 1) Then
            ' ポートクローズ
            serial.Close()
        End If

        ' クローズ
        Close()
    End Sub


    Public Sub writeCommand(ByVal mOutputStream As NetworkStream, ByVal writeBuf As Byte())
        ' データが空でない
        If writeBuf.Length <> 0 Then
            Try
                ' 指定されたデータを出力ストリームに書き込む
                mOutputStream.Write(writeBuf, 0, writeBuf.Length)
                Exit Sub
            Catch ex As Exception
                Debug.WriteLine(ex.Message)
            End Try
        End If
    End Sub
    Public Function readResponse(ByVal mInputStream As NetworkStream) As Byte()
        Dim TotalCount As Integer
        Dim memStream As New MemoryStream()
        Dim rcvBuf As Byte() = New Byte(256) {}
        Dim readCount As Integer
        readCount = 0
        TotalCount = 0

        Try
            ' 受信したデータを出力ストリームに書き込む
            readCount = mInputStream.Read(rcvBuf, 0, rcvBuf.Length)
            While (readCount > 0)
                memStream.Write(rcvBuf, TotalCount, readCount)
                TotalCount += readCount
                readCount = mInputStream.Read(rcvBuf, 0, rcvBuf.Length)
            End While

            ' データがあれば
            If TotalCount > 0 Then
                readResponse = memStream.ToArray()
            End If
        Catch ioe As IOException
            ' データがあれば
            If TotalCount > 0 Then
                readResponse = memStream.ToArray()
            End If
            Debug.WriteLine(ioe.Message)
        Catch se As SocketException
            ' データがあれば
            If TotalCount > 0 Then
                readResponse = memStream.ToArray()
            End If
            Debug.WriteLine(se.Message)
        Catch ex As Exception
            ' データがあれば
            If TotalCount > 0 Then
                readResponse = memStream.ToArray()
            End If
            Debug.WriteLine(ex.Message)
        End Try
        Return memStream.ToArray()
    End Function

    ' TCP/IP受信
    Private Sub ReceiveProc()
        Dim resultBuf() As Byte

        ' TCP/IP モード
        If (connectType = 0) Then
            While fReceive
                Try
                    ' データ受信
                    resultBuf = readResponse(mStream)
                    If resultBuf.Length > 0 Then
                        TxtRecvData.Invoke(SetTxt, TxtRecvData.Text + Encoding.ASCII.GetString(resultBuf))
                    End If
                Catch ex As Exception
                    Debug.WriteLine(ex.Message)
                End Try
            End While
        End If

    End Sub

    Private Sub DataReceivedHandler(sender As Object, e As SerialDataReceivedEventArgs)
        Dim Offset As Byte
        Dim result As Byte
        Dim RetryCount As Integer
        Dim readbuf(1024) As Byte

        Offset = 0
        result = 0
        RetryCount = 0

        ' COM モード
        If (connectType = 1) Then
            While (fReceive)

                result = serial.BytesToRead
                ' 受信データ取得
                serial.Read(readbuf, Offset, result)

                Offset = Offset + result
                ' 50msウェイト
                System.Threading.Thread.Sleep(50)

                If (result > 0) Then
                    RetryCount = 0
                Else
                    Exit While
                End If
            End While

            ' データがあれば追加して表示更新
            If (Offset > 0) Then
                TxtRecvData.Invoke(SetTxt, TxtRecvData.Text + Encoding.ASCII.GetString(readbuf))

            End If
        End If
    End Sub
End Class