diff --git a/kr.devany.googleapi.sdPlugin/manifest.json b/kr.devany.googleapi.sdPlugin/manifest.json
index 2549f10..4fb7ce6 100644
--- a/kr.devany.googleapi.sdPlugin/manifest.json
+++ b/kr.devany.googleapi.sdPlugin/manifest.json
@@ -38,6 +38,25 @@
"UUID": "kr.devany.googleapi.adsensemanagement",
"PropertyInspectorPath": "propertyInspector/adsensemanagement/index.html"
},
+ {
+ "Icon": "images/calendar",
+ "Name": "Google Calendar",
+ "States": [
+ {
+ "FontSize": "10",
+ "TitleAlignment": "bottom",
+ "Image": "images/calendar"
+ }
+ ],
+ "Controllers": [
+ "Keypad",
+ "Information"
+ ],
+ "SupportedInMultiActions": false,
+ "Tooltip": "구글 캘린더",
+ "UUID": "kr.devany.googleapi.googlecalendar",
+ "PropertyInspectorPath": "propertyInspector/googlecalendar/index.html"
+ },
{
"Icon": "images/gmail.png",
"Name": "Gmail",
diff --git a/kr.devany.googleapi.sdPlugin/propertyInspector/googlecalendar/PluginActionPI.js b/kr.devany.googleapi.sdPlugin/propertyInspector/googlecalendar/PluginActionPI.js
new file mode 100644
index 0000000..5f28270
--- /dev/null
+++ b/kr.devany.googleapi.sdPlugin/propertyInspector/googlecalendar/PluginActionPI.js
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/kr.devany.googleapi.sdPlugin/propertyInspector/googlecalendar/index.html b/kr.devany.googleapi.sdPlugin/propertyInspector/googlecalendar/index.html
new file mode 100644
index 0000000..41b66b8
--- /dev/null
+++ b/kr.devany.googleapi.sdPlugin/propertyInspector/googlecalendar/index.html
@@ -0,0 +1,24 @@
+
+
+
+
+ Google Calendar
+
+
+
+
+
+
+
+
+
+
diff --git a/src/GoogleAPI.csproj b/src/GoogleAPI.csproj
index e45684b..4a9e145 100644
--- a/src/GoogleAPI.csproj
+++ b/src/GoogleAPI.csproj
@@ -13,6 +13,21 @@
true
true
preview
+ 게시\
+ true
+ Disk
+ false
+ Foreground
+ 7
+ Days
+ false
+ false
+ true
+ 0
+ 1.0.0.%2a
+ false
+ false
+ true
AnyCPU
@@ -58,6 +73,9 @@
..\packages\Google.Apis.Auth.1.68.0\lib\net462\Google.Apis.Auth.dll
+
+ ..\packages\Google.Apis.Calendar.v3.1.35.1.1321\lib\net45\Google.Apis.Calendar.v3.dll
+
..\packages\Google.Apis.Core.1.68.0\lib\net462\Google.Apis.Core.dll
@@ -74,11 +92,14 @@
..\packages\System.CodeDom.7.0.0\lib\net462\System.CodeDom.dll
+
+
-
+
..\packages\System.Drawing.Common.8.0.1\lib\net462\System.Drawing.Common.dll
+ True
@@ -100,10 +121,14 @@
+
+
+
+
+
-
@@ -119,6 +144,7 @@
+
@@ -132,5 +158,17 @@
+
+
+ False
+ Microsoft .NET Framework 4.8.1%28x86 및 x64%29
+ true
+
+
+ False
+ .NET Framework 3.5 SP1
+ false
+
+
\ No newline at end of file
diff --git a/src/GoogleAPIs/AdSenseManagement/PluginAction.cs b/src/GoogleAPIs/AdSenseManagement/PluginAction.cs
index af42ca6..c8f0224 100644
--- a/src/GoogleAPIs/AdSenseManagement/PluginAction.cs
+++ b/src/GoogleAPIs/AdSenseManagement/PluginAction.cs
@@ -44,7 +44,16 @@ public PluginAction(ISDConnection connection, InitialPayload payload) : base(con
private async void Connection_OnTitleParametersDidChange(object sender, SDEventReceivedEventArgs e)
{
Logger.Instance.LogMessage(TracingLevel.INFO, "OnTitleParametersDidChange Event Handled");
- await DisplayInitialAsync();
+
+ if (!File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"DevAny\StreamDock.Plugins\GoogleAPI\Google.Apis.Auth.OAuth2.Responses.TokenResponse-user")))
+ {
+ await DisplayInitialAsync();
+ }
+ else
+ {
+ await DisplayBusyAsync();
+ await UpdateApiDataAsync();
+ }
}
///
diff --git a/src/GoogleAPIs/GoogleAPIs.cs b/src/GoogleAPIs/GoogleAPIs.cs
index c12b5ea..d244614 100644
--- a/src/GoogleAPIs/GoogleAPIs.cs
+++ b/src/GoogleAPIs/GoogleAPIs.cs
@@ -6,6 +6,7 @@
using Google.Apis.Adsense.v2;
using Google.Apis.Auth.OAuth2;
+using Google.Apis.Calendar.v3;
namespace StreamDock.Plugins.GoogleAPIs
{
@@ -31,7 +32,10 @@ protected async Task GetClientSecretAsync()
{
credential = await GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.FromStream(stream).Secrets,
- new[] { AdsenseService.Scope.AdsenseReadonly },
+ new[] {
+ AdsenseService.Scope.AdsenseReadonly,
+ CalendarService.Scope.Calendar
+ },
"user", CancellationToken.None);
}
Logger.Instance.LogMessage(TracingLevel.INFO, "Read client_secrets.json");
diff --git a/src/GoogleAPIs/GoogleCalendar/ApiAction.cs b/src/GoogleAPIs/GoogleCalendar/ApiAction.cs
new file mode 100644
index 0000000..bd324a4
--- /dev/null
+++ b/src/GoogleAPIs/GoogleCalendar/ApiAction.cs
@@ -0,0 +1,110 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+using BarRaider.SdTools;
+
+using Google.Apis.Calendar.v3;
+using Google.Apis.Services;
+
+using Newtonsoft.Json.Linq;
+
+namespace StreamDock.Plugins.GoogleAPIs.GoogleCalendar
+{
+ ///
+ /// API 동작 정의 프로시저
+ ///
+ internal class ApiAction : GoogleAPI
+ {
+ PluginSettings pluginSettings { get; set; }
+ Item item { get; set; }
+
+ internal ApiAction(PluginSettings pluginsettings, Item item)
+ {
+ this.pluginSettings = pluginsettings;
+ this.item = item;
+ }
+ internal async Task GetService()
+ {
+ // 서비스 생성
+ var service = new CalendarService(new BaseClientService.Initializer()
+ {
+ HttpClientInitializer = await GetClientSecretAsync(),
+ ApplicationName = "StreamDock Plugin"
+ });
+
+ return service;
+ }
+ ///
+ /// 키가 눌렸을 때 동작 정의. Google API 통신.
+ ///
+ internal async Task- ExecuteAsync()
+ {
+ Item _item = this.item;
+
+ try
+ {
+ // 서비스 생성
+ var service = new CalendarService(new BaseClientService.Initializer()
+ {
+ HttpClientInitializer = await GetClientSecretAsync(),
+ ApplicationName = "StreamDock Plugin"
+ });
+
+ // 구글 API 통신 인스턴스
+ GoogleAPIQuery googleAPIQuery = new GoogleAPIQuery(service);
+
+ if (pluginSettings.CalendarSummary.IsNullOrEmpty())
+ {
+ item.calendarID = googleAPIQuery.GetPrimaryCalendar().Id;
+ }
+ else
+ {
+ item.calendarID = googleAPIQuery.GetCalendar(pluginSettings.CalendarSummary).Id;
+ }
+
+ Logger.Instance.LogMessage(TracingLevel.INFO, item.calendarID);
+
+ // StreamDock 설정에 따른 동작 호출
+ item.Events = await googleAPIQuery.CalendarEventsToday(item.calendarID);
+
+ // 디스플레이용 데이터 가공
+ _item = SetDisplayValue();
+ }
+ catch (Exception ex)
+ {
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.Message);
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.StackTrace);
+ }
+ return _item;
+ }
+
+ ///
+ /// StreamDock 설정에 따라 표시할 데이터를 지정합니다.
+ ///
+ ///
+ internal Item SetDisplayValue()
+ {
+ try
+ {
+ item.DisplayValues.Clear();
+
+ foreach (var value in item.Events) {
+ if (value.End.Date.IsDateTime())
+ {
+
+ }
+ item.DisplayValues.Add(value.Summary);
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.Message);
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.StackTrace);
+ }
+
+ return item;
+ }
+ }
+}
diff --git a/src/GoogleAPIs/GoogleCalendar/GoogleAPIQuery.cs b/src/GoogleAPIs/GoogleCalendar/GoogleAPIQuery.cs
new file mode 100644
index 0000000..aa4bd31
--- /dev/null
+++ b/src/GoogleAPIs/GoogleCalendar/GoogleAPIQuery.cs
@@ -0,0 +1,80 @@
+using System.Collections.Generic;
+using System.Linq;
+
+using BarRaider.SdTools;
+
+using Google.Apis.Calendar.v3;
+using Google.Apis.Calendar.v3.Data;
+
+using System.Threading.Tasks;
+using Google.Apis.Adsense.v2.Data;
+using System;
+
+namespace StreamDock.Plugins.GoogleAPIs.GoogleCalendar
+{
+ internal class GoogleAPIQuery
+ {
+ private CalendarService service;
+
+ ///
+ /// 클래스의 새 인스턴스를 초기화합니다.
+ ///
+ /// 요청을 실행할 애드센스 서비스 개체입니다.
+ /// 검색할 최대 페이지 크기입니다.
+ internal GoogleAPIQuery(CalendarService service)
+ {
+ this.service = service;
+ }
+
+ ///
+ /// 계정의 모든 캘린더를 가져옵니다.
+ ///
+ /// 검색된 계정의 마지막 페이지입니다.
+ internal IList GetAllCalendars()
+ {
+ string pageToken = null;
+ CalendarList calendarList = null;
+
+ do
+ {
+ var calendarListRequest = service.CalendarList.List();
+ calendarListRequest.PageToken = pageToken;
+ calendarList = calendarListRequest.Execute();
+ pageToken = calendarList.NextPageToken;
+ } while (pageToken != null);
+ return calendarList.Items;
+ }
+ ///
+ /// 단일 캘린더를 가져옵니다.
+ ///
+ ///
+ internal CalendarListEntry GetCalendar(string summary)
+ {
+ return GetAllCalendars().First(s => s.Summary == summary);
+ }
+ ///
+ /// 단일 캘린더를 가져옵니다.
+ ///
+ ///
+ internal CalendarListEntry GetPrimaryCalendar()
+ {
+ return GetAllCalendars().First(s => s.Primary == true);
+ }
+ ///
+ /// 오늘 이벤트를 가져옵니다.
+ ///
+ ///
+ internal async Task> CalendarEventsToday(string id)
+ {
+ var requeust = service.Events.List(id);
+
+ requeust.MaxResults = 5;
+ requeust.TimeMin = DateTime.Today;
+ requeust.TimeMax = DateTime.Today.AddDays(1).AddSeconds(-1);
+
+ var result = await requeust.ExecuteAsync();
+
+ return result.Items;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/GoogleAPIs/GoogleCalendar/Models/Item.cs b/src/GoogleAPIs/GoogleCalendar/Models/Item.cs
new file mode 100644
index 0000000..f0f0d32
--- /dev/null
+++ b/src/GoogleAPIs/GoogleCalendar/Models/Item.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+using Google.Apis.Calendar.v3;
+using Google.Apis.Calendar.v3.Data;
+
+namespace StreamDock.Plugins.GoogleAPIs.GoogleCalendar
+{
+ ///
+ /// API 데이터를 보관하는 클래스입니다. static은 스트림독의 모든 키에 공유됩니다.
+ /// 데이터 형식은 API에서 제공하는 데이터 클래스를 사용하세요.
+ ///
+ public class Item
+ {
+ // 공유 데이터
+ internal static IList Calendars { get; set; }
+
+ // 개별 데이터
+ internal CalendarsResource Calendar { get; set; }
+ internal string calendarID { get; set; }
+ internal IList Events { get; set; } = new List();
+ internal bool CalendarExists => !Calendars.IsNullOrEmpty() && Calendars.Any();
+
+ internal IList DisplayValues { get; set; } = new List();
+
+ internal void Init()
+ {
+ }
+ }
+}
diff --git a/src/GoogleAPIs/GoogleCalendar/Models/PluginSettings.cs b/src/GoogleAPIs/GoogleCalendar/Models/PluginSettings.cs
new file mode 100644
index 0000000..6d7b8a0
--- /dev/null
+++ b/src/GoogleAPIs/GoogleCalendar/Models/PluginSettings.cs
@@ -0,0 +1,47 @@
+using System;
+using System.Drawing;
+
+using BarRaider.SdTools;
+
+using Newtonsoft.Json;
+
+using System.ComponentModel;
+
+namespace StreamDock.Plugins.GoogleAPIs.GoogleCalendar
+{
+ public class PluginSettings : INotifyPropertyChanged
+ {
+ //TODO
+ [JsonProperty(PropertyName = "CalendarList")]
+ public string PiCalendarList { get; set; }
+ public string CalendarSummary { get; set; } // 캘린더 이름
+ public string CalendarListJSON { get; set; }
+
+ [JsonProperty(PropertyName = "frontColor")]
+ public string PiFrontColor { get; set; }
+ public Color FrontColor => GraphicsTools.ColorFromHex(PiFrontColor);
+
+ [JsonProperty(PropertyName = "backColor")]
+ public string PiBackColor { get; set; }
+ public Color BackColor => GraphicsTools.ColorFromHex(PiBackColor);
+
+ public static PluginSettings CreateDefaultSettings()
+ {
+ PluginSettings instance = new PluginSettings();
+ instance.PiCalendarList = String.Empty;
+ instance.PiFrontColor = "#FFFFFF";
+ instance.PiBackColor = String.Empty;
+ return instance;
+ }
+
+ public event PropertyChangedEventHandler PropertyChanged;
+ protected void OnPropertyChanged(PropertyChangedEventArgs e)
+ {
+ PropertyChanged?.Invoke(this, e);
+ }
+ protected void OnPropertyChanged(string propertyName)
+ {
+ OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
+ }
+ }
+}
diff --git a/src/GoogleAPIs/GoogleCalendar/PluginAction.cs b/src/GoogleAPIs/GoogleCalendar/PluginAction.cs
new file mode 100644
index 0000000..e550aa9
--- /dev/null
+++ b/src/GoogleAPIs/GoogleCalendar/PluginAction.cs
@@ -0,0 +1,332 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+
+using BarRaider.SdTools;
+using BarRaider.SdTools.Wrappers;
+
+using Newtonsoft.Json.Linq;
+
+namespace StreamDock.Plugins.GoogleAPIs.GoogleCalendar
+{
+ ///
+ /// manifest.json 에서 선언한 플러그인 UUID
+ ///
+ [PluginActionId("kr.devany.googleapi.googlecalendar")]
+ public class PluginAction : KeypadBase
+ {
+ Item item { get; set; }
+ PluginSettings pluginSettings { get; set; }
+
+ public PluginAction(ISDConnection connection, InitialPayload payload) : base(connection, payload)
+ {
+ pluginSettings = (payload.Settings == null || payload.Settings.Count == 0) ? PluginSettings.CreateDefaultSettings() : payload.Settings.ToObject();
+ item = new();
+
+ Connection.OnApplicationDidLaunch += Connection_OnApplicationDidLaunch;
+ Connection.OnApplicationDidTerminate += Connection_OnApplicationDidTerminate;
+ Connection.OnDeviceDidConnect += Connection_OnDeviceDidConnect;
+ Connection.OnDeviceDidDisconnect += Connection_OnDeviceDidDisconnect;
+ Connection.OnPropertyInspectorDidAppear += Connection_OnPropertyInspectorDidAppear;
+ Connection.OnPropertyInspectorDidDisappear += Connection_OnPropertyInspectorDidDisappear;
+ Connection.OnSendToPlugin += Connection_OnSendToPlugin;
+ Connection.OnTitleParametersDidChange += Connection_OnTitleParametersDidChange;
+ }
+
+ ///
+ /// 제목이 변경되거나 스트림독에 플러그인이 나타날 때 호출됩니다.titleParametersDidChange
+ /// 하드웨어 기준.
+ ///
+ ///
+ ///
+ private async void Connection_OnTitleParametersDidChange(object sender, SDEventReceivedEventArgs e)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "OnTitleParametersDidChange Event Handled");
+
+ if (!File.Exists(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"DevAny\StreamDock.Plugins\GoogleAPI\Google.Apis.Auth.OAuth2.Responses.TokenResponse-user")))
+ {
+ await DisplayInitialAsync();
+ }
+ else
+ {
+ await DisplayBusyAsync();
+ await UpdateApiDataAsync();
+ }
+ }
+
+ ///
+ /// PropertyInspector가 sendToPlugin 이벤트를 사용할 때 플러그인에서 받은 이벤트입니다.
+ /// OnPropertyInspectorDidAppear 이벤트와 동시에 호출됩니다.
+ ///
+ ///
+ ///
+ private void Connection_OnSendToPlugin(object sender, SDEventReceivedEventArgs e)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "OnSendToPlugin Event Handled");
+ }
+
+ ///
+ /// PropertyInspector가 표시될 때마다 호출됩니다.
+ ///
+ ///
+ ///
+ private void Connection_OnPropertyInspectorDidAppear(object sender, SDEventReceivedEventArgs e)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "OnPropertyInspectorDidAppear Event Handled");
+
+ }
+
+ ///
+ /// PropertyInspector가 숨겨질 때마다 호출됩니다.
+ ///
+ ///
+ ///
+ private void Connection_OnPropertyInspectorDidDisappear(object sender, SDEventReceivedEventArgs e)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "OnPropertyInspectorDidDisappear Event Handled");
+ }
+
+
+ ///
+ /// 장치 연결 끊김 이벤트
+ ///
+ ///
+ ///
+ private void Connection_OnDeviceDidDisconnect(object sender, SDEventReceivedEventArgs e)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "OnDeviceDidDisconnect Event Handled");
+ }
+
+ ///
+ /// 장치 연결 이벤트
+ ///
+ ///
+ ///
+ private void Connection_OnDeviceDidConnect(object sender, SDEventReceivedEventArgs e)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "OnDeviceDidConnect Event Handled");
+ }
+
+ ///
+ /// 앱 종료 이벤트
+ ///
+ ///
+ ///
+ private void Connection_OnApplicationDidTerminate(object sender, SDEventReceivedEventArgs e)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "OnApplicationDidTerminate Event Handled");
+ }
+
+ ///
+ /// 앱 실행 이벤트
+ ///
+ ///
+ ///
+ private void Connection_OnApplicationDidLaunch(object sender, SDEventReceivedEventArgs e)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "OnApplicationDidLaunch Event Handled");
+ }
+
+ ///
+ /// 스트림독에 플러그인이 표시되지 않으면 호출됩니다.
+ ///
+ public override void Dispose()
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "Destructor called");
+ }
+
+ ///
+ /// 키를 눌렀을 때 호출됩니다.
+ ///
+ ///
+ public override void KeyPressed(KeyPayload payload)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "KeyPressed called");
+ }
+
+ ///
+ /// 키를 뗄 때 호출됩니다.
+ ///
+ ///
+ public async override void KeyReleased(KeyPayload payload)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "KeyReleased called");
+
+ if (CheckExistData())
+ {
+ System.Diagnostics.Process.Start(item.Events.First().HtmlLink);
+ }
+ else
+ {
+ await DisplayBusyAsync();
+ await UpdateApiDataAsync();
+ }
+ }
+
+ ///
+ /// 매 초 호출되는 메서드입니다.
+ ///
+ public override void OnTick()
+ {
+ }
+
+ ///
+ /// PropertyInspector에서 값이 변경될 때마다 호출됩니다.
+ ///
+ ///
+ public async override void ReceivedSettings(ReceivedSettingsPayload payload)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "ReceivedSettings called");
+
+ Tools.AutoPopulateSettings(pluginSettings, payload.Settings);
+
+ await SaveSettingsAsync();
+ await DisplayInitialAsync();
+ }
+
+ public override void ReceivedGlobalSettings(ReceivedGlobalSettingsPayload payload)
+ {
+ Logger.Instance.LogMessage(TracingLevel.INFO, "ReceivedGlobalSettings called");
+ }
+
+ #region Private Methods
+ ///
+ /// 설정 값을 스트림독으로 전달합니다.
+ ///
+ ///
+ private async Task SaveSettingsAsync()
+ {
+ await Connection.SetSettingsAsync(JObject.FromObject(pluginSettings));
+ }
+
+ ///
+ /// 기존 데이터가 있는지 검사합니다.
+ ///
+ ///
+ private bool CheckExistData()
+ {
+ return item.Events.Any();
+ }
+
+ ///
+ /// 초기 이미지를 표시합니다.
+ ///
+ private async Task DisplayInitialAsync()
+ {
+ try
+ {
+ if (!CheckExistData())
+ {
+ item.DisplayValues.OnlyOne("Press Key...");
+ }
+ else
+ {
+ UpdateValues();
+ }
+ await Connection.SetImageAsync(UpdateKeyImage(item, true), null, true); // 초기 이미지 출력
+ }
+ catch (Exception ex)
+ {
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.Message);
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.StackTrace);
+ }
+ }
+ ///
+ /// 작업 중임을 알리는 이미지를 표시합니다.
+ ///
+ private async Task DisplayBusyAsync()
+ {
+ try
+ {
+ TitleParameters tp = new TitleParameters(new FontFamily("Arial"), FontStyle.Bold, 12, Color.White, true, TitleVerticalAlignment.Middle);
+ using (Bitmap image = Tools.GenerateGenericKeyImage(out Graphics graphics))
+ {
+ graphics.FillRectangle(new SolidBrush(Color.Yellow), 0, 0, image.Width, image.Height);
+ graphics.AddTextPath(tp, image.Height, image.Width, "Loading...", Color.Black, 7); //TODO 지역화
+#if DEBUG
+ Logger.Instance.LogMessage(TracingLevel.INFO, "DisplayBusyAsync: 스트림독으로 이미지 전송 중...");
+#endif
+ await Connection.SetImageAsync(image);
+ graphics.Dispose();
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.Message);
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.StackTrace);
+ }
+ }
+ ///
+ /// PI 설정에 따라 Google API 데이터를 갱신합니다.
+ ///
+ private async Task UpdateApiDataAsync()
+ {
+ try
+ {
+ item = await GetApiInstance().ExecuteAsync();
+ Logger.Instance.LogMessage(TracingLevel.INFO, "UpdateApiDataAsync: Sending Image to Stream Dock...");
+ await Connection.SetImageAsync(UpdateKeyImage(item), null, true);
+ }
+ catch (Exception ex)
+ {
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.Message);
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.StackTrace);
+ }
+ }
+ ///
+ /// PI 설정에 따라 이미 수신된 Google API 데이터로 갱신합니다.
+ ///
+ private void UpdateValues()
+ {
+ GetApiInstance().SetDisplayValue();
+ }
+ ///
+ /// 키 이미지를 변경합니다. 출력할 정보를 이미지로 변환합니다.
+ ///
+ private Bitmap UpdateKeyImage(Item item, bool initial = false)
+ {
+ Bitmap bmp = null;
+ try
+ {
+ bmp = new Bitmap(ImageHelper.GetImage(pluginSettings.BackColor));
+
+ for (int i = 0; i < item.DisplayValues.Count; i++)
+ {
+ var font = new Font("Arial", 32, FontStyle.Bold, GraphicsUnit.Pixel);
+ var stringFormat = new StringFormat
+ {
+ Alignment = StringAlignment.Near,
+ LineAlignment = StringAlignment.Center
+ };
+ var isRGB = stringFormat.Alignment == StringAlignment.Near;
+
+ using (var graphics = Graphics.FromImage(bmp))
+ {
+ //font = ImageHelper.ResizeFont(graphics, item.DisplayValues[i], font);
+ graphics.DrawString(item.DisplayValues[i], font, new SolidBrush(pluginSettings.FrontColor), !isRGB ? 72 : 5, (144 / (item.DisplayValues.Count + 1)) * (i + 1), stringFormat);
+ }
+
+ //bmp = new Bitmap(ImageHelper.SetImageText(bmp, item.DisplayValues[i], new SolidBrush(pluginSettings.FrontColor), 72, (144 / (item.DisplayValues.Count + 1)) * (i + 1)));
+ }
+ }
+ catch (Exception ex)
+ {
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.Message);
+ Logger.Instance.LogMessage(TracingLevel.ERROR, ex.StackTrace);
+ }
+ return bmp;
+ }
+ ///
+ /// Google API 쿼리 클래스의 인스턴스를 가져옵니다.
+ ///
+ ///
+ private ApiAction GetApiInstance()
+ {
+ return new ApiAction(pluginSettings, item);
+ }
+ #endregion
+ }
+}
diff --git a/src/packages.config b/src/packages.config
index 762eb59..69edf52 100644
--- a/src/packages.config
+++ b/src/packages.config
@@ -4,6 +4,7 @@
+