Scratch 3.0 Scratch Link를 수정해보기

Scratch 3.0은 외부기기와 연동하기 위해서 Scratch Link 앱을 이용해야 한다. (Scratch 내부에 구현할 수도 있을 것 같은데, 이렇게 되면 다른 운영체제에서 호환이 안될테니 아마도 이렇게 만들어 놓은듯 하다) 내부를 들여다보면 Scratch Link에서 WebSocket 서버를 제공하고, BLE, BT로 구분하여 접속할 수 있다. 통신은 JSONRPC를 이용한다. BLE, BT 모두 프로토콜은 동일하다.

따라서 Bluetooth 시리얼, BLE 등을 이용한 기기들은 기존 프로토콜을 이용하여 접속 및 연동이 가능하다. OROCA-Edubot도 이와 같은 과정을 통해 연동에 성공하였다. 이제 좀더 나아가 시리얼포트를 이용할 경우 (예를 들어 Arduino 보드나 사용자가 개발한 보드들)엔 어떻게 해야 할까?

고민해본 결과 가장 클리어한 방법은 Scratch Link를 확장하여 시리얼 통신을 지원하게끔 하면 될 것 같다. 마침 기존까진 실행파일로만 제공되었던 Scratch Link가 이젠 소스까지 제공되고 있다. 개발 지원 운영체제는 macOS와 윈도우이다.

소스는 https://github.com/llk/scratch-link에서 받을 수 있다. 개발PC에 일단 클론해 보고,

$ git clone https://github.com/LLK/scratch-link.git

README.md 파일에 나온 것과 같은 과정을 통해 빌드해보자. 보안 WebSocket를 사용해야 하므로 인증서가 필요하다. 나중에 판매하거나 양상 목적이라면 돈을 주고 구입해야 하지만, 개인이 사용할 경우엔 PC에서 쉽게 생성 가능하다.

$ cd scratch-link
$ cd Certificates
$ openssl req -x509 -out scratch-device-manager.cer -keyout scratch-device-manager.key \
  -newkey rsa:2048 -nodes -sha256 \
  -subj '/CN=scratch-device-manager' -extensions EXT -config <( \
   printf "[dn]\nCN=localhost\n[req]\ndistinguished_name = dn\n[EXT]\nsubjectAltName=DNS:localhost\nkeyUsage=digitalSignature\nextendedKeyUsage=serverAuth")

$ ./convert-certificates.sh

위 과정이 완료되면 out 디렉토리에  scratch-device-manager.pem, scratch-device-manager.pfx 파일이 생성된다.

현재 내가 사용하고 있는 개발환경은 macOS 이므로, macOS 폴더로 이동하여 빌드를 시작한다. Xcode, pngcrush를 미리 설치되어 있어야 한다. Xcode는 앱스토어에서, pngcrush는 homebrew를 이용하면 쉽게 설치할 수 있다.

$ cd ..
$ cd macOS
$ make

빌드에 필요한 패키지들이 자동으로 설치되고, 에러가 없이 완료되면 dist 디렉토리가 생성되고 Scratch Link 앱이 생성되어 있음을 볼 수 있다.

이제 이 앱을 실행해보면, 기존과 같이 메뉴바에 Scratch Link가 위치한다.

Scratch 3.0를 실행하고, BLE와 BT 등 기존과 동일하게 동작하는지 확인한다. 지난번 개발환경 구축 포스팅에서 device-manager.scratch.mit.edu를 hosts 파일을 이용해 127.0.0.1로 강제 변경하였는데, 이제 Scratch Link를 직접 사용할 수 있으므로 localhost로 변경하여 사용해도 무방하다.

따라서, hosts 파일을 변경하는 작업을 하지 않고, scratch-vm 내에서 다음의 파일에 있는 웹소켓 주소를 localhost로 변경한다.

> scratch-vm/src/io/ble.js

const ScratchLinkWebSocket = 'wss://localhost:20110/scratch/ble';
> scratch-vm/src/io/bt.js

const ScratchLinkWebSocket = 'wss://localhost:20110/scratch/bt';

(추가) 최근 변경된 버전에선 ./util/scratch-link-websocket.js 에서 저 링크들을 관리하는 듯 하다. 따라서 해당 파일을 수정해주면 됨.

> scratch-vm/src/util/scratch-link-websocket.js
28: this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/ble');
31: this._ws = new WebSocket('wss://device-manager.scratch.mit.edu:20110/scratch/bt'); 

이제 Scratch 3.0을 실행하고 확장카드를 실행해보면,

사파리의 경우, 위와 같이 Scratch Link와의 연결이 되지 않는다. 새로운 사파리 창을 띄우고 https://localhost:20110 로 접속한다. 다음과 같이 나오는데,

Show Details 버튼을 누르고, 아래쪽에 visit this website 링크를 누르고 다시 한번 접속하겠다고 하면, 어드민 암호를 입력하고 현재의 인증서가 사파리에 저장된다.

이제 Scratch 3.0에서 정상적으로 실행됨을 볼 수 있다.

다음엔 Scratch Link의 소스를 분석하고 시리얼 통신이 가능하도록 모듈을 작성해보도록 한다.


참고링크

Scratch 3.0 블로킹 블럭 만들기

확장블럭 중 블로킹 기능을 필요로 하는 블럭을 만들어야 할 필요가 있다. 예를 들면 로봇의 경우 setDistance, setRotation 등 특정 거리나 특정 각도까지 움직이고, 이때 동작이 완료될 때까지 기다려야 하는 블럭이 존재한다.

Scratch 3.0의 Extension의 경우 개발 언어는 Javascript이다. 따라서 일반 언어에서 사용하듯 while 문을 이용한 제어가 불가능하다. 만약 while 문을 사용하면 스크립트 실행 자체가 멈춰버리므로, 프로그램 자체가 멈춰버리고, 이게 길게되면 각종 브라우저에서 에러와 같이 인식한다.

이를 구현하기 위해서 Promise와 setInterval의 조합으로 해결이 가능하다. 로봇이 움직이고 있다는 신호는 로봇의 상태 정보를 통해 파악할 수 있고, 움직이는 명령을 보낸 후, 로봇의 상태 정보를 지속적으로 모니터링하여 로봇의 동작이 완료되었음을 의미하는 플래그가 셋되면 블럭의 동작을 완료하면 된다.

기존 setDistance() 함수는 다음과 같이 되어 있다.

setDistance (args) {
    const l_dist = parseInt(args.L_DIST);
    const r_dist = parseInt(args.R_DIST);

    this._peripheral.setDistance(l_dist, r_dist);
}

이제 여기에 플래그를 모니터링하고, 블럭의 동작을 완료하는 부분을 추가한다.

setDistance (args) {
    const l_dist = parseInt(args.L_DIST);
    const r_dist = parseInt(args.R_DIST);

    this._peripheral.setDistance(l_dist, r_dist);

    return new Promise(resolve => {
        var first_check = true;
        var ttt = setInterval(() => {
            if(this._peripheral.isRobotMoving == false && first_check == true) {
                first_check = false;
            }
            else if(this._peripheral.isRobotMoving == false && first_check == false) {
                resolve();
                clearInterval(ttt);
            }
        }, 100);
    });
}

이제 로봇의 연결하고 위 블럭을 실행해보면, 다음과 같이 동작이 완료될 때까지 대기함을 볼 수 있다.

Scratch 3.0 업데이트

스크레치 3.0은 현재도 활발하게 업데이트가 진행 중이다. 이에 따라, 기존에 작성하였던 Extension들도 이에 맞추어 몇가지 수정해야 하는 상황이 발생한다.

scratch-gui

  • 확장카드의 이미지들의 위치가 한 디렉토리로 통일됨. 기존은 외부 연결에 사용되는 아이콘 그림의 경우 peripheral-connection에 넣었으나, 이젠 확장카드 이름의 디렉토리에 모두 넣어 사용하고 peripheral-connection 디렉토리는 사라짐.
  • 기존 외부링크로 되어 있던 리소스들이 로컬로 전환 중. 사운드, 이미지 등이 로컬 파일로 존재. 즉, 이제 인터넷 연결 없이도 원할히 사용 가능.
  • 확장카드 추가 – gdx, LEGO Boost 등

scratch-vm

  • 추가된 확장카드에 대한 소스들 추가.

scratch-l10n

  • 추가된 확장카드에 대한 언어 추가.