/// <summary> /// Sends the command to the device specified /// </summary> /// <param name="command">The command to send</param> /// <param name="bulbMacAddress">The MAC address of the bulb that will receive the command (used for mesh networking)</param> /// <param name="panControllerMacAddress">The pan controller MAC address that will receive the command (used for mesh networking)</param> /// <param name="remoteIPAddress">The IP address that will physically receive the command first</param> /// <returns>Returns false if the command couldn't be sent for whatever reason</returns> private async Task <bool> SendCommandRaw(LifxCommand command, string bulbMacAddress, string panControllerMacAddress, string remoteIPAddress) { try { LifxDataPacket packet = new LifxDataPacket(command); packet.TargetMac = LifxHelper.StringToByteArray(bulbMacAddress); packet.PanControllerMac = LifxHelper.StringToByteArray(panControllerMacAddress); using (var stream = await new DatagramSocket().GetOutputStreamAsync(new HostName(remoteIPAddress), LifxHelper.LIFX_PORT.ToString())) { using (var writer = new DataWriter(stream)) { writer.WriteBytes(packet.PacketData); await writer.StoreAsync(); } } return(true); } catch (Exception) { return(false); } }
/// <summary> /// The listner clients message recieved event handler. /// This is where the message will be converted into a LifxMessage and will invoke the MessageRecieved event handler if anything is subscribed to it /// </summary> /// <param name="sender">The socket that recieved the packet</param> /// <param name="args">Where the packet information is contained</param> private void lifxCommunicatorClient_MessageReceived(DatagramSocket sender, DatagramSocketMessageReceivedEventArgs args) { if (IsDisposed) { return; } uint bufferArraySize = args.GetDataReader().UnconsumedBufferLength; Byte[] receiveBytes = new Byte[bufferArraySize]; args.GetDataReader().ReadBytes(receiveBytes); LifxDataPacket packet = new LifxDataPacket(receiveBytes); LifxMessage receivedMessage = LifxHelper.PacketToMessage(packet); if (receivedMessage != null) // Check to make sure the packet we recieved was sent from a LIFX bulb, others can be sending on the same port { // If the packet type is a pan gateway we need to handle this a bit differently if (receivedMessage.PacketType == MessagePacketType.PanGateway) { // This locks the variable and lets any senders will waiting for a pan gateway know that we have received the message and you can stop retrying lock (commandsAwaitingResponse) { // Ensure that there are senders awaiting a message if (commandsAwaitingResponse.ContainsKey(receivedMessage.PacketType)) { commandsAwaitingResponse[receivedMessage.PacketType] = receivedMessage; // Sets the reply (from bulb) message to this message messageResumer[receivedMessage.PacketType].Release(); // Stops the senders from retrying to ask for pan gateway messages } } // Sets up the pan handler class and assigns the bulb to it LifxPanController foundPanHandler = new LifxPanController() { MACAddress = LifxHelper.ByteArrayToString(receivedMessage.ReceivedData.PanControllerMac), IPAddress = args.RemoteAddress.DisplayName }; foundPanHandler.Bulbs.Add(new LifxBulb(foundPanHandler, args.RemoteAddress.DisplayName, LifxHelper.ByteArrayToString(receivedMessage.ReceivedData.PanControllerMac))); // Invoke the PanControllerFound event handler PanControllerFound.Invoke(this, foundPanHandler); return; } // If the incoming packet isn't a pan controller, just lock the variable // and lets any senders that may be waiting for a return message know that we have received the message and you can stop retrying lock (commandsAwaitingResponse) { // If there is someone waiting for a recieved message, i.e. the command is *meant* to receive something from the bulb // let it know we have found it (Release) and assign the message to the varaible // Otherwise we have received a LifxMessage we didn't ask for. Ensure that there is someone subscribed to the event handler and Invoke with the message if (commandsAwaitingResponse.ContainsKey(receivedMessage.PacketType)) { commandsAwaitingResponse[receivedMessage.PacketType] = receivedMessage; messageResumer[receivedMessage.PacketType].Release(); } else { if (MessageRecieved != null) { MessageRecieved.Invoke(this, receivedMessage); } } } } }
/// <summary> /// Converts a raw <see cref="LifxDataPacket">LifxDataPacket</see> to a <see cref="LifxMessage">LifxMessage</see> /// </summary> /// <param name="packet">Raw DataPacket to convert from</param> /// <returns>A <see cref="LifxMessage">LifxMessage</see> if implemented or recognised otherwise null</returns> public static LifxMessage PacketToMessage(LifxDataPacket packet) { switch (MessagePacketTypeToEnum(packet.PacketType)) { case MessagePacketType.Unknown: break; case MessagePacketType.PanGateway: return(new LifxPanGatewayStateMessage(packet)); case MessagePacketType.PowerState: return(new LifxPowerStateMessage(packet)); case MessagePacketType.WifiInfo: return(new LifxWiFiInfoMessage(packet)); case MessagePacketType.WifiFirmwareState: return(new LifxWiFiFirmwareMessage(packet)); case MessagePacketType.WifiState: break; case MessagePacketType.AccessPoint: break; case MessagePacketType.Label: return(new LifxLabelMessage(packet)); case MessagePacketType.Tags: return(new LifxTagsMessage(packet)); case MessagePacketType.TagLabels: return(new LifxTagLabelMessage(packet)); case MessagePacketType.LightStatus: return(new LifxLightStatusMessage(packet)); case MessagePacketType.TimeState: break; case MessagePacketType.ResetSwitchState: break; case MessagePacketType.DummyLoad: break; case MessagePacketType.MeshInfo: break; case MessagePacketType.MeshFirmwareState: break; case MessagePacketType.VersionState: break; case MessagePacketType.Info: break; case MessagePacketType.MCURailVoltage: break; default: return(null); } return(null); }