private void manuallyEnterIPAddressToolStripMenuItem_Click_1(object sender, EventArgs e) { string ip = Microsoft.VisualBasic.Interaction.InputBox("Enter the IP address of the Roku on your local network (as shown in Settings > Network > About):", "Add Roku"); if (!string.IsNullOrEmpty(ip) && IPAddress.TryParse(ip, out IPAddress _)) { var device = new HttpRokuDevice($"roku.custom.{ip}", new Uri($"http://{ip}:8060/")); AddRoku(device); } }
private async Task HttpPostTest(Func <IRokuDevice, Task> inputFunc, string relativeUrl) { var handler = new HttpMessageHandlerMock(MockBehavior.Strict); Expression <Func <HttpRequestMessage, bool> > volumeUpRequest = message => message.Method == HttpMethod.Post && message.RequestUri == new Uri(new Uri("http://localhost/"), relativeUrl); handler.SetupSendAsync(volumeUpRequest, new HttpResponseMessage(HttpStatusCode.OK)); var device = new HttpRokuDevice("deviceId", new Uri("http://localhost"), handler.Object); await inputFunc(device); handler.VerifySendAsync(Times.Exactly(1)); }
private async Task HttpGetTest <TResult>(Func <IRokuDevice, Task <TResult> > inputFunc, string relativeUrl, string xmlResult, Action <TResult> assertResult) { var handler = new HttpMessageHandlerMock(MockBehavior.Strict); Expression <Func <HttpRequestMessage, bool> > volumeUpRequest = message => message.Method == HttpMethod.Get && message.RequestUri == new Uri(new Uri("http://localhost/"), relativeUrl); handler.SetupSendAsync(volumeUpRequest, new HttpResponseMessage(HttpStatusCode.OK) { Content = new StringContent(xmlResult) }); var device = new HttpRokuDevice("deviceId", new Uri("http://localhost"), handler.Object); var result = await inputFunc(device); handler.VerifySendAsync(Times.Exactly(1)); assertResult(result); }
public async Task InputKeyPressMultipleKeys() { var handler = new HttpMessageHandlerMock(MockBehavior.Strict); Expression <Func <HttpRequestMessage, bool> > volumeUpRequest = message => message.Method == HttpMethod.Post && message.RequestUri == new Uri("http://localhost/keypress/VolumeUp"); handler.SetupSendAsync(volumeUpRequest, new HttpResponseMessage(HttpStatusCode.OK)); Expression <Func <HttpRequestMessage, bool> > zRequest = message => message.Method == HttpMethod.Post && message.RequestUri == new Uri("http://localhost/keypress/Lit_z"); handler.SetupSendAsync(zRequest, new HttpResponseMessage(HttpStatusCode.OK)); var client = new HttpRokuDevice("deviceId", new Uri("http://localhost"), handler.Object); await client.Input.KeyPressAsync(new PressedKey[] { SpecialKeys.VolumeUp, 'z' }); handler.VerifySendAsync(Times.Exactly(2)); }
public async Task DiscoverDevicesAsync(Func <HttpDiscoveredDeviceContext, Task <bool> > onDeviceDiscovered, CancellationToken cancellationToken = default(CancellationToken)) { string discoverRequest = "M-SEARCH * HTTP/1.1\n" + "Host: 239.255.255.250:1900\n" + "Man: \"ssdp:discover\"\n" + "ST: roku:ecp\n" + ""; var bytes = Encoding.UTF8.GetBytes(discoverRequest); using (var udpClient = new UdpClient(endPoint)) { await udpClient.SendAsync(bytes, bytes.Length, "239.255.255.250", 1900).ConfigureAwait(false); while (!cancellationToken.IsCancellationRequested) { var receiveTask = Task.Run( async() => { try { return(await udpClient.ReceiveAsync().ConfigureAwait(false)); } catch (ObjectDisposedException) { // NOTE: We assume that a disposal exception is an attempt to cancel an // outstanding ReceiveAsync() by closing the socket (disposing the // UdpClient). throw new OperationCanceledException(); } }); var cancellationTask = Task.Delay(TimeSpan.FromMilliseconds(-1), cancellationToken); var completedTask = await Task.WhenAny(receiveTask, cancellationTask).ConfigureAwait(false); if (completedTask == cancellationTask) { // NOTE: We allow the OperationCanceledException to bubble up, causing disposal of the // UdpClient which would force any pending ReceiveAsync() to throw an // ObjectDisposedException. await cancellationTask.ConfigureAwait(false); return; } var rawResponse = await receiveTask.ConfigureAwait(false); var response = await ParseResponseAsync(rawResponse.Buffer).ConfigureAwait(false); if (response.StatusCode == 200 && response.Headers.TryGetValue("ST", out string stHeader) && stHeader == "roku:ecp" && response.Headers.TryGetValue("LOCATION", out string location) && Uri.TryCreate(location, UriKind.Absolute, out Uri locationUri) && response.Headers.TryGetValue("USN", out string usn)) { var serialNumber = usn.StartsWith("uuid:roku:ecp:") ? usn.Substring("uuid:roku:ecp:".Length) : usn; var device = new HttpRokuDevice(serialNumber, locationUri, this.handler); bool cancelDiscovery = false; var context = new HttpDiscoveredDeviceContext(device, serialNumber); if (onDeviceDiscovered != null) { cancelDiscovery = await onDeviceDiscovered(context).ConfigureAwait(false); } var args = new HttpDeviceDiscoveredEventArgs(context) { CancelDiscovery = cancelDiscovery }; this.DeviceDiscovered?.Invoke(this, args); cancelDiscovery = args.CancelDiscovery; var baseArgs = new DeviceDiscoveredEventArgs(context) { CancelDiscovery = cancelDiscovery }; this.baseDeviceDiscovered?.Invoke(this, baseArgs); cancelDiscovery = baseArgs.CancelDiscovery; if (cancelDiscovery) { return; } } } } }