My Meter is using 300 baud, 7 data bits one stopbit therefore I had to adjust some peaces. Furthermore this slow communication needs some sleep-timers so the unit can work it out. My meter will only reply the total usage since installation, therefore I need to calculate the current usage.
The script is currently waiting till the counter increases and calculates the usage using timestamps. With the slow communication this way of calculation is guessing the current usage always a little too high because I can't get a live update when the counter increases. Other way around would be to poll only each couple of minutes giving a better guess but far less updates to domoticz... Maybe someone has a smart idea to improve this?
I removed a couple redundancies and debug-writelines in the code when pasting it here, but it should still work out of the box.
Code: Select all
<#
.SYNOPSIS
Listens to and read data from a serial port (e.g. COM port)
.DESCRIPTION
The purpose of this script is to keep listening and read D0 data from a serial port - preconfigured for BAUD300.
All the data captured will be displayed and log into a file.
.AUTHOR
Cornholio1234 2017, using source from Heiswayi Nrird, 2016
#>
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')]
[Alias()]
[OutputType([int])]
function SerialPortReader
{
[CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='Medium')]
[Alias()]
[OutputType([int])]
Param
(
[Parameter(Mandatory=$false, Position=0)]
[ValidateNotNullOrEmpty()]
[string]$PortName = "COM6",
[Parameter(Mandatory=$false, Position=1)]
[ValidateNotNullOrEmpty()]
[int]$BaudRate = 300,
[Parameter(Mandatory=$false, Position=2)]
[ValidateNotNullOrEmpty()]
[System.IO.Ports.Parity]$Parity = [System.IO.Ports.Parity]"Even",
[Parameter(Mandatory=$false, Position=3)]
[ValidateNotNullOrEmpty()]
[int]$DataBits = 7,
[Parameter(Mandatory=$false, Position=4)]
[ValidateNotNullOrEmpty()]
[System.IO.Ports.StopBits]$StopBits = [System.IO.Ports.StopBits]"One",
[Parameter(Mandatory=$false, Position=5)]
[ValidateNotNullOrEmpty()]
[System.IO.Ports.Handshake]$Handshake = [System.IO.Ports.Handshake]"None",
[Parameter(Mandatory=$false, Position=6)]
[ValidateNotNullOrEmpty()]
[int]$ReadInterval = 3
)
$proceed = $false
Write-Output ("Checking PortName...")
foreach ($item in [System.IO.Ports.SerialPort]::GetPortNames())
{
if ($item -eq $PortName)
{
$proceed = $true
Write-Output ("--> PortName " + $PortName + " is available")
break
}
}
if ($proceed -eq $false)
{
Write-Warning ("--> PortName " + $PortName + " not found")
return
}
try
{
$port = New-Object System.IO.Ports.SerialPort
$port.PortName = $PortName
$port.BaudRate = $BaudRate
$port.Parity = $Parity
$port.DataBits = $DataBits
$port.StopBits = $StopBits
$port.Handshake = $Handshake
$currentDate = Get-Date -Format yyyyMMdd
Write-Output ("Establishing connection to the port...")
Start-Sleep -Milliseconds 1000
$port.Open()
Write-Output $port
Write-Output ("--> Connection established.")
Write-Output ("")
}
catch [System.Exception]
{
Write-Error ("Failed to connect : " + $_)
$error[0] | Format-List -Force
if ($port -ne $null) { $port.Close() }
exit 1
}
Start-Sleep -Milliseconds 1000
# Request flags sent to my meter to aquire current usage
[Byte[]] $request = 0x2F,0x3F,0x21,0x0D,0x0A
[Byte[]] $request2 = 0x06,0x30,0x30,0x30,0x0D,0x0A
$counter = 999999999
$lastcount = 0
$update = [DateTime]::Now
$lastupdate = [DateTime]::Now
$key = if ($host.UI.RawUI.KeyAvailable) { $host.UI.RawUI.ReadKey('NoEcho, IncludeKeyDown') }
do
{
#$key = if ($host.UI.RawUI.KeyAvailable) { $host.UI.RawUI.ReadKey('NoEcho, IncludeKeyDown') }
if ($port.IsOpen)
{
Write-Output("back")
Start-Sleep -Milliseconds 100
#$data = $port.ReadLine()
$port.Write($request, 0, $request.Count)
Start-Sleep -Milliseconds 1000
$port.Write($request2, 0, $request2.Count)
Start-Sleep -Milliseconds 8000
#$data = $port.ReadExisting()
[byte[]]$readBuffer = New-Object byte[] ($port.ReadBufferSize + 1)
try
{
[int]$count = $port.Read($readBuffer, 0, $port.ReadBufferSize)
[string]$data = [System.Text.Encoding]::ASCII.GetString($readBuffer, 0, $count)
}
catch { }
Write-Output($data)
$length = $data.Length
# remove newline chars
$data = $data -replace [System.Environment]::NewLine,""
$pos = $data.IndexOf("1.8.0*00(")
$rightPart = ([decimal]($data.Substring($pos+9,9)))
$watt = 0
$getTimestamp = ([DateTime]::Now).tostring("yyMMdd hh:mm", $e)
Write-Output ("[" + $getTimestamp + "] " + $rightPart + " Watt: " +$watt)
$diff = $rightpart-$counter
#Write-Output("Diff:"+$diff)
if ( $diff -lt 0){
Write-Output (("output:"+$counter+"-"+$rightpart+'='+$diff))
$lastcount = $counter
$counter = $rightPart
$diff = 0
}
if ( $diff -gt 0){
$lastcount = $counter
$counter = $rightPart
$lastupdate = $update
$update=[DateTime]::Now
$watt = ($diff/(($update-$lastupdate).TotalHours)*1000)
Invoke-WebRequest -Uri ('http://192.168.1.10:8080/json.htm?type=command¶m=udevice&idx=943&nvalue=0&svalue='+$watt+';'+($rightPart*1000)) >$null 2>&1
}
Write-Output("Sleeping "+$ReadInterval+" Seconds...");
Start-Sleep -Seconds $ReadInterval
}
} until ($key.VirtualKeyCode -eq 81) # until 'q' is pressed
if ($port -ne $null) { $port.Close() }
}