Skip to content

Commit a7d56e7

Browse files
authored
Merge pull request #88 from entrylabs/feature/hwLite
하드웨어 웹연결 가이드 문서 추가
2 parents 7c12567 + 834fac3 commit a7d56e7

File tree

3 files changed

+278
-0
lines changed

3 files changed

+278
-0
lines changed
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
---
2+
layout: page
3+
title: 브라우저로 연결하기에 하드웨어 등록
4+
type: guide
5+
category: 'Entry HW'
6+
order: 6
7+
---
8+
9+
## 브라우저로 연결하기란?
10+
'브라우저로 연결하기'이하 '하드웨어 웹연결'은 [web serial api](https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API)을 사용하여 브라우저와 하드웨어 기기를 직접 연결하는 기능입니다.
11+
기존의 엔트리 하드웨어는 "사용자 기기 <=> [Entry HW 프로그램](https://playentry.org/download/hardware) <=> [엔트리 만들기 웹 페이지](https://playentry.org/ws/new)" 의 구조를 가지고 있습니다.
12+
하드웨어 웹연결은 Entry HW 프로그램을 사용하지 않고 "사용자 기기 <=> 엔트리 만들기 웹 페이지"의 구조를 가집니다.
13+
14+
사용자 입장에서는 사용이 간편하고, 개발자 입장에서도 [entry-js](https://github.com/entrylabs/entryjs)의 코드만 관리하면 된다는 장점이 있습니다.
15+
하지만, 펌웨어와 드라이버 제공이 불가능하기에 하드웨어 제조사에서 별도의 안내를 해야하고 실험적이 기능이기에 연결이 불안정할 수도 있습니다
16+
17+
<br>
18+
19+
## 유의사항
20+
- 반드시 **자사 하드웨어 관련 파일만 수정**을 부탁드립니다. hw_Lite.js 나 기타 공용파일들 수정은 반영이 어렵습니다.
21+
- 하드웨어 웹연결에서는 기본적으로 펌웨어를 제공하지 않습니다. WS의 '펌웨어 다운로드' 버튼은 .hex파일을 다운로드하여 사용자가 직접 펌웨어 업데이트가 가능한 기기를 위한 기능입니다.
22+
- 하드웨어 웹연결 기능은 개발 초기 단계로 추후 **제공 함수나 연결 라이프사이클이 변경될 수 있습니다**. 경우에 따라서는 제조사측 코드를 수정해야 할 수 있으므로 미리 유의 부탁드립니다.
23+
24+
<br>
25+
26+
## PR 파일 간략 설명
27+
![HwLite_select1](/images/entry-hw/HwLite_select1.png)
28+
29+
이 단원에서는 최종적으로 제조사가 entryjs에 PR해야할 파일 작성시 유의사항과 간략한 역할을 기술합니다.
30+
하드웨어 웹연결을 지원하기 위해선 아래 3종류의 파일이 필수적으로 추가되어야 합니다. 아래 3파일을 작성후 entryjs의 develop-hw로 PR부탁드립니다.
31+
32+
### block_모듈명 _lite.js
33+
- 반드시 entryjs > src > playground > blocks > hardwareLite 하위에 위치해야합니다.
34+
- 파일명은 반드시 block_ 모듈명 _lite.js 이어야 합니다.
35+
- 이 파일에서 하드웨어 웹연결에 필요한 정보를 담고있는 모듈클래스를 정의하게 됩니다.
36+
- 기존 하드웨어 연결에서 entryjs의 block_모듈명.js와 entry-hw의 모듈명.js의 역할을 모두 가지고 있습니다.
37+
38+
### metadata_모듈명 _lite.json
39+
- 반드시 entryjs > src > playground > blocks > hardwareLite 하위에 위치해야합니다.
40+
- 파일명은 반드시 metadata_ 모듈명 _lite.json 이어야 합니다.
41+
- 웹연결 모듈에 대한 메타데이터를 가지고 있습니다.
42+
- 이 파일의 moduleId와 block_ 모듈명 _lite.js 의 클래스 내 id는 반드시 일치해야 합니다.(포맷이 다르므로 다른 하드웨어 웹연결 파일들을 예시로 참고해 주세요.)
43+
- 이 파일의 title, description은 WS에서 '브라우저로 연결하기' 클릭시 나타나는 위의 이미지화면에서 모듈카드의 정보를 가지고 있습니다.
44+
45+
### 모듈명.png
46+
- 반드시 entryjs > images > hw_lite 하위에 위치해야 합니다.
47+
- '브라우저로 연결하기' 클릭시 나타나는 위의 이미지화면에서 보여지는 이미지 파일입니다.
48+
- 파일명은 block_ 모듈명 _lite.js 에서 정의한 클래스 생성자의 this.imageName과 일치해야 합니다.
49+
50+
<br>
51+
52+
## block_ 모듈명 _lite.js 구조 설명
53+
WS가 실행되었을경우, Entry.모듈클래스 를 추가하는 함수가 즉시 실행됩니다.
54+
이 파일에 정의되는 모듈클래스 구조와 역할은 다음과 같습니다.
55+
56+
### 모듈클래스
57+
58+
``` javascript
59+
'use strict';
60+
61+
(function () {
62+
Entry.ArduinoLite = new (class ArduinoLite {
63+
constructor() {
64+
this.id = '010101'; // id는 6자리 모두 입력해야 합니다.
65+
this.name = 'ArduinoLite';
66+
this.url = 'http://www.arduino.cc/';
67+
this.imageName = 'arduinolite.png';
68+
this.title = {
69+
ko: '아두이노 우노',
70+
en: 'Arduino Uno',
71+
};
72+
this.duration = 32; // 엔트리js에서 기기와 통신하는 함수를 호출하는 duration 간격입니다.
73+
this.blockMenuBlocks = [
74+
'arduinolite_get_number_sensor_value',
75+
'arduinolite_get_digital_value',
76+
];
77+
this.portData = {
78+
baudRate: 9600,
79+
duration: 32, // web serial api에서 기기와 통신하는 duration 간격입니다.
80+
dataBits: 8,
81+
parity: 'none',
82+
stopBits: 1,
83+
bufferSize: 512,
84+
constantServing: true,
85+
};
86+
this.readablePorts = [];
87+
this.setZero();
88+
}
89+
90+
setZero() {
91+
this.port = new Array(14).fill(0);
92+
this.digitalValue = new Array(14).fill(0);
93+
this.remoteDigitalValue = new Array(14).fill(0);
94+
this.analogValue = new Array(6).fill(0);
95+
this.readablePorts = _range(0, 19);
96+
97+
if (Entry.hwLite && Entry.hwLite.serial) {
98+
Entry.hwLite.serial.update();
99+
}
100+
}
101+
102+
// 디바이스에서 값을 읽어옵니다.
103+
handleLocalData(data) {}
104+
105+
//디바이스에 값을 씁니다.
106+
requestLocalData() {
107+
const queryString = [];
108+
// ...
109+
return queryString;
110+
}
111+
112+
setLanguage() {
113+
return {
114+
ko: {
115+
template: {
116+
arduinolite_text: '%1',
117+
arduinolite_get_sensor_number: '%1',
118+
arduinolite_get_port_number: '%1',
119+
},
120+
Device: {
121+
arduinolite: '아두이노',
122+
},
123+
Menus: {
124+
arduinolite: '아두이노',
125+
},
126+
},
127+
en: {
128+
template: {
129+
arduinolite_text: '%1',
130+
arduinolite_get_sensor_number: '%1',
131+
arduinolite_get_port_number: '%1',
132+
},
133+
Device: {
134+
arduinolite: 'arduinolite',
135+
},
136+
Menus: {
137+
arduinolite: 'ArduinoLite',
138+
},
139+
},
140+
};
141+
}
142+
143+
getBlocks() {
144+
return {
145+
arduinolite_get_sensor_number: {
146+
color: EntryStatic.colorSet.block.default.HARDWARE,
147+
outerLine: EntryStatic.colorSet.block.darken.HARDWARE,
148+
skeleton: 'basic_string_field',
149+
statements: [],
150+
params: [
151+
{
152+
type: 'Dropdown',
153+
options: [
154+
['0', 'A0'],
155+
['1', 'A1'],
156+
['2', 'A2'],
157+
['3', 'A3'],
158+
['4', 'A4'],
159+
['5', 'A5'],
160+
],
161+
value: 'A0',
162+
fontSize: 11,
163+
bgColor: EntryStatic.colorSet.block.darken.HARDWARE,
164+
arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE,
165+
},
166+
],
167+
events: {},
168+
def: {
169+
params: [null],
170+
},
171+
paramsKeyMap: {
172+
PORT: 0,
173+
},
174+
func(sprite, script) {
175+
return script.getStringField('PORT');
176+
},
177+
},
178+
// ...
179+
};
180+
}
181+
})();
182+
})();
183+
184+
module.exports = Entry.ArduinoLite;
185+
186+
187+
188+
```
189+
190+
- constructor
191+
- imageName : 샘플파일 이미지와 이름이 같아야 합니다
192+
- portData : web-serial api를 사용해 브라우저로 기기와 통신하기위한 세팅값입니다. 연결이 불안정한경우가 아니라면 가급적 수정하지 않는것을 추천드립니다.
193+
- duration : 기기와 통신하는 간격입니다.(ms단위)
194+
- blockMenuBlocks : 블럭명세 정보입니다.
195+
196+
- get monitorTemplate() : WS에서 하드웨어 연결시 좌측 ''오브젝트 추가하기'' 하단의 4번째 탭에 보여지는 센서 모니터링 툴을 사용하기 위한 함수입니다. 초기값 세팅 역할을 합니다.
197+
198+
- getMonitorPort() : monitorTemplate()와 마찬가지로 모니터링 툴용 함수입니다. 실시간 값 갱신을 위한 함수입니다.
199+
200+
- setZero() : 연결시작 및 연결해제시 기기상태를 초기화하기 위한 함수입니다.
201+
202+
- handleLocalData(data) : 기기로부터 값을 읽어서 WS에 반영하는 함수입니다. (기기로부터 값 읽음) this.portData.constantServing일 경우 사용합니다.
203+
204+
- requestLocalData() : WS의 블록동작의 명령을 기기에게 쓰는 함수입니다. (기기에 값 쓰기) this.portData.constantServing일 경우 사용합니다.
205+
206+
- getBlocks() : 블럭 상세 정보 및 로직을 반환하는 함수입니다.
207+
208+
209+
210+
<br>
211+
212+
## 통신방법
213+
디바이스와 통신하는 방법에는 아래 2가지가 있습니다.
214+
215+
### 지속 통신
216+
- 사용자 액션(블럭 실행)이 없어도 항상 지정된 duration간격만큼 지속통신하는 방법입니다.
217+
- block_ 모듈명 _lite.js 의 생성자에서 this.duration값을 지정하고, this.portData.constantServing 를 true로 세팅하게되면 handleLocalData(data)함수와 requestLocalData() 함수가 자동으로 실행되게 됩니다.
218+
- ex. [block_arduino_lite.js](https://github.com/entrylabs/entryjs/blob/develop/src/playground/blocks/hardwareLite/block_arduino_lite.js), [block_sensorboard_lite](https://github.com/entrylabs/entryjs/blob/develop/src/playground/blocks/hardwareLite/block_sensorboard_lite.js), [block_hamster_lite](https://github.com/entrylabs/entryjs/blob/develop/src/playground/blocks/hardwareLite/block_hamster_lite.js)
219+
220+
### 단건 통신
221+
- 사용자 액션(블럭 실행)이 있을때만 통신하는 방법입니다.
222+
- 필요할 때만 통신하므로 일반적으로 지속통신방법보다 부하가 적지만, '계속 반복하기' 블럭 안에서 하드웨어 블럭을 사용하는 것처럼(초당 60번 호출) 단기간에 많은 통신을 할 경우 문제가 발생할 수도 있습니다.
223+
- Entry.hwLite.serial.sendAsyncWithThrottle(기기에 입력할 값 : buffer | string, 리턴값 여부 | boolean)으로 호출할 수 있습니다. 첫번째 파라미터에는 기기에 입력할 버퍼, 두번째 파라미터를 false로 할 경우 기기로부터 받는 응답값을 받지 않습니다. 상세구조는 Entry.hwLite.serial.sendAsync() 함수를 확인 부탁드립니다.
224+
- ex. [block_microbit2_lite](https://github.com/entrylabs/entryjs/blob/develop/src/playground/blocks/hardwareLite/block_microbit2_lite.js)
225+
226+
#### Entry.hwLite.serial.sendAsyncWithThrottle
227+
- Return : 기기로부터 리턴된 value값
228+
229+
| 파라미터 | 타입 | 선택적 | 설명 |
230+
| ---------- | ---------------- | ------ | ------------------------------------------------------------ |
231+
| data | Buffer \| string | | 기기에 송신할 데이터입니다. string 타입일경우 utf8로 인코딩되어 송신됩니다. |
232+
| isResetReq | boolean | ✔️ | 데이터를 송신한 이후에 기기로부터 응답을 받지 않고 함수를 종료합니다. |
233+
| callback | Function | ✔️ | 함수가 존재할경우, 송수신 완료 후 callback(value)값을 리턴합니다. |
234+
235+
236+
<br>
237+
238+
## 기타 웹연결 관련 함수들
239+
### Entry.playground.addHardwareLiteModule
240+
웹연결에 사용할 모듈을 선택하는 함수입니다.
241+
파라미터로 Entry.모듈명(ex. Entry.Neobot)을 넣으면 해당 하드웨어가 선택됩니다.
242+
실제 운영 엔트리WS에서는 '브라우저로 연결하기' => '팝업에서 모듈 선택 후 불러오기' 까지 진행하면 자동으로 이 함수가 실행되지만, entryjs만 사용한 개발환경에서는 위 팝업을 사용할 수 없기 때문에 직접 함수를 실행시켜주셔야 합니다.
243+
244+
245+
246+
| 파라미터 | 타입 | 선택적 | 설명 |
247+
| -------- | ------------------------------------------------------------ | ------ | ------------------------------- |
248+
| module | [EntryHardwareBlockModule](https://github.com/entrylabs/entryjs/blob/edb5380602a0f035fb2b20eb9d2b7c8f1247f15d/types/index.d.ts#L180) | | 웹연결에 사용할 모듈객체입니다. |
249+
250+
251+
252+
### Entry.hwLite.connect
253+
웹연결 연결실행 함수입니다.
254+
255+
### Entry.hwLite.disconnect
256+
웹연결 연결해제 함수입니다. 가급적 직접 호출보다는 '연결 해제하기' 버튼을 사용해주세요.
257+
258+
### Entry.hwLite.serial.handleConnectErrorInEngineRun
259+
연결중 기기가 멈추거나 화면이 멈추는 등, 강제종료가 필요한 상황에 사용하는 함수입니다.
260+
261+
### Entry.hwLite.getConnectFailedMenu
262+
연결실패화면을 출력해야 할 때 사용합니다.
263+
264+
![HwLite_failedMenu1](/images/entry-hw/HwLite_failedMenu1.png)
265+
266+
<br>
267+
268+
## 테스트하기
269+
다음 2가지 방법으로 테스트하실수 있습니다.
270+
271+
A. entryjs와 entry-tool을 함께 적용하고 계시다면 어려움없이 하드웨어 탭에서 '브라우저로 연결하기' > 모듈선택 > 포트선택으로 테스트하실수 있습니다.
272+
B. entryjs에서 yarn serve만으로 테스트하고 계시다면, 아래 순서로 진행해주세요
273+
- 크롬 개발자도구에서 `Entry.playground.addHardwareLiteModule(Entry.모듈클래스명);`를 입력합니다. 사용자가 팝업창에서 해당모듈을 선택했을때 실행되는 동작입니다.
274+
- 크롬 개발자도구에서 `Entry.hwLite.connect();`를 입력합니다. 사용자가 연결하기 버튼을 클릭할때 실행되는 동작입니다.
275+
- 모듈이 연결된 포트를 선택하고 완료를 누르면 블록이 출력됩니다.
276+
277+
혹시 연결이 정상적으로 진행되지 않는다면 Entry.모듈명과 Entry.HARDWARE_LITE_LIST['모듈ID'] 이 존재하는지 확인 부탁드립니다, 둘중 하나라도 없다면 정상동작하지 않습니다. 모듈의 name, id 등을 체크해주세요.
278+
67.7 KB
Loading
1.54 MB
Loading

0 commit comments

Comments
 (0)