using EvtSource; using MyCore.Models.Arlo; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using ServiceStack; using System; using System.Collections.Generic; using System.Linq; using System.Net.Http; using System.Net.Http.Headers; using System.Text; using System.Threading.Tasks; namespace MyCore.Services { public class ArloService { // API HTTP private const string _arloUrl = "https://arlo.netgear.com/hmsweb"; private string _loginUrl = $"{_arloUrl}/login/v2"; private string _userProfileUrl = $"{_arloUrl}/users/profile"; private string _userSessionUrl = $"{_arloUrl}/users/session"; private string _userFriendsUrl = $"{_arloUrl}/users/friends"; private string _userLocationUrl = $"{_arloUrl}/users/locations"; private string _userServiceLevelUrl = $"{_arloUrl}/users/serviceLevel/v2"; private string _userDevicesUrl = $"{_arloUrl}/users/devices"; private string _userLibraryUrl = $"{_arloUrl}/users/library"; private string _userLibraryMetadataUrl = $"{_arloUrl}/users/library/metadata/v2"; private string _userPaymentOffersUrl = $"{_arloUrl}/users/payment/offers"; private string _userDevicesNotifyUrl = $"{_arloUrl}/users/devices/notify"; private string _clientSubscribeUrl = $"{_arloUrl}/client/subscribe"; private static string _email = "fransolet.thomas@gmail.com"; private static string _password = "Coconuts09"; private static LoginResult resultToken; private List allArloDevices; private List allUserMedias; public class Credential { public string email; public string password; } public class DateInterval { public string dateFrom; public string dateTo; } public class LoginResult { public string userId; public string email; public string token; public string paymentId; public int authenticated; public string accountStatus; public string serialNumber; public string countryCode; public bool tocUpdate; public bool policyUpdate; public bool validEmail; public bool arlo; public long dateCreated; } // Motion Detection Test - {"from":"XXX-XXXXXXX_web","to":"XXXXXXXXXXXXX","action":"set","resource":"cameras/XXXXXXXXXXXXX","transId":"web!XXXXXXXX.XXXXXXXXXXXXXXXXXXXX","publishResponse":true,"properties":{"motionSetupModeEnabled":true,"motionSetupModeSensitivity":80}} public class MotionDetection { public string from; public string to; public string action; public string resource; public string transId; public bool publishResponse = true; public PropertiesRequestMotionSubscription properties; } public class PropertiesRequest { public bool motionSetupModeEnabled; public int motionSetupModeSensitivity; } public class PropertiesRequestMotionSubscription { public string[] devices; } public enum RequestType { Get, Post } public enum Request { LOGIN, DEVICES, LIBRARY } public ArloService() { try { // LOGIN var loginTask = Task.Run(() => RequestURI(new Uri(_loginUrl), RequestType.Post, Request.LOGIN)); loginTask.Wait(); if (loginTask.Result != "") { //RESULT TOKEN var data = ((JObject)JsonConvert.DeserializeObject(loginTask.Result))["data"]; resultToken = JsonConvert.DeserializeObject(data.ToString()); // GET DEVICE LIST var deviceTask = Task.Run(() => RequestURI(new Uri(_userDevicesUrl), RequestType.Get, Request.DEVICES)); deviceTask.Wait(); if (deviceTask.Result != "") { data = ((JObject)JsonConvert.DeserializeObject(deviceTask.Result))["data"]; // RETRIEVE ALL ARLO DEVICES allArloDevices = JsonConvert.DeserializeObject>(data.ToString()); } // GET USER LIBRARY var libraryTask = Task.Run(() => RequestURI(new Uri(_userLibraryUrl), RequestType.Post, Request.LIBRARY)); libraryTask.Wait(); if (libraryTask.Result != "") { data = ((JObject)JsonConvert.DeserializeObject(libraryTask.Result))["data"]; // RETRIEVE ALL DATA IN USER LIBRARY allUserMedias = JsonConvert.DeserializeObject>(data.ToString()); } //SSE CONNEXION ConnexionToSSE(); } } catch (Exception e) { resultToken = null; } } static async Task RequestURI(Uri u, RequestType requesType, Request request) { try { var response = string.Empty; var body = ""; HttpContent c = null; using (var client = new HttpClient()) { switch (request) { case Request.LOGIN: body = JsonConvert.SerializeObject(new Credential { email = _email, password = _password }).ToString(); c = new StringContent(body, Encoding.UTF8, "application/json"); break; case Request.LIBRARY: DateTime last7Days = new DateTime(DateTime.Now.Year, 1, 1).AddDays(DateTime.Now.DayOfYear - 7 - 1); body = JsonConvert.SerializeObject(new DateInterval { dateFrom = last7Days.ToString("yyyyMMdd"), dateTo = DateTime.Now.ToString("yyyyMMdd")}).ToString(); c = new StringContent(body, Encoding.UTF8, "application/json"); break; case Request.DEVICES: default: break; } client.DefaultRequestHeaders.Add("User-Agent", "okhttp/3.6.0"); if (resultToken != null) client.DefaultRequestHeaders.Add("Authorization", resultToken.token); if (requesType == RequestType.Get) { HttpResponseMessage result = await client.GetAsync(u); response = await result.Content.ReadAsStringAsync(); } if (requesType == RequestType.Post) { HttpResponseMessage result = await client.PostAsync(u, c); if (result.IsSuccessStatusCode) response = await result.Content.ReadAsStringAsync(); } } return response; } catch (Exception e) { Console.WriteLine("ArloService - An error occured in RequestURI"); return null; } } public void ConnexionToSSE() { /*var sseClient = new ServerEventsClient($"{_clientSubscribeUrl}?token={resultToken.token}", new string[] { "EventStream" }) { OnConnect = e => { Console.WriteLine($"{e.IsAuthenticated}, {e.UserId}, {e.DisplayName}"); } }.Start();*/ var evt = new EventSourceReader(new Uri($"{_clientSubscribeUrl}?token={resultToken.token}")).Start(); evt.MessageReceived += async (object sender, EventSourceMessageEventArgs e) => { using (var client = new HttpClient()) { ArloDevice baseStation = allArloDevices.Where(d => d.deviceType == "basestation").FirstOrDefault(); ArloDevice camera = allArloDevices.Where(d => d.deviceType == "camera").FirstOrDefault(); Console.WriteLine($"{e.Event} : {e.Message}"); // ask for motion event test //Motion Detection Test - { "from":"XXX-XXXXXXX_web","to":"XXXXXXXXXXXXX","action":"set","resource":"cameras/XXXXXXXXXXXXX","transId":"web!XXXXXXXX.XXXXXXXXXXXXXXXXXXXX","publishResponse":true,"properties":{ "motionSetupModeEnabled":true,"motionSetupModeSensitivity":80} } /*MotionDetection motionDetection = new MotionDetection(); motionDetection.from = $"{baseStation.userId}_web"; motionDetection.to = $"{baseStation.deviceId}"; motionDetection.action = "set"; motionDetection.resource = $"cameras/{camera.deviceId}"; motionDetection.transId = $"web!XXXXXXXX.XXXXXXXXXXXXXXXXXXXX"; motionDetection.publishResponse = true; PropertiesRequest propertiesRequest = new PropertiesRequest(); propertiesRequest.motionSetupModeEnabled = true; propertiesRequest.motionSetupModeSensitivity = 80; motionDetection.properties = propertiesRequest; var body = JsonConvert.SerializeObject(motionDetection).ToString();*/ // Try to subscribe to motion for camera /*MotionDetection motionDetection = new MotionDetection(); motionDetection.from = $"{baseStation.userId}_web"; motionDetection.to = $"{baseStation.deviceId}"; motionDetection.action = "set"; motionDetection.resource = $"subscriptions/{baseStation.userId}_web"; motionDetection.transId = $"web!XXXXXXXX.XXXXXXXXXXXXXXXXXXXX"; motionDetection.publishResponse = false; PropertiesRequestMotionSubscription propertiesRequestMotionSubscription = new PropertiesRequestMotionSubscription(); propertiesRequestMotionSubscription.devices = new string[] { camera.deviceId }; motionDetection.properties = propertiesRequestMotionSubscription; var body = JsonConvert.SerializeObject(motionDetection).ToString(); HttpContent c = new StringContent(body, Encoding.UTF8, "application/json"); client.DefaultRequestHeaders.Add("xcloudId", baseStation.xCloudId); client.DefaultRequestHeaders.Add("Authorization", resultToken.token); HttpResponseMessage result = await client.PostAsync($"{ _userDevicesNotifyUrl}/{baseStation.deviceId}", c); if (result.IsSuccessStatusCode) { var response = await result.Content.ReadAsStringAsync(); }*/ } }; evt.Disconnected += async (object sender, DisconnectEventArgs e) => { Console.WriteLine($"Retry: {e.ReconnectDelay} - Error: {e.Exception}"); await Task.Delay(e.ReconnectDelay); evt.Start(); // Reconnect to the same URL }; } } }