Skip to content

Instantly share code, notes, and snippets.

@nrclark
Created December 27, 2023 17:46
Show Gist options
  • Save nrclark/186b424d1fe75f53e9c06e01ba9baedc to your computer and use it in GitHub Desktop.
Save nrclark/186b424d1fe75f53e9c06e01ba9baedc to your computer and use it in GitHub Desktop.
Powershell script that bridges a COM port to a TCP socket.
#!/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -file
<#
.SYNOPSIS
PowerShell TCP/IP Client for Serial Port Communication.
.DESCRIPTION
This script establishes a TCP connection to a specified server and port and
relays data to and from a specified serial port (COM port).
.PARAMETER server
The IP address / hostname of the TCP server to connect to.
.PARAMETER port
The port number of the TCP server to connect to. Must be in the range 1-65535.
.PARAMETER comport
The COM port for serial communication.
.PARAMETER baud
The baud rate for serial communication. Default is 9600.
.PARAMETER parity
The parity for serial communication. Options are 'None', 'Odd', 'Even',
'Mark', 'Space'. Default is 'None'.
.PARAMETER stopbits
The stop bits for serial communication. Options are 'None', 'One', 'Two',
'OnePointFive'. Default is 'One'.
.PARAMETER databits
The data bits for serial communication. Options are 5, 6, 7, 8. Default is 8.
.PARAMETER help
Displays help information for this script.
.EXAMPLE
.\SerialBridge.ps1 -server "192.168.1.10" -port 1234 -comport "COM3"
Connects to a TCP server at 192.168.1.10:1234 and relays data to and from
COM3 with default serial settings.
On the other end of the link, a receiver can be set up using socat like this:
socat TCP-LISTEN:8080,reuseaddr pty,link=$SOME_FILE,raw,echo=0
(note: the pty output can be replaced with whatever is appropriat for your
application)
.NOTES
Ensure that the COM port and TCP server are available and configured
correctly before running the script.
.LINK
Documentation_Link_If_Available
#>
param (
[ValidatePattern("([0-9]{1,3}[.]){3}[0-9]{1,3}")]
[Parameter(Mandatory = $true)][string] $server,
[Parameter(Mandatory = $true)][int] $port,
[Parameter(Mandatory = $true)][string] $comport,
[int] $baud = 9600,
[ValidateSet("None", "Odd", "Even", "Mark", "Space")]
[string] $parity = "None",
[ValidateSet("None", "One", "Two", "OnePointFive")]
[string] $stopbits = "One",
[ValidateSet(5, 6, 7, 8)]
[int]$databits = 8
)
$ErrorActionPreference = "Stop"
$parity = [System.IO.Ports.parity]($parity)
$stopbits = [System.IO.Ports.stopbits]($stopbits)
Write-Output "server: [$server]"
Write-Output "port: [$port]"
Write-Output "comport: [$comport]"
Write-Output "baud: [$baud]"
Write-Output "stopbits: [$stopbits]"
Write-Output "databits: [$databits]"
Write-Output ""
try {
# Connect to the TCP server
$client = New-Object System.Net.Sockets.TcpClient
$client.NoDelay = $true
$client.LingerState.Enabled = $true
$client.LingerState.LingerTime = 0
Write-Output "Connecting to: ${server}:${port}..."
$connect_job = $client.ConnectAsync($server, $port)
while (-not $connect_job.IsCompleted) {
Start-Sleep -Milliseconds 10
}
if ($null -ne $connect_job.Exception) {
Write-Error "Failed to connect to remote server."
throw $connect_job.Exception
}
Write-Output "Connected to the server."
Write-Output "Opening $comport..."
$serialPort = New-Object System.IO.Ports.SerialPort $comport,
$baud, $parity,
$databits, $stopbits
$serialPort.Open()
$serialPort.DiscardInBuffer()
$serialPort.DiscardOutBuffer()
Write-Output "Serial port is open."
$stream = $client.GetStream()
$bufsize = [math]::min($client.ReceiveBufferSize, $serialPort.ReadBufferSize)
$buffer = New-Object byte[] $bufsize
Write-Output "Begin forwarding serial traffic."
while ($true) {
$wait = $true
if ($serialPort.BytesToRead -gt 0) {
$wait = $false
$readCount = $serialPort.Read($buffer, 0, $serialPort.BytesToRead)
$stream.Write($buffer, 0, $readCount)
}
if ($stream.DataAvailable) {
$wait = $false
$readCount = $stream.Read($buffer, 0, $buffer.Length)
$serialPort.Write($buffer, 0, $readCount)
}
if ($wait) {
Start-Sleep -Milliseconds 1
}
}
}
catch {
Write-Output "An error occurred: $_"
}
finally {
if ($serialPort -and $serialPort.IsOpen) {
$serialPort.Close()
}
if ($client -and $client.Connected) {
$client.Close()
}
}
Write-Output "Connection closed."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment