* 경고 *
해당 포스팅은 교육적인 목적입니다. 절대 악용, 남용 하면 아니되옵니다.
안녕하세요 라이프온룸 입니다. !!ㅎㅎ
오늘은 아두이노 Pro Micro로 들어온 시리얼 데이터로 매크로 Keyboard, Mouse 를 만들어 보겠습니다.
준비물은 간단합니다. Arduino Pro Micro 만 있으면 되요 ㅎㅎ
아두이노 Pro Micro는 Arduino Leonardo 호환 보드로 Atmega32u4 칩에 프로그램이 가능합니다. 그래서 시리얼 HID 모두 가능하지요 ! 다만 5V 버전과 3.3V 이 존재합니다. 5V 버전의 경우 16MHz로 동작하는데 아래 보면 오실레이터 부분에 5V인 경우에는 16 이라는 숫자가 보일 거고 3.3V 일 경우에는 8 이라는 숫자가 보일 겁니다.
주의할 점은 아두이노 IDE에서 보드를 잘 못 선택하고 스케치를 업로드 하면 벽돌이 될 수 있습니다…. 저의 경우 3.3V 의 부트로더가 Lily Pad Arduino Usb 였는데 Arduino/Genuino Micro 로 스케치 업로드 했다가 바로 벽돌 됐습니다. ㅜㅜ 복구하는 방법은 아래 URL을 참고 하세요. 간단히 설명드리자면 RST 와 GND를 두번 쇼트 시키고 8초 안에 빈 스케치를 주입하시면 됩니다.
//learn.sparkfun.com/tutorials/pro-micro–fio-v3-hookup-guide/troubleshooting-and-faq
여튼 그래서 무슨 보드를 쓰는지 잘 숙지하고 있어야 하고 스케치 업로드 할 때 주의하셔야 합니다. Pro Micro는 잘 못 하면 벽돌이 잘 된다고 하네요 ㅜㅜ
저의 경우 5V 버전으로 작업 했는데요 아두이노를 연결하면 아래처럼 Leonardo 라고 인식합니다. 이렇게 인식이 되면 일단 정상 동작 하는 겁니다.
1. 아두이노 코드
자 그럼 이제 먼저 아두이노 코드를 짜볼게요
/* /mMo/12,12| /mlC/p| /mlC/r| /mKey/hello| */ #include "Mouse.h" #include "Keyboard.h" #include "HID.h" int x,y = -1; void setup() { Serial.begin(9600); // Sends a clean report to the host. This is important on any Arduino type. Keyboard.begin(); Mouse.begin(); } void loop() { if (Serial.available()) { String mouseString = Serial.readStringUntil('|'); mouseString.trim(); if (mouseString.charAt(0) == '/') { // send like this - "/mMo/5,5" if (mouseString.substring(1, 4).equals(F("mMo")) == true) { //------------------------------- int slashIdx = mouseString.indexOf('/', 1); if (slashIdx > 0) { int commaIdx = mouseString.indexOf(',', slashIdx + 1); if (commaIdx > 0) { x = mouseString.substring(slashIdx + 1, commaIdx).toInt(); y = mouseString.substring(commaIdx + 1).toInt(); } else { x = mouseString.substring(slashIdx + 1).toInt(); y = 0; } Mouse.move(x, y, 0); //Serial.print(x);Serial.print(':');Serial.println(y); } //------------------------------- Serial.println(F("move")); } else if (mouseString.substring(1, 4).equals(F("mlC")) == true) { //------------------------------- int slashIdx = mouseString.indexOf('/', 1); if (slashIdx > 0) { char action = mouseString.substring(slashIdx + 1)[0]; if ((action == 'p') && (!Mouse.isPressed(MOUSE_LEFT))) { Mouse.press(MOUSE_LEFT); Serial.println(F("Pre")); } else if ((action == 'r') && (Mouse.isPressed(MOUSE_LEFT))) { Mouse.release(MOUSE_LEFT); Serial.println(F("Rls")); } } else { Mouse.press(); delay(400); Mouse.release(); Serial.println(F("Click")); } //------------------------------- } else if (mouseString.substring(1, 4).equals(F("mrC")) == true) { //------------------------------- int slashIdx = mouseString.indexOf('/', 1); if (slashIdx > 0) { char action = mouseString.substring(slashIdx + 1)[0]; if ((action == 'p') && (!Mouse.isPressed(MOUSE_RIGHT))) { Mouse.press(MOUSE_RIGHT); Serial.println(F("Pre")); } else if ((action == 'r') && (Mouse.isPressed(MOUSE_RIGHT))) { Mouse.release(MOUSE_RIGHT); Serial.println(F("Rls")); } } else { Mouse.press(MOUSE_RIGHT); delay(400); Mouse.release(MOUSE_RIGHT); Serial.println(F("Click")); } } else if (mouseString.substring(1, 5).equals(F("mKey")) == true) { //------------------------------- int slashIdx = mouseString.indexOf('/', 1); if (slashIdx > 0) { Keyboard.print(mouseString.substring(slashIdx + 1)); } //------------------------------- Serial.println(F("Key")); } } } }아래 명령예시 입니다. 마우스 이동, 좌클릭, 우클릭, Keyboard 타자를 지원 합니다.
- /mMo/12,12| – 마우스를 현위치에서 12, 12, 만큼 움직임
- /mlC/p| – 현재 좌표 마우스 누르기
- /mlC/r| – 현재 좌표 마우스 때기
- /mKey/hello| – hello 그대로 Keyboard 입력
요 상태에서 아래 설정으로 스케치를 업로드를 합니다. (5V 16MHz 사용 중)
- 보드 : Arduino/Genuino Micro
- 포트 :COM21 (Arduino/Genuino Micro)
업로드 후 시리얼 모니터를 열고 위 예시를 시험해보세요 !! 명령이 성공하면 명령 종류에 따라서 String을 Serial로 Return 해 줍니다. ㅎ
2. Python Code
그럼 윈도우에서 Python Code로 키보드 ‘F4’를 누르면 3초 뒤 “Hello”를 출력하는 예제를 해보겠습니다. 우선 아래 라이브러리를 설치하고 갈게요
pip install pyserial pip install keyboard pip install mouse설치를 하셨으면 serialFunc.py 라는 파일을 만들고 아래 코드를 입력해 줍니다.
import serial import time # /mMo/12,12| # /mlC| # /mlC/p| # /mlC/r| # /mrC| # /mrC/p| # /mrC/r| # /mKey/keyinput| class ExternalHID: ser = 0 def __init__(self, comport): try: self.ser = serial.Serial(comport, 9600, timeout=1) except Exception as e: print(str(e)) def disconnectSerial(self): self.ser.close() def checkSerial(self): if self.ser == 0: print('Serial Not available') return False else: return True def mouseMove(self, x, y): if not self.checkSerial(): return False moveCommand = '/mMo/%d,%d|' % (x, y) self.ser.write(str.encode(moveCommand)) rsp = self.ser.readline() if rsp.strip() == b'move': return True else: return False def mouseClick(self, button): if not self.checkSerial(): return False if button == 'left': moveCommand = '/m%sC|' % ('l') elif button == 'right': moveCommand = '/m%sC|' % ('r') else: return False self.ser.write(str.encode(moveCommand)) rsp = self.ser.readline() if rsp.strip() == b'Click': print('HID Click Success') return True else: return False def keyboardInput(self, keyinput): if not self.checkSerial(): return False moveCommand = '/mKey/%s|' % keyinput self.ser.write(str.encode(moveCommand)) rsp = self.ser.readline() if rsp.strip() == b'Key': return True else: return False def mousePress(self, button): if not self.checkSerial(): return False print(str(button)) if button == 'left': moveCommand = '/m%sC/p|' % ('l') elif button == 'right': moveCommand = '/m%sC/p|' % ('r') else: return False self.ser.write(str.encode(moveCommand)) rsp = self.ser.readline() if rsp.strip() == b'Pre': return True else: return False def mouseRelease(self, button): if not self.checkSerial(): return False print(str(button)) if button == 'left': moveCommand = '/m%sC/r|' % ('l') elif button == 'right': moveCommand = '/m%sC/r|' % ('r') else: return False self.ser.write(str.encode(moveCommand)) rsp = self.ser.readline() if rsp.strip() == b'Rls': return True else: return False if __name__ == "__main__": import keyboard as key import time ser = ExternalHID('COM21') def printHello(): state = False returnList = [] while True: val = key.is_pressed('F4') if state != val: if val == True: time.sleep(3) ser.keyboardInput('Hello') state = val while True: time.sleep(0.001) printHello()이 코드는 아두이노에서 정의한 Keyboard, Mouse 제어 스트링을 Serial 통신으로 보내주는 역할을 합니다. 다양한 함수를 만들어 놨으니 한번 사용해 보세요 !
코드를 입력 했으면 Pycharm 혹은 Cmd 에서 실행시킨 뒤 메모장에 마우스를 위치시키고 ‘F4’ 를 눌러보세요 ! 그럼 약 3초 뒤에 Hello 라는 단어가 메모장에 써질 겁니다.
이쯤에서 로아 낚시 매크로 시리즈를 보고 오신 분이 계신다면 이게 뭔 뻘짓이지 ? 그냥 ser.keyboardInput(‘Hello’) 대신 key.write(‘Hello’) 쓰면 되는거 아닌가? 라는 아주 합리적인 의문을 가지실 수 있습니다.
하지만 후자는 S/W 적인 방법입니다. 게임에 적용 할 때면 안 먹히는 경우가 꽤 있습니다. 특히 게임 상에서 마우스 이벤트로 특정 버튼을 누르려 할 때 안되는 경우가 종종 있습니다.(물론 이건 제 지식이 짧아서 일 수 있습니다… ㅜㅜ)
이 포스트의 하드웨어 메크로는 가능데스죠 ㅋㅋ 악용은 금지 입니다. ..
오늘의 포스팅은 여기까지 입니다. 모두들 좋은 밤 되세요 ㅎㅎㅎ