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';

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

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

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

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

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


참고링크

Advertisements

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

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

Scratch 3.0 exe, app으로 패키징하기

모든 개발이 완료되고, 배포를 해야 하는 경우에 윈도우의 경우 exe 파일, macOS의 경우 .app으로 패키징하여야 한다. 물론 소스 파일을 배포하고 사용자가 지난번 포스팅(https://ahnbk.com/?p=366, https://ahnbk.com/?p=383)과 같이 개발환경을 갖추어서 실행할 수 있지만 매우 복잡하고, 릴리즈 모드가 아닌 관계로 살짝 느린 면이있다.

Scratch 3.0은 React.js를 사용하여 개발되었다. 즉 이를 실행하기 위해선 웹브라우저가 필요하다. 개발 시에는 webpack-dev-server를 이용하였다. 이를 대체할 것이 필요한데, 이때 필요한 것이 Electron(https://electronjs.org)이다.

Electron은 NodeJS, Chromium을 이용하여 JavaScript, HTML, CSS를 이용하여 동일한 소스로 Windows, macOS, Linux 등에서 실행 가능한 Desktop 앱을 개발할 수 있는 플랫폼이다.

Electron은 npm을 이용하여 쉽게 설치할 수 있다.

$ npm install -g electron

다음으로 지금까지 개발한 Scratch 3.0을 릴리즈 형태로 빌드한다. Scratch-gui 디렉토리로 이동하여 다음과 같이 입력한다.

$ cd scratch-gui
$ npm run-script build

이제 빌드가 완료되면, build 디렉토리에 release 모드로 빌드된 파일들이 생성되어 있음을 볼 수 있다.

이제 편의상 scratch-app 디렉토리를 하나 생성하고 위 build 디렉토리를 복사한다. 다음으로 election 앱을 만들기 위해 다음과 같이 입력한다.

$ cd scratch-app
$ npm init

This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (scratch-app) 
version: (1.0.0) 
description: Scratch 3.0 for OROCA Edubot
entry point: (index.js) main.js
test command: 
git repository: 
keywords: scratch, oroca, edubot, block-coding
author: Byeong-Kyu Ahn
license: (ISC) BSD-2-Clause
About to write to /Users/byeongkyu/Developer/scratch/scratch-app/package.json:

{
  "name": "scratch-app",
  "version": "1.0.0",
  "description": "Scratch 3.0 for OROCA Edubot",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "scratch",
    "oroca",
    "edubot",
    "block-coding"
  ],
  "author": "Byeong-Kyu Ahn",
  "license": "BSD-2-Clause"
}


Is this OK? (yes) 

위와 같이 사용자의 환경에 맞추어 입력하게 되면, package.json 파일이 생성되어 있음을 볼수 있다. package.json 파일을 에디터를 이용해 다음과 같이 수정한다.

{
  "name": "scratch-app",
  "version": "1.0.0",
  "description": "Scratch 3.0 for OROCA Edubot",
  "main": "main.js",
  "scripts": {
    "start": "electron ."
  },
  "keywords": [
    "scratch",
    "oroca",
    "edubot",
    "block-coding"
  ],
  "author": "Byeong-Kyu Ahn",
  "license": "BSD-2-Clause"
}

이제 main.js 파일을 생성하고 다음과 같이 입력한다.

const { app, BrowserWindow } = require('electron')
var path = require('path')

let win

function createWindow () {
  win = new BrowserWindow({
    frame: true,
    width: 1200,
    height: 800,
    icon: path.join(__dirname, 'assets/icons/png/64x64.png')
  })

  win.loadFile('./build/index.html')

  win.on('closed', () => {
    win = null
  })
}

app.on('ready', createWindow)

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit()
  }
})

app.on('activate', () => {
  if (win === null) {
    createWindow()
  }
})

다음과 같이 입력하여 실행해 본다.

$ npm start

정상적으로 되었다면, 앱이 실행 됨을 볼 수 있다.

이제 이렇게 생성된 electron 앱을 패키징하는 과정만 남아 있다. 먼저 앱의 아이콘을 생성한다. 기본값은 Electron의 기본 아이콘이다. 이미지 편집기 등을 이용하여 1024×1024 크기의 png 파일을 생성한다.

윈도우 앱의 경우 ico 파일을 사용하고, macOS의 경우 icn 파일을 사용한다. https://icoconvert.com, https://iconverticons.com/online 등의 웹페이지에서 변환이 가능하다. 생성된 파일을 scratch-app 디렉토리에 복사한다.

다음으로 electron-packager를 설치한다. npm을 이용하여 쉽게 설치할 수 있다.

$ npm install -g electron-packager

다음으로 패키징에 필요한 electron을 설치한다.

$ cd scratch-app
$ npm install --save-dev electron

마지막으로 macOS용 앱을 패키지할 경우 다음과 같이 입력한다.

$ electron-packager . --overwrite --platform=darwin --arch=x64 --icon=./assets/icons/edubot_icon.icns --prune=true --out=release-builds

다음과 같은 메시지가 나오면 성공

Packaging app for platform darwin x64 using electron v4.0.8
Wrote new app to release-builds/scratch-app-darwin-x64

이제 위에서 알려준 디렉토리로 이동해 보면 .app 파일이 생성되어 있음을 볼 수 있다. macOS의 경우 /Application으로 복사하여 사용하면 된다.

윈도우용 앱을 패키징 할 때, macOS에서 진행하는 경우 wine 툴이 필요하다. homebrew를 이용하여 쉽게 설치가 가능하다.

$ brew install wine

설치가 완료되면, 다음과 같이 입력하여 윈도우용 앱을 패키징한다.

$ electron-packager . scratch-edubot-app --overwrite --platform=win32 --arch=x64 --icon=assets/icons/edubot_icon.ico --prune=true --out=release-builds --version-string.CompanyName="OROCA" --version-string.FileDescription="OROCA Edubot" --version-string.ProductName="Scratch Edubot"

다음과 같은 메시지가 나오고 해당 디렉토리로 이동하면 exe 파일이 생성됨을 볼 수 있다.

Packaging app for platform win32 x64 using electron v4.0.8
Wrote new app to release-builds/scratch-edubot-app-win32-x64

위 디렉토리를 압축하여 윈도우 환경에서 exe 파일을 실행한다.

끝!

Scratch 3.0 확장블럭 종류

Scratch엔 다양한 종류의 블럭들이 존재한다. 사용자가 확장 블럭을 만들 경우, 제공되는 데이터의 종류에 맞추어 블럭을 만들어야 하는데, 반드시 다음의 종류 중 하나 이어야 한다.

참고할 파일은 scratch/scratch-vm/src/extension-support/block-type.js이다.

1.BOOLEAN

육각형 모양으로 되어 있으며, 출력 결과는 true or false 두개의 값만을 가진다. 주로 논리(If else 등)에서 사용된다.

2.COMMAND

위와 아래에 다른 블럭을 연결할 수 있으며, 주로 어떠한 명령을 내리기 위해 사용한다.

3.CONDITIONAL

COMMAND 블럭의 특수한 형태로, 주어진 조건에 맞을 시, 바로 아래에 연결된 블럭을 실행한다. 조건이 맞든 맞지 않든, 다음 블럭으로 무조건 실행한다. (Non blocking 실행이라는 의미인듯)

4.HAT

위와 같이 생긴 블럭으로 스택 (블럭들이 연결되어 있는 모듬)의 처음에만 위치 할 수 있다. 한마디로 특정 기능의 맨처음에 위치

5.EVENT

HAT 블럭의 특수한 형태로, 특정 이벤트를 만족하면 실행하는 블럭. 거의 대부분의 HAT 블럭이 이와 같은 형태임.

6.LOOP

위아래 블럭 연결이 가능하고, Child 블럭을 포함하는 블럭. Child 블럭을 반복하여 실행함. 횟수나 조건식 등을 포함하여 Loop를 제어할 수 있음.

7. REPORTER

숫자나 문자등 값을 저장하고 있는 블럭. 단일값인 경우 앞쪽에 체크 박스가 존재하며 이를 클릭하면 Sprite 화면에서 값을 모니터링 가능. 배열값인 경우는 체크박스가 존재하지 않으며, 블럭을 터치하는 경우 값 확인 가능.

Scratch 3.0 확장블럭 다국어 지원

Scratch 3.0은 다국어를 지원한다. 인터페이스에서부터 블럭까지 모든 부분을 다국어를 지원하도록 만들수 있다. 이를 위해선 scratch-l10n 을 수정하여야 한다.

먼저 지난번 개발환경 구축과 마찬가지로 scratch-l10n을 클론하여 사용한다. 지난번 Scratch 개발 공간 내에 다음과 같이 입력한다.

$ git clone https://github.com/byeongkyu/scratch-l10n.git
$ cd scratch-l10n
$ npm install
$ npm link

이제 scratch-gui가 local에 있는 scratch-l10n을 사용하도록 연결하여 준다.

$ cd scratch-gui
$ npm install
$ npm link scratch-l10n scratch-blocks scratch-vm
/Users/byeongkyu/Developer/scratch/scratch-gui/node_modules/scratch-blocks -> /usr/local/lib/node_modules/scratch-blocks -> /Users/byeongkyu/Developer/scratch/scratch-blocks
/Users/byeongkyu/Developer/scratch/scratch-gui/node_modules/scratch-vm -> /usr/local/lib/node_modules/scratch-vm -> /Users/byeongkyu/Developer/scratch/scratch-vm
/Users/byeongkyu/Developer/scratch/scratch-gui/node_modules/scratch-l10n -> /usr/local/lib/node_modules/scratch-l10n -> /Users/byeongkyu/Developer/scratch/scratch-l10n

확장카드

먼저 확장카드에 대한 부분을 수정해보록 한다. 지난번 설명했던 바와 같이, 확장카드는 scratch/scratch-gui/src/lib/libraries/extensions/index.jsx 파일 내에 위치한다. Edubot의 경우엔 다음과 같이 되어 있다.

    {
        name: 'OROCA Edubot',
        extensionId: 'edubot',
        collaborator: 'OROCA',
        iconURL: edubotImage,
        insetIconURL: edubotMenuImage,
        description: (
            <FormattedMessage
                defaultMessage="Play with powerful small robot!"
                description="Description for the 'OROCA_Edubot' extension"
                id="gui.extension.edubot.description"
            />
        ),
        featured: true,
        disabled: false,
        bluetoothRequired: true,
        launchPeripheralConnectionFlow: true,
        useAutoScan: false,
        peripheralImage: edubotPeripheralImage,
        smallPeripheralImage: edubotMenuImage,
        connectingMessage: (
            <FormattedMessage
                defaultMessage="Connecting"
                description="Message to help people connect to their edubot."
                id="gui.extension.edubot.connectingMessage"
            />
        ),
        helpLink: 'https://github.com/oroca/OROCA-EduBot'
    },

여기에서 다국어 지원이 가능한 부분은 description의 “Play with powerful small robot!”과 connectingMessage의 “Connecting”이다. 이 부분은 각각 gui.extension.edubot.description과 gui.extension.edubot.connectingMessage와 같은 id를 가지고 있다.

이제 다시 scratch-l10n으로 가서 다음의 경로에 있는 파일을 수정한다.

scratch/scratch-l10n/editor/interface/en.js

파일을 열고, 임의의 곳에 다음과 같이 입력한다.

    "gui.extension.edubot.description": "Play with powerful small robot!",
    "gui.extension.edubot.connectingMessage": "Connecting",

이제 한국어를 지원하게 하려면, 같은 경로의 ko.js 파일을 열고 다음과 같이 입력한다.

    "gui.extension.edubot.description": "조그맣지만 강력한 로봇과 놀아보세요.",
    "gui.extension.edubot.connectingMessage": "연결 중",

저장한 다음, 빌드한다. 실제로 빌드를 하여야 scratch-gui에서 사용할 수 있는 파일이 만들어진다.

$ cd scratch/scratch-l10n
$ npm run-script build

빌드 과정이 완료되면, dist와 locales 디렉토리가 생성되고 위에서 수정된 내용을 반영하여 파일을 만들어준다. 이제 Scratch를 실행하고, 잘 적용되었는지 확인해본다.

다국어의 선택은 왼쪽 상단의 지구본 모양을 눌러서 선택한다.

먼저 영어 버전은 다음과 같다.

다음으로 인터페이스를 한국어로 바꾸면,

한글도 잘 적용됨을 볼 수 있다.


확장블럭

블럭들도 위와 마찬가지로 각 요소별로 id를 가지고 있다. 이 id를 각 언어에 맞추어 작성해주면 된다. 반복 작업이 대부분이므로 한가지 예만 들어보도록 한다. Edubot의 블럭 중 버튼에 관련된 다음의 블럭에 대해 한국어로 표시되게끔 해보도록 한다.

위 블럭에 대한 서술은 scratch/scratch-vm/src/extensions/scratch3_edubot/index.js 파일에 있다. getInfo() 함수 내에

                {
                    opcode: 'whenButtonPressed',
                    text: formatMessage({
                        id: 'edubot.whenButtonPressed',
                        default: 'when button pressed',
                        description: 'when the button on the edubot is pressed'
                    }),
                    blockType: BlockType.HAT,
                    arguments: {
                    }
                },
                {
                    opcode: 'isButtonPressed',
                    text: formatMessage({
                        id: 'edubot.isButtonPressed',
                        default: 'button pressed?',
                        description: 'is the button on the edubot pressed?'
                    }),
                    blockType: BlockType.BOOLEAN,
                    arguments: {
                    }
                },

와 같이 되어 있는데, 좀 전과 마찬가지로 각 텍스트에 대해 id가 부여되어 있음을 볼수 있다. 따라서 이에 대한 부분을 수정해주면 된다. 블럭에 관련한 부분은 scratch/scratch-l10n/editor/extensions 디렉토리에 있다. 먼저 영어 대한 부분부터 작성한다. en.js 파일을 열고 임의의 위치에 다음과 같이 입력한다.

    "edubot.whenButtonPressed": "when button pressed",
    "edubot.isButtonPressed": "button pressed?",

다음으로 한국어에 대한 부분은 ko.js 파일을 열고 임의의 위치에 다음과 같이 입력한다.

    "edubot.whenButtonPressed": "버튼이 눌리면",
    "edubot.isButtonPressed": "버튼이 눌러졌는가?",

수정된 파일을 저장하고, 위와 마찬가지고 빌드 작업을 진행한다.

$ cd scratch/scratch-l10n
$ npm run-script build

이제 Scratch를 다시 실행해보면,

잘 적용이 됨을 볼수 있다. 끝!

Scratch 3.0 스크래치 링크 설치 및 사용

Scratch 3.0에서 외부 기기 및 서비스를 이용하기 위해선 Scratch Link를 사용해야 한다. 물론 확장 프로그램에서 직접 하드웨어에 접속하게 해도 되지만, Scratch 개발자들은 다양한 하드웨어를 같은 프로토콜로 연결하기 위해 Scratch Link를 외부에 실행하고, 이를 통해 하드웨어와 연결한다.

Scratch와 Scratch Link는 websocket을 이용하여 통신한다. 패킷 내용은 까보면 json으로 구성되어 있다. Scratch Link는 시리얼통신 (블루투스 시리얼 포함), Bluetooth LE를 이용해 외부 하드웨어와 연결한다. Linux, macOS의 경우 위 기능을 모두 지원하나, 윈도우의 경우 10버전에서만 Bluetooth LE를 지원한다.

Scratch Link는 아직 소스가 공개되어 있지 않으므로, 설치하기 위해선 다음의 링크를 이용한다.

위 링크에서 파일을 다운로드 한 다음 설치한다.

Scratch Link를 사용하기 위해선 hosts 파일의 수정이 필요하다. 이유는 모르겠지만 Scratch Link의 서버 주소가 Local에서 실행되고 있음에도 불구하고 device-manager.scratch.mit.edu로 되어 있기 때문에 그냥 사용하게 되면 연결이 되지 않는다. 따라서 위 주소를 Local로 접속하도록 만들어야 되는데, 이를 위해 hosts 파일을 수정한다.

macOS

macOS에서 hosts 수정은 아주 간단하다. 터미널을 열고

$ sudo vi /etc/hosts
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting.  Do not change this entry.
##
127.0.0.1       localhost
127.0.0.1       device-manager.scratch.mit.edu
255.255.255.255 broadcasthost
::1             localhost

시스템 파일이기 때문에, 계정 암호가 필요하다. 위와 같이 수정하고 저장한다. 그 다음

$ ping device-manager.scratch.mit.edu
PING device-manager.scratch.mit.edu (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.045 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.053 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.107 ms
...

와 같이 나오면 성공.

Windows 10

윈도우의 hosts 파일은 C:\Windows\System32\drivers\etc에 위치한다. 하지만 직접 수정하는 것을 막아놨기 때문에, 탐색기로 위 위치로 이동한 후 hosts 파일을 임의의 위치로 복사한다.

Notepad나 기타 편집기를 이용하여, 다음과 같이 수정한다.

# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

127.0.0.1	device-manager.scratch.mit.edu

그런 다음 수정된 파일을 C:\Windows\System32\drivers\etc에 복사해 넣는다.

와 같이 나오고, 덮어 씌우겠다고 선택하면,

와 같이 나오는데, Continue를 눌러 진행한다. 그런 다음 코맨드 창을 열고 ping을 테스트해보면,

와 같이 나오면 성공.

설치된 Scratch Link를 실행하면 websocket 서버가 백그라운드에서 실행된다.

이제 사용할 준비 끝.

Scratch 3.0 확장블럭 추가 (1)

Scratch가 3.0으로 버전이 올라가면서 사용자가 확장 블럭 (Extension)을 추가하는 것이 좀더 간단해졌다. 확장 블럭은 Scratch의 기본 기능 외에 다양한 하드웨어나 클라우드 서비스의 기능을 사용할 수 있는 것인데, 메인 화면 왼쪽 하단의 버튼을 눌러 추가한다.

Scratch에 기본적으로 포함되어 있는 확장 블럭은 다음과 같다. 외부 기기나 하드웨어 클라우드 서비스 등이 포함된다.

이제 이것들 이외에 사용자만의 블럭을 추가 할 수 있다. 이 작업은 크게 두가지로 나뉠 수 있는데, 처음은 위 화면에서 본것과 같은 확장 카드를 추가하기, 다음으론 확장 블럭 생성하기이다.

먼저 사용할 이미지를 준비한다. 위 확장 카드에서 가장 크게 보이는 이미지로, 크기는 600×372 이고, png 타입이다.

준비된 이미지를 다음의 경로에 복사한다. (경로는 앞 포스트에서 설명한 경로를 기준으로 설명함).

~/Developer/scratch/scratch-gui/src/lib/libraries/extensions/edubot.png

다음으로 확장카드에 들어갈 작은 이미지와 추후 메인화면의 카테고리에 들어갈 중간 사이즈의 이미지를 준비한다. 이 이미지는 가급적이면 SVG 타입의 벡터 이미지를 사용한다. (벡터 이미지는 Illustrator, Sketch, Affinity Designer 등의 툴을 사용하면 쉽게 생성 가능)

112×92 SVG
39×39 SVG

준비된 이미지를 다음의 경로에 복사한다. (디렉토리를 생성해야함).

~/Developer/scratch/scratch-gui/src/lib/libraries/extensions/peripheral-connection/edubot/edubot-illustration.svg
~/Developer/scratch/scratch-gui/src/lib/libraries/extensions/peripheral-connection/edubot/edubot-small.svg

이제 index.jsx 파일을 수정한다. 파일의 경로는 다음과 같다.

~/Developer/scratch/scratch-gui/src/lib/libraries/extensions/index.jsx

저장된 이미지에 대한 변수 선언

import edubotImage from './edubot.png';
import edubotPeripheralImage from './peripheral-connection/edubot/edubot-illustration.svg';
import edubotMenuImage from './peripheral-connection/edubot/edubot-small.svg';

이제 중간 쯤 적당한 곳에 블럭 생성을 위한 코드 삽입.

    {
        name: 'OROCA_Edubot',
        extensionId: 'edubot',
        collaborator: 'OROCA',
        iconURL: edubotImage,
        insetIconURL: edubotMenuImage,
        description: (
            <FormattedMessage
                defaultMessage="Play with powerful small robot!"
                description="Description for the 'OROCA_Edubot' extension"
                id="gui.extension.oroca_edubot.description"
            />
        ),
        featured: true,
        disabled: false,
        bluetoothRequired: true,
        launchPeripheralConnectionFlow: true,
        useAutoScan: false,
        peripheralImage: edubotPeripheralImage,
        smallPeripheralImage: edubotMenuImage,
        connectingMessage: (
            <FormattedMessage
                defaultMessage="Connecting"
                description="Message to help people connect to their edubot."
                id="gui.extension.edubot.connectingMessage"
            />
        ),
        helpLink: 'https://github.com/oroca/OROCA-EduBot'
    },

각 설정값의 의미는 다음과 같다.

이외에도

  • extensionId: 확장블럭에 대한 고유 이름
  • launchPeripheralConnectionFlow: 선택시 기기를 연결하기 위한 다이얼로그를 실행할 지 여부
  • useAutoScan: 다이얼로그를 띄운 뒤, 자동 스캔 시작 여부

일단 저렇게 수정한 파일을 저장한다. 다음으로 확장블럭에 대한 파일을 작성한다. 해당 경로는 다음과 같다.

~/Developer/scratch/scratch-vm/src/extensions

위 디렉토리에 확장 블럭의 파일을 위한 디렉토리를 생성하고, index.js 파일을 생성한다. index.js 파일의 템플릿은 ~/Developer/scratch/scratch-gui/src/examples/extensions/example-extension.js 를 참고한다.

일단 여기까지!.

Scratch 3.0 소개

Scratch (https://scratch.mit.edu)는 전세계적으로 가장 널리 알려진 블럭 코딩 툴이다. 다른 거의 대부분의 블럭 코딩 도구들이 참조를 하고 있고, 거의 유사한 형태로 개발되고 있기도 하다.

MIT 미디어랩의  Lifelong Kindergarten Group에서 프로젝트로 개발되고 있고, 이전 버전은 사용해보지 않아서 모르겠지만 3.0은 오픈소스 형태로 개발중이며, 사용하고 있는 거의 모든 소스를 공개해 놓고 있다.

블럭 관련한 부분은 구글 Blockly를 가져와 디자인, 일부 동작 관련한 부분을 수정하여 사용하고 있으며, 나머지는 그룹에서 자체 개발 중인듯 하다.

사용하고 싶은 기업이나 개발자들은 자유롭게 복사해서 수정, 재배포 등이 가능하다. Scratch의 스크린샷을 책이나 발표자료에 사용하는 것도 가능하며, 브로셔 등에도 삽입이 가능하다. 다만 각 자료에 다음과 같은 내용을 담아주길 권고하고 있다.

“Scratch is a coding language and online community where you can create your own interactive stories, games, and animations — and share your creations with others around the world. As young people create and share Scratch projects, they learn to think creatively, reason systematically, and work collaboratively. Scratch is a project of the Scratch Foundation in collaboration with the Lifelong Kindergarten group at the MIT Media Lab. It is available for free at https://scratch.mit.edu

Scratch를 사업화에 사용하려는 기업에서 소스를 가져와 수정하고 이를 상용화 하여도 문제가 없다. 자세한 라이센스 및 사용 관련한 내용은 https://scratch.mit.edu/info/faq 를 참조하면 된다.

실제 동작하는 데모 버전을 구경하고 싶다면 https://llk.github.io/scratch-gui/develop/ 에서 사용해볼 수 있다.