D0 Power Meter (Optokopf) using PowerShell

All kinds of 'OS' scripts
Post Reply
Cornholio1234
Posts: 29
Joined: Thursday 03 March 2016 12:01
Target OS: Windows
Domoticz version: V3.4964
Location: Germany
Contact:

D0 Power Meter (Optokopf) using PowerShell

Post by Cornholio1234 » Wednesday 22 November 2017 10:42

I couldn't find something working out of the box so I merged a serial-reader script with some brain-power. Maybe it is of use for someone else:
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&param=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() }
}


Windows Server, Aeotec Z-Stick Gen5, V3.4964

Post Reply

Who is online

Users browsing this forum: No registered users and 3 guests