/// <summary> /// Sends data asynchronously to a connected OpenWiz.WizSocket. /// </summary> /// <param name="s">The data to send.</param> /// <param name="handle">The handle to the remote light.</param> /// <param name="callback">The System.AsyncCallback delegate to fall after the send completes.</param> /// <param name="state">An object that will be passed into the callback.</param> /// <exception cref="System.ArgumentNullException"> /// s is null. /// </exception> /// <exception cref="System.Net.Sockets.SocketException"> /// An error occurred when attempting to access the underlying socket. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The underlying socket has been closed. /// </exception> /// <returns>An System.IAsyncResult that references the asynchronous send.</returns> /// public IAsyncResult BeginSend(WizState s, WizHandle handle, AsyncCallback callback, object state) { byte[] buffer = s.ToUTF8(); return(socket.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, new IPEndPoint(handle.Ip, PORT_DISCOVER), callback, state)); }
/// <summary> /// Constructs the service, targeting the a specific home of lights. /// </summary> /// <param name="homeId">The Home ID to which the user's lights belong</param> /// <param name="hostIp">The IPv4 of the host machine, in standard dot notation</param> /// <param name="hostMac">The MAC of the host machine's interface card, 6 bytes wide</param> /// public WizDiscoveryService(int homeId, string hostIp, byte[] hostMac) { WizState registrationData = WizState.MakeRegistration(homeId, hostIp, hostMac); Debug.WriteLine($"[INFO] WizDiscoveryService@{hostIp}: Made registration info: {registrationData}"); pingData = registrationData.ToUTF8(); this.hostIp = hostIp; KeepAlive = false; }
/// <summary> /// Ends a pending asynchronous recieve. /// </summary> /// <param name="asyncResult">An System.IAsyncResult that stores state information /// for this asynchronous operation.</param> /// <exception cref="System.ArgumentException"> /// asyncResult was not returned by a call to OpenWiz.WizSocket.BeginRecieve(System.AsyncCallback,System.Object) /// </exception> /// <exception cref="System.InvalidOperationException"> /// OpenWiz.WizSocket.EndReceive(System.IAsyncResult) was previously called /// for the asynchronous receive. /// </exception> /// <exception cref="System.ArgumentNullException"> /// asyncResult or handle is null. /// </exception> /// <exception cref="System.Net.Sockets.SocketException"> /// An error occurred when attempting to access the underlying socket. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The underlying socket has been closed. /// </exception> /// <returns>If successful, the OpenWiz.WizState; /// otherwise, an invalid System.Net.Sockets.Socket error.</returns> /// public WizState EndReceiveFrom(WizHandle handle, IAsyncResult result) { EndPoint ep = new IPEndPoint(handle.Ip, 0); int rLen = socket.EndReceiveFrom(result, ref ep); byte[] buffer = bufferMap[handle.Ip.ToString()]; bufferMap.Remove(handle.Ip.ToString()); return(WizState.Parse(new ArraySegment <byte>(buffer, 0, rLen))); }
/// <summary> /// Receives data from a bound OpenWiz.WizSocket. /// </summary> /// <exception cref="System.ArgumentNullException"> /// handle is null. /// </exception> /// <exception cref="System.Net.Sockets.SocketException"> /// An error occurred when attempting to access the underlying socket. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The underlying socket has been disposed. /// </exception> /// <exception cref="System.Security.SecurityException"> /// A caller in the call stack does not have the required permissions. /// </exception> /// <returns>The remote state.</returns> /// public WizState ReceiveFrom(WizHandle handle) { if (handle == null) { throw new ArgumentNullException("handle cannot be null"); } byte[] buffer = new byte[BUFFER_SIZE]; EndPoint ep = new IPEndPoint(handle.Ip, 0); int rLen = socket.ReceiveFrom(buffer, ref ep); return(WizState.Parse(new ArraySegment <byte>(buffer, 0, rLen))); }
/// <summary> /// Sends data to a connected OpenWiz.WizSocket. /// </summary> /// <param name="s">A OpenWiz.WizState containing the data to be sent.</param> /// <param name="handle">The handle to the remote light.</param> /// <exception cref="System.ArgumentNullException"> /// s or handle are null. /// </exception> /// <exception cref="System.Net.Sockets.SocketException"> /// An error occurred when attempting to access the underlying socket. /// </exception> /// <exception cref="System.ObjectDisposedException"> /// The underlying socket has been disposed. /// </exception> /// <returns>the number of bytes sent</returns> /// public int SendTo(WizState s, WizHandle handle) { if (s == null) { throw new ArgumentNullException("s cannot be null"); } if (handle == null) { throw new ArgumentNullException("handle cannot be null"); } byte[] bytes = s.ToUTF8(); return(socket.SendTo(bytes, new IPEndPoint(handle.Ip, PORT_DISCOVER))); }
/// Responsible for handling responses from Wiz lights private void ReceiveCallback(IAsyncResult ar) { if (!KeepAlive) { return; } IPEndPoint ep = new IPEndPoint(IPAddress.Any, PORT_DISCOVERY); byte[] data = discoveryClient.EndReceive(ar, ref ep); string jsonString = Encoding.UTF8.GetString(data); WizState wState = WizState.Parse(data); Action <WizHandle> discoveryAction = (Action <WizHandle>)ar.AsyncState; if (wState == null) { Debug.WriteLine($"[WARNING] WizDiscoveryService@{hostIp}: Got bad json message:"); Debug.WriteLine($"\t{jsonString}"); } else if (wState.Error != null) { Debug.Write($"[WARNING] WizDiscoveryService@{hostIp}: Encountered "); if (wState.Error.Code == null) { Debug.Write("unknwon error"); } else { Debug.Write($"error {wState.Error.Code}"); } if (wState.Error.Message != null) { Debug.Write($" -- {wState.Error.Message}"); } Debug.WriteLine($" from {ep.Address}"); Debug.WriteLine($"\t{jsonString}"); } else if (wState.Result != null) { Debug.WriteLine($"[INFO] WizDiscoveryService@{hostIp}: Got response:"); Debug.WriteLine($"\t{jsonString}"); WizHandle handle = new WizHandle(wState.Result.Mac, ep.Address); discoveryAction.Invoke(handle); } discoveryClient.BeginReceive(new AsyncCallback(ReceiveCallback), discoveryAction); }
/// <summary> /// Parses an object from an ArraySegment. /// </summary> /// <param name="bytes">A byte array holding UTF8 encoded json</param> /// <returns>A state object, or null if one cannot be constructed.</returns> /// public static WizState Parse(ArraySegment <byte> bytes) { if (bytes == null || bytes.Count < 1) { return(null); } WizState state = null; try { state = JsonSerializer.Deserialize <WizState>(bytes, new JsonSerializerOptions { IgnoreNullValues = true, PropertyNameCaseInsensitive = true }); } catch (JsonException e) { Console.WriteLine($"[INFO] WizLightState::Parse encountered an exception -- {e.Message}"); Console.WriteLine(e.StackTrace); } return(state); }