PSLegoEV3WindowsPowerShell.psm1
#Le Dirty Dev Code to import all sub files with functions <#Get-ChildItem $PSScriptRoot\Functions\*.ps1 | ForEach-Object { Write-Verbose "Importing $($_.FullName)" & { . $_.FullName } }#> #TODO Add Bluebooth and usb communication # Add multiple parameter sets depending on selected communications type Function Connect-EV3 { param( [Parameter(Mandatory = $true, ParameterSetName = 'local')] $IPAddress, [Parameter(Mandatory = $true, ParameterSetName = 'azureIoT')] $AzureIoTConnectionString ) #Init Robot #Dev hardcoded dll #[System.Reflection.Assembly]::LoadFrom("C:\Program Files\WindowsPowerShell\Modules\PSLegoEV3WindowsPowerShell\Lego.Ev3.Desktop.dll") $script:Mode = "local" if ($null -ne $AzureIoTConnectionString) { $script:Mode = "azureiot" } switch ($script:Mode) { "local" { try { $com = new-object Lego.Ev3.Desktop.NetworkCommunication -ArgumentList $IPAddress $script:brick = new-object Lego.Ev3.Core.Brick -ArgumentList $com, $true $brick.ConnectAsync().Wait() } catch [AggregateException] { $currentError = $_ throw $currentError.Exception.InnerExceptions } } "azureiot" { #import-module C:\TFS\ev3dev\AzureIoT\AzureIoT.psm1 -Force import-module AzureIoT -Force #region Create a CloudClient $CloudClientParams = @{ iotConnString = $AzureIoTConnectionString } $Script:azureIoTCloudClient = Get-IoTCloudClient @CloudClientParams } } } Function Set-Ev3AzureIoTDeviceName($AzureIoTDeviceName) { $script:AzureIoTDeviceName = $AzureIoTDeviceName } Function Invoke-EV3StepMotor { param( [Lego.Ev3.Core.OutputPort] $OutputPort, [int] $Speed, [int] $Steps, [int] $RampUpSteps = 0, [int] $RampDownSteps = 0, [Boolean] $Brake = $false ) if($global:Mode -eq "azureiot"){ throw "Not supported yet in Azure IoT mode"} $script:brick.DirectCommand.StepMotorAtPowerAsync($OutputPort, $Speed, $RampUpSteps, $Steps, $RampDownSteps, $Brake); } Function Invoke-EV3StopMotor { param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 0)] [Lego.Ev3.Core.OutputPort] $OutputPort, [Boolean] $Brake = $false ) if($global:Mode -eq "azureiot"){ throw "Not supported yet in Azure IoT mode"} $script:brick.DirectCommand.StopMotorAsync($OutputPort, $Brake) } Function Start-EV3LiveControl { param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 0)] [ValidateSet("GRIPP3R")] #Current only supports gripper robot $RobotType = "GRIPP3R" ) switch ($RobotType) { "GRIPP3R" { #Forward Set-PSReadlineKeyHandler -key UpArrow -ScriptBlock { Invoke-EV3Forward } #Backward Set-PSReadlineKeyHandler -key DownArrow -ScriptBlock { Invoke-EV3Backward } #Right Turn Set-PSReadlineKeyHandler -key RightArrow -ScriptBlock { Invoke-EV3Turn -Direction Right } #Left turn Set-PSReadlineKeyHandler -key LeftArrow -ScriptBlock { Invoke-EV3Turn -Direction Left } #Grab Set-PSReadlineKeyHandler -key PageUp -ScriptBlock { Invoke-EV3Gripp3rAction -Action "Grab" } #Release Set-PSReadlineKeyHandler -key PageDown -ScriptBlock { Invoke-EV3Gripp3rAction -Action "Release" } } } } Function Invoke-EV3Forward { param( [int] $Steps = 140, [Lego.Ev3.Core.OutputPort] $OutputPortLeft = "C", [Lego.Ev3.Core.OutputPort] $OutputPortRight = "B", [String] $AzureIoTDeviceName, [int] $Speed = 100 ) switch ($script:Mode) { "local" { $script:brick.BatchCommand.StepMotorAtPower($OutputPortLeft, $Speed, $Steps, $false) $script:brick.BatchCommand.StepMotorAtPower($OutputPortRight, $Speed, $Steps, $false) $script:brick.BatchCommand.SendCommandAsync().Wait() } "azureiot" { $duration = $Steps * 1 #duration in seconds $commands = @{ leftSpeed = 1000 # 100% speed leftDuration = $duration rightSpeed = 1000 rightDuration = $duration } #region send message from Cloud $cloudMessageParams = @{ deviceId = $script:AzureIoTDeviceName messageString = $commands | convertto-json cloudClient = $script:azureIoTCloudClient } Send-IoTCloudMessage @cloudMessageParams } } #switch ($script:Mode) { } Function Invoke-EV3Backward { param( [int] $Steps = 140, [Lego.Ev3.Core.OutputPort] $OutputPortLeft = "C", [Lego.Ev3.Core.OutputPort] $OutputPortRight = "B" ) switch ($script:Mode) { "local" { Invoke-EV3StepMotor -OutputPort $OutputPortLeft -Speed -100 -Steps $Steps Invoke-EV3StepMotor -OutputPort $OutputPortRight -Speed -100 -Steps $Steps } "azureiot" { $duration = $Steps * 1 #duration in seconds $commands = @{ leftSpeed = -1000 # 100% speed leftDuration = $duration rightSpeed = -1000 rightDuration = $duration } #region send message from Cloud $cloudMessageParams = @{ deviceId = $script:AzureIoTDeviceName messageString = $commands | convertto-json cloudClient = $script:azureIoTCloudClient } Send-IoTCloudMessage @cloudMessageParams } } #switch ($script:Mode) { } Function Invoke-EV3Turn { param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 1)] [ValidateSet("Left", "Right")] [String] $Direction, [int] $Steps = 140, [Lego.Ev3.Core.OutputPort] $OutputPortLeft = "C", [Lego.Ev3.Core.OutputPort] $OutputPortRight = "B" ) switch ($Direction) { "Left" { $LeftSpeed = -100 $RightSpeed = 100 break } "Right" { $LeftSpeed = 100 $RightSpeed = -100 break } } switch ($script:Mode) { "local" { Invoke-EV3StepMotor -OutputPort $OutputPortLeft -Speed $LeftSpeed -Steps $Steps Invoke-EV3StepMotor -OutputPort $OutputPortRight -Speed $RightSpeed -Steps $Steps } "azureiot" { $duration = $Steps * 1 #duration in seconds $commands = @{ leftSpeed = $LeftSpeed * 10 # 100% speed leftDuration = $duration rightSpeed = $RightSpeed * 10 rightDuration = $duration } #region send message from Cloud $cloudMessageParams = @{ deviceId = $script:AzureIoTDeviceName messageString = $commands | convertto-json cloudClient = $script:azureIoTCloudClient } Send-IoTCloudMessage @cloudMessageParams } } #switch ($script:Mode) { } Function Invoke-EV3Gripp3rAction { param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 0)] [ValidateSet("Grab", "Release")] [String] $Action, [int] $Steps = 700, [Lego.Ev3.Core.OutputPort] $OutputPort = "A" ) switch ($script:Mode) { "local" { switch ($Action) { "Grab" { Invoke-EV3StepMotor -OutputPort $OutputPort -Speed 50 -Steps $Steps Start-sleep -Seconds 2 Invoke-EV3StopMotor -OutputPort $OutputPort break } "Release" { Invoke-EV3StepMotor -OutputPort $OutputPort -Speed -50 -Steps $Steps Start-sleep -Seconds 2 Invoke-EV3StopMotor -OutputPort $OutputPort break } } } "azureiot" { $duration = $Steps + 1300 * 1 #duration in seconds switch ($Action) { "Grab" { $commands = @{ grabSpeed = 500 grabDuration = $duration } break } "Release" { $commands = @{ grabSpeed = -500 grabDuration = $duration } break } } #region send message from Cloud $cloudMessageParams = @{ deviceId = $script:AzureIoTDeviceName messageString = $commands | convertto-json cloudClient = $script:azureIoTCloudClient } Send-IoTCloudMessage @cloudMessageParams } } #switch ($script:Mode) { } Function ConvertTo-Ev3Steps { param( [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 0)] $Value, [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 1)] [ValidateSet("Centimeters", "Inches")] $Type = "Centimeters", [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true, Position = 2)] [ValidateSet("GRIPP3R")] #Current only supports gripper robot $RobotType = "GRIPP3R" ) switch ($RobotType) { "GRIPP3R" { switch ($Type) { "Centimeters" { return $Value * 35 } "Inches" { return $Value * 89 } } } } } Function Enable-EV3EdgeProtection { param( [Lego.Ev3.Core.OutputPort] $OutputPortLeft = "C", [Lego.Ev3.Core.OutputPort] $OutputPortRight = "B", [Lego.Ev3.Core.InputPort] $InputPort = "One", [ScriptBlock] $InvokeScriptBlock ) if($global:Mode -eq "azureiot"){ throw "Not supported yet in Azure IoT mode"} #$brick.Ports[[Lego.Ev3.Core.InputPort]::One].SetMode([Lego.Ev3.Core.ColorMode]::Color) $brick.Ports[$InputPort].SetMode([Lego.Ev3.Core.ColorMode]::Color) $global:currentEdgeOutputPortLeft = $OutputPortLeft $global:currentEdgeOutputPortRight = $OutputPortRight $global:currentEdgeScriptBlock = $InvokeScriptBlock #start on transparent as we dont want it to stop right away if it is not setup yet $colorLast = "Transparent" $ActionBrickChanged = { #[int] [Lego.Ev3.Core.ColorSensorColor]::Black $colorCurrent = [string][Lego.Ev3.Core.ColorSensorColor] [int] $event.SourceArgs.Ports[0]["One"].SIValue $colorCurrent if ($colorCurrent -ne $global:colorLast) { if ("Transparent" -eq $colorCurrent) { Invoke-EV3StopMotor -OutputPort $global:currentEdgeOutputPortLeft Invoke-EV3StopMotor -OutputPort $global:currentEdgeOutputPortRight if ($null -ne $global:currentEdgeScriptBlock) { & $global:currentEdgeScriptBlock } } $global:colorLast = $colorCurrent #Clear-Host $colorCurrent } } UnRegister-Event -SourceIdentifier "BrickChanged" -ErrorAction SilentlyContinue Register-ObjectEvent -InputObject $brick -EventName BrickChanged -SourceIdentifier "BrickChanged" -Action $ActionBrickChanged -Verbose } |