PSMQTT.psm1
#Region '.\prefix.ps1' -1 # The content of this file will be prepended to the top of the psm1 module file. This is useful for custom module setup is needed on import. # Add M2Mqtt dependency library Add-Type -Path "$PSScriptRoot\Include\M2Mqtt.Net.dll" # Import custom formatting Update-FormatData -AppendPath "$PSScriptRoot\Include\PSMQTT.Format.ps1xml" #EndRegion '.\prefix.ps1' 8 #Region '.\Classes\PSMQTTMessage.class.ps1' -1 class PSMQTTMessage { [string]$Topic [string]$Payload [byte[]]$PayloadUTF8ByteA [datetime]$Timestamp [boolean]$DupFlag [int]$QosLevel [boolean]$Retain PSMQTTMessage( [string]$Topic, [string]$Payload ) { $this.Topic = $Topic $this.Payload = $Payload $this.PayloadUTF8ByteA = [System.Text.Encoding]::UTF8.GetBytes($Payload) $this.Timestamp = (Get-Date) } PSMQTTMessage( [System.Management.Automation.PSEventArgs]$EventObject ) { $this.Topic = $EventObject.SourceEventArgs.Topic $this.Payload = [System.Text.Encoding]::ASCII.GetString($EventObject.SourceEventArgs.Message) $this.PayloadUTF8ByteA = $EventObject.SourceEventArgs.Message $this.DupFlag = $EventObject.SourceEventArgs.DupFlag $this.QosLevel = $EventObject.SourceEventArgs.QosLevel $this.Retain = $EventObject.SourceEventArgs.Retain $this.Timestamp = $EventObject.TimeGenerated } [string] ToString () { return ($this.Topic + ';' + $this.Payload) } } #EndRegion '.\Classes\PSMQTTMessage.class.ps1' 41 #Region '.\Private\Assert-FolderExist.ps1' -1 function Assert-FolderExist { <# .SYNOPSIS Verify and create folder .DESCRIPTION Verifies that a folder path exists, if not it will create it .PARAMETER Path Defines the path to be validated .EXAMPLE 'C:\Temp' | Assert-FolderExist This will verify that the path exists and if it does not the folder will be created #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [string] $Path ) process { $exists = Test-Path -Path $Path -PathType Container if (!$exists) { $null = New-Item -Path $Path -ItemType Directory } } } #EndRegion '.\Private\Assert-FolderExist.ps1' 31 #Region '.\Private\Invoke-GarbageCollect.ps1' -1 function Invoke-GarbageCollect { <# .SYNOPSIS Calls system.gc collect method. Purpose is mainly for readability. .DESCRIPTION Calls system.gc collect method. Purpose is mainly for readability. .EXAMPLE Invoke-GarbageCollect #> [system.gc]::Collect() } #EndRegion '.\Private\Invoke-GarbageCollect.ps1' 13 #Region '.\Public\Connect-MQTTBroker.ps1' -1 function Connect-MQTTBroker { <# .DESCRIPTION This function establishes a session with the MQTT broker and returns a session object that should then be passed along when using other cmdlets. .EXAMPLE $Session = Connect-MQTTBroker -Hostname mqttbroker.contoso.com -Port 1234 -Username mqttuser -Password (ConvertTo-SecureString -String 'P@ssw0rd1' -AsPlainText -Force) Establish a MQTT Broker session with authentication .EXAMPLE $Session = Connect-MQTTBroker -Hostname mqttbroker.contoso.com -Port 1234 Establish a MQTT Broker session without authentication .PARAMETER Hostname Defines the hostname of the MQTT Broker to connect to .PARAMETER Port Defines the port of the MQTT Broker. Defaults to 1883. .PARAMETER Username Defines the username to use when connecting to the MQTT broker .PARAMETER Password Defines the password (securestring) to use when connecting to the MQTT Broker .PARAMETER TLS Defines if the connection should be encrypted #> [cmdletBinding(DefaultParameterSetName = 'Anon')] param( [Parameter(Mandatory)] [string] $Hostname, [Parameter()] [int] $Port, [Parameter(Mandatory, ParameterSetName = 'Auth')] [string] $Username, [Parameter(Mandatory, ParameterSetName = 'Auth')] [securestring] $Password, [Parameter()] [switch] $TLS ) #TODO implement additional connection properties like certificate ssl options etc. Different default ports based on # Use default ports if none are specified if (-not $PSBoundParameters['Port']) { if ($TLS) { $Port = 1884 } else { $Port = 1883 } } $MqttClient = New-Object -TypeName uPLibrary.Networking.M2Mqtt.MqttClient -ArgumentList $Hostname, $Port, $TLS, $null, $null, 'None' switch ($PSCmdlet.ParameterSetName) { 'Anon' { $null = $MqttClient.Connect([guid]::NewGuid()) } 'Auth' { $null = $MqttClient.Connect([guid]::NewGuid(), $Username, (([pscredential]::New($Username, $Password)).GetNetworkCredential().Password)) } } return $MqttClient } #EndRegion '.\Public\Connect-MQTTBroker.ps1' 87 #Region '.\Public\Disconnect-MQTTBroker.ps1' -1 function Disconnect-MQTTBroker { <# .DESCRIPTION This function will disconnect a MQTTBroker session .EXAMPLE Disconnect-MQTTBroker -Session $Session .PARAMETER Session Defines the MQTTBroker session to use #> [cmdletBinding()] param( [Parameter(Mandatory)] [uPLibrary.Networking.M2Mqtt.MqttClient] $Session ) $Session.Disconnect() } #EndRegion '.\Public\Disconnect-MQTTBroker.ps1' 23 #Region '.\Public\Send-MQTTMessage.ps1' -1 function Send-MQTTMessage { <# .DESCRIPTION This function will publish a message to a MQTT topic. .EXAMPLE Send-MQTTMEssage -Session $Session -Topic 'foo' -Payload '{"attribute":"value"}' .PARAMETER Session Defines the MQTTBroker session to use .PARAMETER Topic Defines the topic to publish the message to .PARAMETER Payload Defines the message as a string .PARAMETER Quiet Defines that messages are sent without outputing any objects. #> [cmdletBinding()] param( [Parameter(Mandatory)] [uPLibrary.Networking.M2Mqtt.MqttClient] $Session, [Parameter(Mandatory)] [string] $Topic, [Parameter()] [string] $Payload, [Parameter()] [switch] $Quiet ) try { $Message = [PSMQTTMessage]::New($Topic, $Payload) # Publish message to MQTTBroker $null = $Session.Publish($Message.Topic, $Message.PayloadUTF8ByteA) # Return object unless quiet if (-not $Quiet) { return $Message } } catch { $_ } } #EndRegion '.\Public\Send-MQTTMessage.ps1' 60 #Region '.\Public\Watch-MQTTTopic.ps1' -1 function Watch-MQTTTopic { <# .DESCRIPTION This function will subscribe to message published to a MQTT topic. .EXAMPLE Watch-MQTTTopic -Session $Session -Topic "topic/#" .PARAMETER Session Defines the MQTTBroker session to use .PARAMETER Topic Defines the topic to publish the message to #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingWriteHost', '', Justification = 'Deliberate use of WH. Function still returns objects. This write host is only used to indicate that the function is listening for events. Its rather important that such a status message is NOT picked up by the pipeline.')] [cmdletBinding()] param( [Parameter(Mandatory)] [uPLibrary.Networking.M2Mqtt.MqttClient] $Session, [Parameter(Mandatory)] [string] $Topic ) PROCESS { try { $SourceIdentifier = [guid]::NewGuid() Register-ObjectEvent -InputObject $Session -EventName MqttMsgPublishReceived -SourceIdentifier $SourceIdentifier $null = $Session.Subscribe($Topic, 0) Write-Host 'Listening...' -ForegroundColor Cyan while ($Session.IsConnected -and (Get-EventSubscriber -SourceIdentifier $SourceIdentifier)) { try { Get-Event -SourceIdentifier $SourceIdentifier -ErrorAction Stop | ForEach-Object { [PSMQTTMessage]::New($PSItem) Remove-Event -EventIdentifier $PSItem.EventIdentifier } } catch [ArgumentException] { if ($_.Exception.message -eq "Event with source identifier '$SourceIdentifier' does not exist.") { Start-Sleep -Milliseconds 100 } } catch { throw $_ } } } catch { $_ } finally { $null = $Session.Unsubscribe($Topic) Unregister-Event -SourceIdentifier $SourceIdentifier } } } #EndRegion '.\Public\Watch-MQTTTopic.ps1' 74 #Region '.\suffix.ps1' -1 # The content of this file will be appended to the top of the psm1 module file. This is useful for custom procesedures after all module functions are loaded. #EndRegion '.\suffix.ps1' 2 |