Ejemplo n.º 1
0
        //
        // Send a command over UDP
        //
        public static void SendUDP(object sender, DoWorkEventArgs ea)
        {
            const int MAX_RECVBUFFER_SIZE = 2048;

            // Create a new socket instance
            // Since this socket is only used within the WiFi network, the preference is on the NonCellular side,
            // to not send the UDP broadcast into the Internet, it wouldn't be delivered...
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
            socket.SetNetworkPreference(NetworkSelectionCharacteristics.NonCellular);
            SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();

            // Let's assume that the local network broadcast address can be created by changing the last digit to 255
            // - Like 192.168.0.xx -> 192.168.0.255
            // WP8 does support sending to IPAddress.Broadcast, i.e. "255.255.255.255", but there's something
            // wrong with the socket handling:
            // - Cannot use 'SendToAsync', but have to use 'ConnectAsync' instead
            // - Cannot receive any data using the same socket (code seems OK, but nothing is received)
            byte[] localBroadcastAddressBytes = FindMyIPAddress().GetAddressBytes();
            localBroadcastAddressBytes[3] = 255;
            IPAddress localBroadcast = new IPAddress(localBroadcastAddressBytes);

            socketEventArg.RemoteEndPoint = new IPEndPoint(localBroadcast, UDPPort);
            socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
            {
                switch (e.LastOperation)
                {
                    case SocketAsyncOperation.SendTo: // The broadcast was sent successfully, now start listening on the same socket
                        Socket sock = e.UserToken as Socket;
                        socketEventArg.SetBuffer(new Byte[MAX_RECVBUFFER_SIZE], 0, MAX_RECVBUFFER_SIZE);
                        sock.ReceiveFromAsync(socketEventArg);
                        break;

                    case SocketAsyncOperation.ReceiveFrom: // Received a response to the broadcast
                        if (e.SocketError == System.Net.Sockets.SocketError.Success)
                        {
                            // Retrieve the data from the buffer
                            var response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
                            response = response.Trim('\0');

                            System.Diagnostics.Debug.WriteLine("Received JSON data: " + response);

                            // Is this is an 'identify' or 'command' response?
                            HeatPumpIdentifyResponse identifyResponse = (HeatPumpIdentifyResponse)JsonFunctions.DeserializeFromStringToJson(response, typeof(HeatPumpIdentifyResponse));
                            System.Diagnostics.Debug.WriteLine("Response to command: " + identifyResponse.command + ": " + response);

                            // Run the notification handler (if found)
                            if (App.ViewModel.notificationHandlers.ContainsKey(identifyResponse.command))
                            {
                                System.Diagnostics.Debug.WriteLine("Found handler for command " + identifyResponse.command);
                                App.ViewModel.notificationHandlers[identifyResponse.command](response);
                            }
                        }
                        break;
                }
            });

            // Add the data to be sent into the send buffer
            byte[] payload = Encoding.UTF8.GetBytes((string)ea.Argument);
            socketEventArg.SetBuffer(payload, 0, payload.Length);

            // Add the socket as the UserToken for use within the event handler
            socketEventArg.UserToken = socket;

            // Send the UDP broadcast
            socket.SendToAsync(socketEventArg);
        }