Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
e43595c
엔트리-파로듈 하드웨어 로직
AnnaJinK Mar 9, 2023
944692c
하드웨어로 부터 버퍼를 받아서 \r\n 기준으로 버퍼를 잘라 주는 기능추가
AnnaJinK Mar 15, 2023
edc87a9
Update robotry_parodule.js
AnnaJinK Mar 15, 2023
a14d1db
엔트리에서 받은데이터 처리 명령어와 제어문 처리 구현 버퍼 합성은 아직
AnnaJinK Mar 30, 2023
0ee2993
타이머와 데이터 변화 확인해서 정해진 횟수만큼 버퍼 생성
AnnaJinK Mar 30, 2023
bbc65bd
데이터 전송 간격 10ms
AnnaJinK Apr 6, 2023
a7e0e7d
버퍼 상태를 업데이트하여 한 줄로 전송하도록 함
AnnaJinK Apr 6, 2023
5a79e77
Update robotry_parodule.js
AnnaJinK Apr 7, 2023
5c8c56e
Merge branch 'entrylabs:develop-hw' into develop-hw
AnnaJinK Apr 10, 2023
1ea7429
Update robotry_parodule.js
AnnaJinK Apr 12, 2023
208c57d
최종 버퍼 1회만 전송하도록
AnnaJinK Apr 14, 2023
64ebafd
장치 직접 선택 없이 PID 로 장치 연결 하도록 함
AnnaJinK Apr 19, 2023
52e6430
엔트리로 부터 넘어오는 터미널 넘버와 미들웨어에서 사용하는 배열 구조가 달라 버퍼 업데이트가 잘못되는 문제 수정
AnnaJinK Apr 20, 2023
f3c32da
Update robotry_parodule.json
AnnaJinK Apr 24, 2023
24fb594
Merge branch 'develop-hw' of https://github.com/robotryDev/entry-hw i…
AnnaJinK Aug 1, 2023
b02db81
센서 데이터 수신 모니터링
AnnaJinK Aug 3, 2023
dfe19a8
하드웨어 로직에서 센서 데이터를 처리할 수 있도록 함
AnnaJinK Aug 8, 2023
b587966
모듈 이미지 수정
AnnaJinK Aug 8, 2023
7f8c23a
Update robotry_robitStage.js
AnnaJinK Aug 8, 2023
bca0e29
하드웨어로 부터 모듈의 종류 데이터를 엔트리로 넘겨줄 수 있도록 함. 기본적으로 1분에 한번씩 확인하도록 하고 사용자가 모듈…
AnnaJinK Aug 9, 2023
c24d114
Update robotry_parodule.js
AnnaJinK Aug 11, 2023
2ab69e3
시리얼 통신부 개선
AnnaJinK Aug 15, 2023
7a89b45
Update robotry_parodule.js
AnnaJinK Aug 16, 2023
3ea47a0
펌웨어 업데이트 도구 추가
AnnaJinK Aug 24, 2023
52a41c7
알수없는 모듈 상태 추가
AnnaJinK Aug 24, 2023
eefab1f
시러얼 포트 닫을때 신호 전송
AnnaJinK Aug 29, 2023
962bd28
가독성을 위해 십진수 대신 16진수로 표기
AnnaJinK Aug 30, 2023
d965873
Update robotry_parodule.js
AnnaJinK Aug 30, 2023
e810811
파로듈 펌웨어 업데이트 도구
AnnaJinK Aug 30, 2023
c44fa76
프로그램 이름 변경
AnnaJinK Aug 30, 2023
acdcae1
드라이버 대신 펌웨어 도구로 표기
AnnaJinK Aug 30, 2023
3d69669
주석 추가
AnnaJinK Aug 30, 2023
7f6b6d3
공백제거
AnnaJinK Aug 30, 2023
71525c3
공백 정리
AnnaJinK Aug 30, 2023
736e1eb
Update robotry_parodule.js
AnnaJinK Aug 30, 2023
8dab1e7
var to let, " to '
AnnaJinK Aug 30, 2023
b4c1608
=> 로 수정
AnnaJinK Aug 30, 2023
adbb2a5
Update robotry_parodule.js
AnnaJinK Aug 30, 2023
6c10619
Update robotry_parodule.js
AnnaJinK Aug 30, 2023
00f0ddf
컨벤션 정리
AnnaJinK Aug 30, 2023
ad6a414
Update robotry_parodule.js
AnnaJinK Aug 30, 2023
f918356
타임아웃 수정
AnnaJinK Aug 30, 2023
d2a99f0
오작동 수정
AnnaJinK Aug 30, 2023
de4e80a
없어도 동작에 문제없음
AnnaJinK Aug 30, 2023
c567236
var -> let 변경
AnnaJinK Aug 30, 2023
9b7d595
펌웨어 도구 업데이트
AnnaJinK Aug 30, 2023
6cd80ee
LED 픽셀로 변경
AnnaJinK Aug 31, 2023
e8ecc41
듀레이션 최적화
AnnaJinK Sep 11, 2023
c13b863
동일 한 데이터는 1초에 한번은 갱신하도록 함
AnnaJinK Sep 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added app/drivers/robotry/Parodule_Firmware.exe
Binary file not shown.
304 changes: 304 additions & 0 deletions app/modules/robotry_parodule.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,304 @@
const BaseModule = require('./robotry');
class Parodule extends BaseModule {
// 클래스 내부에서 사용될 필드들을 이곳에서 선언합니다.
constructor() {
super();
this.sp = null;
this.controlTypes = {
DIGITAL: 0,
ANALOG: 1,
STRING: 2,
};
this.UNKNOWN = 207;
this.NONE = 208;
this.PIXEL = 209;
this.MOTOR = 210;
this.BUZZER = 211;
this.paroduleData = {
SENSOR: {
'0': 0,
'1': 0,
'2': 0,
'3': 0,
},
MODULE: {
'0': 0,
'1': 0,
'2': 0,
'3': 0,
},
MODULE1: '픽셀',
MODULE2: '픽셀',
MODULE3: '픽셀',
MODULE4: '픽셀',
};
this.isConnect = false;
this.cmdTime = 0;
this.portTimeList = [0, 0, 0, 0, 0];
this.terminal = [0xee, 0xee, 0xee, 0xee, '\n']; // 터미널 버퍼 저장 공간
this.moduleOff = [0xff, 0x55, 0xc8, 0xc8, 0xc8, 0xc8, '\n']; // 모듈 종료 인터럽트
// this.bleDisconCode = new Buffer('123\r\n');
this.paroduleEntry = new Buffer('entry\r\n'); // 엔트리 모듈 내부 셰이킹
this.paroduleInit = [0xff, 0x55, 0xff, 0xff, 0xff, 0xff, 0x0a]; // 엔트리용 모듈 인식 코드
this.paroduleClose = new Buffer('spclose\r\n'); // 시리어 포트 종료 신호
this.isSend = true;
this.pre_time = 0;
}
/*
최초에 커넥션이 이루어진 후의 초기 설정.
handler 는 워크스페이스와 통신하 데이터를 json 화 하는 오브젝트입니다. (datahandler/json 참고)
config 은 module.json 오브젝트입니다.
*/
init(handler, config) {
this.handler = handler;
this.config = config;
}
setSerialPort(sp) {
let self = this;
this.sp = sp;
}
afterConnect(that, cb) {
that.connected = true;
if (cb) {
cb('connected');
}
}
connect() {
this.isConnect = true;
}
/*
연결 후 초기에 송신할 데이터가 필요한 경우 사용합니다.
requestInitialData 를 사용한 경우 checkInitialData 가 필수입니다.
이 두 함수가 정의되어있어야 로직이 동작합니다. 필요없으면 작성하지 않아도 됩니다.
*/
requestInitialData() {
return this.paroduleEntry;
}
// 연결 후 초기에 수신받아서 정상연결인지를 확인해야하는 경우 사용합니다.
checkInitialData(data, config) {
if (data) {
return true;
}
else {
return false;
}

}
// 주기적으로 하드웨어에서 받은 데이터의 검증이 필요한 경우 사용합니다.
validateLocalData(data) {
return true;
}
/*
하드웨어 기기에 전달할 데이터를 반환합니다.
slave 모드인 경우 duration 속성 간격으로 지속적으로 기기에 요청을 보냅니다.
*/
requestLocalData() {
// 하드웨어로 보낼 데이터 로직
if (!this.isConnect) {
return;
}
if (this.sendBuffers.length > 0) {
if (this.sp) {
this.sp.write(this.sendBuffers.shift(), () => {
this.sp.drain(() => {
});
});
}
}
return null;
}

// 하드웨어에서 온 데이터 처리
handleLocalData(data) {
let self = this;
let datas = this.getDataByBuffer(data);
// 데이터 처리 로직
datas.forEach((data) => {
// 센서 데이터만 걸러냄
if (data.length < 6) {
return;
}
else if (data[0] == 0xff && data[1] == 0x44) {
//console.log(data);
let temp = ['', '', '', ''];
let readData = data.subarray(2, data.length);
for (let i = 0; i < 4; i++) {
self.paroduleData.MODULE[i] = readData[i];
}
for (let i = 0; i < 4; i++) {
let value = self.paroduleData.MODULE[i];
if (value == this.PIXEL) {
temp[i] = '픽셀';
}
else if (value == this.MOTOR) {
temp[i] = '모터';
}
else if (value == this.BUZZER) {
temp[i] = '부저';
}
else if (value == this.NONE) {
temp[i] = '없음';
} else {
temp[i] = '모름';
}
}
self.paroduleData.MODULE1 = temp[0];
self.paroduleData.MODULE2 = temp[1];
self.paroduleData.MODULE3 = temp[2];
self.paroduleData.MODULE4 = temp[3];
}
else if (data[0] == 0xff && data[1] == 0x66) {
let readData = data.subarray(2, data.length);
for (let i = 0; i < 4; i++) {
self.paroduleData.SENSOR[i] = readData[i];
}
}
});
}
// 엔트리로 전달할 데이터
requestRemoteData(handler) {
let self = this;
if (!self.paroduleData) {
return;
}
this.lastSendTime = this.lastTime;
Object.keys(this.paroduleData).forEach(function (key) {
if (self.paroduleData[key] != undefined) {
handler.write(key, self.paroduleData[key]);
self.canSendData = false;
}
});
}
// 엔트리에서 받은 데이터에 대한 처리
handleRemoteData(handler) {
let self = this;
let cmdDatas = handler.read('CMD');
let getDatas = handler.read('GET');
let setDatas = handler.read('SET');
let time = handler.read('TIME');
let buffer = new Buffer([]);
// 입력 모듈일 경우
if (getDatas) {
}
// 출력 모듈일 경우
if (setDatas) {
let setKey = Object.keys(setDatas);
setKey.forEach(function (port) {
let data = setDatas[port];
if (data) {
if (self.portTimeList[port] < data.time) {
self.portTimeList[port] = data.time
if (!self.isRecentData(port, data.type, data.data)) {
self.recentCheckData[port] = {
type: data.type,
data: data.data
}
self.updateTerminalBuffer(port);
buffer = new Buffer(self.makeOutputBuffer(data.type, null));
}
}
}
});

}
// 커맨드 명령어
if (cmdDatas) {
if (self.cmdTime < cmdDatas.time) {
self.cmdTime = cmdDatas.time;

if (!self.isRecentData(cmdDatas.data)) {
self.recentCheckData = {
data: cmdDatas.data
}
buffer = new Buffer(cmdDatas.data);
}
}
}
if (buffer.length) {
this.sendBuffers.push(buffer);
}
else {
buffer = new Buffer([0xff, 0x55, 0xff, 0xff, 0xff, 0xff, 0x0a]);
if (this.isSend) {
this.isSend = false;
this.sendBuffers.push(buffer);
}
}
}
// recentCheckData 리스트에 있는 경우 true 반환 아니면 false
isRecentData(port, type, data) {
let isRecent = false;
const interval = 1000;

if (port in this.recentCheckData) {
if (this.recentCheckData[port].type === type && this.recentCheckData[port].data === data) {
isRecent = true;
if (Date.now() - this.pre_time > interval) { // 같은 데이터가 연속인 경우 1초에 한번만 전송
this.pre_time = Date.now();
isRecent = false;
}
else {
isRecent = true;
}
}
}
return isRecent;
}

updateTerminalBuffer(port) {
if (this.recentCheckData[port].data === 0) {
this.terminal[port] = 238;
}
else {
this.terminal[port] = this.recentCheckData[port].data;
}
}
makeOutputBuffer(dataType, data) {
let buffer;
if (dataType == this.controlTypes.STRING) {
buffer = new Buffer(data);
}
else if (dataType == this.controlTypes.DIGITAL) {
buffer = new Buffer([
0xff,
0x55,
this.terminal[0],
this.terminal[1],
this.terminal[2],
this.terminal[3],
0x0a
]);
}
else {
}
return buffer;
}
// '\r\n' 을 기준으로 버퍼를 자른다
getDataByBuffer(buffer) {
let datas = [];
let lastIndex = 0;
buffer.forEach(function (value, idx) {
if (value == 13 && buffer[idx + 1] == 10) {
datas.push(buffer.subarray(lastIndex, idx));
lastIndex = idx + 2;
}
});
return datas;
}
// 연결 해제되면 시리얼 포트 제거
disconnect(connect) {
const spClose = this.paroduleClose;
if (this.sp) {
this.sp.write(spClose, () => {
this.sp.drain(() => {
connect.close();
this.isConnect = false;
})
})
}
}
// 리셋
reset() {
}
}
module.exports = new Parodule();
29 changes: 29 additions & 0 deletions app/modules/robotry_parodule.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"id": "4B0201",
"name": {
"en": "Parodule",
"ko": "파로듈"
},
"category": "board",
"platform": ["win32", "darwin"],
"icon": "robotry_parodule.png",
"module": "robotry_parodule.js",
"url": "http://parob.io",
"email": "[email protected]",
"reconnect": true,
"driver": [{
"win32-x64": "robotry/Parodule_Firmware.exe",
"translate": "펌웨어 업데이트"
}],
"hardware": {
"type": "serial",
"control": "slave",
"duration": 25,
"pnpId": "1001",
"flowControl": "hardware",
"baudRate": 115200,
"lostTimer": 1000,
"byteDelimiter": [13, 10],
"firmwarecheck": false
}
}
Binary file added app/modules/robotry_parodule.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading