ソースを参照

refactoring EspClient to make it futer testable

faqmoroz 1 週間 前
コミット
9fac87ef09

+ 0 - 116
Minolta Remote/EspClient.cs

@@ -1,116 +0,0 @@
-using Org.Apache.Http.Conn;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Text.Json;
-using System.Text.Json.Nodes;
-using System.Threading.Tasks;
-
-namespace Minolta_Remote
-{
-    public class EspClient
-    {
-        private readonly HttpClient httpClient;
-        private readonly string baseUri = "http://192.168.1.200";
-
-        class DTO
-        {
-            public bool Result { get; set; }
-        }
-
-        public EspClient() {
-            var handler = new HttpClientHandler();
-
-
-            handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
-            {                
-                    return true;
-            };
-            
-            httpClient = new HttpClient(handler);
-        }
-
-        private DTO? DeserilizeString(string jsonString)
-        {
-            var jObj = JsonObject.Parse(jsonString);
-            if (jObj != null)
-            {
-                return jObj.Deserialize<DTO>();
-            }
-            return null;
-        }
-
-        public async Task<bool?> Focus()
-        {
-            try
-            {
-                var response = await httpClient.GetAsync($"{baseUri}/api/focus");
-                var res = await response.Content.ReadAsStringAsync();
-                var x = DeserilizeString(res);
-                return x?.Result;
-            }
-            catch
-            {
-                return false;
-            }
-        }
-
-        public async Task<bool?> TakePhoto(int? ms = null)
-        {
-            try
-            {
-                HttpResponseMessage response = null;
-                if (ms.HasValue)
-                    response = await httpClient.GetAsync($"{baseUri}/api/takePhoto?msec={ms.Value}");
-                else
-                {
-                    response = await httpClient.GetAsync($"{baseUri}/api/takePhoto");
-                }
-                var res = await response.Content.ReadAsStringAsync();
-                var x = DeserilizeString(res);
-                return x?.Result;
-            }
-            catch
-            {
-                return false;
-            }
-        }
-
-        public async Task<bool?> Reset()
-        {
-            try
-            {
-                var response = await httpClient.GetAsync($"{baseUri}/api/reset");
-                var res = await response.Content.ReadAsStringAsync();
-                var x = DeserilizeString(res);
-                return x?.Result;
-            }
-            catch
-            {
-                return false;
-            }
-        }
-
-        public async Task<bool?> Multiple(int count, int delay, int? ms = null)
-        {
-            try
-            {
-                HttpResponseMessage response = null;
-                if (ms.HasValue)
-                    response = await httpClient.GetAsync($"{baseUri}/api/multiple?count={count}&delay={delay}&msec={ms.Value}");
-                else
-                {
-                    response = await httpClient.GetAsync($"{baseUri}/api/multiple?count={count}&delay={delay}");
-                }
-                var res = await response.Content.ReadAsStringAsync();
-                var x = DeserilizeString(res);
-                return x?.Result;
-            }
-            catch
-            {
-                return false;
-            }
-        }
-    }
-}

+ 9 - 6
Minolta Remote/MainPage.xaml.cs

@@ -1,26 +1,29 @@
-namespace Minolta_Remote
+using Minolta_Remote.Services;
+
+namespace Minolta_Remote
 {
     public partial class MainPage : ContentPage
     {
-
-        private readonly EspClient espClient;
+        private readonly IEspClient espClient;
+        
         public MainPage()
         {
             InitializeComponent();
-            espClient = new EspClient();
+            var factory = new EspClientFactory();
+            espClient = factory.CreateEspClient();
         }
 
         private async void Focus_Button_Clicked(object sender, EventArgs e)
         {
             this.Prefocus.IsEnabled = false;
-            bool? result =await espClient.Focus();
+            var result = await espClient.FocusAsync();
             this.Prefocus.IsEnabled = true;
         }
 
         private async void TakePhoto_Button_Clicked(object sender, EventArgs e)
         {
             this.TakePhoto.IsEnabled = false;
-            bool? result = await espClient.TakePhoto();
+            var result = await espClient.TakePhotoAsync();
             this.TakePhoto.IsEnabled = true;
         }
     }

+ 13 - 10
Minolta Remote/ProTab.xaml.cs

@@ -1,13 +1,16 @@
+using Minolta_Remote.Services;
+
 namespace Minolta_Remote;
 
 public partial class ProTab : ContentPage
 {
-
-    private readonly EspClient espClient;
+    private readonly IEspClient espClient;
+    
     public ProTab()
-	{
-		InitializeComponent();
-        espClient = new EspClient();
+    {
+        InitializeComponent();
+        var factory = new EspClientFactory();
+        espClient = factory.CreateEspClient();
         ShootTime.Text = "1000";
         SelfiTimer.Text = "0";
         Prefocus.IsToggled = true;
@@ -24,18 +27,18 @@ public partial class ProTab : ContentPage
             if (selfiTime>0)
             {
                 System.Threading.Thread.Sleep(selfiTime);
-                await espClient.Focus();
+                await espClient.FocusAsync();
                 System.Threading.Thread.Sleep(1000);
-                await espClient.TakePhoto(shootTime);
+                await espClient.TakePhotoAsync(shootTime);
             }
             else
             {
                 if (isPrefocusEnabled)
                 {
-                    await espClient.Focus();
+                    await espClient.FocusAsync();
                     System.Threading.Thread.Sleep(1000);
                 }
-                await espClient.TakePhoto(shootTime);
+                await espClient.TakePhotoAsync(shootTime);
             }
         }
         catch { }
@@ -46,7 +49,7 @@ public partial class ProTab : ContentPage
     private async void ResetButon_Clicked(object sender, EventArgs e)
     {
         ResetButon.IsEnabled = false;
-        await espClient.Reset();
+        await espClient.ResetAsync();
         ResetButon.IsEnabled = true;
     }
 }

+ 68 - 0
Minolta Remote/Services/EspClient.cs

@@ -0,0 +1,68 @@
+namespace Minolta_Remote.Services
+{
+    public class EspClient : IEspClient
+    {
+        private readonly EspClientRepository repository;
+
+        public EspClient(EspClientRepository repository)
+        {
+            this.repository = repository;
+        }
+
+        public async Task<EspClientResponse> FocusAsync()
+        {
+            try
+            {
+                var result = await repository.GetAsync("/api/focus");
+                return result?.Result == true ? EspClientResponse.Success() : EspClientResponse.Failure("Focus request failed");
+            }
+            catch (Exception ex)
+            {
+                return EspClientResponse.Failure(ex.Message);
+            }
+        }
+
+        public async Task<EspClientResponse> TakePhotoAsync(int? ms = null)
+        {
+            try
+            {
+                var endpoint = ms.HasValue ? $"/api/takePhoto?msec={ms.Value}" : "/api/takePhoto";
+                var result = await repository.GetAsync(endpoint);
+                return result?.Result == true ? EspClientResponse.Success() : EspClientResponse.Failure("TakePhoto request failed");
+            }
+            catch (Exception ex)
+            {
+                return EspClientResponse.Failure(ex.Message);
+            }
+        }
+
+        public async Task<EspClientResponse> ResetAsync()
+        {
+            try
+            {
+                var result = await repository.GetAsync("/api/reset");
+                return result?.Result == true ? EspClientResponse.Success() : EspClientResponse.Failure("Reset request failed");
+            }
+            catch (Exception ex)
+            {
+                return EspClientResponse.Failure(ex.Message);
+            }
+        }
+
+        public async Task<EspClientResponse> MultipleAsync(int count, int delay, int? ms = null)
+        {
+            try
+            {
+                var endpoint = ms.HasValue
+                    ? $"/api/multiple?count={count}&delay={delay}&msec={ms.Value}"
+                    : $"/api/multiple?count={count}&delay={delay}";
+                var result = await repository.GetAsync(endpoint);
+                return result?.Result == true ? EspClientResponse.Success() : EspClientResponse.Failure("Multiple request failed");
+            }
+            catch (Exception ex)
+            {
+                return EspClientResponse.Failure(ex.Message);
+            }
+        }
+    }
+}

+ 12 - 0
Minolta Remote/Services/EspClientConfig.cs

@@ -0,0 +1,12 @@
+namespace Minolta_Remote.Services
+{
+    public class EspClientConfig
+    {
+        public string BaseUri { get; set; }
+
+        public EspClientConfig(string baseUri)
+        {
+            BaseUri = baseUri;
+        }
+    }
+}

+ 7 - 0
Minolta Remote/Services/EspClientDto.cs

@@ -0,0 +1,7 @@
+namespace Minolta_Remote.Services
+{
+    public class EspClientDto
+    {
+        public bool Result { get; set; }
+    }
+}

+ 23 - 0
Minolta Remote/Services/EspClientFactory.cs

@@ -0,0 +1,23 @@
+namespace Minolta_Remote.Services
+{
+    public class EspClientFactory : IEspClientFactory
+    {
+        private readonly string baseUri = "http://192.168.1.200";
+
+        public EspClientFactory()
+        {
+        }
+
+        public IEspClient CreateEspClient()
+        {
+            var handler = new HttpClientHandler();
+            handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true;
+
+            var httpClient = new HttpClient(handler);
+            var config = new EspClientConfig(baseUri);
+            var repository = new EspClientRepository(httpClient, config);
+
+            return new EspClient(repository);
+        }
+    }
+}

+ 37 - 0
Minolta Remote/Services/EspClientRepository.cs

@@ -0,0 +1,37 @@
+using System.Text.Json;
+using System.Text.Json.Nodes;
+
+namespace Minolta_Remote.Services
+{
+    public class EspClientRepository
+    {
+        private readonly HttpClient httpClient;
+        private readonly EspClientConfig config;
+
+        public EspClientRepository(HttpClient httpClient, EspClientConfig config)
+        {
+            this.httpClient = httpClient;
+            this.config = config;
+        }
+
+        public async Task<EspClientDto?> GetAsync(string endpoint)
+        {
+            try
+            {
+                var response = await httpClient.GetAsync($"{config.BaseUri}{endpoint}");
+                var jsonString = await response.Content.ReadAsStringAsync();
+                return DeserializeResponse(jsonString);
+            }
+            catch (Exception ex)
+            {
+                throw new InvalidOperationException($"Failed to call endpoint: {endpoint}", ex);
+            }
+        }
+
+        private EspClientDto? DeserializeResponse(string jsonString)
+        {
+            var jObj = JsonObject.Parse(jsonString);
+            return jObj?.Deserialize<EspClientDto>();
+        }
+    }
+}

+ 11 - 0
Minolta Remote/Services/EspClientResponse.cs

@@ -0,0 +1,11 @@
+namespace Minolta_Remote.Services
+{
+    public class EspClientResponse
+    {
+        public bool IsSuccess { get; set; }
+        public string? ErrorMessage { get; set; }
+
+        public static EspClientResponse Success() => new() { IsSuccess = true };
+        public static EspClientResponse Failure(string errorMessage) => new() { IsSuccess = false, ErrorMessage = errorMessage };
+    }
+}

+ 10 - 0
Minolta Remote/Services/IEspClient.cs

@@ -0,0 +1,10 @@
+namespace Minolta_Remote.Services
+{
+    public interface IEspClient
+    {
+        Task<EspClientResponse> FocusAsync();
+        Task<EspClientResponse> TakePhotoAsync(int? ms = null);
+        Task<EspClientResponse> ResetAsync();
+        Task<EspClientResponse> MultipleAsync(int count, int delay, int? ms = null);
+    }
+}

+ 7 - 0
Minolta Remote/Services/IEspClientFactory.cs

@@ -0,0 +1,7 @@
+namespace Minolta_Remote.Services
+{
+    public interface IEspClientFactory
+    {
+        IEspClient CreateEspClient();
+    }
+}