티스토리 뷰

반응형

smartthings를 st 공식 api사용하지 않고, api와 같은 형태로 사용하기(api의 문제점 포함)

 

삼성 가전의 스마트싱스를 개발로 가져오면서 몇가지 불편한점이 존재

-API 사용이 어렵다(가입 인증 WebHook등등)

-공식 API를 사용된 순간 API 서버를 타야하기때문에 반응속도도 느리고, 동기화에도 큰 문제가 생긴다

-스마트싱스 공식앱만이 로컬환경(로컬망)에서 동작하기때문에 속도가 빠르다

 

이정보를 종합했을때 기본적인 방법으로는 내가 개발한 앱이나 환경에서 빠른 속도로 쓸 방법이 없었다

그래서 고민 끝내 생각해낸 결과

 

 

 

 

1.윈도우 ST앱의 자동화를 활용

2.해당화면을 늘 유지 할 수있게 만든 후 좌표를 활용한 매크로를 개발

3.해당 좌표와 기능을 DB(또는 메타데이터)로 저장하여 외부 프로토콜을 통해서 Hooking 동작을 하게 처리한다

using bss_st_api.Helpers;
using Launcher_SE.Helpers;
using Rito;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using testMouse.Helpers;
using static Rito.HookHelper;

namespace bss_st_api
{
    public partial class MainWindow : Window
    {
        float interval = 5.0f;

        System.Drawing.Point iconPT = new System.Drawing.Point(407, 1063);

        System.Drawing.Point pt01 = new System.Drawing.Point(407, 1063);
        System.Drawing.Point pt02 = new System.Drawing.Point(35, 238);
        System.Drawing.Point pt03 = new System.Drawing.Point(31, 240);
        System.Drawing.Point pt04 = new System.Drawing.Point(36, 58);
        System.Drawing.Color c = System.Drawing.Color.FromArgb(1, 0, 120, 212);
        HookHelper hook;

        string currentValue;
        bool isSave = false;
        bool isEdit = false;
        bool isServer = false;

        string path = @"C:\projects\bss-ex\"; 

        DispatcherTimer timer;
        DispatcherTimer processTimer;

        public bool UtilHeper { get; private set; }

        public MainWindow()
        {

            InitializeComponent();
            Init();
            RunPlayMode();
            

        }

        private void Instance_PacketReceiveEventHandlerEvent(string code)
        {
            if (!isEdit)
            {
                var coordinate = XmlHelper.Instance.Get(code);
                if (!coordinate.Equals("fail"))
                {
                    int x = int.Parse(coordinate.Split(':')[0]);
                    int y = int.Parse(coordinate.Split(':')[1]);

                    hook.ForceSetCursor(x, y);
                    hook.ForceLeftClick();
                }
            }
            else
            {

            }
        }

        private void Hook_OnRightButtonUp(MouseHookInfo mouseStruct)
        {
            MousePoint point1 = hook.GetCursorPosition();
            currentValue = $"{point1.x}:{point1.y}";
            Write(currentValue);

            var bounds = Screen.PrimaryScreen.Bounds;
            using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(System.Drawing.Point.Empty, System.Drawing.Point.Empty, bounds.Size);
                }

                //현재 위치 좌표
                System.Drawing.Color color = bitmap.GetPixel(point1.x, point1.y);

                Write(color.ToString());

            }
                if (isSave)
            {
                MousePoint point = hook.GetCursorPosition();
                currentValue = $"{point.x}:{point.y}";
                Write(currentValue);
                XmlHelper.Instance.Save(txt_index.Text, currentValue);
                txt_index.Text = (int.Parse(txt_index.Text) + 1).ToString();
            }
        }

        private void BtnSave_Click(object sender, RoutedEventArgs e)
        {
            if (isSave)
            {
                isSave = false;
                btnSave.Content = "Save Off";
            }
            else
            {
                isSave = true;
                btnSave.Content = "Save On";
            }
        }

        public void Init()
        {
            timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(interval);
            timer.Tick += Timer_Tick;

            processTimer = new DispatcherTimer();
            processTimer.Interval = TimeSpan.FromSeconds(3);
            processTimer.Tick += ProcessTimer_Tick;
            //processTimer.Start();

            hook = new HookHelper();
            hook.Begin();
            hook.OnRightButtonUp += Hook_OnRightButtonUp;

            btnSave.Click += BtnSave_Click;
            btnServer.Click += BtnServer_Click;
            UdpHelper.Instance.Start();
            UdpHelper.Instance.PacketReceiveEventHandlerEvent += Instance_PacketReceiveEventHandlerEvent;
        }

        private void ProcessTimer_Tick(object sender, EventArgs e)
        {
            processTimer.Stop();
            ProcessStartInfo startInfo = new ProcessStartInfo()
            {
                FileName = "cmd.exe",
                Arguments = "/c python main.py", // "/c"는 CMD에게 명령어를 실행하고 종료하라는 의미야
                UseShellExecute = false,
                RedirectStandardInput = true,
                RedirectStandardOutput = true,
                CreateNoWindow = false, // CMD 창을 보고 싶으면 이걸 false로 설정
                WindowStyle = ProcessWindowStyle.Minimized,
                WorkingDirectory = path // CMD가 실행될 경로
            };



            Process cmdProcess = new Process() { StartInfo = startInfo };
            cmdProcess.Start();

            //using (StreamWriter sw = cmdProcess.StandardInput)
            //{
            //    if (sw.BaseStream.CanWrite)
            //    {
            //        // 이 경로에서 실행하고 싶은 명령어들
            //        sw.WriteLine("run.bat");
            //        // 다른 명령어 실행 예
            //        // sw.WriteLine("dir");
            //    }
            //}
   
        }

        private void BtnServer_Click(object sender, RoutedEventArgs e) 
        {
            if (isServer)
            {
                isServer = false;
                timer.Stop();
                btnServer.Content = "Server Stop";
            }
            else
            {
                isServer = true;
                timer.Stop();
                timer.Start();
                btnServer.Content = "Server Start";
            }
        }

        protected override void OnKeyUp(System.Windows.Input.KeyEventArgs e)
        {
            if(e.Key == Key.D1)
            {
                var test = new System.Drawing.Point(413, 1057);

                var bounds = Screen.PrimaryScreen.Bounds;
                using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
                {
                    using (Graphics g = Graphics.FromImage(bitmap))
                    {
                        g.CopyFromScreen(System.Drawing.Point.Empty, System.Drawing.Point.Empty, bounds.Size);
                    }

                    //현재 위치 좌표
                    System.Drawing.Color color = bitmap.GetPixel(test.X,test.Y);

                    Write(color.ToString());

                }

            }
        }

        private async void Timer_Tick(object sender, EventArgs e)
        {
            var bounds = Screen.PrimaryScreen.Bounds;
            using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height))
            {
                using (Graphics g = Graphics.FromImage(bitmap))
                {
                    g.CopyFromScreen(System.Drawing.Point.Empty, System.Drawing.Point.Empty, bounds.Size);
                }

                //현재 위치 좌표
                System.Drawing.Color color = bitmap.GetPixel(iconPT.X, iconPT.Y);

                if (UtilHelper.diff(color, c))
                {
                    Debug.WriteLine("실행중");
                }
                else
                {
                    isEdit = true;
                    hook.ForceSetCursor(pt01.X, pt01.Y);
                    hook.ForceLeftClick();
                    list.Items.Insert(0, "아이콘 실행");
                    await Task.Delay(5000);

                    //hook.ForceSetCursor(pt02.X, pt02.Y);
                    //hook.ForceLeftClick();
                    //list.Items.Insert(0, "전체화면 체크");
                    //await Task.Delay(1000);

                    hook.ForceSetCursor(pt03.X, pt03.Y);
                    hook.ForceLeftClick();
                    list.Items.Insert(0, "자동화 실행");
                    await Task.Delay(2000);

                    hook.ForceSetCursor(pt04.X, pt04.Y);
                    hook.ForceLeftClick();
                    list.Items.Insert(0, "탭 최소화");
                    await Task.Delay(2000);
                    isEdit = false;
                }
            }
        }
        public void Write(string text)
        {
            list.Items.Insert(0, text);
        }

        public async void RunPlayMode()
        {
            hook.ForceSetCursor(pt01.X, pt01.Y);
            hook.ForceLeftClick();
            list.Items.Insert(0, "아이콘 실행");
            await Task.Delay(5000);

            //hook.ForceSetCursor(pt02.X, pt02.Y);
            //hook.ForceLeftClick();
            //list.Items.Insert(0, "전체화면 체크");
            //await Task.Delay(1000);

            hook.ForceSetCursor(pt03.X, pt03.Y);
            hook.ForceLeftClick();
            list.Items.Insert(0, "자동화 실행");
            await Task.Delay(2000);

            hook.ForceSetCursor(pt04.X, pt04.Y);
            hook.ForceLeftClick();
            list.Items.Insert(0, "탭 최소화");
            await Task.Delay(2000);
        }
    }
}

 

4.비정상적인 팝업이나 예외처리를 추가로 해준다.

import pyautogui
import time
from datetime import datetime  # 현재 시간 정보를 가져오기 위해 추가

def find_and_click_center(image_path):
    while True:  # 무한 루프를 사용하여 계속해서 이미지를 찾음
        try:
            location = pyautogui.locateOnScreen(image_path, confidence=0.8)
            if location is not None:
                # 이미지를 찾았다면, 중앙 좌표를 클릭
                center = pyautogui.center(location)
                pyautogui.click(center)
                now = datetime.now()  # 현재 시간 가져오기
                print(f"{now.strftime('%Y-%m-%d %H:%M:%S')} : {center}")
                # 현재 시간을 년-월-일 시:분:초 형식으로 출력
        except Exception as e:
            pass  # 예외가 발생해도 아무 메시지도 출력하지 않음

        time.sleep(0.5)  # 이미지를 찾은 후 또는 찾지 못했을 때 0.5초 대기

# 이미지 경로 지정
image_path = '1.png'  # 실제 이미지 파일 경로로 변경
find_and_click_center(image_path)

 

 

5.

 

반응형
댓글
반응형