Functions/Connect-XiaomiHome.psm1
#region Namespaces/Modules using namespace System.Net; using namespace System.Net.Sockets; using module ..\Classes\XiaomiConnection.psm1; #endregion <# .SYNOPSIS Initializes and returns a connection with Xiaomi Smart Home network .DESCRIPTION The function creates a local UDP server, which is going to be used to interact with the Xiaomi Gateway device, as well as all the sensors. The local server joins the same multicast group as the gateway device, as the initial gateway discovery is being done via multicast. .PARAMETER MulticastGroup The multicast group, to which the newly created UDP server should join. If not specified, 224.0.0.50 is used, as per Xiaomi documentation .PARAMETER MulticastPeerPort The number of multicast peer port, required for sending the initial message to the gateways on the network. If not specified, 4321 is used, as per Xiaomi documentation .PARAMETER LocalPort The number of the UDP port, which is going to be used to listen on the local computer. If not specified, 9882 is used, as per Xiaomi documentation .OUTPUTS [XiaomiConnection]. An object, containing information about the initialized connection .EXAMPLE C:\PS> Connect-XiaomiHome Socket : System.Net.Sockets.UdpClient IsAlive : True LocalPort : 9882 MulticastGroup : 224.0.0.50 MulticastPeerPort : 4321 #> Function Connect-XiaomiHome { [CmdletBinding()] [OutputType([XiaomiConnection])] #region Parameters PARAM( # Multicast group: [Parameter( Position = 0, Mandatory = $FALSE )] [String]$MulticastGroup = '224.0.0.50', # Multicast peer port: [Parameter( Position = 1, Mandatory = $FALSE )] [ValidateRange(0, 65534)] [Int]$MulticastPeerPort = 4321, # Local port: [Parameter( Position = 2, Mandatory = $FALSE )] [ValidateRange(0, 65534)] [Int]$LocalPort = 9882 ) #endregion PROCESS { # Make sure the local port is not in use: If (-NOT ($NULL -EQ ($process = [XiaomiConnection]::CheckIfPortIsInUse($LocalPort)))) { Write-Error ` -Category ConnectionError ` -Message ("Cannot establish connection, because UDP port "` + "$($LocalPort) is already in use by '$($process.ProcessName)' ($($process.ID))") ` -RecommendedAction "Try closing '$($process.ProcessName)' and reruning the cmdlet"; Return; } # Try to parse the Multicast Group as a real IP address: Try { $MulticastGroupAddress = [IpAddress]::Parse($MulticastGroup); } Catch { Write-Error ` -Category InvalidType ` -Message "Cannot parse multicast group '$($MulticastGroup)' as an IP address" ` -RecommendedAction "Make sure the provided mutlicast group IP is correct"; Return; } # Try creating UDP server and joining it to the multicast group: Try { $socket = New-Object -TypeName UdpClient -ArgumentList $LocalPort; $socket.JoinMulticastGroup($MulticastGroupAddress); # Set timeouts to avoid it freezing for too long: $socket.Client.SendTimeout = 5000; $socket.Client.ReceiveTimeout = 5000; } Catch { Write-Error ` -Category ProtocolError ` -Message "Cannot create a local UDP server under $($LocalPort) port" ` -RecommendedAction ("Make sure the port is not in use, the multicast group is correct and you "` + "have sufficient permissions to perform the operation"); Return; } # Return the connection object: Return [XiaomiConnection]::New($socket, $LocalPort, $MulticastGroupAddress, $MulticastPeerPort); } } |