├── _config.yml ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ └── bug_report.md ├── LICENSE ├── PlotoSpawnerConfig.json ├── FUNCTIONS.md ├── README.md └── Install-Ploto.ps1 /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [tydeno] 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior. 15 | Your params 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | Make sure you've ran the affected Ploto command using -verbose param and post it here. 23 | 24 | **Ploto Version in use** 25 | - eg 1.0.9.4.9.1 26 | 27 | **Additional context** 28 | Add any other context about the problem here. 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 tydeno 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PlotoSpawnerConfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "PlotterName": "plotozero", 3 | "PlotterUsed": "Stotik", 4 | "PathToUnofficialPlotter": "C:\\Users\\Tydeno\\Desktop\\madMAx43v3r_chia-plotter_win_build_v0.0.4\\chia_plot.exe", 5 | "EnableAlerts": "true", 6 | "EnablePlotoFyOnStart": "true", 7 | "ChiaWindowStyle": "normal", 8 | "PathToPloto": "C:\\Users\\Tydeno\\Desktop\\Ploto\\Ploto.psm1", 9 | "EnableMover": "true", 10 | "PathsToMovePlotsTo": "Q:\\Plotter,Z:", 11 | 12 | "DiskConfig": [ 13 | { 14 | "TempDrives": "F:", 15 | "Temp2Drives": "J:", 16 | "OutDrives": "L:,K:", 17 | "EnableT2": "true", 18 | "ReplotDrives": "" 19 | } 20 | ], 21 | "SpawnerConfig": [ 22 | { 23 | "ReplotForPool": "false", 24 | "ReplotPlotsOlderThan": "18.6.2021", 25 | "IntervallToCheckInMinutes": "1", 26 | "InputAmountToSpawn": "50", 27 | "WaitTimeBetweenPlotOnSeparateDisks": "1", 28 | "WaitTimeBetweenPlotOnSameDisk": "1", 29 | "MaxParallelJobsOnAllDisks": "1", 30 | "MaxParallelJobsOnSameDisk": "1", 31 | "MaxParallelJobsInPhase1OnAllDisks": "1", 32 | "StartEarly": "false", 33 | "StartEarlyPhase": "4" 34 | } 35 | ], 36 | "JobConfig": [ 37 | { 38 | "KSizeToPlot": "32", 39 | "BufferSize": "", 40 | "Thread": "24", 41 | "Buckets": "256", 42 | "Bitfield": "false", 43 | "FarmerKey": "YourKey", 44 | "PoolKey": "YourKey", 45 | "P2SingletonAdress": "" 46 | } 47 | ], 48 | "SpawnerAlerts": [ 49 | { 50 | "DiscordWebhookURL": "https://discord.com/api/webhooks/YourcustomURLWebhookEnding", 51 | "WhenJobSpawned": "true", 52 | "WhenNoOutDrivesAvailable": "true", 53 | "WhenJobCouldNotBeSpawned": "true", 54 | "PeriodOfReportInHours": "0.5" 55 | } 56 | ] 57 | } 58 | -------------------------------------------------------------------------------- /FUNCTIONS.md: -------------------------------------------------------------------------------- 1 | ## Get-PlotoOutDrives 2 | Gets all Windows Volumes that match the -OutDriveDenom parameter and checks if free space is greater than 107 GB (amount currently used by final chia plots). 3 | It wraps all the needed information of the volume like DriveLetter, ChiaDriveType, VolumeName, a bool IsPlootable, and the calculated amount of plots to hold into a object and returns the collection of objects as the result of that function. 4 | 5 | #### Example: 6 | 7 | ```powershell 8 | Get-PlotoOutDrives -OutDriveDenom "out" 9 | ``` 10 | 11 | #### Output: 12 | 13 | ``` 14 | DriveLetter : D: 15 | ChiaDriveType : Out 16 | VolumeName : ChiaOut2 17 | FreeSpace : 363.12 18 | IsPlottable : True 19 | AmountOfPlotsToHold : 3 20 | 21 | DriveLetter : K: 22 | ChiaDriveType : Out 23 | VolumeName : ChiaOut3 24 | FreeSpace : 364.24 25 | IsPlottable : True 26 | AmountOfPlotsToHold : 3 27 | ``` 28 | 29 | #### Parameters: 30 | | Name | Required | Type | Description | 31 | |---------------|----------|--------|------------------------------------------------------------------------------------------------------------------------------------------| 32 | |OutDriveDenom | Yes | String | A common denominator for all your drives used as out drives. All drives with that denom in name will be used to store done plots. 33 | 34 | 35 | 36 | ## Get-PlotoTempDrives 37 | Gets all Windows Volumes that match the -TempDriveDenom parameter and checks if free space is greater than 270 GB (amount currently used by chia plots as temp storage). 38 | It wraps all the needed information of the volume like DriveLetter, ChiaDriveType, VolumeName, a bool IsPlootable, and the calculated amount of plots to temp, whether it has a plot in porgress (determined by checking if the drive contains any file) into a object and returns the collection of objects as the result of that function. 39 | 40 | #### Example: 41 | 42 | ```powershell 43 | Get-PlotoTempDrives -TempDriveDenom "plot" 44 | ``` 45 | #### Output: 46 | 47 | ``` 48 | DriveLetter : E: 49 | ChiaDriveType : Temp 50 | VolumeName : ChiaPlot 3 Evo 860 512GB 51 | FreeSpace : 437.28 52 | TotalSpace : 465.76 53 | hasFolder : False 54 | IsPlottable : True 55 | HasPlotInProgress : False 56 | AmountOfPlotsInProgress : 0 57 | AmountOfPlotsToTempMax : 1 58 | AvailableAmountToPlot : 1 59 | PlotInProgressID : 60 | 61 | DriveLetter : F: 62 | ChiaDriveType : Temp 63 | VolumeName : ChiaPlot4 NVME FullDisk 1 64 | FreeSpace : 446.76 65 | TotalSpace : 465.75 66 | hasFolder : False 67 | IsPlottable : True 68 | HasPlotInProgress : False 69 | AmountOfPlotsInProgress : 0 70 | AmountOfPlotsToTempMax : 1 71 | AvailableAmountToPlot : 1 72 | PlotInProgressID : 73 | 74 | 75 | ## Invoke-PlotoJob 76 | Calls Get-PlotoTempDrives to get all Temp drives that are plottable. For each tempDrive it determines the most appropriate OutDrive (using Get-PlotoOutDrives function), stitches together the ArgumentList for chia and fires off the chia plot job using chia.exe. For each created PlotJob the function creates an Object and appends it to a collection of objects, which are returned upon the function call. 77 | 78 | #### Example: 79 | 80 | ```powershell 81 | Invoke-PlotoJob -BufferSize 3390 -Thread 2 -OutDriveDenom "out" -TempDriveDenom "plot" -WaitTimeBetweenPlotOnSeparateDisks 0.1 -WaitTimeBetweenPlotOnSameDisk 0.1 -MaxParallelJobsOnAllDisks 2 -MaxParallelJobsOnSameDisk 1 -EnableBitfield $true -Verbose 82 | ``` 83 | #### Output: 84 | 85 | ``` 86 | PlotoSpawnerJobId : 49ab3c48-532b-4f17-855d-3c5b4981528b 87 | ProcessID : 9024 88 | OutDrive : D: 89 | TempDrive : H: 90 | ArgumentsList : plots create -k 32 -b 3390 -r 2 -t H:\ -d D:\ 91 | ChiaVersionUsed : 1.1.2 92 | LogPath : C:\Users\me\.chia\mainnet\plotter\PlotoSpawnerLog_30_4_0_49_49ab3c48-532b-4f17-855d-3c5b4981528b_Tmp-E_Out-K.txt 93 | StartTime : 4/29/2021 1:55:50 PM 94 | ``` 95 | 96 | ## Start-PlotoSpawns 97 | Main function that nests all else. 98 | Continously calls Invoke-PlotoJob and states progress and other information. It runs until it created the amount of specified Plot by using the -InputAmountToSpawn param. 99 | 100 | #### Example: 101 | 102 | ```powershell 103 | Start-PlotoSpawns -BufferSize 3390 -Thread 2 -InputAmountToSpawn 36 -OutDriveDenom "out" -TempDriveDenom "plot" -WaitTimeBetweenPlotOnSeparateDisks 0.1 -WaitTimeBetweenPlotOnSameDisk 0.1 -MaxParallelJobsOnAllDisks 2 -MaxParallelJobsOnSameDisk 1 -EnableBitfield $true 104 | ``` 105 | 106 | #### Output: 107 | 108 | ``` 109 | PlotoManager @ 4/29/2021 1:45:38 PM : Amount of spawned Plots in this iteration: 2 110 | PlotoManager @ 4/29/2021 1:45:38 PM : Overall spawned Plots since start of script: 2 111 | ``` 112 | 113 | 114 | # PlotoManage 115 | Allows you to check status of your current plot jobs aswell as stopping them and cleaning the temp drives. 116 | 117 | ## Get-PlotoJobs 118 | Analyzes the plotter logs (standard chia.exe output redirected, enriched with additional data) and shows the status, pid and drives in use. The function only pick up data of plot logs that have been spawned using PlotoSpawner (as it deploys initial data like PID of process and drives use). The additional logs are stored in the same location as the standrad logs. If you delete those, this function wont be able to read certain properties anymore. 119 | 120 | #### Example: 121 | ```powershell 122 | Get-PlotoJobs | ft 123 | ``` 124 | 125 | #### Output: 126 | ``` 127 | JobId PlotId PID Status TempDrive OutDrive LogPath 128 | ----------------- ------ --- ------------ --------- -------- ------- 129 | 2e39e295-ccd9-4abf-94e9-01a854cbfa24 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx None Completed E: K: C:\Users\... 130 | ed2133b0-018c-44db-81e7-61befbda8031 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx None Completed F: D: C:\Users\... 131 | bc3b44b1-b290-4487-a552-c4dda2e11366 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx None Completed H: K: C:\Users\... 132 | 10e6deb5-6a13-4a0d-9c77-8c65d717bf6b xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx None Completed Q: D: C:\Users\... 133 | f865e425-ada4-44f0-8537-23a033aef302 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx None Completed Q: D: C:\Users\... 134 | b19eaef4-f9b3-4807-8870-a959e5aa3a21 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx None Completed I: D: C:\Users\... 135 | 278615e9-8e4d-4af4-bfcc-4665412aae89 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx None Completed Q: K: C:\Users\... 136 | 137 | ``` 138 | 139 | ## Remove-AbortedJobs 140 | Gets all Jobs from Get-PlotoJobs that are aborted (where no process runs to PID) and foreach call Stop-PlotoJob 141 | 142 | #### Example: 143 | 144 | ```powershell 145 | Remove-AbortedJobs 146 | ``` 147 | 148 | #### Output: 149 | ``` 150 | PlotoRemoveAbortedJobs @ 5/1/2021 6:42:24 PM : Found aborted Jobs to be deleted: 6cfb4e4a-cb71-4f2a-9387-17a8049ce625 85b08573-054d-46f0-b7e3-755f9ce021bc cbab519c-2f26-41c9-b3fa-8bcb0ba36d3a 2b0ab204-3b0e-4e8c-b04c-a884859ae637 f639cb35-23a8-4010-a1db-ab6186bd117c 151 | PlotoRemoveAbortedJobs @ 5/1/2021 6:42:24 PM : Cleaning up... 152 | PlotoStopJob @ 5/1/2021 6:42:24 PM : ERROR: Cannot bind parameter 'Id'. Cannot convert value "None" to type "System.Int32". Error: "Input string was not in a correct format." 153 | PlotoStopJob @ 5/1/2021 6:42:24 PM : Found .tmp files for this job to be deleted. Continue with deletion. 154 | PlotoStopJob @ 5/1/2021 6:42:24 PM : Removed temp files on F: 155 | PlotoStopJob @ 5/1/2021 6:42:24 PM : Removed log files for this job. 156 | PlotoStopJob @ 5/1/2021 6:42:25 PM : ERROR: Cannot bind parameter 'Id'. Cannot convert value "None" to type "System.Int32". Error: "Input string was not in a correct format." 157 | PlotoStopJob @ 5/1/2021 6:42:25 PM : Found .tmp files for this job to be deleted. Continue with deletion. 158 | PlotoStopJob @ 5/1/2021 6:42:25 PM : Removed temp files on H: 159 | PlotoStopJob @ 5/1/2021 6:42:25 PM : Removed log files for this job. 160 | PlotoStopJob @ 5/1/2021 6:42:25 PM : ERROR: Cannot bind parameter 'Id'. Cannot convert value "None" to type "System.Int32". Error: "Input string was not in a correct format." 161 | PlotoStopJob @ 5/1/2021 6:42:25 PM : Found .tmp files for this job to be deleted. Continue with deletion. 162 | PlotoStopJob @ 5/1/2021 6:42:25 PM : Removed temp files on E: 163 | PlotoStopJob @ 5/1/2021 6:42:25 PM : Removed log files for this job. 164 | PlotoStopJob @ 5/1/2021 6:42:26 PM : ERROR: Cannot bind parameter 'Id'. Cannot convert value "None" to type "System.Int32". Error: "Input string was not in a correct format." 165 | PlotoStopJob @ 5/1/2021 6:42:26 PM : Found .tmp files for this job to be deleted. Continue with deletion. 166 | PlotoStopJob @ 5/1/2021 6:42:26 PM : Removed temp files on J: 167 | PlotoStopJob @ 5/1/2021 6:42:26 PM : Removed log files for this job. 168 | PlotoStopJob @ 5/1/2021 6:42:26 PM : ERROR: Cannot bind parameter 'Id'. Cannot convert value "None" to type "System.Int32". Error: "Input string was not in a correct format." 169 | PlotoStopJob @ 5/1/2021 6:42:26 PM : Found .tmp files for this job to be deleted. Continue with deletion. 170 | PlotoStopJob @ 5/1/2021 6:42:26 PM : Removed temp files on I: 171 | PlotoStopJob @ 5/1/2021 6:42:26 PM : Removed log files for this job. 172 | PlotoRemoveAbortedJobs @ 5/1/2021 6:42:26 PM : Removed Amount of aborted Jobs: 5 173 | ``` 174 | The Error below is known and only says that the process is already closed. This is expected. In the future this error may be surpressed. 175 | 176 | ``` 177 | PlotoStopJob @ 5/1/2021 6:42:26 PM : ERROR: Cannot bind parameter 'Id'. Cannot convert value "None" to type "System.Int32". Error: "Input string was not in a correct format." 178 | ``` 179 | 180 | # PlotoMove 181 | Continously searches for final Plots on your OutDrives and moves them to your desired location. I do this for transferring plots from my plotting machine to my farming machine. 182 | 183 | ## Get-PlotoPlots 184 | Searches defined Outdrives for Final Plots (file that end upon .plot) and returns an array with final plots. 185 | 186 | #### Example: 187 | ```powershell 188 | Get-PlotoPlots -OutDriveDenom "out" 189 | ``` 190 | 191 | #### Output: 192 | ``` 193 | Iterating trough Drive: @{DriveLetter=D:; ChiaDriveType=Out; VolumeName=ChiaOut2; FreeSpace=59.04; TotalSpace=0; IsPlottable=False; AmountOfPlotsToHold=0} 194 | Checking if any item in that drive contains .PLOT as file ending... 195 | Found a Final plot: plot-k32-2021-04-30-18-52-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot 196 | Found a Final plot: plot-k32-2021-04-30-19-02-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot 197 | Found a Final plot: plot-k32-2021-04-30-19-12-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot 198 | Found a Final plot: plot-k32-2021-04-30-19-42-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot 199 | Iterating trough Drive: @{DriveLetter=K:; ChiaDriveType=Out; VolumeName=ChiaOut3; FreeSpace=262.86; TotalSpace=0; IsPlottable=True; AmountOfPlotsToHold=2} 200 | Checking if any item in that drive contains .PLOT as file ending... 201 | Found a Final plot: plot-k32-2021-04-30-18-57-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot 202 | Found a Final plot: plot-k32-2021-04-30-19-12-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot 203 | -------------------------------------------------------------------------------------------------- 204 | 205 | FilePath Name 206 | -------- ---- 207 | D:\plot-k32-2021-04-30-18-52-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot plot-k32-2021-04-... 208 | D:\plot-k32-2021-04-30-19-02-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot plot-k32-2021-04-... 209 | D:\plot-k32-2021-04-30-19-12-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot plot-k32-2021-04-... 210 | D:\plot-k32-2021-04-30-19-42-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot plot-k32-2021-04-... 211 | K:\plot-k32-2021-04-30-18-57-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot plot-k32-2021-04-... 212 | K:\plot-k32-2021-04-30-19-12-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot plot-k32-2021-04-... 213 | ``` 214 | 215 | ## Move-PlotoPlots 216 | Grabs the found plots from Get-PlotoPlots and moves them to either a local/external drive using Move-Item cmdlet or to a UNC path using Background Intelligence TRansfer Service (Bits). You can define the OutDrives to search for Plots, TransferMethod and Destination. 217 | 218 | Make sure TrasnferMethod and Destination match. 219 | 220 | #### Example: 221 | 222 | ```powershell 223 | Move-PlotoPlots -DestinationDrive "\\Desktop-xxxxx\d" -OutDriveDenom "out" -TransferMethod BITS 224 | ``` 225 | 226 | #### Output: 227 | ``` 228 | PlotoMover @ 5/1/2021 7:08:09 PM : Moving plot: D:\plot-k32-2021-04-30-18-52-dxxxxxxxxxxxxxxxxxxxxxxxxxxxxx00454fxxxxxxxxxxxxxxxxxxxxxxxxxx64.plot to \\Desktop-xxxxx\d using BITS 229 | ``` 230 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## [Ploto](https://www.ploto.rocks) 2 | An easy to use, customizable and heavily reliable Windows PowerShell based Chia Plotting Manager. 3 | 4 | 5 | ![image](https://user-images.githubusercontent.com/83050419/123462242-57fa0a00-d5ea-11eb-9506-03cb578ce77d.png) 6 | ![image](https://user-images.githubusercontent.com/83050419/123462300-6c3e0700-d5ea-11eb-9c2f-f5915c758580.png) 7 | 8 | # Table of content 9 | * [Contact](https://github.com/tydeno/Ploto/tree/main#contact) 10 | * [How you can support this project](https://github.com/tydeno/Ploto/tree/main#how-you-can-support-this-project) 11 | * [Is it safe to use?](https://github.com/tydeno/Ploto/tree/main#is-it-safe-to-use) 12 | * [How it works](https://github.com/tydeno/Ploto/tree/main#plotospawn) 13 | * [Understanding Plot and OutDrives](https://github.com/tydeno/Ploto/tree/main#understanding-plot-and-outdrive-denominators) 14 | * [About -2 drives](https://github.com/tydeno/Ploto/tree/main#about--2-drives) 15 | * [About parallelization on separate disks](https://github.com/tydeno/Ploto/tree/main#about-parallelization-on-separate-disks) 16 | * [About parallelization on the same disk](https://github.com/tydeno/Ploto/tree/main#about-parallelization-on-the-same-disk) 17 | * [About DIscord webhooks](https://github.com/tydeno/Ploto/tree/main#alright-i-saw-that-discord-bot-picture-how-do-i-use-that) 18 | * [Plotting with your Pool & Farmer Key](https://github.com/tydeno/Ploto/tree/main#plotting-with-your-pool--farmer-key) 19 | * [Plotting for pools](https://github.com/tydeno/Ploto/tree/main#plotting-for-pools) 20 | * [About replotting](https://github.com/tydeno/Ploto/tree/main#about-replotting) 21 | * [About running custom plotters](https://github.com/tydeno/Ploto/tree/main#about-running-custom-plotters) 22 | * [Status Codes and their meaning (Chia official plotter)]() 23 | * [Status Codes and their meaning (madmax/stotik custom plotter)]() 24 | * [How to](https://github.com/tydeno/Ploto/tree/main#prereqs) 25 | * [Install Ploto](https://github.com/tydeno/Ploto/tree/main#how-to-install-ploto) 26 | * [Spawn Plots](https://github.com/tydeno/Ploto/tree/main#how-to-spawn-plots) 27 | * [Get Jobs](https://github.com/tydeno/Ploto/tree/main#how-to-get-jobs) 28 | * [Move Plots](https://github.com/tydeno/Ploto/tree/main#how-to-move-plots) 29 | * [FAQ](https://github.com/tydeno/Ploto/tree/main#faq) 30 | 31 | ## Contact 32 | https://www.ploto.rocks/ 33 | 34 | For general chatting, issues and support of how to use Ploto, you may join the Discord below. 35 | If you find any bugs, do not hesitate to create or update an issue directly here in GitHub. 36 | 37 | * ### [Ploto Discord](https://discord.gg/NgEsMDWWT5) 38 | 39 | ## How you can support this project 40 | In case you'd like to to support the development of Ploto in a monetary way, you may donate in the currencies below with the according wallet adresses: 41 | * XCH Adress: xch19ddu8lxgq2g6ssnk7kmexmwxazapvdt7fp8cekeun0cdm9jt6vxsqg30yt 42 | 43 | Or trough my [GitHub Sponsoring page](https://github.com/sponsors/tydeno) 44 | 45 | 46 | # PlotoSpawn 47 | TLDR: It plots 1x plot on each TempDrive (if you have 6x TempDrives = 6x parallel Plot Jobs) as long as you want it to and as long as you have OutDrive space. 48 | When and where Plots are spawned is defined by PlotoSpawnerConfig.json. 49 | 50 | Ploto checks periodically, if a TempDrive and OutDrive is available for plotting. 51 | If there is no TempDrive available, or no OutDrive, Ploto checks again in amount of minutes defines in $config.IntervallToCheckInMinutes 52 | 53 | When there is one available, Ploto determines the best OutDrive (most free space) and calls chia.exe to start the plot. 54 | Ploto iterates once through all available TempDrives and spawns a plot per each TempDrive (as long as enough OutDrive space is given). 55 | After that, Ploto checks if amount Spawned is equal as defined as input. If not, Ploto keeps going until it is. 56 | 57 | ### Understanding Plot and OutDrives 58 | To define your temp and outdrives you use the config. 59 | To define a folder within a drive, use following notation: 60 | `F:\\afolder,E:\\anotherone,K:\\somefolder` 61 | 62 | to define several drivesuse :`F:,E:,K:` 63 | 64 | Important: There are no spaces allowed betwen the ","! 65 | 66 | 67 | ### About -2 drives 68 | Ploto now supports -2 drives. You define them just like plot and tempdrives. On each Job Ploto checks if a -2 drive is plottable. If yes, it spawns the job using that -2 drive. If not, it spawns the job without the drive. 69 | 70 | > -2 [tmp dir 2]: Define a secondary temporary directory for plot creation. This is where Plotting Phase 3 (Compression) and Phase 4 (Checkpoints) occur. Depending on your OS, > -2 might default to either -t or -d. Therefore, if either -t or -d are running low on space, it's recommended to set -2 manually. The -2 dir requires an equal amount of > > working space as the final size of the plot. 71 | 72 | ### About parallelization on separate disks 73 | Using the Parameter "-MaxParallelJobsOnAllDisks", you can define how many Plots Jobs overall there should be in parallel. So this will be your hard cap. If there are as many jobs as you defined as max, PlotoSpawner wont spawn further Jobs. This keeps your system from overcommiting. 74 | Using the Parameter "-BufferSize", you can define RAM used per process, the default value is 3390MB. 75 | Using the Parameter "-Thread", you can define threads used per process the default value is 2 threads. 76 | 77 | ### About parallelization on the same disk 78 | Using "MaxParallelJobsOnSameDisks" you can define how many PlotsJobs there should be in parallel on a single disk. This param affects all Disks that can host more than 1 Plot. Ploto checks each disk for free space and determines the amount of plots it can hold as a tempDrive. Also being aware of the jobs in progress. It will spawn as many jobs as possible by the disk until it reached either the hard cap of -MaxParallelJobsOnAllDisks or -MaxParallelJobsOnSameDisk 79 | 80 | 81 | If I launch PlotoSpawner with these params like this: 82 | ``` 83 | WaitTimeBetweenPlotOnSeparateDisks = 15 84 | WaitTimeBetweenPlotOnSameDisk = 60 85 | MaxParallelJobsOnAllDisks = 7 86 | MaxParallelJobsOnSameDisk = 3 87 | ``` 88 | The following will happen: 89 | 90 | PlotoSpawner will at max spawn 7 parallel jobs, and max 3 Jobs in parallel on the same disk. This means for my temp drive setup the following: 91 | | Name | DriveLetter | Type | Size | Total Plots in parallel | 92 | |---------------|----------|--------|--------------|-------------------------| 93 | |ChiaPlot 1 | I:\ | SATA SSD | 465 GB | 1 94 | |ChiaPlot 2 | H:\ | SATA SSD | 465 GB | 1 95 | |ChiaPlot 3 | E:\ | SATA SSD | 465 GB | 1 96 | |ChiaPlot 4 | Q:\ | SATA SSD | 1810 GB | 3 97 | |ChiaPlot 5 | J:\ | NVME SSD PCI 16x | 465 GB | 1 98 | 99 | So there will be 7x Plot jobs running in parallel with defined wait time in minutes betwen jobs on each disk and the same Disk. 100 | Drive Q:\ will never see more than 3x Plots in parallel as defined by -MaxParallelJobsOnSameDisk 3 101 | 102 | When a job is done and a temp drive becommes available again, PlotoSpawner will spawn the next jobs, until it has spawned the amount you specified as -InputAmountToSpawn or it reaches it max cap. 103 | 104 | PlotoSpawner redirects the output of chia.exe to to the following path: 105 | * C:\Users\Tydeno\.chia\mainnet\plotter\ (Tydeno is adjusted with your Username) 106 | 107 | And creates two log files for each job with the following notation: 108 | * PlotoSpawnerLog_30_4_0_49_49ab3c48-532b-4f17-855d-3c5b4981528b_Tmp-E_Out-K.txt (chia.exe output) 109 | * PlotoSpawnerLog_30_4_0_49_49ab3c48-532b-4f17-855d-3c5b4981528b_Tmp-E_Out-K'@'Stat.txt (Additional Info from PLotoSpawner) 110 | 111 | ### Alright, I saw that Discord Bot picture, how do I use that? 112 | You can control whether you want to receive and what kind of alerts in a handy config file. 113 | Now change the WebhookUrl to match the URL of your Discord Servers Webhook and enable/disable alert notifications as you wish. [How to create a Discord Webhook](https://support.discord.com/hc/en-us/articles/228383668-Intro-to-Webhooks). 114 | 115 | Set the Name for your plotter, as it allows you to distinguish between alerts for each plotter. You may also use several Webhooks in different Discord Channels. 116 | 117 | When you Start Ploto, make sure you also specified the Parameter "EnableAlerts" in the config. If not specified, your Disocrd remains silent. 118 | 119 | ### Plotting with your Pool & Farmer Key 120 | If your keys are not the present on the machine you want to plot, you need to specify -p (PoolKey) and -f (FarmerKey) param of your farm, in order to farm these plots correctly. 121 | If no -pf and -f param are specified, it uses the available keys. 122 | 123 | ### Plotting for pools 124 | Ploto now supports pool plotting, since we know the needed commands. 125 | Be advises that this in BETA mode right now. 126 | 127 | To create portable pool plots, we need to use the param "P2Singleton" in the config. 128 | Therefore we need to create a singleton that points to a pool first, and then we can start plotting. 129 | If you want to plot portable pools, make sure your PoolKey is NOT specified in the config, as this will mess thing up. 130 | 131 | ### About replotting 132 | Ploto now supports the ability to replot existing drives. This assumes you have one or more drives with final plots that are actively being farmed. 133 | If you now launch Ploto with 'Replot: "true"' and your denom for your ReplotDrives (drives you want to replot), the following will happen: 134 | 135 | 1. Ploto launches a Watchdog that looks for jobs that are about to enter phase 4 and have property "IsReplot=True" 136 | 2. If there is a job entering phase 4 with "IsReplot=True", it deletes the oldest plot on the drive, the replotJob uses as OutDrive. 137 | 138 | All ReplotJobs launchd, will use the the drives as OutDrive, that match the ReplotDriveDenom. So if you replot, make sure you set the InputAmountToSpawn to exactly the number of Plots you want to Replot. Currently Ploto does not know with which keys/singletons a Plot was plotted. So it keeps going and potentially deletes already replotted jobs, if InputAmountToSpawn is too high. This can lead to unneccesary wear & tear. 139 | 140 | The replotting mechanism features a * `"ReplotPlotsOlderThan": "20.6.2021` parameter in config. It allows you to define which plots shall be replotted and which not by specifying a date as seen above. This is a mandatory param if you want to replot, as its the only way to determine which plots shall be replotted 141 | It picks those drives that have final plots on it for replotting. If there is no drive that has plots to replot, its chooses the best suited OutDrive by free space. If there is none, it aborts. 142 | 143 | ## About running custom plotters 144 | Ploto now supports custom plotters. This functionality was implemented to support madMAx43v3r's chia-plotter. It also allows to use sever other forks, like Stotiks and catchmeifyoucans release. 145 | 146 | To run a custom plotter, make sure you define "PlotterUsed: Stotik" in your config. Use the value "Stotitk" for all custom plotters. 147 | Also make sure that you add the fullpath of the customplotter to the config. Then simply run Ploto as usually. 148 | 149 | When setting up your conifg; Take into consideration how your custom Plotter works! 150 | 151 | ## Prereqs 152 | The following prereqs need to be met in order for Ploto to function properly: 153 | * chia.exe is installed (version is determined automatically) 154 | * You may need to change PowerShell Execution Policy to allow the script to be imported. 155 | 156 | You can do it by using Set-ExecutionPolicy like this: 157 | ```powershell 158 | Set-ExecutionPolicy RemoteSigned -Scope CurrentUser 159 | ``` 160 | 161 | * In some cases, you may need to set ExecutionPolicy to "Bypass" (If it does not allow Import with "RemoteSigned") 162 | 163 | ```powershell 164 | Set-ExecutionPolicy Bypass -Scope CurrentUser 165 | ``` 166 | 167 | ## How to Install Ploto 168 | 1. Download Ploto as .ZIP from [here](https://github.com/tydeno/Ploto/archive/refs/heads/main.zip) 169 | 2. Launch PowerShell as Admin and cd to the path where the downloaded source is 170 | 3. Launch `Install-Ploto.ps1` (If your User does not have Admin right, run it as Admin) by dotsourcing it. 171 | 4. Let the Script run trough and if you do not have a config yet, let the Script create one for you 172 | 173 | ## How to Spawn Plots 174 | 1. Launch PlotoSpawner 175 | ```powershell 176 | Start-PlotoSpawns 177 | ``` 178 | ``` 179 | PlotoSpawner @ 4/30/2021 3:19:13 AM : Spawned the following plot Job: 180 | JobId : ad917660-9de9-4810-8977-6ace317d7ddb 181 | ProcessID : 13192 182 | OutDrive : K: 183 | TempDrive : Q: 184 | ArgumentsList : plots create -k 32 -t Q:\ -d K:\ -e 185 | ChiaVersionUsed : 1.1.2 186 | LogPath : C:\Users\me\.chia\mainnet\plotter\PlotoSpawnerLog_30_4_3_19_ad917660-9de9-4810-8977-6ace317d7ddb_Tmp-Q_Out-K.txt 187 | StartTime : 4/30/2021 3:19:13 AM 188 | 189 | PlotoManager @ 4/30/2021 3:49:13 AM : Amount of spawned Plots in this iteration: 6 190 | PlotoManager @ 4/30/2021 3:49:13 AM : Overall spawned Plots since start of script: 6 191 | ``` 192 | 2. Leave the PowerShell Session open (can be minimized) 193 | 194 | ## How to get Jobs 195 | 1. Open another PowerShell session 196 | 2. Launch Get-PlotoJobs and format Output 197 | ```powershell 198 | Get-PlotoJobs | ft 199 | ``` 200 | 201 | ``` 202 | JobId PlotId PID Status TempDrive OutDrive LogPath 203 | ----------------- ------ --- ------------ --------- -------- ------- 204 | 49ab3c48-532b-4f17-855d-3c5b4981528b xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 11856 3.6 E: K: C:\Users\me\.chia... 205 | 8a0cc01e-37e7-4507-ad6e-cad9401c1381 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 9184 3.6 F: K: C:\Users\me\.chia... 206 | 95c7cd61-bd88-45a3-a6a2-c243338de480 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 1604 3.5 H: D: C:\Users\me\.chia... 207 | 465355ef-7da6-4691-8137-3eeba98976d5 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 16280 3.4 I: K: C:\Users\me\.chia... 208 | 2120b771-2376-49f5-8d47-99a411865ec9 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 14228 3.3 J: D: C:\Users\ne\.chia... 209 | ad917660-9de9-4810-8977-6ace317d7ddb xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 13192 2.2 Q: K: C:\Users\me\.chia... 210 | 2b8596cd-3369-4e8c-a04f-26c85acdfd82 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 9752 2.1 Q: K: C:\Users\me\.chia... 211 | cfff29b8-fdee-4988-ae89-9db035d809bc xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 11176 1.6 Q: K: C:\Users\me\.chia... 212 | ``` 213 | 214 | Check Jobs With PerformanceCounters: 215 | ```powershell 216 | Get-PlotoJobs -PerfCounter 217 | ``` 218 | 219 | ``` 220 | JobId : 10e6deb5-6a13-4a0d-9c77-8c65d717bf6b 221 | PlotId : 332f93247b707d3bcf977889edff9bcbc9f0c3d3e30bfd941328bd7bf424f03a 222 | PID : 6648 223 | Status : 3.6 224 | TempDrive : Q: 225 | OutDrive : D: 226 | LogPath : C:\Users\me\.chia\mainnet\plotter\PlotoSpawnerLog_30_4_19_12_10e6deb5-6a13-4a0d-9c77-8c65d71 227 | 7bf6b_Tmp-Q_Out-D.txt 228 | StatLogPath : C:\Users\me\.chia\mainnet\plotter\PlotoSpawnerLog_30_4_19_12_10e6deb5-6a13-4a0d-9c77-8c65d71 229 | 7bf6b_Tmp-Q_Out-D@Stat.txt 230 | PlotSizeOnDisk : 48.03 GB 231 | cpuUsagePercent : 0.49 232 | memUsageMB : 2676 233 | CompletionTimeInHours : Still in progress 234 | ``` 235 | 236 | To get a better Overview, select the Proprties you want to see and use Format-Table: 237 | ```powershell 238 | Get-PlotoJobs -PerfCounter | ? {$_.Status -ne "Completed"} | select PID, Status, TempDrive, OutDrive, cpuUsage, memUsageMB, PlotSizeOnDisk | ft 239 | ``` 240 | 241 | ``` 242 | PID Status TempDrive OutDrive cpuUsagePercent memUsageMB PlotSizeOnDisk 243 | --- ------------ --------- -------- --------------- ---------- -------------- 244 | 8144 3.5 Q: K: 0.58 2130 89.46 GB 245 | 6648 3.6 Q: D: 6.24 2676 48.03 GB 246 | 5444 3.6 Q: D: 3.29 2676 48.03 GB 247 | ``` 248 | 249 | ### Status Codes and their meaning (Chia official plotter) 250 | See below for a definition of what phase coe is associated with which chia.exe log output. 251 | ```powershell 252 | "Starting plotting progress into temporary dirs:*" {$StatusReturn = "Initializing"} 253 | "Starting phase 1/4*" {$StatusReturn = "1.0"} 254 | "Computing table 1" {$StatusReturn = "1.1"} 255 | "F1 complete, time*" {$StatusReturn = "1.1"} 256 | "Computing table 2" {$StatusReturn = "1.1"} 257 | "Computing table 3" {$StatusReturn = "1.2"} 258 | "Computing table 4" {$StatusReturn = "1.3"} 259 | "Computing table 5" {$StatusReturn = "1.4"} 260 | "Computing table 6" {$StatusReturn = "1.5"} 261 | "Computing table 7" {$StatusReturn = "1.6"} 262 | "Starting phase 2/4*" {$StatusReturn = "2.0"} 263 | "Backpropagating on table 7" {$StatusReturn = "2.1"} 264 | "Backpropagating on table 6" {$StatusReturn = "2.2"} 265 | "Backpropagating on table 5" {$StatusReturn = "2.3"} 266 | "Backpropagating on table 4" {$StatusReturn = "2.4"} 267 | "Backpropagating on table 3" {$StatusReturn = "2.5"} 268 | "Backpropagating on table 2" {$StatusReturn = "2.6"} 269 | "Starting phase 3/4*" {$StatusReturn = "3.0"} 270 | "Compressing tables 1 and 2" {$StatusReturn = "3.1"} 271 | "Compressing tables 2 and 3" {$StatusReturn = "3.2"} 272 | "Compressing tables 3 and 4" {$StatusReturn = "3.3"} 273 | "Compressing tables 4 and 5" {$StatusReturn = "3.4"} 274 | "Compressing tables 5 and 6" {$StatusReturn = "3.5"} 275 | "Compressing tables 6 and 7" {$StatusReturn = "3.6"} 276 | "Starting phase 4/4*" {$StatusReturn = "4.0"} 277 | "Writing C2 table*" {$StatusReturn = "4.1"} 278 | "Time for phase 4*" {$StatusReturn = "4.2"} 279 | "Renamed final file*" {$StatusReturn = "Completed"} 280 | ``` 281 | 282 | ### Status Codes and their meaning (madmax/stotik custom plotter) 283 | See below for a definition of what phase coe is associated with which chia.exe log output. 284 | ```powershell 285 | "Process ID*" {$StatusReturn = "Initializing"} 286 | "Plot Name*" {$StatusReturn = "1.1"} 287 | "*P1] Table 1*" {$StatusReturn = "1.2"} 288 | "*P1] Table 2*" {$StatusReturn = "1.3"} 289 | "*P1] Table 3*" {$StatusReturn = "1.4"} 290 | "*P1] Table 4*" {$StatusReturn = "1.5"} 291 | "*P1] Table 5*" {$StatusReturn = "1.6"} 292 | "*P1] Table 6*" {$StatusReturn = "1.7"} 293 | "*P1] Table 7*" {$StatusReturn = "1.8"} 294 | "Phase 1 took*" {$StatusReturn = "2.0"} 295 | "*P2] Table 7 rewrite*" {$StatusReturn = "2.1"} 296 | "*P2] Table 6 rewrite*" {$StatusReturn = "2.2"} 297 | "*P2] Table 5 rewrite*" {$StatusReturn = "2.3"} 298 | "*P2] Table 4 rewrite*" {$StatusReturn = "2.4"} 299 | "*P2] Table 3 rewrite*" {$StatusReturn = "2.5"} 300 | "*P2] Table 2 rewrite*" {$StatusReturn = "2.6"} 301 | "Phase 2 took*" {$StatusReturn = "3.0"} 302 | "*P3-2] Table 2 rewrite took*" {$StatusReturn = "3.1"} 303 | "*P3-2] Table 3 rewrite took*" {$StatusReturn = "3.2"} 304 | "*P3-2] Table 4 rewrite took*" {$StatusReturn = "3.3"} 305 | "*P3-2] Table 5 rewrite took*" {$StatusReturn = "3.4"} 306 | "*P3-2] Table 6 rewrite took*" {$StatusReturn = "3.5"} 307 | "*P3-2] Table 7 rewrite took*" {$StatusReturn = "3.6"} 308 | "Phase 3 took*" {$StatusReturn = "4.0"} 309 | "*P4] Finished writing C2 table*" {$StatusReturn = "4.1"} 310 | "Phase 4 took*" {$StatusReturn = "4.2"} 311 | "Total plot creation*" {$StatusReturn = "4.2"} 312 | "Started copy*" {$StatusReturn = "4.3"} 313 | ``` 314 | 315 | ## How to Stop Jobs 316 | 1. Open a PowerShell session and import Module "Ploto" or use an existing one. 317 | 2. Get PlotJobSpawnerId of Job you want to stop by calling "Get-PlotJobs" 318 | 3. Stop the process: 319 | 320 | ```powershell 321 | Stop-PlotoJob -JobId cfff29b8-fdee-4988-ae89-9db035d809bc 322 | ``` 323 | or if you want to Stop all Jobs that are aborted: 324 | ```powershell 325 | Remove-AbortedPlotoJobs 326 | ``` 327 | 328 | ## How to Move Plots 329 | As you may have noticed in my ref setup: I have little OutDrive storage capacity (1TTB roughly). 330 | This is only possible as I continously move the final Plots to my farming machine with lots of big drives. 331 | 332 | I do this by moving plots to a external drive and plug that into my farmer, and sometimes I also transfer plots across my network (not the fatest, thats why I kind of have to do the running around approach) 333 | 334 | PlotoMover helps to automate this process. In PlotoSpawnerConfig.json, you can define several drives you want to move your final plots to. Mover then checks all defined outdrives for final plots and moves one by one trough Background Inteligence Transfer Service (BITS) to the desired location. In order for remote destination targets (your farmers/harvesters) to recognized correctly, these drives needed to be mapped as network drives and have a volume letter assigned (eg Z:\) for mover to tbe able to grab them. 335 | 336 | To enable mover,, in the config set EnablerMover to "true" and define the PathsToMovePlotsTo according the example config. 337 | Then the next time you launch `Start-PlotoSpawns` mover will be launched aswell. 338 | 339 | 340 | ## How to Check Farm Logs 341 | If you want to peek at your farm logs you can use Check-PLotoFarmLogs: 342 | 1. Launch a PowerShell session and Import Ploto Module 343 | 2. Launch Check-PlotoFarmLogs with your desired LogLevel. It accepts EligiblePlots, Error and Warning. 344 | ```powershell 345 | Get-PlotoFarmLog -LogLevel error 346 | ``` 347 | 348 | ``` 349 | 2021-05-03T23:34:45.532 full_node full_node_server : ERROR Exception: , closing connection {'host': '127.0.0.1', 'port': 8449}. Traceback (most recent call last): 350 | concurrent.futures._base.CancelledError 351 | 2021-05-03T23:34:48.454 full_node full_node_server : ERROR Exception: , closing connection {'host': '127.0.0.1', 'port': 8449}. Traceback (most recent call last): 352 | concurrent.futures._base.CancelledError 353 | 2021-05-03T23:34:52.548 full_node full_node_server : ERROR Exception: , closing connection {'host': '127.0.0.1', 'port': 8449}. Traceback (most recent call last): 354 | concurrent.futures._base.CancelledError 355 | 2021-05-03T23:35:03.845 full_node full_node_server : ERROR Exception: , closing connection {'host': '127.0.0.1', 'port': 8449}. Traceback (most recent call last): 356 | concurrent.futures._base.CancelledError 357 | 2021-05-03T23:35:08.720 full_node full_node_server : ERROR Exception: , closing connection {'host': '127.0.0.1', 'port': 8449}. Traceback (most recent call last): 358 | concurrent.futures._base.CancelledError 359 | 2021-05-03T23:35:15.360 full_node full_node_server : ERROR Exception: , closing connection {'host': '127.0.0.1', 'port': 8449}. Traceback (most recent call last): 360 | concurrent.futures._base.CancelledError 361 | ``` 362 | # FAQ 363 | > Can I shut down the script when I dont want Ploto to spawn more Plots? 364 | 365 | Yep. The individual Chia Plot Jobs wont be affected by that. 366 | 367 | > My config does not laod due to an error. What can I do? 368 | 369 | Make sure all '"' and "," are set correctly. Also make sure for PLotoPathToModule you use "/" instead of "\\". 370 | 371 | > Ploto wont start due to an error. What can I do? 372 | 373 | Try flushing your logs. You can simply move them to another folder. This is due to the fact that Ploto handles log different than the Chia GUI/CLI Plotter. 374 | 375 | # Knowns Bugs and Limitations 376 | Please be aware that Ploto was built for my specific setup. I try to generalize it as much as possible, but thats not easy-breezy. 377 | So what works for me, may not ultimately work for you. 378 | Please also bear in mind that unexpected beahviour and or bugs are possible. 379 | 380 | These are known: 381 | * Only works when Drives are dedicated to plotting (dont hold any other files) 382 | * If you start to use Ploto and you have Logs created by GUI or any other manager in C:\Users\me.chia\mainnet\plotter\, Get-PlotoPlots wont the able to read the status. 383 | Make sure you delete/move all existing Logs in said path. 384 | * Can only display and stop PlotJobs that have been spawned using PlotoSpawner 385 | * Using the -PerfCounter param on Get-PlotoJobs takes a while to load 386 | * PlotoMover is very limited right now, may break copy jobs at times (Bits) 387 | * PlotoMover does not check for available free space on network drives as its unaware of it (only does for local drives) 388 | * If you have more than 1x version of chia within your C:\Users\Me\AppData\Local\chia-blockchain folder, Ploto wont be able to determine the version and will fail. 389 | Make sure theres only one available folder with chia.exe (eg. app-1.1.3) 390 | 391 | ## Function details 392 | For a detailled documentation of all available functions, their params in- and outputs see the links below, or 393 | [here](https://github.com/tydeno/Ploto/blob/main/Functions.md) 394 | ### PlotoSpawn 395 | * [Get-PlotoOutDrives](https://github.com/tydeno/Ploto/blob/main/Functions.md#get-plotooutdrives) 396 | * [Get-PlotoTempDrives](https://github.com/tydeno/Ploto/blob/main/Functions.md#get-plototempdrives) 397 | * [Invoke-PlotoJob](https://github.com/tydeno/Ploto/blob/main/Functions.md#invoke-plotojob) 398 | * [Start-PlotoSpawn](https://github.com/tydeno/Ploto/blob/main/Functions.md#start-plotospawns) 399 | 400 | ### PlotoManage 401 | * [Get-PlotoJobs](https://github.com/tydeno/Ploto/blob/main/Functions.md#get-plotojobs) 402 | * [Stop-PlotoJob](https://github.com/tydeno/Ploto/blob/main/Functions.md#stop-plotojob) 403 | * [Remove-AbortedJobs](https://github.com/tydeno/Ploto/blob/main/Functions.md#remove-abortedjobs) 404 | 405 | ### PlotoMove 406 | * [Get-PlotoPlots](https://github.com/tydeno/Ploto/blob/main/Functions.md#get-plotoplots) 407 | * [Move-PlotoPlots](https://github.com/tydeno/Ploto/blob/main/Functions.md#move-plotoplots) 408 | * [Start-PlotoMove](https://github.com/tydeno/Ploto/blob/main/Functions.md#start-plotomove) 409 | ### PlotoFarmer 410 | * [Get-PlotoFarmLog](https://github.com/tydeno/Ploto/blob/main/README.md#check-farm-logs) 411 | -------------------------------------------------------------------------------- /Install-Ploto.ps1: -------------------------------------------------------------------------------- 1 | <# 2 | .SYNOPSIS 3 | Name: Ploto 4 | Version: 0.841 5 | Author: Tydeno 6 | 7 | 8 | .DESCRIPTION 9 | "Installs" Ploto from your downloaded clone of Ploto. 10 | A basic Windows PowerShell based Chia Plotting Manager. Cause I was tired of spawning them myself. Basically spawns and moves Plots around. 11 | https://github.com/tydeno/Ploto 12 | #> 13 | 14 | 15 | #Helper functions 16 | function Get-JsonDifference 17 | { 18 | <# 19 | .SYNOPSIS 20 | Compares two JSON strings and generated stringified JSON object representing differences. 21 | 22 | LIMITATIONS: 23 | 1. Arrays sub-objects are compared literally as strings after every object within array is sorted by keys and 24 | whole array is minified afterwards. 25 | 26 | 2. Due to limitation of ConvertTo-Json in PowerShell 5.1 27 | object with case sensitive keys are not supported. E.g. Can't have object wil `KeyName` and `keyname`. 28 | 29 | .PARAMETER FromJsonString 30 | Old variant of stringified JSON object. 31 | 32 | .PARAMETER ToJsonString 33 | New variant of stringified JSON object that FromJsonString will be compared to. 34 | 35 | .PARAMETER Depth 36 | Depth used on resulting object conversion to JSON string ('ConvertTo-Json -Depth' parameter). 37 | Is it also used when converting Array values into JSON string after it has been sorted for comparison logic. 38 | 39 | .PARAMETER Compress 40 | Set to minify resulting object 41 | 42 | .OUTPUTS 43 | JSON string with the following JSON object keys: 44 | - Added - items that were not present in FromJsonString and are now in ToJsonString JSON object. 45 | - Changed - items that were present in FromJsonString and in ToJsonString containing new values are from ToJsonString JSON object. 46 | - ChangedOriginals - - items that were present in FromJsonString and in ToJsonString containing old values are from FromJsonString JSON object. 47 | - Removed - items that were present in FromJsonString and are missing in ToJsonString JSON object. 48 | - NotChanged - items that are present in FromJsonString and in ToJsonString JSON objects with the same values. 49 | - New - Merged Added and Changed resulting objects representing all items that have changed and were added. 50 | 51 | .EXAMPLE 52 | Get-JsonDifference -FromJsonString '{"foo_gone":"bar","bar":{"foo":"bar","bar":"foo"},"arr":[{"bar":"baz","foo":"bar"},1]}' ` 53 | -ToJsonString '{"foo_added":"bar","bar":{"foo":"bar","bar":"baz"},"arr":[{"foo":"bar","bar":"baz"},1]}' 54 | { 55 | "Added": { 56 | "foo_added": "bar" 57 | }, 58 | "Changed": { 59 | "bar": { 60 | "bar": "baz" 61 | } 62 | }, 63 | "ChangedOriginals": { 64 | "bar": { 65 | "bar": "foo" 66 | } 67 | }, 68 | "Removed": { 69 | "foo_gone": "bar" 70 | }, 71 | "NotChanged": { 72 | "bar": { 73 | "foo": "bar" 74 | }, 75 | "arr": [ 76 | { 77 | "foo": "bar", 78 | "bar": "baz" 79 | }, 80 | 1 81 | ] 82 | }, 83 | "New": { 84 | "foo_added": "bar", 85 | "bar": { 86 | "bar": "baz" 87 | } 88 | } 89 | } 90 | 91 | .LINK 92 | https://github.com/choovick/ps-jsonutils 93 | 94 | #> 95 | [CmdletBinding()] 96 | [OutputType([String])] 97 | param( 98 | [Parameter(Mandatory = $true)] 99 | [String]$FromJsonString, 100 | [Parameter(Mandatory = $true)] 101 | [String]$ToJsonString, 102 | [Parameter(Mandatory = $false)] 103 | [String]$Depth = 25, 104 | [Switch]$Compress 105 | ) 106 | try 107 | { 108 | # Convert to PSCustomObjects 109 | $FromObject = ConvertFrom-Json -InputObject $FromJsonString 110 | $ToObject = ConvertFrom-Json -InputObject $ToJsonString 111 | # Ensuring both inputs are objects 112 | try 113 | { 114 | if (([PSCustomObject]@{ }).GetType() -ne $FromObject.GetType()) 115 | { 116 | throw 117 | } 118 | } 119 | catch 120 | { 121 | throw "FromJsonString must be an object at the root" 122 | } 123 | try 124 | { 125 | if (([PSCustomObject]@{ }).GetType() -ne $ToObject.GetType()) 126 | { 127 | throw 128 | } 129 | } 130 | catch 131 | { 132 | throw "ToJsonString must be an object at the root" 133 | } 134 | 135 | return Get-JsonDifferenceRecursion -FromObject $FromObject -ToObject $ToObject | ConvertTo-Json -Depth $Depth -Compress:$Compress 136 | 137 | } 138 | catch 139 | { 140 | throw 141 | } 142 | 143 | } 144 | 145 | function Get-JsonDifferenceRecursion 146 | { 147 | <# 148 | .SYNOPSIS 149 | INTERNAL - Compares two PSCustomObjects produced via ConvertFrom-Json cmdlet. 150 | 151 | .PARAMETER FromObject 152 | Old variant of JSON object. 153 | 154 | .PARAMETER ToObject 155 | New variant of JSON object. 156 | 157 | .PARAMETER Depth 158 | Depth used when converting Array values into JSON string after it has been sorted for comparison logic. 159 | 160 | .OUTPUTS 161 | PSCustomObject with the following object keys: 162 | - Added - items that were not present in FromJsonString and are now in ToJsonString JSON object. 163 | - Changed - items that were present in FromJsonString and in ToJsonString containing new values are from ToJsonString JSON object. 164 | - ChangedOriginals - - items that were present in FromJsonString and in ToJsonString containing old values are from FromJsonString JSON object. 165 | - Removed - items that were present in FromJsonString and are missing in ToJsonString JSON object. 166 | - NotChanged - items that are present in FromJsonString and in ToJsonString JSON objects with the same values. 167 | - New - Merged Added and Changed resulting objects representing all items that have changed and were added. 168 | #> 169 | [CmdletBinding()] 170 | [OutputType([PSCustomObject])] 171 | param( 172 | $FromObject, 173 | $ToObject, 174 | $Depth = 25 175 | ) 176 | try 177 | { 178 | $Removed = [PSCustomObject]@{ } 179 | $Changed = [PSCustomObject]@{ } 180 | $ChangedOriginals = [PSCustomObject]@{ } 181 | $Added = [PSCustomObject]@{ } 182 | $New = [PSCustomObject]@{ } 183 | $NotChanged = [PSCustomObject]@{ } 184 | 185 | # Now for sort can capture each value of input object 186 | foreach ($Property in $ToObject.PsObject.Properties) 187 | { 188 | # Access the name of the property 189 | $ToName = $Property.Name 190 | # Access the value of the property 191 | $ToValue = $Property.Value 192 | 193 | # getting types handling null 194 | if ($null -eq $ToValue) 195 | { 196 | $ToValueType = $Script:NullType 197 | } 198 | else 199 | { 200 | $ToValueType = $ToValue.GetType() 201 | } 202 | 203 | # check if property exists in FromObject (in PS 5.1 we cant support case sensitive keys https://github.com/PowerShell/PowerShell/issues/3705) 204 | if ([bool]($FromObject.PSObject.Properties.Name -match [System.Text.RegularExpressions.Regex]::Escape($ToName))) 205 | { 206 | # old value 207 | $FromValue = $FromObject.$ToName 208 | 209 | # getting from object type 210 | # getting types handling null 211 | if ($null -eq $FromObject.$ToName) 212 | { 213 | $FromValueType = $Script:NullType 214 | } 215 | else 216 | { 217 | $FromValueType = $FromObject.$ToName.GetType() 218 | } 219 | 220 | # if both of them are object, continue recursion 221 | if ($FromValueType -eq ([PSCustomObject]@{ }).GetType() -and $ToValueType -eq ([PSCustomObject]@{ }).GetType()) 222 | { 223 | $Result = Get-JsonDifferenceRecursion -FromObject $FromValue -ToObject $ToValue 224 | # capture differences 225 | if (-not [string]::IsNullOrWhiteSpace($Result.Added)) 226 | { 227 | Add-Member -InputObject $Added -MemberType NoteProperty -Name $ToName -Value $Result.Added 228 | } 229 | if (-not [string]::IsNullOrWhiteSpace($Result.Removed)) 230 | { 231 | Add-Member -InputObject $Removed -MemberType NoteProperty -Name $ToName -Value $Result.Removed 232 | } 233 | if (-not [string]::IsNullOrWhiteSpace($Result.Changed)) 234 | { 235 | Add-Member -InputObject $Changed -MemberType NoteProperty -Name $ToName -Value $Result.Changed 236 | } 237 | if (-not [string]::IsNullOrWhiteSpace($Result.ChangedOriginals)) 238 | { 239 | Add-Member -InputObject $ChangedOriginals -MemberType NoteProperty -Name $ToName -Value $Result.ChangedOriginals 240 | } 241 | if (-not [string]::IsNullOrWhiteSpace($Result.NotChanged)) 242 | { 243 | Add-Member -InputObject $NotChanged -MemberType NoteProperty -Name $ToName -Value $Result.NotChanged 244 | } 245 | if (-not [string]::IsNullOrWhiteSpace($Result.New)) 246 | { 247 | Add-Member -InputObject $New -MemberType NoteProperty -Name $ToName -Value $Result.New 248 | } 249 | } 250 | # if type is different 251 | elseif ($FromValueType -ne $ToValueType) 252 | { 253 | # capturing new value in changed object 254 | Add-Member -InputObject $Changed -MemberType NoteProperty -Name $ToName -Value $ToValue 255 | Add-Member -InputObject $New -MemberType NoteProperty -Name $ToName -Value $ToValue 256 | Add-Member -InputObject $ChangedOriginals -MemberType NoteProperty -Name $ToName -Value $FromValue 257 | } 258 | # If both are arrays, items should be sorted by now, so we will stringify them and compare as string case sensitively 259 | elseif ($FromValueType -eq @().GetType() -and $ToValueType -eq @().GetType()) 260 | { 261 | # stringify array 262 | $FromJSON = Get-SortedPSCustomObjectRecursion $FromObject.$ToName | ConvertTo-Json -Depth $Depth 263 | $ToJSON = Get-SortedPSCustomObjectRecursion $ToObject.$ToName | ConvertTo-Json -Depth $Depth 264 | 265 | # add to changed object if values are different for stringified array 266 | if ($FromJSON -cne $ToJSON) 267 | { 268 | Add-Member -InputObject $Changed -MemberType NoteProperty -Name $ToName -Value $ToValue 269 | Add-Member -InputObject $New -MemberType NoteProperty -Name $ToName -Value $ToValue 270 | Add-Member -InputObject $ChangedOriginals -MemberType NoteProperty -Name $ToName -Value $FromValue 271 | } 272 | else 273 | { 274 | Add-Member -InputObject $NotChanged -MemberType NoteProperty -Name $ToName -Value $ToValue 275 | } 276 | } 277 | # other primitive types changes 278 | else 279 | { 280 | if ($FromValue -cne $ToValue) 281 | { 282 | Add-Member -InputObject $Changed -MemberType NoteProperty -Name $ToName -Value $ToValue 283 | Add-Member -InputObject $New -MemberType NoteProperty -Name $ToName -Value $ToValue 284 | Add-Member -InputObject $ChangedOriginals -MemberType NoteProperty -Name $ToName -Value $FromValue 285 | } 286 | else 287 | { 288 | Add-Member -InputObject $NotChanged -MemberType NoteProperty -Name $ToName -Value $ToValue 289 | } 290 | } 291 | } 292 | # if value does not exist in the from object, then its was added 293 | elseif (-not [bool]($FromObject.PSObject.Properties.Name -match [System.Text.RegularExpressions.Regex]::Escape($ToName))) 294 | { 295 | Add-Member -InputObject $Added -MemberType NoteProperty -Name $ToName -Value $ToValue 296 | Add-Member -InputObject $New -MemberType NoteProperty -Name $ToName -Value $ToValue 297 | } 298 | } 299 | 300 | # Looping from object to find removed items 301 | foreach ($Property in $FromObject.PsObject.Properties) 302 | { 303 | # Access the name of the property 304 | $FromName = $Property.Name 305 | # Access the value of the property 306 | $FromValue = $Property.Value 307 | 308 | # if property not on to object, its removed 309 | if (-not [bool]($ToObject.PSObject.Properties.Name -match [System.Text.RegularExpressions.Regex]::Escape($FromName))) 310 | { 311 | Add-Member -InputObject $Removed -MemberType NoteProperty -Name $FromName -Value $FromValue 312 | } 313 | } 314 | 315 | return [PSCustomObject]@{ 316 | Added = $Added 317 | Changed = $Changed 318 | ChangedOriginals = $ChangedOriginals 319 | Removed = $Removed 320 | NotChanged = $NotChanged 321 | New = $New 322 | } 323 | } 324 | catch 325 | { 326 | throw 327 | } 328 | } 329 | 330 | function ConvertTo-KeysSortedJSONString 331 | { 332 | <# 333 | .SYNOPSIS 334 | Sorts JSON strings by object keys. 335 | 336 | .PARAMETER JsonString 337 | Input JSON string 338 | 339 | .PARAMETER Depth 340 | Used for ConvertTo-Json on resulting object 341 | 342 | .PARAMETER Compress 343 | Returned minified JSON 344 | 345 | .OUTPUTS 346 | String of sorted and stringified JSON object 347 | 348 | .EXAMPLE 349 | ConvertTo-KeysSortedJSONString -JsonString '{"b":1,"1":{"b":null,"a":1}}' 350 | { 351 | "1": { 352 | "a": 1, 353 | "b": null 354 | }, 355 | "b": 1 356 | } 357 | 358 | .LINK 359 | https://github.com/choovick/ps-jsonutils 360 | 361 | #> 362 | [CmdletBinding()] 363 | [OutputType([String])] 364 | param( 365 | [Parameter(Mandatory = $true)] 366 | [String]$JsonString, 367 | [Parameter(Mandatory = $false)] 368 | [String]$Depth = 25, 369 | [Switch]$Compress 370 | ) 371 | try 372 | { 373 | $ResultObject = Get-SortedPSCustomObjectRecursion -InputObject (ConvertFrom-Json $JsonString) 374 | return $ResultObject | ConvertTo-Json -Compress:$Compress -Depth $Depth 375 | } 376 | catch 377 | { 378 | throw 379 | } 380 | } 381 | 382 | function Get-SortedPSCustomObjectRecursion 383 | { 384 | <# 385 | .SYNOPSIS 386 | INTERNAL - Recursion to sort PSCustomObject produced via ConvertFrom-Json by keys. 387 | Can take $null, that will be simply returned. 388 | 389 | .PARAMETER InputObject 390 | PSCustomObject produced via ConvertFrom-Json 391 | 392 | .OUTPUTS 393 | PSCustomObject sorted by keys 394 | 395 | #> 396 | [CmdletBinding()] 397 | [OutputType([Object])] 398 | param( 399 | [Parameter(Mandatory = $false)] 400 | [PSCustomObject]$InputObject 401 | ) 402 | 403 | try 404 | { 405 | # null handle 406 | if ($null -eq $InputObject) 407 | { 408 | return $InputObject 409 | } 410 | # object 411 | if ($InputObject.GetType() -eq ([PSCustomObject]@{ }).GetType()) 412 | { 413 | # soft object by keys 414 | # thanks to https://stackoverflow.com/a/44056862/2174835 415 | $SortedInputObject = New-Object PSCustomObject 416 | $InputObject | 417 | Get-Member -Type NoteProperty | Sort-Object Name | ForEach-Object { 418 | Add-Member -InputObject $SortedInputObject -Type NoteProperty ` 419 | -Name $_.Name -Value $InputObject.$($_.Name) 420 | } 421 | 422 | # Now for sort can capture each value of input object 423 | foreach ($Property in $SortedInputObject.PsObject.Properties) 424 | { 425 | # Access the name of the property 426 | $PropertyName = $Property.Name 427 | # Access the value of the property 428 | $PropertyValue = $Property.Value 429 | 430 | $SortedInputObject.$PropertyName = Get-SortedPSCustomObjectRecursion -InputObject $PropertyValue 431 | } 432 | 433 | return $SortedInputObject 434 | } 435 | # array, sort each item within array 436 | elseif ($InputObject.GetType() -eq @().GetType()) 437 | { 438 | $SortedArrayObjects = @() 439 | 440 | foreach ($Item in $InputObject) 441 | { 442 | $SortedArrayObjects += @(Get-SortedPSCustomObjectRecursion -InputObject $Item) 443 | } 444 | 445 | return $SortedArrayObjects 446 | } 447 | # primitive are not sorted as returned as is 448 | return $InputObject 449 | } 450 | catch 451 | { 452 | throw 453 | } 454 | } 455 | 456 | # Mainlogic 457 | 458 | Write-Host "InstallPloto @"(Get-Date)": Hello there! My Name is Ploto. This script guides you trough the setup of myself." -ForegroundColor Magenta 459 | 460 | $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition 461 | 462 | Write-Host ("InstallPloto @"+(Get-Date)+": Path I got launched from: "+$scriptPath) 463 | 464 | $PathToPloto = $scriptPath+"\Ploto.psm1" 465 | 466 | #Get Version of ploto in source for folder name (posh structure) 467 | $Pattern = "Version:" 468 | $PlotoVersionInSource = (Get-Content $PathToPloto | Select-String $pattern).Line.Trimstart("Version: ") 469 | 470 | Write-Host "InstallPloto @"(Get-Date)": Installing Version: $PlotoVersionInSource of Ploto on this machine." 471 | 472 | $IsInstalledFromRelease = $scriptPath.Split("\") 473 | $CountInThere = ($IsInstalledFromRelease.Count)-1 474 | if ($IsInstalledFromRelease[$CountInThere] -ne "Ploto") 475 | { 476 | Write-Host "InstallPloto @"(Get-Date)": Ploto Install script is launched from Release. Need to rewrite its name to 'Ploto'" -ForegroundColor Yellow 477 | $RenameFinalCopy = $true 478 | } 479 | else 480 | { 481 | $RenameFinalCopy = $false 482 | } 483 | 484 | $DestinationForModule = $Env:ProgramFiles+"\WindowsPowerShell\Modules\" 485 | $DestinationContainer = $Env:ProgramFiles+"\WindowsPowerShell\Modules\Ploto" 486 | $DestinationFullPathForModule = $Env:ProgramFiles+"\WindowsPowerShell\Modules\Ploto.psm1" 487 | 488 | Write-Host "InstallPloto @"(Get-Date)": Lets check if a version of Ploto is installed in:"$Env:ProgramFiles"\WindowsPowerShell\Modules" -ForegroundColor Cyan 489 | 490 | If (Test-Path $DestinationContainer) 491 | { 492 | Write-Host "InstallPloto @"(Get-Date)": There is a version of Ploto installed in:"$Env:ProgramFiles"\WindowsPowerShell\Modules" -ForegroundColor Cyan 493 | 494 | #Lets get version of Script 495 | $PlotoVersionInstalled = (Get-Content $DestinationContainer"\Ploto.psm1" | Select-String $pattern).Line.Trimstart("Version: ") 496 | 497 | Write-Host "InstallPloto @"(Get-Date)": Current version installed:"$PlotoVersionInstalled -ForegroundColor Cyan 498 | 499 | If ($PlotoVersionInstalled -le $PlotoVersionInSource) 500 | { 501 | Write-Host "InstallPloto @"(Get-Date)": Version in downloaded Source is newer or the same as installed Version." -ForegroundColor Yellow 502 | $Update = Read-Host -Prompt "InstallPloto: Do you want to update your existing version?" 503 | 504 | if ($Update -eq "Yes" -or $Update -eq "y") 505 | { 506 | Write-Host "InstallPloto @"(Get-Date)": Starting update of Module..." -ForegroundColor Cyan 507 | try 508 | { 509 | Write-Host "InstallPloto @"(Get-Date)": Deleting old version in:"$DestinationContainer -ForegroundColor Cyan 510 | Get-Item -Path $DestinationContainer | Remove-Item -Recurse -Force -ErrorAction Stop 511 | Write-Host "InstallPloto @"(Get-Date)": Successfully removed previous version of Ploto in:"$DestinationContainer -ForegroundColor Green 512 | } 513 | catch 514 | { 515 | Write-Host $_.Exception.Message -ForegroundColor Red 516 | Write-Host "InstallPloto @"(Get-Date)": Could not remove older version." -ForegroundColor Red 517 | break 518 | } 519 | try 520 | { 521 | Copy-Item -Path $scriptPath -Destination $DestinationForModule -Force -Recurse 522 | Write-Host "InstallPloto @"(Get-Date)": Copied Module successfully to:"$DestinationForModule -ForegroundColor Green 523 | } 524 | 525 | catch 526 | { 527 | Write-Host "InstallPloto @"(Get-Date)": Could not install Module in:"$Env:ProgramFiles"\WindowsPowerShell\Modules" -ForegroundColor Red 528 | Write-Host $_.Exception.Message -ForegroundColor Red 529 | break 530 | } 531 | } 532 | else 533 | { 534 | Write-Host "InstallPloto @"(Get-Date)": We skipped updating. Using currently installed version of Ploto:"$PlotoVersionInSource -ForegroundColor Yellow 535 | } 536 | } 537 | 538 | } 539 | else 540 | { 541 | Write-Host "InstallPloto @"(Get-Date)": There is no version of Ploto installed in:"$Env:ProgramFiles"\WindowsPowerShell\Modules" -ForegroundColor Cyan 542 | Write-Host "InstallPloto @"(Get-Date)": Starting copy of Module..." 543 | try 544 | { 545 | 546 | Copy-Item -Path $scriptPath -Destination $DestinationForModule -Force -Recurse 547 | Write-Host "InstallPloto @"(Get-Date)": Copied Module successfully to:"$DestinationForModule -ForegroundColor Green 548 | } 549 | 550 | catch 551 | { 552 | Write-Host "InstallPloto @"(Get-Date)": Could not install Module in:"$Env:ProgramFiles"\WindowsPowerShell\Modules" -ForegroundColor Red 553 | Write-Host $_.Exception.Message -ForegroundColor Red 554 | break 555 | } 556 | } 557 | 558 | if ($RenameFinalCopy -eq $true) 559 | { 560 | Write-Host "InstallPloto @"(Get-Date)": Renaming Ploto folder in: "$DestinationForModule -ForegroundColor yellow 561 | $buildedpath = $DestinationForModule+"\"+$IsInstalledFromRelease[$CountInThere] 562 | Write-Host "InstallPloto @"(Get-Date)": Builde Path to rename:"$buildedpath -ForegroundColor yellow 563 | 564 | try 565 | { 566 | Rename-Item -path $buildedpath -NewName "Ploto" -Force -ErrorAction Stop 567 | Write-Host "InstallPloto @"(Get-Date)": Renamed Module successfully!" -ForegroundColor Green 568 | } 569 | catch 570 | { 571 | Write-Host "InstallPloto @"(Get-Date)": Could not rename final Module to 'Ploto'. You may need to rename manually in:"$DestinationForModule -ForegroundColor red 572 | Write-Host $_.Exception.Message -ForegroundColor Red 573 | } 574 | 575 | 576 | } 577 | 578 | 579 | Write-Host "InstallPloto @"(Get-Date)": Lets check the current set Execution Policy..." -ForegroundColor Cyan 580 | $ExecPolicy = Get-ExecutionPolicy 581 | Write-Host "InstallPloto @"(Get-Date)": Execution Policy is set to: "$ExecPolicy 582 | 583 | 584 | #get ExecPolicy 585 | if (!($ExecPolicy -ne "RemoteSigned" -or "Bypass")) 586 | { 587 | Write-Host "InstallPloto @"(Get-Date)": Alright, ExecutionPolicy is NOT RemoteSigned or Bypass. Need to adjust..." -ForegroundColor Yellow 588 | try 589 | { 590 | Set-ExecutionPolicy RemoteSigned -Scope CurrentUser 591 | Write-Host "InstallPloto @"(Get-Date)": I set Execution Policy to RemoteSigned." 592 | } 593 | catch 594 | { 595 | 596 | Write-Host $_.Exception.Message -ForegroundColor red 597 | Write-Host "InstallPloto @"(Get-Date)": I ran into trouble setting RemoteSigned. Trying to set Bypass." -ForegroundColor Yellow 598 | 599 | try 600 | { 601 | Set-ExecutionPolicy -ExecutionPolicy Bypass 602 | Write-Host "InstallPloto @"(Get-Date)": I set Execution Policy to Bypass." 603 | } 604 | catch 605 | { 606 | Write-Host "InstallPloto @"(Get-Date)": I ran into trouble setting RemoteSigned and Bypass. Aorting. Maybe launch Script as Admin." -ForegroundColor Red 607 | Write-Host $_.Exception.Message -ForegroundColor Red 608 | break 609 | } 610 | } 611 | } 612 | 613 | try 614 | { 615 | Import-Module $PathToPloto 616 | Write-Host "InstallPloto @"(Get-Date)": Wooho! I've managed to imort the Ploto Module!" -ForegroundColor Green 617 | } 618 | catch 619 | { 620 | Write-Host "InstallPloto @"(Get-Date)": Aww... I ran into trouble importing the Module. See below for details." -ForegroundColor Red 621 | Write-Host $_.Exception.Message -ForegroundColor Red 622 | break 623 | 624 | } 625 | 626 | 627 | 628 | Write-Host "InstallPloto @"(Get-Date)": Okay, next step is getting the config and setting it together with you..." 629 | 630 | Write-Host "InstallPloto @"(Get-Date)": Checking if we have new properties in config from new version..." -ForegroundColor Cyan 631 | 632 | $pathtolchech = $env:HOMEDRIVE+$env:HOMEPath+"\.chia\mainnet\config\PlotoSpawnerConfig.json" 633 | $sourcecfg = Get-Content -raw -Path $scriptPath"\PlotoSpawnerConfig.json" | ConvertFrom-Json 634 | if (Test-Path $pathtolchech) 635 | { 636 | $installedcfg = Get-Content -raw -Path $env:HOMEDRIVE$env:HOMEPath"\.chia\mainnet\config\PlotoSpawnerConfig.json" | ConvertFrom-Json 637 | $old = Get-Content -raw -Path $env:HOMEDRIVE$env:HOMEPath"\.chia\mainnet\config\PlotoSpawnerConfig.json" 638 | $new = Get-Content -raw -Path $scriptPath"\PlotoSpawnerConfig.json" 639 | $compare = Get-JsonDifference -FromJsonString $old -ToJsonString $new -Depth 32 | ConvertFrom-Json 640 | $checkAdded = $compare.added 641 | 642 | if ($checkAdded -match "@") 643 | { 644 | Write-Host "InstallPloto @"(Get-Date)": New properties were introduced in new version, need to update config!" -ForegroundColor Yellow 645 | Write-Host "InstallPloto @"(Get-Date)": Added: "$compare.added -ForegroundColor Yellow 646 | 647 | } 648 | else 649 | { 650 | Write-Host "InstallPloto @"(Get-Date)": No new properties were introduced in config" -ForegroundColor Green 651 | } 652 | 653 | } 654 | else 655 | { 656 | Write-Host "InstallPloto @"(Get-Date)": No productive config found among this usercontext." 657 | } 658 | 659 | 660 | $SkipCFG = Read-Host "InstallPloto: Do you want to set the config? If not, we skip that, because you alreay have one in place (eg. Yes or y)" 661 | 662 | If ($SkipCFG -eq "Yes" -or $SkipCFG -eq "y") 663 | { 664 | try 665 | { 666 | 667 | $PathToConfig = $scriptPath+"\PlotoSpawnerConfig.json" 668 | 669 | $config = Get-Content -raw -Path $PathToConfig | ConvertFrom-Json -ErrorAction Stop 670 | 671 | Write-Host "InstallPloto @"(Get-Date)": Wuepa! We could grab the config! Next up is setting its values with you." -ForegroundColor Green 672 | } 673 | catch 674 | { 675 | 676 | Write-Host "PlotoManager @"(Get-Date)": Could not read Config. Check your config with the hints below and on https://jsonformatter.org/ for validation. If you cant get it to run, join Ploto Discord for help. " -ForegroundColor Red 677 | 678 | if ($_.Exception.Message -like "*1384*") 679 | { 680 | Write-Host "PlotoManager @"(Get-Date)": Looks like your PathToPlotoModule is not specified correctly. You have to use \ instead of /!" -ForegroundColor Yellow 681 | } 682 | 683 | if ($_.Exception.Message -like "*1093*") 684 | { 685 | Write-Host "PlotoManager @"(Get-Date)": Looks like there is a ',' missing somewhere at the end of a line " -ForegroundColor Yellow 686 | } 687 | 688 | if ($_.Exception.Message -like "*1094*") 689 | { 690 | Write-Host "PlotoManager @"(Get-Date)": Looks like there is a '$a' missing somewhere at the beginning or end of a property " -ForegroundColor Yellow 691 | } 692 | 693 | 694 | 695 | if ($_.Exception.Message -notlike "*1384*" -and $_.Exception.Message -notlike "*1093*" -and $_.Exception.Message -notlike "*1094*") 696 | { 697 | Write-Host "PlotoManager @"(Get-Date)": Could not determine possible rootcause. Check your config on https://jsonformatter.org/ for validation. If you cant get it to run, join Ploto Discord for help." -ForegroundColor Red 698 | Write-Host $_.Exception.Message -ForegroundColor red 699 | } 700 | 701 | Start-Sleep 30 702 | 703 | Write-Host "Exiting cause there is no readable config." -ForegroundColor Red 704 | break 705 | } 706 | 707 | if ($config.PathToPloto -eq "C:/Users/Tydeno/Desktop/Ploto/Ploto.psm1" -or $config.PathToPloto -eq "") 708 | { 709 | 710 | $config.PathToPloto = $PathToPloto 711 | 712 | } 713 | 714 | 715 | Write-Host "-------------------------------------" 716 | Write-Host "ConfigurePloto: Lets go over to the basic config..." -ForegroundColor Cyan 717 | 718 | $PlotterName = Read-Host -Prompt "ConfigurePloto: Enter the name of your plotter (eg: SirNotPlotAlot)" 719 | $config.PlotterName = $PlotterName 720 | 721 | $EnableAlerts = Read-Host -Prompt "ConfigurePloto: Do you want to enable Discord Notifications? (eg: Yes or No)" 722 | If ($EnableAlerts -eq "Yes" -or $EnableAlerts -eq "yes" -or $EnableAlerts -eq "y") 723 | { 724 | $config | % {$_.EnableAlerts = "true"} 725 | $config | % {$_.EnablePlotoFyOnStart = "true"} 726 | 727 | $WebhookURL = Read-Host -Prompt "Enter the WebhookURL of Discord where you want to receive alerts:" 728 | $config.SpawnerAlerts | % {$_.DiscordWebhookUrl = $WebhookURL} 729 | 730 | $PeriodToReport = Read-Host -Prompt "In what intervall in hours would you like to receive a summary? (eg: 0.5)" 731 | $config.SpawnerAlerts | % {$_.WhenJobSpawned = "true"} 732 | $config.SpawnerAlerts | % {$_.WhenNoOutDrivesAvailable = "true"} 733 | $config.SpawnerAlerts | % {$_.WhenJobCouldNotBeSpawned = "true"} 734 | $config.SpawnerAlerts | % {$_.PeriodOfReportInHours = $PeriodToReport} 735 | } 736 | else 737 | { 738 | $config | % {$_.EnableAlerts = "false"} 739 | $config | % {$_.EnablePlotoFyOnStart = "false"} 740 | } 741 | 742 | $EnableMover = Read-Host "ConfigurePloto: Do you want to enable PlotoMover (moves final plots to defined path)? (eg: Yes or No)" 743 | if ($EnableMover -eq "y" -or $EnableMover -eq "Yes") 744 | { 745 | $PathsToMoveTo = Read-Host "Configure Ploto: Define the paths you want to move final plots to:" 746 | $config | % {$_.EnableMover = "true"} 747 | $config | % {$_.PathsToMovePlotsTo = $PathsToMoveTo} 748 | } 749 | else 750 | { 751 | $config | % {$_.EnableMover = "false"} 752 | $config | % {$_.PathsToMovePlotsTo = ""} 753 | } 754 | 755 | $WindowStyle = Read-Host -Prompt "ConfigurePloto: Do you want to the plot jobs in background? (eg: Yes or No)" 756 | 757 | Write-Host "-------------------------------------" 758 | 759 | Write-Host "ConfigurePloto: Lets go over to the disk config..." 760 | Write-Host "ConfigurePloto: To define your drives, use the following notation:" 761 | Write-Host "ConfigurePloto: To define one drive, use the following notation: F:" 762 | Write-Host "ConfigurePloto: To define several drives, use the following notation: F:,E:,K:" 763 | Write-Host "ConfigurePloto: To define a folder within a drive, use following notation: F:\afolder,E:\anotherone,K:\somefolder" 764 | $TempDrives = Read-Host -Prompt "ConfigurePloto: Define your TempDrives." 765 | $config.DiskConfig | % {$_.TempDrives = $TempDrives} 766 | 767 | $OutDrives = Read-Host -Prompt "ConfigurePloto: Define your OutDrives" 768 | $config.DiskConfig | % {$_.OutDrives = $OutDrives} 769 | 770 | $EnableT2 = Read-Host -Prompt "ConfigurePloto: Do you want to enable T2 drives? (eg: Yes or No)" 771 | 772 | if ($EnableT2 -eq "Yes" -or $EnableT2 -eq "yes" -or $EnableT2 -eq "y") 773 | { 774 | $config.DiskConfig | % {$_.EnableT2 = "true"} 775 | $t2denom = Read-Host -Prompt "ConfigurePloto: Define your t2drives" 776 | 777 | } 778 | else 779 | { 780 | $config.DiskConfig | % {$_.EnableT2 = "false"} 781 | $t2denom = "" 782 | } 783 | 784 | $config.DiskConfig | % {$_.Temp2drives = $t2denom} 785 | 786 | 787 | $replot = Read-Host -Prompt "ConfigurePloto: Do you want to replot existing plots? (eg: Yes or No)" 788 | if ($replot -eq "Yes" -or $replot -eq "yes" -or $replot -eq "y") 789 | { 790 | Write-Host "ConfigurePloto: Will be replotting." -ForegroundColor Magenta 791 | $config.SpawnerConfig | % {$_.ReplotForPool = "true"} 792 | $replotDenom = Read-Host "Define your ReplotDrives" 793 | $config.DiskConfig | % {$_.ReplotDrives = $replotDenom} 794 | } 795 | else 796 | { 797 | Write-Host "ConfigurePloto: Will not be replotting." -ForegroundColor Magenta 798 | $config.DiskConfig | % {$_.ReplotDrives = ""} 799 | $config.SpawnerConfig | % {$_.ReplotForPool = "false"} 800 | } 801 | 802 | $PlotForPools = Read-Host "ConfigurePloto: Do you want to create poolable, portable plots? (eg: Yes or No)" 803 | 804 | 805 | if ($PlotForPools -eq "Yes" -or $PlotForPools -eq "y") 806 | { 807 | $P2 = Read-Host "ConfigurePloto: Enter your P2SingletonAdress to be used by the plots (eg: 76x8s9s89sjhsdsshdsi)" 808 | $fk = Read-host -Prompt "ConfigurePloto: Define your farmer key (eg: dskofsjfias09eidaoufoj...)" 809 | $config.JobConfig | % {$_.P2SingletonAdress = $P2} 810 | $config.JobConfig | % {$_.FarmerKey = $fk} 811 | } 812 | else 813 | { 814 | $pfkeys = Read-Host -Prompt "ConfigurePloto: Do you want to specify -p and -f keys for plotting? DO NOT DO THIS IF YOU WANT PORTABLE POOL PLOTS! (eg: Yes or No)" 815 | 816 | if ($pfkeys -eq "Yes" -or $pfkeys -eq "y") 817 | { 818 | $pk = Read-host -Prompt "ConfigurePloto: Define your pool key (eg: 982192183012830173jdi832...)" 819 | $fk = Read-host -Prompt "ConfigurePloto: Define your farmer key (eg: dskofsjfias09eidaoufoj...)" 820 | $config.JobConfig | % {$_.PoolKey = $pk} 821 | $config.JobConfig | % {$_.FarmerKey = $fk} 822 | } 823 | } 824 | 825 | if ($WindowStyle -eq "Yes" -or $WindowStyle -eq "yes" -or $WindowStyle -eq "y") 826 | { 827 | $config.ChiaWindowStyle = "hidden" 828 | } 829 | else 830 | { 831 | $config.ChiaWindowStyle = "normal" 832 | } 833 | 834 | 835 | Write-Host "-------------------------------------" 836 | Write-Host "ConfigurePloto: Lets go over to the job config..." -ForegroundColor Cyan 837 | 838 | $PlotterToUse = Read-Host -Prompt "ConfigurePloto: Which Plotter do you want to use? Enter 'Stotik' for Madmax Stotik or enter 'Chia' for official Chia plotter" 839 | 840 | if ($PlotterToUse -eq "Stotik" -or $PlotterToUse -eq "stotik") 841 | { 842 | 843 | Write-Host "ConfigurePloto: We will be using MadMax plotter. Pay attention when configuring the JobConfig that you take into consideration how madmax/stotik work" -ForegroundColor Magenta 844 | $config | % {$_.PlotterUsed = $PlotterToUse} 845 | $PathtoStotik = Read-Host -Prompt "ConfigurePloto: Enter fullpath to chia_plots.exe" 846 | $config | % {$_.PathToUnofficialPlotter = $PathtoStotik} 847 | } 848 | else 849 | { 850 | Write-Host "ConfigurePloto: We will be using official Chia Plotter." -ForegroundColor Magenta 851 | $PlotterToUse = "Chia" 852 | $config | % {$_.PlotterUsed = $PlotterToUse} 853 | } 854 | 855 | 856 | $InputAmountToSpawn = Read-Host -Prompt "ConfigurePloto: How many plots do you want to be spawned overall? (eg: 1000)" 857 | $config.SpawnerConfig | % {$_.InputAmounttoSpawn = $InputAmountToSpawn} 858 | 859 | $IntervallToCheckIn = Read-Host -Prompt "ConfigurePloto: In what intervall do you want to check for new jobs in minutes? (eg: 5)" 860 | $config.SpawnerConfig | % {$_.IntervallToCheckInMinutes = $IntervallToCheckIn} 861 | 862 | $WaitSep = Read-Host -Prompt "ConfigurePloto: What stagger time do you want between jobs on separate disks in minutes? (eg. 15)" 863 | $config.SpawnerConfig | % {$_.WaitTimeBetweenPlotOnSeparateDisks = $WaitSep} 864 | 865 | $WaitSame = Read-Host -Prompt "ConfigurePloto: What stagger time do you want between jobs on same disks in minutes? (eg. 45)" 866 | $config.SpawnerConfig | % {$_.WaitTimeBetweenPlotOnSameDisk = $WaitSame} 867 | 868 | $MaxPa = Read-Host -Prompt "ConfigurePloto: How many Jobs do you want to be run max in parallel? (eg: 15)" 869 | $config.SpawnerConfig | % {$_.MaxParallelJobsOnAllDisks = $MaxPa} 870 | 871 | $MaxPaSame = Read-Host -Prompt "ConfigurePloto: How many Jobs do you want to be run max in parallel on the same disk? (eg: 3)" 872 | $config.SpawnerConfig | % {$_.MaxParallelJobsOnSameDisk = $MaxPaSame} 873 | 874 | $MaxP1 = Read-Host -Prompt "ConfigurePloto: How many Jobs do you want to be run max in parallel in phase 1? (eg: 9)" 875 | $config.SpawnerConfig | % {$_.MaxParallelJobsInPhase1OnAllDisks = $MaxP1} 876 | 877 | $StartE = Read-Host -Prompt "ConfigurePloto: Do you want to start a new Job early? (eg: Yes or No)" 878 | If ($StartE -eq "Yes" -or $StartE -eq "yes" -or $StartE -eq "y") 879 | { 880 | $config.SpawnerConfig | % {$_.StartEarly = "true"} 881 | $config.SpawnerConfig | % {$_.StartEarlyPhase = "4"} 882 | } 883 | else 884 | { 885 | $config.SpawnerConfig | % {$_.StartEarly = "false"} 886 | } 887 | 888 | if ($PlotterToUse -ne "Stotik" -or $PlotterToUse -ne "stotik") 889 | { 890 | $bSize = Read-Host -Prompt "ConfigurePloto: Define BufferSize for jobs (eg: 3390)" 891 | $config.JobConfig | % {$_.BufferSize = $bSize} 892 | } 893 | 894 | $buckets = Read-Host -Prompt "ConfigurePloto: Define amount of buckets (eg: 128)" 895 | $config.JobConfig | % {$_.Buckets = $buckets} 896 | 897 | $ts = Read-Host -Prompt "ConfigurePloto: Define amount of Threads for jobs (eg: 4)" 898 | $config.JobConfig | % {$_.Thread = $ts} 899 | 900 | $bf = Read-Host -Prompt "ConfigurePloto: Do you want to disable Bitfield? NOT RECOMMENDED TO DISABLE! (eg. Yes or No)" 901 | 902 | if ($bf = "Yes" -or $bf -eq "yes" -or $bf -eq "y") 903 | { 904 | $config.JobConfig | % {$_.Bitfield = "false"} 905 | } 906 | else 907 | { 908 | $config.JobConfig | % {$_.Bitfield = "true"} 909 | } 910 | 911 | Write-Host "--------------------------" 912 | 913 | 914 | try 915 | { 916 | Write-Host "ConfigurePloto @"(Get-Date)": Saving the config in this folder (where Ploto is stored) with your values..." 917 | $config | ConvertTo-Json -Depth 32 | Set-Content $PathToConfig -Force 918 | Write-Host "InstallPloto @"(Get-Date)": Saved config successfully." -ForegroundColor Green 919 | } 920 | 921 | catch 922 | { 923 | Write-Host "InstallPloto @"(Get-Date)": Could not update config in this folder (where Ploto is stored). See below for details." -ForegroundColor Red 924 | Write-Host $_.Exception.Message -ForegroundColor Red 925 | break 926 | } 927 | 928 | Write-Host "ConfigurePloto @"(Get-Date)": Do you want to get this configuration into production?" 929 | Write-Host "ConfigurePloto @"(Get-Date)": If you have a current configuration going, it will be overwritten with the values above. Are your sure you want to continue?" -ForegroundColor Yellow 930 | $consent = Read-Host -Prompt "Enter 'Yes' or 'y' to continue. Every other inpout aborts." 931 | 932 | if ($consent -eq "Yes" -or $consent -eq "y") 933 | { 934 | try 935 | { 936 | 937 | $tempdrives = Get-PlotoTempDrives 938 | Write-Host "Will be using the following Drives as TempDrives:" 939 | $tempdrives | ft 940 | 941 | $outdrives = Get-PlotoOutDrives 942 | 943 | Write-Host "Will be using the following Drives as OutDrives:" 944 | $outdrives | ft 945 | 946 | $t2drives = Get-PlotoT2Drives 947 | Write-Host "Will be using the following Drives as T2Drives:" 948 | $t2drives | ft 949 | 950 | $destination = $env:HOMEDRIVE+$env:HOMEPath+"\.chia\mainnet\config\" 951 | Copy-Item -Path $PathToConfig -Destination $destination -Force 952 | Write-Host "InstallPloto @"(Get-Date)": Copied config successfully to: " $destination -ForegroundColor Green 953 | Write-Host "InstallPloto @"(Get-Date)": Okay, we are finally ready to roll!" -ForegroundColor Green 954 | } 955 | catch 956 | { 957 | Write-Host "InstallPloto @"(Get-Date)": Could not copy config to: "$destination -ForegroundColor Red 958 | Write-Host $_.Exception.Message -ForegroundColor Red 959 | break 960 | } 961 | } 962 | else 963 | { 964 | Write-Host "InstallPloto @"(Get-Date)": Did not copy saved config to production." 965 | } 966 | 967 | } 968 | else 969 | { 970 | Write-Host "InstallPloto @"(Get-Date)": We skipped setting the config. Only updated Ploto Module." -ForegroundColor Yellow 971 | } 972 | 973 | 974 | 975 | Write-Host "InstallPloto @"(Get-Date)": Ploto was installed correctly on this System." -ForegroundColor Green 976 | 977 | Write-Host "InstallPloto @"(Get-Date)": To launch it, start a PowerShell Session and run 'Start-PlotoSpawns'" 978 | --------------------------------------------------------------------------------