Learning PowerShell for Chia

can you share further on how to use this script. I try putting in Powershell but does not seem to work. Already edit the path and all

2 Likes

okay so ive changed the log level to INFO and ive got a note saying 0 plots eligible for farming althought the gui says its farming. i also have a few lines which say duplicate compact proof. how do i actually make sure the plots i have are farming

i also need some help here

This works in newer pwsh versions but not the default ones shipped with windows. There you need to make $matches into an object select-object expects. The difference is between:

$matches | select *

and

new-object -type psobject -property $matches | select *

So this works:

$logpattern = "INFO.*(?<Plots>\d+) plots.*Found (?<Proofs>\d+).*Time\: (?<Time>\d+\.\d+) s"

get-content ~\.chia\mainnet\log\*.log* |
where-object {$_ -match $logpattern} |
%{new-object -type psobject -property $matches} |
select Plots,Proofs,Time
3 Likes

okay so i checked the debug log in powershell-showing that timelord is not active for 60 seconds at a time and restarts all chains this is a problem right?..if it needs to send parts of a block (potential) to my node. any help in this would be greatly appreciated

Adding this here because it’s so useful, thanks @login-taken

1 Like

Please bear with me on relatively noob question from non-programmer background.
I’ve tried to open Powershell function library and follow with the code.

This basically define the pattern of output text that we want to extract

This defines the log path

Get the text that matches the designated pattern

I have no idea on the first line, but the second basically define what output look like.

Here I want to display output which has Proofs exceeds 5 sec for example.
That requires “if” statement e.g.

if Proofs > 5
select Plots,Proofs,Time

or are there another way to filter out output more easily

It’s not my code, I’m only a janitor, haven’t thought about the design.

But you can extend it with another pipe to something like this:

where-object {$_.time -ge <time>}

-ge is ≤ greater-or-equal comparison operator, so filtering values exceeding or equal to number you put in <time> placeholder. You can type help comparison to see other operators, they’re like in bash. In my case I don’t have multi-second times, so I used a fraction:

get-content ~\.chia\mainnet\log\*.log* |
where-object {$_ -match $logpattern} |
%{new-object -type psobject -property $matches} |
select Plots,Proofs,Time |
where-object {$_.time -ge 0.4}

Plots Proofs Time
----- ------ ----
1     0      0.42330
1     0      0.46909
1     0      0.40821
1     0      0.48624

It’s possible to combine more comparisons with -and:

where-object {$_.time -ge 0.2 -and $_.plots -gt 0}

Plots Proofs Time
----- ------ ----
1     0      0.27058
1     0      0.42330
1     0      0.35163
1     0      0.24420

and -or:

where-object {$_.time -ge 0.2 -or $_.plots -gt 0}

Plots Proofs Time
----- ------ ----
0     0      0.25796
1     0      0.11802
1     0      0.17058
0     0      0.23197
1 Like

Thank you for further explanation.
I try to add more detail (date and time) on the output.

Typical output is

2021-05-05T19:49:10.214 harvester chia.harvester.harvester: INFO 0 plots were eligible for farming 94844cf10c... Found 0 proofs. Time: 0.01562 s. Total XXX plots

Here we already have the pattern you made

INFO.*(?<Plots>\d+) plots.*Found (?<Proofs>\d+).*Time\: (?<Time>\d+\.\d+) s

I assume that .* is the wildcard… not sure if it’s called that.
Want to add 2021-05-05T19:49:10.214 to the output

$logpattern = "(?<DateTime>\d+).*INFO.*(?<Plots>\d+) plots.*Found (?<Proofs>\d+).*Time\: (?<Time>\d+\.\d+) s"
get-content ~\.chia\mainnet\log\*.log* |
where-object {$_ -match $logpattern} |
%{new-object -type psobject -property $matches} |
select DateTime,Plots,Proofs,Time |
where-object {$_.time -ge 0.4}

It ofc does not work which I believe my new pattern is definitely wrong

I imagine something like below with the trimmed DateTime

DateTime                  Plots  Proofs  Time
2021-05-05 at 19:49:10      0     0      0.25796
2021-05-05 at 20:50:20      1     0      0.11802
2021-05-05 at 21:51:30      1     0      0.17058
2021-05-05 at 22:52:40      0     0      0.23197
Total of 4 rounds (2%) from 200 rounds exceed 0.4 sec from 2021-05-05 at 19:49:10 to 2021-05-05 at 22:52:40

I will take full course on this, but this is kinda an engineer trying to do the reverse engineering :slight_smile:

1 Like

Pattern is not actually PowerShell. It’s a regular expression, and (?<>) is a syntax for a named capture group, between chevrons going a name that can be referenced. So it’s complicated. Matching a date is a good example how involved regex are for parsing. Simple (yet complex) will do too, like ^[^a-z\s]*. Hm that doesn’t work, so ^.*?\s.

$datepattern = "^.*?\s"
# $varaibles are expanded also within "soft quotes"
$logpattern = "^(?<date>$datepattern).*INFO.*(?<Plots>\d+) plots.*Found (?<Proofs>\d+).*Time\: (?<Time>\d+\.\d+) s"
get-content ~\.chia\mainnet\log\*.log* |
where-object {$_ -match $logpattern} |
%{new-object -type psobject -property $matches} |
select date, plots, proofs, time
2 Likes

Requires PowerShell 7 or above.

Get Filter Times

gc ~\.chia\mainnet\log\*.log* | ? {$_ -match "INFO.*(?<Plots>\d+) plots.*Found (?<Proofs>\d+).*Time\: (?<Time>\d+\.\d+) s"} | %{$matches} | select Plots,Proofs,Time

In A Function

function Get-FilterProofs
{
    gc ~\.chia\mainnet\log\*.log* | ? {$_ -match "INFO.*(?<Plots>\d+) plots.*Found (?<Proofs>\d+).*Time\: (?<Time>\d+\.\d+) s"} | %{$matches} | select Plots,Proofs,Time
}

Sorted Version

Get-FilterProofs | sort time

Filter Times Above 5 Seconds

Get-FilterProofs | Where {$_.Time -ge 5} | sort time
2 Likes

These are great; thank you for sharing them!

Much appreciated. This is very useful.

I randomly get the time > 1 sec around 5-7 times/hour
probably try to track with event at that time to further reduce the occurrence

I regularly see 1.5s a few times an hour. I ain’t sweating it. Sometimes up to 7+ seconds if checking the plots. Once I see 5+ seconds on a regularl basis then I will start mitigating.

Also, I didn’t realize this but there are newer versions of Powershell you can install from GitHub:

Windows 10 includes Powershell v5 out of the box – you can install Powershell v7 side by side from the github page:

1 Like

You may also peek at my repo for reference. Not saying thats how things are done, but maybe you get some inspiration. And with the new won PowerShell knowledge, you also may contribute to the Ploto Module :slight_smile:
tydeno/Ploto: A Windows PowerShell based Chia Plotting Manager. Lets you automatically spawn and move plots. Sends you notifications on the go. (github.com)

1 Like

Line 615 use a resolved wild-card path and drop the splitting:

$ChiaExecutable = Resolve-Path ~\AppData\Local\chia-blockchain\app-*\resources\app.asar.unpacked\daemon\chia.exe

I do not understand why you are not able to bring in the DiscordImage module as a class and utilize it. Are you trying to access the class functions statically?

1 Like

If I use the DiscordClasses and functions in their own Module, I can‘t use these classes in the subsequent functions of Ploto Module. To load classes, you need to use „using modul“ which has to be the first line of a script or module. Even with using that, the classes were not known in subsequent functions of Ploto Module. If I’d access these classes directly from Ploto Module and not a function within the module, It would work. So I think it’s a scoping issues, but I could not resolve that in a timely manner. With Import-Module you only import the functions, but not the classes.I tried for several hours but eventually gave up.

If you know a handy way to load and access the Discord Classes I‘m more than eager to know how! :slight_smile:

In your Discord class, create a function to instantiate a DiscordImage class, export that function in the Discord module. Then in your Plot module, import module, invoke the “new discord image instance” function that was previously exported, then you have access to all the functionality encapsulated in the DiscordImage class. Classes in PowerShell are kind of broken, but they do actually make sense. A cautionary note, if you dot source the class module in to your current powershell session at the CLI, you unfortunately need to reload your entire session when you change your class, so try to avoid that during development because there is nothing more frustrating than banging your head on the desk of “but I fixed that bug! why is it still broken!?!” for an hour, only to realise it isn’t reloading the updated version.

Note: Untested code

Class DiscordImage
    {
    [String]$Message
    [String]$Icon

    Function Get-Image
    {
       # TODO
    }

    Function Get-Message
    {
       # TODO
       InternalFunctionOnlyDiscordImageCanInvoke
    }

}

Function InternalFunctionOnlyDiscordImageCanInvoke
{
   echo "internal function"
}

Function New-DiscordImage
{
    [DiscordImage]::New()
}

Export-ModuleMember -Function New-DiscordImage
# WARNING: if you run this code in your CLI, then modify your class file, you will need to kill pwsh and reload it for any changes to take effect
import-module discord_image.ps1
$discordimage=new-discordimage # instantiate the new object
$discordimage # returns the type
$discordimage.GetMessage # invokes a member function
InternalFunctionOnlyDiscordImageCanInvoke # error out
$discordimage.InternalFunctionOnlyDiscordImageCanInvoke # error out
$discordimage | gm # inspect the object

You are correct, in that it is a scoping issue. Using module would be the ideal solution, but as you can atest, the functionality is kinda broken. Import-module (dot source) brings in the contents of the module, but appears to not import the class. Well, it does, but it won’t let you instantiate it. There is no built-in mechanism of PowerShell to make that bridge unfortunately, but you can bridge it yourself with an exported function that will instantiate the class.

And one further note, if the class module doesn’t exist on the path, using module usually breaks. You can use using module and everything works as expected, but a lot of developers avoid it and go with the dot source method instead because using requires placement as first non-comment line of the module and cannot be conditionally imported and requires environmental path or explicit path inclusion.

3 Likes

Thank you very much for your in-depth explanation. I will try the approach of a function that instantiates the classes. Will make the Ploto Module much more accessible/readable. But yes, the way classes work in PowerShell is atleast for me quite a mess. I also got to admit that I never made use of PoSh classes before, so I deeply appreciate that you took the time for your explanation.

1 Like