From 5c4aa5e0b2bca9d323eb5b48e24017a232690999 Mon Sep 17 00:00:00 2001 From: TaeJuneJoung Date: Tue, 27 Aug 2024 18:33:13 +0900 Subject: [PATCH 01/21] =?UTF-8?q?:sparkles:=EB=84=A4=EC=98=A4=ED=94=BD?= =?UTF-8?q?=EC=85=80=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocks/hardware/block_neo_cannon.js | 446 +++++++++++++++++- .../hardwareLite/block_neo_cannon_lite.js | 368 ++++++++++++++- 2 files changed, 793 insertions(+), 21 deletions(-) diff --git a/src/playground/blocks/hardware/block_neo_cannon.js b/src/playground/blocks/hardware/block_neo_cannon.js index d242d9f6b7..b665cb9207 100644 --- a/src/playground/blocks/hardware/block_neo_cannon.js +++ b/src/playground/blocks/hardware/block_neo_cannon.js @@ -19,6 +19,7 @@ Entry.NeoCannon = { d9: 0, d10: 0, angleState: 0, + neopixel: 0, }, setZero() { let portMap = Entry.NeoCannon.PORT_MAP; @@ -91,6 +92,11 @@ Entry.NeoCannon.setLanguage = function() { neo_cannon_rgb_led_color_picker: 'RGB LED %1 %2', neo_cannon_rgb_led_pwm: 'RGB LED 빨강 %1 초록 %2 파랑 %3 %4', neo_cannon_rgb_led_off: 'RGB LED 끄기 %1', + neo_cannon_neopixel_color_picker: 'Neopixel %1번 %2 (으)로 켜기 %3', + neo_cannon_neopixel: 'Neopixel %1번 빨 %2 녹 %3 파 %4 (으)로 켜기 %5', + neo_cannon_neopixel_color_picker_all_on: 'Neopixel 전체 %1 (으)로 켜기 %2', + neo_cannon_neopixel_all_on: 'Neopixel 전체 빨 %1 녹 %2 파 %3 (으)로 켜기 %4', + neo_cannon_neopixel_all_off: 'Neopixel 전체 끄기 %1', }, Helper: { @@ -116,7 +122,17 @@ Entry.NeoCannon.setLanguage = function() { 'RGB LED를 색을 선택하여 원하는 색상을 나타낼 수 있습니다.
(주의, LED모드로 진행해주세요.)', neo_cannon_rgb_led_pwm: 'RGB LED에 세기값(0~255)을 주어 원하는 색상을 나타낼 수 있습니다.
(주의, LED모드로 진행해주세요.)', - neo_cannon_rgb_led_off: 'RGB LED를 끌 수 있습니다.', + neo_cannon_rgb_led_off: + 'RGB LED를 끌 수 있습니다.', + neo_cannon_neopixel_color_picker: + '색을 보고 RGB색상을 정하여 정해진 네오픽셀를 켤 수 있습니다.
(참고, 네오픽셀번호는 0번부터 17번까지 입니다.)', + neo_cannon_neopixel: + '정해준 네오픽셀 번호에 빨강, 파랑, 초록의 색을 넣고 조합하여 네오픽셀를 켤 수 있습니다.
(참고, 네오픽셀번호는 0번부터 17번까지 입니다.)', + neo_cannon_neopixel_color_picker_all_on: + '색을 보고 RGB색상을 정하여 모든 네오픽셀를 켤 수 있습니다.', + neo_cannon_neopixel_all_on: + '빨강, 파랑, 초록의 색을 넣고 조합하여 모든 네오픽셀를 켤 수 있습니다.', + neo_cannon_neopixel_all_off: '모든 네오픽셀를 끌 수 있습니다.', }, }, en: { @@ -135,6 +151,11 @@ Entry.NeoCannon.setLanguage = function() { neo_cannon_rgb_led_color_picker: 'RGB LED %1 %2', neo_cannon_rgb_led_pwm: 'RGB LED R %1 G %2 B %3 %4', neo_cannon_rgb_led_off: 'RGB LED OFF', + neo_cannon_neopixel_color_picker: 'Neopixel number %1 turn on %2 %3', + neo_cannon_neopixel: 'Neopixel number %1 turn on R %2 G %3 B %4 %5', + neo_cannon_neopixel_color_picker_all_on: 'All Neopixel turn on %1 %2', + neo_cannon_neopixel_all_on: 'All Neopixel turn on R %1 G %2 B %3 %4', + neo_cannon_neopixel_all_off: 'All Neopixel turn off %1', }, }, }; @@ -155,6 +176,11 @@ Entry.NeoCannon.blockMenuBlocks = [ 'neo_cannon_rgb_led_color_picker', 'neo_cannon_rgb_led_pwm', 'neo_cannon_rgb_led_off', + 'neo_cannon_neopixel_color_picker', + 'neo_cannon_neopixel', + 'neo_cannon_neopixel_color_picker_all_on', + 'neo_cannon_neopixel_all_on', + 'neo_cannon_neopixel_all_off', ]; Entry.NeoCannon.getBlocks = function() { @@ -1479,6 +1505,424 @@ Entry.NeoCannon.getBlocks = function() { ], }, }, + neo_cannon_neopixel: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + null, + ], + type: 'neo_cannon_neopixel', + }, + paramsKeyMap: { + NUM: 0, + RED: 1, + GREEN: 2, + BLUE: 3, + }, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + let num = script.getNumberValue('NUM', script); + num = num % 18 + + let red = script.getNumberValue('RED', script); + let green = script.getNumberValue('GREEN', script); + let blue = script.getNumberValue('BLUE', script); + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + if (num) { + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + num, + red, + green, + blue + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); + } + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixel(%1, %2, %3, %4)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_neopixel_color_picker: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + null, + null, + ], + type: 'neo_cannon_neopixel_color_picker', + }, + paramsKeyMap: { + NUM: 0, + COLOR: 1, + }, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + let num = script.getNumberValue('NUM', script); + num = num % 18 + + let value = script.getStringField('COLOR'); + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + if (num) { + let red = parseInt(value.substr(1, 2), 16); + let green = parseInt(value.substr(3, 2), 16); + let blue = parseInt(value.substr(5, 2), 16); + + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + num, + red, + green, + blue + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); + } + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixelColorPicker(%1, %2)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neo_cannon_neopixel_color_picker_all_on: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + null, + ], + type: 'neo_cannon_neopixel_color_picker_all_on', + }, + paramsKeyMap: { + COLOR: 0, + }, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + let value = script.getStringField('COLOR'); + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + let red = parseInt(value.substr(1, 2), 16); + let green = parseInt(value.substr(3, 2), 16); + let blue = parseInt(value.substr(5, 2), 16); + + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + red, + green, + blue + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixelColorPickerAllOn(%1)', + textParams: [ + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neo_cannon_neopixel_all_on: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + null, + ], + type: 'neo_cannon_neopixel_all_on', + }, + paramsKeyMap: { + RED: 0, + GREEN: 1, + BLUE: 2, + }, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + + let red = script.getNumberValue('RED', script); + let green = script.getNumberValue('GREEN', script); + let blue = script.getNumberValue('BLUE', script); + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + red, + green, + blue + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixelAllON(%1, %2, %3)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_neopixel_all_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null,], + type: 'neo_cannon_neopixel_all_off', + }, + paramsKeyMap: {}, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + sq.neopixel = 0; + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixelAllOFF()', + textParams: [], + }, + ], + }, + }, }; }; diff --git a/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js b/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js index 246710f81a..d319b7c62e 100644 --- a/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js +++ b/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js @@ -1,9 +1,9 @@ 'use strict'; -(function() { +(function () { Entry.NeoCannonLite = new (class NeoCannonLite { constructor() { - this.id = '41.2'; + this.id = '410201'; this.name = 'NeoCannonLite'; this.url = 'http://www.neo3ds.com/'; this.imageName = 'neocannonlite.png'; @@ -30,6 +30,11 @@ 'neocannonlite_rgb_led_color_picker', 'neocannonlite_rgb_led_pwm', 'neocannonlite_rgb_led_off', + 'neocannonlite_neopixel_color_picker', + 'neocannonlite_neopixel_color_picker_all_on', + 'neocannonlite_neopixel', + 'neocannonlite_neopixel_all_on', + 'neocannonlite_neopixel_all_off', ]; this.portData = { baudRate: 115200, @@ -41,7 +46,7 @@ constantServing: true, }; this.__toneTable = { - '0': 0, + 0: 0, C: 1, CS: 2, D: 3, @@ -56,18 +61,18 @@ B: 12, }; this.__toneMap = { - '1': [33, 65, 131, 262, 523, 1046, 2093, 4186], - '2': [35, 69, 139, 277, 554, 1109, 2217, 4435], - '3': [37, 73, 147, 294, 587, 1175, 2349, 4699], - '4': [39, 78, 156, 310, 622, 1245, 2637, 4978], - '5': [41, 82, 165, 330, 659, 1319, 2794, 5274], - '6': [44, 87, 175, 349, 698, 1397, 2849, 5588], - '7': [46, 92, 185, 370, 740, 1480, 2960, 5920], - '8': [49, 98, 196, 392, 784, 1568, 3136, 6272], - '9': [52, 104, 208, 415, 831, 1661, 3322, 6645], - '10': [55, 110, 220, 440, 880, 1760, 3520, 7040], - '11': [58, 117, 233, 466, 932, 1865, 3729, 7459], - '12': [62, 123, 247, 494, 988, 1976, 3951, 7902], + 1: [33, 65, 131, 262, 523, 1046, 2093, 4186], + 2: [35, 69, 139, 277, 554, 1109, 2217, 4435], + 3: [37, 73, 147, 294, 587, 1175, 2349, 4699], + 4: [39, 78, 156, 310, 622, 1245, 2637, 4978], + 5: [41, 82, 165, 330, 659, 1319, 2794, 5274], + 6: [44, 87, 175, 349, 698, 1397, 2849, 5588], + 7: [46, 92, 185, 370, 740, 1480, 2960, 5920], + 8: [49, 98, 196, 392, 784, 1568, 3136, 6272], + 9: [52, 104, 208, 415, 831, 1661, 3322, 6645], + 10: [55, 110, 220, 440, 880, 1760, 3520, 7040], + 11: [58, 117, 233, 466, 932, 1865, 3729, 7459], + 12: [62, 123, 247, 494, 988, 1976, 3951, 7902], }; this.setZero(); } @@ -93,7 +98,7 @@ } setZero() { - this.txData = new Array(14).fill(0); + this.txData = new Array(68).fill(0); this.sensorData = { VIBE: 0, @@ -107,10 +112,30 @@ D9: 0, D10: 0, ANGLE: 0, + NEOPIXEL: [ + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + ], }; - if (Entry.hwLite) { - Entry.hwLite.update(); + if (Entry.hwLite && Entry.hwLite.serial) { + Entry.hwLite.serial.update(); } } @@ -161,9 +186,10 @@ const txData = this.txData; let checkSum = 0; const dataLen = txData.length; + const pixelNum = 18; txData[0] = 0xff; - txData[1] = 0x0e; + txData[1] = 0x44; txData[2] = 0x01; txData[3] = 0x03; txData[4] = workerData.OCTAVE; @@ -174,7 +200,12 @@ txData[9] = workerData.D9; txData[10] = workerData.D10; txData[11] = workerData.ANGLE; - txData[13] = 0xa; + for (let i = 0; i < pixelNum; i++) { + txData[i * 3 + 12] = workerData.NEOPIXEL[i].RED; + txData[i * 3 + 13] = workerData.NEOPIXEL[i].GREEN; + txData[i * 3 + 14] = workerData.NEOPIXEL[i].BLUE; + } + txData[dataLen - 1] = 0xa; for (let i = 2; i < dataLen - 2; i++) { checkSum += txData[i]; @@ -471,6 +502,76 @@ return script.callReturn(); } + setNeopixel(script) { + let num = script.getNumberValue('NUM', script); + const redPower = script.getNumberValue('RED', script); + const greenPower = script.getNumberValue('GREEN', script); + const bluePower = script.getNumberValue('BLUE', script); + + num = num % 18; + + this.workerData.NEOPIXEL[num].RED = redPower; + this.workerData.NEOPIXEL[num].GREEN = greenPower; + this.workerData.NEOPIXEL[num].BLUE = bluePower; + return script.callReturn(); + } + + setAllNeopixel(script) { + const redPower = script.getNumberValue('RED', script); + const greenPower = script.getNumberValue('GREEN', script); + const bluePower = script.getNumberValue('BLUE', script); + + for (let num = 0; num < 18; num++) { + this.workerData.NEOPIXEL[num].RED = redPower; + this.workerData.NEOPIXEL[num].GREEN = greenPower; + this.workerData.NEOPIXEL[num].BLUE = bluePower; + } + + return script.callReturn(); + } + + setNeopixelPicker(script) { + let num = script.getNumberValue('NUM', script); + const color = script.getStringField('COLOR'); + + num = num % 18; + + const redPower = parseInt(color.substr(1, 2), 16); + const greenPower = parseInt(color.substr(3, 2), 16); + const bluePower = parseInt(color.substr(5, 2), 16); + + this.workerData.NEOPIXEL[num].RED = redPower; + this.workerData.NEOPIXEL[num].GREEN = greenPower; + this.workerData.NEOPIXEL[num].BLUE = bluePower; + return script.callReturn(); + } + + setAllNeopixelPicker(script) { + const color = script.getStringField('COLOR'); + + const redPower = parseInt(color.substr(1, 2), 16); + const greenPower = parseInt(color.substr(3, 2), 16); + const bluePower = parseInt(color.substr(5, 2), 16); + + for (let num = 0; num < 18; num++) { + this.workerData.NEOPIXEL[num].RED = redPower; + this.workerData.NEOPIXEL[num].GREEN = greenPower; + this.workerData.NEOPIXEL[num].BLUE = bluePower; + } + + return script.callReturn(); + } + + setNeopixelOff(script) { + for (let num = 0; num < 18; num++) { + this.workerData.NEOPIXEL[num].RED = 0; + this.workerData.NEOPIXEL[num].GREEN = 0; + this.workerData.NEOPIXEL[num].BLUE = 0; + } + + return script.callReturn(); + } + // Block setLanguage() { return { @@ -493,6 +594,13 @@ neocannonlite_rgb_led_color_picker: 'RGB LED %1 %2', neocannonlite_rgb_led_pwm: 'RGB LED 빨강 %1 초록 %2 파랑 %3 %4', neocannonlite_rgb_led_off: 'RGB LED 끄기 %1', + neocannonlite_neopixel_color_picker: '네오픽셀 %1번 %2 (으)로 켜기 %3', + neocannonlite_neopixel: '네오픽셀 %1번 빨 %2 녹 %3 파 %4 (으)로 켜기 %5', + neocannonlite_neopixel_color_picker_all_on: + '네오픽셀 전체 %1 (으)로 켜기 %2', + neocannonlite_neopixel_all_on: + '네오픽셀 전체 빨 %1 녹 %2 파 %3 (으)로 켜기 %4', + neocannonlite_neopixel_all_off: '네오픽셀 전체 끄기 %1', }, Device: { neocannonlite: '네오캐논', @@ -520,6 +628,11 @@ neocannonlite_rgb_led_color_picker: 'RGB LED %1 %2', neocannonlite_rgb_led_pwm: 'RGB LED R %1 G %2 B %3 %4', neocannonlite_rgb_led_off: 'RGB LED OFF', + neocannonlite_neopixel_color_picker: 'Neopixel number %1 turn on %2 %3', + neocannonlite_neopixel: 'Neopixel number %1 turn on R %2 G %3 B %4 %5', + neocannonlite_neopixel_color_picker_all_on: 'All Neopixel turn on %1 %2', + neocannonlite_neopixel_all_on: 'All Neopixel turn on R %1 G %2 B %3 %4', + neocannonlite_neopixel_all_off: 'All Neopixel turn off %1', }, Device: { neocannonlite: 'neocannonlite', @@ -1604,6 +1717,221 @@ ], }, }, + neocannonlite_neopixel_color_picker: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + null, + null, + ], + type: 'neocannonlite_neopixel_color_picker', + }, + paramsKeyMap: { + NUM: 0, + COLOR: 1, + }, + class: 'NeoSpiderLite', + isNotFor: ['NeoSpiderLite'], + func(sprite, script) { + return Entry.NeoSpiderLite.setNeopixelPicker(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoSpiderLite.neopixelColorPicker(%1, %2)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neocannonlite_neopixel_color_picker_all_on: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'neocannonlite_neopixel_color_picker_all_on', + }, + paramsKeyMap: { + COLOR: 0, + }, + class: 'NeoSpiderLite', + isNotFor: ['NeoSpiderLite'], + func(sprite, script) { + return Entry.NeoSpiderLite.setAllNeopixelPicker(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoSpiderLite.neopixelColorPickerAllOn(%1)', + textParams: [ + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neocannonlite_neopixel_all_on: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + null, + ], + type: 'neocannonlite_neopixel_all_on', + }, + paramsKeyMap: { + RED: 0, + GREEN: 1, + BLUE: 2, + }, + class: 'NeoSpiderLite', + isNotFor: ['NeoSpiderLite'], + func(sprite, script) { + return Entry.NeoSpiderLite.setAllNeopixel(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoSpiderLite.neopixelAllON(%1, %2, %3)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neocannonlite_neopixel_all_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'neocannonlite_neopixel_all_off', + }, + paramsKeyMap: {}, + class: 'NeoSpiderLite', + isNotFor: ['NeoSpiderLite'], + func(sprite, script) { + return Entry.NeoSpiderLite.setNeopixelOff(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoSpiderLite.neopixelAllOFF()', + textParams: [], + }, + ], + }, + }, }; } })(); From 8d50f0797271ca1899292d5f3e3aedd707c0f168 Mon Sep 17 00:00:00 2001 From: TaeJuneJoung Date: Tue, 3 Sep 2024 13:55:33 +0900 Subject: [PATCH 02/21] =?UTF-8?q?:fire:Neopixel=20issue=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocks/hardware/block_neo_cannon.js | 120 ++++++++--------- .../hardwareLite/block_neo_cannon_lite.js | 125 +++++++++++++++--- 2 files changed, 165 insertions(+), 80 deletions(-) diff --git a/src/playground/blocks/hardware/block_neo_cannon.js b/src/playground/blocks/hardware/block_neo_cannon.js index b665cb9207..a4cce5b7d6 100644 --- a/src/playground/blocks/hardware/block_neo_cannon.js +++ b/src/playground/blocks/hardware/block_neo_cannon.js @@ -30,7 +30,7 @@ Entry.NeoCannon = { Entry.hw.update(); }, toneTable: { - '0': 0, + 0: 0, C: 1, CS: 2, D: 3, @@ -45,18 +45,18 @@ Entry.NeoCannon = { B: 12, }, toneMap: { - '1': [33, 65, 131, 262, 523, 1046, 2093, 4186], - '2': [35, 69, 139, 277, 554, 1109, 2217, 4435], - '3': [37, 73, 147, 294, 587, 1175, 2349, 4699], - '4': [39, 78, 156, 310, 622, 1245, 2637, 4978], - '5': [41, 82, 165, 330, 659, 1319, 2794, 5274], - '6': [44, 87, 175, 349, 698, 1397, 2849, 5588], - '7': [46, 92, 185, 370, 740, 1480, 2960, 5920], - '8': [49, 98, 196, 392, 784, 1568, 3136, 6272], - '9': [52, 104, 208, 415, 831, 1661, 3322, 6645], - '10': [55, 110, 220, 440, 880, 1760, 3520, 7040], - '11': [58, 117, 233, 466, 932, 1865, 3729, 7459], - '12': [62, 123, 247, 494, 988, 1976, 3951, 7902], + 1: [33, 65, 131, 262, 523, 1046, 2093, 4186], + 2: [35, 69, 139, 277, 554, 1109, 2217, 4435], + 3: [37, 73, 147, 294, 587, 1175, 2349, 4699], + 4: [39, 78, 156, 310, 622, 1245, 2637, 4978], + 5: [41, 82, 165, 330, 659, 1319, 2794, 5274], + 6: [44, 87, 175, 349, 698, 1397, 2849, 5588], + 7: [46, 92, 185, 370, 740, 1480, 2960, 5920], + 8: [49, 98, 196, 392, 784, 1568, 3136, 6272], + 9: [52, 104, 208, 415, 831, 1661, 3322, 6645], + 10: [55, 110, 220, 440, 880, 1760, 3520, 7040], + 11: [58, 117, 233, 466, 932, 1865, 3729, 7459], + 12: [62, 123, 247, 494, 988, 1976, 3951, 7902], }, monitorTemplate: { imgPath: 'hw/neo_cannon.png', @@ -74,7 +74,7 @@ Entry.NeoCannon = { BlockState: {}, }; -Entry.NeoCannon.setLanguage = function() { +Entry.NeoCannon.setLanguage = function () { return { ko: { template: { @@ -122,8 +122,7 @@ Entry.NeoCannon.setLanguage = function() { 'RGB LED를 색을 선택하여 원하는 색상을 나타낼 수 있습니다.
(주의, LED모드로 진행해주세요.)', neo_cannon_rgb_led_pwm: 'RGB LED에 세기값(0~255)을 주어 원하는 색상을 나타낼 수 있습니다.
(주의, LED모드로 진행해주세요.)', - neo_cannon_rgb_led_off: - 'RGB LED를 끌 수 있습니다.', + neo_cannon_rgb_led_off: 'RGB LED를 끌 수 있습니다.', neo_cannon_neopixel_color_picker: '색을 보고 RGB색상을 정하여 정해진 네오픽셀를 켤 수 있습니다.
(참고, 네오픽셀번호는 0번부터 17번까지 입니다.)', neo_cannon_neopixel: @@ -183,7 +182,7 @@ Entry.NeoCannon.blockMenuBlocks = [ 'neo_cannon_neopixel_all_off', ]; -Entry.NeoCannon.getBlocks = function() { +Entry.NeoCannon.getBlocks = function () { return { neo_cannon_get_vibe_value: { color: EntryStatic.colorSet.block.default.HARDWARE, @@ -200,7 +199,7 @@ Entry.NeoCannon.getBlocks = function() { class: 'NeoCannonGet', isNotFor: ['NeoCannon'], func(sprite, script) { - let port = 'vibe' + let port = 'vibe'; return Entry.hw.portData[port] || 0; }, @@ -1291,7 +1290,7 @@ Entry.NeoCannon.getBlocks = function() { ], events: {}, def: { - params: ["#0000FF", null], + params: ['#0000FF', null], type: 'neo_cannon_rgb_led_color_picker', }, paramsKeyMap: { @@ -1299,7 +1298,7 @@ Entry.NeoCannon.getBlocks = function() { }, class: 'NeoCannonRGB', isNotFor: ['NeoCannon'], - func: function(sprite, script) { + func: function (sprite, script) { const sq = Entry.hw.sendQueue; let value = script.getStringField('COLOR'); @@ -1399,7 +1398,7 @@ Entry.NeoCannon.getBlocks = function() { }, class: 'NeoCannonRGB', isNotFor: ['NeoCannon'], - func: function(sprite, script) { + func: function (sprite, script) { const sq = Entry.hw.sendQueue; let red = script.getNumberValue('RED', script); @@ -1471,7 +1470,7 @@ Entry.NeoCannon.getBlocks = function() { paramsKeyMap: {}, class: 'NeoCannonRGB', isNotFor: ['NeoCannon'], - func: function(sprite, script) { + func: function (sprite, script) { const sq = Entry.hw.sendQueue; if (!sq.shootState) { @@ -1570,8 +1569,8 @@ Entry.NeoCannon.getBlocks = function() { isNotFor: ['NeoCannon'], func: function (sprite, script) { const sq = Entry.hw.sendQueue; - let num = script.getNumberValue('NUM', script); - num = num % 18 + let num = script.getNumberValue('NUM', script) || 0; + num = num % 18; let red = script.getNumberValue('RED', script); let green = script.getNumberValue('GREEN', script); @@ -1581,20 +1580,18 @@ Entry.NeoCannon.getBlocks = function() { sq.neopixel = {}; } - if (num) { - sq.neopixel = { - type: Entry.NeoCannon.PORT_MAP.neopixel, - data: { - num, - red, - green, - blue - }, - time: new Date().getTime(), - }; - - Entry.hw.update(); - } + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + num, + red, + green, + blue, + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); return script.callReturn(); }, @@ -1665,8 +1662,8 @@ Entry.NeoCannon.getBlocks = function() { isNotFor: ['NeoCannon'], func: function (sprite, script) { const sq = Entry.hw.sendQueue; - let num = script.getNumberValue('NUM', script); - num = num % 18 + let num = script.getNumberValue('NUM', script) || 0; + num = num % 18; let value = script.getStringField('COLOR'); @@ -1674,24 +1671,22 @@ Entry.NeoCannon.getBlocks = function() { sq.neopixel = {}; } - if (num) { - let red = parseInt(value.substr(1, 2), 16); - let green = parseInt(value.substr(3, 2), 16); - let blue = parseInt(value.substr(5, 2), 16); + let red = parseInt(value.substr(1, 2), 16); + let green = parseInt(value.substr(3, 2), 16); + let blue = parseInt(value.substr(5, 2), 16); + + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + num, + red, + green, + blue, + }, + time: new Date().getTime(), + }; - sq.neopixel = { - type: Entry.NeoCannon.PORT_MAP.neopixel, - data: { - num, - red, - green, - blue - }, - time: new Date().getTime(), - }; - - Entry.hw.update(); - } + Entry.hw.update(); return script.callReturn(); }, @@ -1731,10 +1726,7 @@ Entry.NeoCannon.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neo_cannon_neopixel_color_picker_all_on', }, paramsKeyMap: { @@ -1759,7 +1751,7 @@ Entry.NeoCannon.getBlocks = function() { data: { red, green, - blue + blue, }, time: new Date().getTime(), }; @@ -1851,7 +1843,7 @@ Entry.NeoCannon.getBlocks = function() { data: { red, green, - blue + blue, }, time: new Date().getTime(), }; @@ -1896,7 +1888,7 @@ Entry.NeoCannon.getBlocks = function() { ], events: {}, def: { - params: [null,], + params: [null], type: 'neo_cannon_neopixel_all_off', }, paramsKeyMap: {}, diff --git a/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js b/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js index d319b7c62e..a0a1deda00 100644 --- a/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js +++ b/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js @@ -1753,16 +1753,16 @@ NUM: 0, COLOR: 1, }, - class: 'NeoSpiderLite', - isNotFor: ['NeoSpiderLite'], + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], func(sprite, script) { - return Entry.NeoSpiderLite.setNeopixelPicker(script); + return Entry.NeoCannonLite.setNeopixelPicker(script); }, syntax: { js: [], py: [ { - syntax: 'NeoSpiderLite.neopixelColorPicker(%1, %2)', + syntax: 'NeoCannonLite.neopixelColorPicker(%1, %2)', textParams: [ { type: 'Block', @@ -1777,6 +1777,99 @@ ], }, }, + neocannonlite_neopixel: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + null, + ], + type: 'neocannonlite_neopixel', + }, + paramsKeyMap: { + NUM: 0, + RED: 1, + GREEN: 2, + BLUE: 3, + }, + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], + func(sprite, script) { + return Entry.NeoCannonLite.setNeopixel(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannonLite.neopixel(%1, %2, %3, %4)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, neocannonlite_neopixel_color_picker_all_on: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1800,16 +1893,16 @@ paramsKeyMap: { COLOR: 0, }, - class: 'NeoSpiderLite', - isNotFor: ['NeoSpiderLite'], + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], func(sprite, script) { - return Entry.NeoSpiderLite.setAllNeopixelPicker(script); + return Entry.NeoCannonLite.setAllNeopixelPicker(script); }, syntax: { js: [], py: [ { - syntax: 'NeoSpiderLite.neopixelColorPickerAllOn(%1)', + syntax: 'NeoCannonLite.neopixelColorPickerAllOn(%1)', textParams: [ { type: 'Color', @@ -1871,16 +1964,16 @@ GREEN: 1, BLUE: 2, }, - class: 'NeoSpiderLite', - isNotFor: ['NeoSpiderLite'], + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], func(sprite, script) { - return Entry.NeoSpiderLite.setAllNeopixel(script); + return Entry.NeoCannonLite.setAllNeopixel(script); }, syntax: { js: [], py: [ { - syntax: 'NeoSpiderLite.neopixelAllON(%1, %2, %3)', + syntax: 'NeoCannonLite.neopixelAllON(%1, %2, %3)', textParams: [ { type: 'Block', @@ -1917,16 +2010,16 @@ type: 'neocannonlite_neopixel_all_off', }, paramsKeyMap: {}, - class: 'NeoSpiderLite', - isNotFor: ['NeoSpiderLite'], + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], func(sprite, script) { - return Entry.NeoSpiderLite.setNeopixelOff(script); + return Entry.NeoCannonLite.setNeopixelOff(script); }, syntax: { js: [], py: [ { - syntax: 'NeoSpiderLite.neopixelAllOFF()', + syntax: 'NeoCannonLite.neopixelAllOFF()', textParams: [], }, ], From 95c9a1e8d0b57b22f6149b9ec2660e4799842302 Mon Sep 17 00:00:00 2001 From: Jason Kim Date: Wed, 4 Sep 2024 16:04:13 +0900 Subject: [PATCH 03/21] =?UTF-8?q?=EB=A1=9C=EB=B4=87=EC=95=84=EC=9D=B4=20?= =?UTF-8?q?=EB=B8=8C=EB=9D=BC=EC=9A=B0=EC=A0=80=20=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- images/hw_lite/robotis_robotai_lite.png | Bin 0 -> 16871 bytes .../block_robotis_robotai_lite.js | 7681 +++++++++++++++++ .../metadata_robotis_robotai_lite.json | 9 + 3 files changed, 7690 insertions(+) create mode 100644 images/hw_lite/robotis_robotai_lite.png create mode 100644 src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js create mode 100644 src/playground/blocks/hardwareLite/metadata_robotis_robotai_lite.json diff --git a/images/hw_lite/robotis_robotai_lite.png b/images/hw_lite/robotis_robotai_lite.png new file mode 100644 index 0000000000000000000000000000000000000000..fb603c39ea28e266c4fa1039305ad6c6068ccb6a GIT binary patch literal 16871 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

%sG?dGngC;55I5k3#$A`$ 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 mmH!=8?uLhz!_^U>BK`wjc}BarUN{2)0000= 0) { + this.timeouts.splice(idx, 1); + } + } + + __removeAllTimeouts() { + const timeouts = this.timeouts; + for (const i in timeouts) { + clearTimeout(timeouts[i]); + } + this.timeouts = []; + } + + getMonitorPort() { + return { ...this.sensory, ...this.motoring, ...this.lineTracer }; + } + + writePacket(id, address, length, value) { + if (length > 256) { + console.log(`######### invalid length: ${length}`); + return null; + } + console.log('######### writePacket'); + const packet = []; + let i = 0; + packet.push(0xff); + packet.push(0xff); + packet.push(0xfd); + packet.push(0x00); + packet.push(id); + packet.push(length + 5); + packet.push(0x00); + packet.push(INST_WRITE); + packet.push(this.getLowByte(address)); + packet.push(this.getHighByte(address)); + switch (length) { + case 1: + packet.push(this.getLowByte(value)); + break; + case 2: + packet.push(this.getLowByte(value)); + packet.push(this.getHighByte(value)); + break; + case 4: + packet.push(this.getLowByte(this.getLowWord(value))); + packet.push(this.getHighByte(this.getLowWord(value))); + packet.push(this.getLowByte(this.getHighWord(value))); + packet.push(this.getHighByte(this.getHighWord(value))); + break; + default: + for (i = 0; i < length; i++) { + if (typeof value[i] == 'number') { + packet.push(value[i]); + } else if (typeof value[i] == 'string') { + packet.push(value[i].charCodeAt(0)); + } + } + break; + } + const crc = this.updateCRC(0, packet, packet.length); + packet.push(this.getLowByte(crc)); + packet.push(this.getHighByte(crc)); + return packet; + } + + makeWord(a, b) { + return (a & 0xff) | ((b & 0xff) << 8); + } + + getLowByte(a) { + return a & 0xff; + } + + getHighByte(a) { + return (a >> 8) & 0xff; + } + + getLowWord(a) { + return a & 0xffff; + } + + getHighWord(a) { + return (a >> 16) & 0xffff; + } + + updateCRC(crcAccum, dataBlkPtr, dataBlkSize) { + let i = 0; + let j = 0; + let crc = crcAccum; + + for (j = 0; j < dataBlkSize; j++) { + i = ((crc >> 8) ^ dataBlkPtr[j]) & 0xff; + crc = (crc << 8) ^ crcTable[i]; + } + + return crc; + } + + removeStuffing(buffer, length) { + let i = 0; + let stuffLength = 0; + let index = 0; + + for (i = 0; i < length; i++) { + if (i >= 2) { + if (buffer[i - 2] == 0xff && buffer[i - 1] == 0xff && buffer[i] == 0xfd) { + i++; + stuffLength++; + } + } + buffer[index++] = buffer[i]; + } + + return stuffLength; + } + + postCallReturn(script, data, ms) { + /* + if (data == null) { + Entry.engine.isContinue = false; + return script.callReturn(); + } else if (data.length == 0) { + Entry.engine.isContinue = false; + return script.callReturn(); + } + */ + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + for (let i = 0; i < data.length; i++) { + this.robotisBuffer.push(data[i]); + } + //delay ms + setTimeout(() => { + script.timeFlag = 0; + }, ms); + return script; + } else if (script.timeFlag) { + return script; + } else { + delete script.isStart; + delete script.timeFlag; + Entry.engine.isContinue = false; + return script.callReturn(); + } + } + + setLanguage() { + return { + ko: { + template: { + // 주행 제어 + robotis_robotai_lite_drive_simple: '속도 %1 (으)로 %2 하기 %3', + robotis_robotai_lite_drive_advanced: + '왼쪽바퀴 %1 속도로 %2 하기, 오른쪽바퀴 %3 속도로 %4 하기 %5', + robotis_robotai_lite_drive_seperate: + '%1 바퀴 %2 속도로 %3 으로 회전하기 %4', + robotis_robotai_lite_drive_angle: '%1 바퀴 %2 도만큼 %3 으로 회전하기 %4', + robotis_robotai_lite_go_distance: '%1 cm %2 하기 %3', + robotis_robotai_lite_turn_angle: '%1 도 %2 하기%3', + robotis_robotai_lite_follow_line: '%1 속도로 라인 따라가기 %2', + robotis_robotai_lite_stop_at_cross: '교차로 %1 에서 멈추기 %2', + robotis_robotai_lite_turn_at_line: '교차로에서 %1 하고 멈추기 %2', + robotis_robotai_lite_drive_stop: '정지하기 %1', + + robotis_robotai_lite_securitybot_init: '보안로봇 초기화 %1', + robotis_robotai_lite_securitybot_hi: '보안로봇 위아래로 흔들기 %1', + robotis_robotai_lite_securitybot_alert: '보안로봇 좌우로 흔들기 %1', + + robotis_robotai_lite_petbot_happy: '반려로봇 웃음 %1', + robotis_robotai_lite_petbot_sad: '반려로봇 화남 %1', + + robotis_robotai_lite_farmbot_init: '스마트팜 로봇 초기화 %1', + robotis_robotai_lite_farmbot_seek: '농작물 찾기 %1', + robotis_robotai_lite_farmbot_plant_type: '%1 농작물이면', + robotis_robotai_lite_farmbot_harvest_or_not_and_go: '농작물 %1 돌아가기 %2', + + // 값 블록 + robotis_robotai_lite_cm_ir_value: '%1 적외선센서 값', + robotis_robotai_lite_cm_ir_compare: '%1 적외선센서 값이 %2 보다 %3', + robotis_robotai_lite_detectFrontObj: '적외선센서의 %1에 물체가 있으면', // 거리센서를 사용하지 않을 경우 + robotis_robotai_lite_cm_btn_value: '제어기의 %1 버튼을 클릭했을때', + robotis_robotai_lite_cm_joystick_value: + '제어기의 노랑 조이스틱 위치가 %1 이면', + robotis_robotai_lite_mic: '소리의 크기(dB)', + robotis_robotai_lite_detectSound_compare: '소리가 제어기의 %1에서 들리면', + robotis_robotai_lite_imu: '%1축의 %2 값', + robotis_robotai_lite_roll_pitch: '제어기의 %1 값', + robotis_robotai_lite_line_cross_compare: '교차로 모양이 %1이면', + robotis_robotai_lite_environment_value: '%1 값', + robotis_robotai_lite_environment_compare: '%1 값이 %2보다 %3', + robotis_robotai_lite_dxl_value: '%1의 각도값', + + // 소리 + robotis_robotai_lite_scale_simple: '옥타브%1 로 %2 음을 %3로 연주하기 %4', + robotis_robotai_lite_scale_advanced: + '옥타브%1 로 %2 음을 %3박자 연주하기 %4', + robotis_robotai_lite_rest_simple: '%1 %2', + robotis_robotai_lite_rest_advanced: '쉼표 %1 박자 %2', + robotis_robotai_lite_beat_per_minute: '연주 빠르기를 %1 (으)로 정하기 %2', + robotis_robotai_lite_Hello: '로봇 %1 말하기 %2', + robotis_robotai_lite_effectSound: '효과음 %1 재생하기 %2', + robotis_robotai_lite_record: '소리 %1번에 녹음하기 %2', + robotis_robotai_lite_playRecord: '소리 %1번을 재생하기 %2', + + // LCD 제어 + robotis_robotai_lite_screen: '화면 표정을 %1 %2 (으)로 정하기 %3', + robotis_robotai_lite_anim_screen: + '화면 애니메이션을 %1 %2 (으)로 정하기 %3', + robotis_robotai_lite_icon_screen_food_plant: + '화면에 [음식/식물]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5', + robotis_robotai_lite_icon_screen_animal_human: + '화면에 [동물/사람]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5', + robotis_robotai_lite_icon_screen_object_tool: + '화면에 [물건/도구]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5', + robotis_robotai_lite_icon_screen_vehicle_number: + '화면에 [탈것/숫자]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5', + robotis_robotai_lite_text_screen: + '화면에 %1를 (%2, %3)위치에 %4 로 %5으로 표시 %6', + robotis_robotai_lite_pixel: '화면 (%1, %2)위치에 %3 색 점 표시 %4', + robotis_robotai_lite_text_screen_redraw: + '화면에 %1를 (%2, %3)위치에 %4으로 새로 표시 %5', + robotis_robotai_lite_LCDColor: '화면 색상을 %1 (으)로 정하기 %2', + robotis_robotai_lite_LCD_Flash: + '화면을 %1과 %2으로 %3초 간격으로 깜박이기 %4', + robotis_robotai_lite_LCDBright: '화면 밝기를 %1 (으)로 정하기 %2', + + // LED 제어 + robotis_robotai_lite_cm_led: '로봇 %1 LED %2 %3', + robotis_robotai_lite_cm_led_pattern: 'LED %1 %2로 깜박이기 %3', + + // DXL 제어 + robotis_robotai_lite_dxl_set_mode: '%1 모터 %2 모드로 설정 %3', + robotis_robotai_lite_dxl_each_control: + '%1 모터 %2°로 %3 초 동안 움직이기 %4', + robotis_robotai_lite_dxl_set_position: + '%1 모터 %2 속도로 %3° 위치로 회전 %4', + robotis_robotai_lite_dxl_set_rotate: '%1 모터 %2 속도로 %3 으로 %4 %5', + robotis_robotai_lite_dxl_set_multiturn_round: + '%1 모터 %2 속도로 %3 바퀴 %4으로 회전 %5', + + // ai_camera 값 블록 + robotis_robotai_lite_ai_camera_connection_status: 'AI 카메라: %1이면', + robotis_robotai_lite_ai_camera_if_detected: 'AI 카메라: %1 이/가 표시되면', + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: + 'AI 카메라: 화면 중앙과 가까운 %1의 %2', + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: + 'AI 카메라: 화면 중앙과 가까운 화살표의 %1', + robotis_robotai_lite_ai_camera_number_of_learned_id: + 'AI 카메라: 학습한 ID의 갯수', + robotis_robotai_lite_ai_camera_block_value_of_id: + 'AI 카메라: 감지된 ID가 %1인 %2의 %3', + robotis_robotai_lite_ai_camera_arrow_value_of_id: + 'AI 카메라: 감지된 ID가 %1인 화살표의 %2', + + robotis_robotai_lite_ai_camera_if_learned_id: + 'AI 카메라: ID가 %1인 데이터를 학습하였으면', + robotis_robotai_lite_ai_camera_if_detected_id_type: + 'AI 카메라: ID가 %1인 %2데이터를 인식하였으면', + + // AI 카메라 제어 + robotis_robotai_lite_ai_camera_set_mode: + 'AI 카메라: 모드를 %1(으)로 설정 %2', + robotis_robotai_lite_ai_camera_print_custom_text: + 'AI 카메라: 화면 위치 (%1,%2)에 %3를 보여주기%4', + robotis_robotai_lite_ai_camera_clear_custom_text: + 'AI 카메라: 화면의 글 지우기 %1', + }, + Helper: { + // 주행 제어 + robotis_robotai_lite_drive_simple: + '로봇아이를 지정한 속도와 방향으로 주행\n속도범위: -100 ~ 100\n속도단위: %', + robotis_robotai_lite_drive_advanced: + '로봇아이의 좌,우 바퀴를 각각 지정한 속도와 방향으로 회전\n속도범위: -100 ~ 100\n속도단위: %', + robotis_robotai_lite_drive_seperate: + '로봇아이의 지정한 바퀴를 지정한 속도와 방향으로 회전\n속도범위: -100 ~ 100\n속도단위: %', + robotis_robotai_lite_drive_angle: + '로봇아이의 지정한 바퀴를 지정한 방향과 지정한 각도만큼 회전\n각도범위: -5760 ~ 5760\n각도단위: 도', + robotis_robotai_lite_go_distance: + '지정거리만큼 앞 또는 뒤로 이동\n거리범위: -1000 ~ 1000\n거리단위: mm', + robotis_robotai_lite_turn_angle: + '지정한 각도와 방향으로 제자리회전\n각도범위: -360 ~ 360\n각도단위: 도', + robotis_robotai_lite_follow_line: '지정한 수준의 속도로 라인 따라가기 시작', + robotis_robotai_lite_stop_at_cross: '지정한 교차로에서 멈추기', + robotis_robotai_lite_turn_at_line: '교차로에서 지정한 회전을 하고 멈추기', + robotis_robotai_lite_drive_stop: '로봇아이 정지하기', + + robotis_robotai_lite_securitybot_init: + '보안로봇을 초기화합니다. 두 모터를 관절모드로 설정하고 카메라를 얼굴인식모드로 설정합니다.', + robotis_robotai_lite_securitybot_hi: + '보안로봇이 "사용자를 확인하였습니다." 문구를 화면에 표시하고 팔을 위아래로 흔듭니다.', + robotis_robotai_lite_securitybot_alert: + '보안로봇 "사용자가 아닙니다." 문구를 화면에 표시하고 몸을 좌우로 흔듭니다.', + + robotis_robotai_lite_petbot_happy: + '반려로봇이 웃는 표정을 하고 "즐거워요" 라고 말을 하면서 제자리에서 한바퀴 회전합니다.', + robotis_robotai_lite_petbot_sad: + '반려로봇이 화난 표정을 하고 "무서워요" 라고 말을 하면서 뒤로 5cm 후진합니다.', + + robotis_robotai_lite_farmbot_init: + '스마트팜 로봇을 초기화 합니다. 1번 모터를 시작위치로 이동시키고 카메라를 색상인식모드로 설정합니다.', + robotis_robotai_lite_farmbot_seek: '농작물을 발견하면 가까이로 이동합니다.', + robotis_robotai_lite_farmbot_plant_type: '농작물의 유형을 판단합니다.', + robotis_robotai_lite_farmbot_harvest_or_not_and_go: + '농작물을 수확하거나 수확하지 않습니다. 그 이후 우측으로 회전합니다.', + + // 값 블록 + robotis_robotai_lite_cm_ir_value: '지정한 번호의 IR 센서 값(범위: 0 ~ 200)', + robotis_robotai_lite_cm_ir_compare: + "지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_detectFrontObj: + "지정한 방향의 적외선센서에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_cm_btn_value: + "지정한 버튼이 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_cm_joystick_value: + "조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_mic: + '마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.', + robotis_robotai_lite_detectSound_compare: + "소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_imu: + '지정한 축의 지정한 가속도센서/자이로센서의 값\n범위: -100 ~ 100', + robotis_robotai_lite_roll_pitch: + 'roll/pitch 값\nroll: -180° ~ 180°, pitch: -90° ~ 90°', + robotis_robotai_lite_environment_value: + '지정한 센서값\n움직임센서: 0(움직임 없음) / 1(움직임 있음)\n밝기범위: 0 ~ 100%\n온도범위: -25°C ~ 85°C', + robotis_robotai_lite_environment_compare: + "지정한 센서값의 지정한 수식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_line_cross_compare: + "지정한 교차로 모양이면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_dxl_value: + '지정한 모터의 위치 각도값\n범위: -180° ~ 180°', + + // 소리 + robotis_robotai_lite_scale_simple: '지정한 옥타브, 음계, 음표로 연주하기', + robotis_robotai_lite_scale_advanced: '지정한 옥타브, 음계, 박자로 연주하기', + robotis_robotai_lite_rest_simple: '지정한 쉼표 쉬기', + robotis_robotai_lite_rest_advanced: '지정한 박자 쉬기', + robotis_robotai_lite_beat_per_minute: + '연주 빠르기를 지정하기 (BPM)\n범위: 10 ~ 600', + robotis_robotai_lite_Hello: '로봇이 지정한 말소리를 재생하기', + robotis_robotai_lite_effectSound: '로봇이 지정한 효과음을 재생하기', + robotis_robotai_lite_record: '지정번호 보관함에 녹음하여 저장하기', + robotis_robotai_lite_playRecord: '지정번호 보관함의 녹음음성을 재생하기', + + // LCD 제어 + robotis_robotai_lite_screen: '제어기 화면배경의 캐릭터와 표정을 설정', + robotis_robotai_lite_anim_screen: + '제어기 화면 애니메이션의 캐릭터와 표정을 설정', + robotis_robotai_lite_icon_screen_food_plant: + '화면에 [음식/식물]중 특정 아이콘을 표시할 위치와 크기를 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_icon_screen_animal_human: + '화면에 [동물/사람]중 특정 아이콘을 표시할 위치와 크기를 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_icon_screen_object_tool: + '화면에 [물건/도구]중 특정 아이콘을 표시할 위치와 크기를 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_icon_screen_vehicle_number: + '화면에 [탈것/숫자]중 특정 아이콘을 표시할 위치와 크기를 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_text_screen: + '화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120', + robotis_robotai_lite_text_screen_redraw: + '화면에 지정한 문구를 새롭게(문구의 배경 지움) 표시할 위치와 색상을 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_pixel: + '화면에 표시할 점의 위치와 색상을 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120', + robotis_robotai_lite_LCDBright: '화면 밝기를 설정\n밝기범위: 1% ~ 100%', + robotis_robotai_lite_LCDColor: '화면 색상을 설정', + robotis_robotai_lite_LCD_Flash: '화면이 깜박이는 2가지 색상과 간격을 지정', + + // LED 제어 + robotis_robotai_lite_cm_led: '제어기의 지정한 LED를 켜거나 끄기', + robotis_robotai_lite_cm_led_pattern: '제어기의 깜박임 패턴 설정', + + // DXL 제어 + robotis_robotai_lite_dxl_set_mode: '지정한 ID의 모터의 동작모드를 설정', + robotis_robotai_lite_dxl_each_control: + '지정한 ID의 모터가 지정한 각도로 지정한 시간(초)동안 움직이도록 설정', + robotis_robotai_lite_dxl_set_position: + '지정한 ID의 모터가 지정한 속도로 지정한 각도로 움직이도록 설정', + robotis_robotai_lite_dxl_set_rotate: + '지정한 ID의 모터의 회전 속도와 방향을 설정', + robotis_robotai_lite_dxl_set_multiturn_round: + '지정한 ID의 모터가 지정한 속도와 방향으로 지정한 바퀴만큼 회전', + + // AI Camera 값 블록 + robotis_robotai_lite_ai_camera_connection_status: + "AI 카메라가 연결된 상태이면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_ai_camera_if_detected: + "AI 카메라의 LCD화면에 선택한 기호(사각형/화살표)가 표시되면 '참', 아니면 '거짓'으로 판단합니다.", + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: + 'AI 카메라 화면 중앙과 가장 가까운 사각형의 X좌표/Y좌표/너비/높이/학습ID', + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: + 'AI 카메라 화면 중앙과 가장 가까운 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표/학습ID', + robotis_robotai_lite_ai_camera_number_of_learned_id: + 'AI 카메라가 학습한 ID의 갯수', + robotis_robotai_lite_ai_camera_block_value_of_id: + 'AI 카메라가 감지한 사각형중 지정한 ID의 사각형의 X좌표/Y좌표/너비/높이', + robotis_robotai_lite_ai_camera_arrow_value_of_id: + 'AI 카메라가 감지한 화살표중 지정한 ID의 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표', + + robotis_robotai_lite_ai_camera_if_learned_id: + "AI 카메라가 지정한 ID인 데이터를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_ai_camera_if_detected_id_type: + "AI 카메라가 지정한 ID인 지정한 데이터(사각형/화살표)를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.", + + // AI 카메라 제어 + robotis_robotai_lite_ai_camera_set_mode: 'AI 카메라의 모드를 설정', + robotis_robotai_lite_ai_camera_print_custom_text: + 'AI 카메라 화면의 지정한 위치에 지정한 문구 출력\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120', + robotis_robotai_lite_ai_camera_clear_custom_text: + 'AI 카메라 화면에 표시한 모든 문구 지우기', + }, + Blocks: { + robotis_red: '빨강', + robotis_orange: '주황', + robotis_yellow: '노랑', + robotis_green: '초록', + robotis_blue: '파랑', + robotis_brown: '갈색', + robotis_black: '검정', + robotis_white: '흰색', + robotis_left: '왼쪽', + robotis_center: '중앙', + robotis_right: '오른쪽', + robotis_both: '양쪽', + robotis_rgee: '알쥐', + robotis_rla: '알라', + robotis_kkokdu: '꼭두', + robotis_korean1: '안녕하세요', + robotis_korean2: '반가워요', + robotis_korean3: '알겠어요', + robotis_korean4: '아니에요', + robotis_korean5: '모르겠어요', + robotis_korean6: '좋아요', + robotis_korean7: '싫어요', + robotis_korean8: '이름을말하세요', + robotis_korean9: '무엇을도와줄까?', + robotis_korean10: '잘했어', + robotis_korean11: '괜찮아', + robotis_korean12: '다시해보자', + robotis_korean13: '고마워', + robotis_korean14: '다시말해줄래?', + robotis_korean15: '최고야!', + robotis_korean16: '신나요', + robotis_korean17: '즐거워요', + robotis_korean18: '미안해요', + robotis_korean19: '화나요', + robotis_korean20: '부끄러워요', + robotis_korean21: '무서워요', + robotis_korean22: '속상해요', + robotis_korean23: '사랑해요', + robotis_korean24: '예뻐요', + robotis_korean25: '신기해요', + robotis_korean26: '초조해요', + robotis_korean27: '앞으로가자', + robotis_korean28: '뒤로가자', + robotis_korean29: '일어나자', + robotis_korean30: '넘어졌네?', + robotis_korean31: '오예', + robotis_korean32: '아싸', + robotis_korean33: '어머', + robotis_korean34: '이런', + robotis_korean35: '오호', + robotis_korean36: '하하하', + robotis_korean37: '호호호', + robotis_korean38: '졸려', + robotis_korean39: '자장가를들려줘', + robotis_korean40: '안녕', + robotis_korean41: '배고프다', + robotis_korean42: '도토리땡긴다', + robotis_korean43: '아.씻고싶어', + robotis_korean44: '비누목욕시간이야', + robotis_korean45: '심심한데', + robotis_korean46: '간식먹을까', + robotis_korean47: '아파요', + robotis_korean48: '약은없나요?', + robotis_korean49: '어디로가야하지?', + robotis_korean50: '와아도착이다', + robotis_korean51: '왼쪽으로가자', + robotis_korean52: '오른쪽으로가자', + robotis_korean53: '깜짝이야', + robotis_korean54: '찾았다', + robotis_korean55: '여긴없네', + robotis_korean56: '혹시나불렀어?', + robotis_korean57: '내려주세요', + robotis_korean58: '앗', + robotis_korean59: '힝', + robotis_korean60: '이익', + robotis_dog: '개', + robotis_frog: '개구리', + robotis_cat: '고양이', + robotis_chicken: '닭', + robotis_tiger: '호랑이', + robotis_mouse: '쥐', + robotis_ambul: '앰뷸런스', + robotis_Horn: '경적(빵빵)', + robotis_siren: '사이렌(경찰차)', + robotis_whistle: '호루라기', + robotis_gun: '총소리', + robotis_clap: '박수소리', + robotis_melody1: '멜로디1', + robotis_melody2: '멜로디2', + robotis_melody3: '멜로디3', + robotis_melody4: '멜로디4', + robotis_forward: '앞으로', + robotis_backward: '뒤로', + robotis_acceleration: '가속도', + robotis_gyro: '자이로', + robotis_run: '실행', + robotis_cancel: '취소', + robotis_push: '눌림', + robotis_notPush: '안눌림', + robotis_play: '연주', + robotis_rest: '쉼표', + robotis_face01: '와하하', + robotis_face02: '싱글벙글', + robotis_face03: '큭큭큭', + robotis_face04: '냠냠', + robotis_face05: '겁먹음', + robotis_face06: '답답', + robotis_face07: '갸우뚱', + robotis_face08: '어벙벙', + robotis_face09: '고함', + robotis_face10: '화남', + robotis_face11: '킁킁(왼쪽)', + robotis_face12: '킁킁(오른쪽)', + robotis_face13: '킁킁(아래)', + robotis_face14: '안심', + robotis_face15: '기절', + robotis_face16: '헤롱헤롱', + robotis_face17: '하품', + robotis_face18: '졸림', + robotis_face19: '잠듦', + robotis_face20: '마음앓이', + robotis_face21: '폭풍눈물', + robotis_face22: '목욕', + robotis_face23: '햐트뿅뿅', + + robotis_flashing1: '깜박임1', + robotis_flashing2: '깜박임2', + robotis_flashing3: '깜박임3', + robotis_flashing4: '깜박임4', + robotis_flashing5: '깜박임5', + robotis_flashing6: '깜박임6', + robotis_flashing7: '깜박임7', + robotis_flashing8: '깜박임8', + robotis_flashing9: '깜박임9', + robotis_moveF: '전진', + robotis_moveB: '후진', + robotis_moveL: '좌회전', + robotis_moveR: '우회전', + robotis_moveU: 'U턴', + robotis_moveL_in_place: '제자리 좌회전', + robotis_moveR_in_place: '제자리 우회전', + robotis_moveU_in_place: '제자리 U턴', + robotis_moveRG1: '일어서기', + robotis_moveRG2: '앉기', + robotis_moveRG3: '발버둥', + robotis_moveRG4: '발들기', + robotis_stop: '정지', + robotis_roll: '좌우 회전각 (roll)', + robotis_pitch: '앞뒤 회전각 (pitch)', + robotis_direction_forward: '전진방향', + robotis_direction_backward: '후진방향', + robotis_stMotion1: '기본자세', + robotis_stMotion2: '전진', + robotis_stMotion3: '우전진', + robotis_stMotion4: '좌전진', + robotis_stMotion5: '후진', + robotis_stMotion6: '오른쪽으로', + robotis_stMotion7: '왼쪽으로', + robotis_stMotion8: '우회전', + robotis_stMotion9: '좌회전', + robotis_spMotion1: '오른손 들기', + robotis_spMotion2: '오른손 내리기', + robotis_spMotion3: '왼손 들기', + robotis_spMotion4: '왼손 내리기', + robotis_spMotion5: '양손 들기', + robotis_spMotion6: '양손 내리기', + robotis_spMotion7: '뒤로 넘어지기', + robotis_spMotion8: '앞으로 넘어지기', + robotis_spMotion9: '앞으로 일어서기', + robotis_spMotion10: '뒤로 일어서기', + robotis_spMotion11: '방어', + robotis_spMotion12: '공격1', + robotis_spMotion13: '공격2', + robotis_spMotion14: '공격3', + robotis_spMotion15: '공격4', + robotis_screen1: '가위', + robotis_screen2: '바위', + robotis_screen3: '보', + robotis_icon_food_plant_1: '우유', + robotis_icon_food_plant_2: '나무', + robotis_icon_food_plant_3: '스프', + robotis_icon_food_plant_4: '케익', + robotis_icon_food_plant_5: '물', + robotis_icon_food_plant_6: '주스', + robotis_icon_food_plant_7: '당근', + robotis_icon_food_plant_8: '사과', + robotis_icon_food_plant_9: '오렌지', + robotis_icon_food_plant_10: '고기', + robotis_icon_food_plant_11: '화분', + robotis_icon_food_plant_12: '장미', + robotis_icon_food_plant_13: '포도', + robotis_icon_food_plant_14: '감자', + robotis_icon_food_plant_15: '사탕', + robotis_icon_food_plant_16: '치즈', + robotis_icon_food_plant_17: '식빵', + robotis_icon_food_plant_18: '꽃들', + robotis_icon_food_plant_19: '커피', + robotis_icon_food_plant_20: '튤립', + robotis_icon_food_plant_21: '바나나', + robotis_icon_food_plant_22: '과일들', + robotis_icon_food_plant_23: '햄버거', + robotis_icon_food_plant_24: '피자', + robotis_icon_animal_human_1: '시바견', + robotis_icon_animal_human_2: '강아지', + robotis_icon_animal_human_3: '곰', + robotis_icon_animal_human_4: '새', + robotis_icon_animal_human_5: '오리', + robotis_icon_animal_human_6: '사자', + robotis_icon_animal_human_7: '호랑이', + robotis_icon_animal_human_8: '말', + robotis_icon_animal_human_9: '양', + robotis_icon_animal_human_10: '상어1(왼쪽)', + robotis_icon_animal_human_11: '상어1(오른쪽)', + robotis_icon_animal_human_12: '상어2(왼쪽)', + robotis_icon_animal_human_13: '상어2(오른쪽)', + robotis_icon_animal_human_14: '물고기1', + robotis_icon_animal_human_15: '물고기2', + robotis_icon_animal_human_16: '물고기3', + robotis_icon_animal_human_17: '문어', + robotis_icon_animal_human_18: '원숭이', + robotis_icon_animal_human_19: '닭', + robotis_icon_animal_human_20: '돼지', + robotis_icon_animal_human_21: '사람(살찐)', + robotis_icon_animal_human_22: '사람(수영복)', + robotis_icon_animal_human_23: '아기', + robotis_icon_animal_human_24: '사람(달리는)', + robotis_icon_animal_human_25: '사람(노래하는)', + robotis_icon_animal_human_26: '사람(앉은)', + robotis_icon_animal_human_27: '사람(화난)', + robotis_icon_animal_human_28: '사람(만세)', + robotis_icon_animal_human_29: '왕', + robotis_icon_animal_human_30: '왕자', + robotis_icon_animal_human_31: '공주', + robotis_icon_animal_human_32: '요리사', + robotis_icon_animal_human_33: '의사', + robotis_icon_animal_human_34: '간호사', + robotis_icon_object_tool_1: '가방', + robotis_icon_object_tool_2: '상자', + robotis_icon_object_tool_3: '머그컵', + robotis_icon_object_tool_4: '모자(중절모)', + robotis_icon_object_tool_5: '모자(캡모자)', + robotis_icon_object_tool_6: '열쇠', + robotis_icon_object_tool_7: '장난감', + robotis_icon_object_tool_8: '책', + robotis_icon_object_tool_9: '곰인형', + robotis_icon_object_tool_10: '드럼', + robotis_icon_object_tool_11: '메모장', + robotis_icon_object_tool_12: '볼펜', + robotis_icon_object_tool_13: '책상', + robotis_icon_object_tool_14: '테이블', + robotis_icon_object_tool_15: '의자', + robotis_icon_object_tool_16: '침대', + robotis_icon_object_tool_17: '텐트', + robotis_icon_object_tool_18: '접시', + robotis_icon_object_tool_19: '축구공', + robotis_icon_object_tool_20: '종', + robotis_icon_object_tool_21: '손목시계', + robotis_icon_object_tool_22: '신발', + robotis_icon_object_tool_23: '전등', + robotis_icon_object_tool_24: '라디오', + robotis_icon_object_tool_25: '지폐', + robotis_icon_object_tool_26: '자', + robotis_icon_object_tool_27: '카메라', + robotis_icon_object_tool_28: '스푼', + robotis_icon_object_tool_29: '건반', + robotis_icon_object_tool_30: '달력', + robotis_icon_object_tool_31: '칼', + robotis_icon_object_tool_32: '풍선', + robotis_icon_object_tool_33: '물통', + robotis_icon_object_tool_34: '나무막대(세로)', + robotis_icon_object_tool_35: '나무막대(가로)', + robotis_icon_object_tool_36: '낚시바늘', + robotis_icon_vehicle_number_1: '자동차', + robotis_icon_vehicle_number_2: '버스', + robotis_icon_vehicle_number_3: '트럭', + robotis_icon_vehicle_number_4: '지프', + robotis_icon_vehicle_number_5: '자전거', + robotis_icon_vehicle_number_6: '전철', + robotis_icon_vehicle_number_7: '기차', + robotis_icon_vehicle_number_8: '비행기', + robotis_icon_vehicle_number_9: '전투기(세로)', + robotis_icon_vehicle_number_10: '전투기(가로)', + robotis_icon_vehicle_number_11: '로켓', + robotis_icon_vehicle_number_12: '어선', + robotis_icon_vehicle_number_13: '여객선', + robotis_icon_vehicle_number_14: '잠수항(왼쪽)', + robotis_icon_vehicle_number_15: '잠수함(오른쪽)', + robotis_icon_vehicle_number_16: '비행기(왼쪽)', + robotis_icon_vehicle_number_17: '비행기(오른쪽)', + robotis_icon_vehicle_number_18: '비행기(윗쪽)', + robotis_icon_vehicle_number_19: '우주선(왼쪽)', + robotis_icon_vehicle_number_20: '우주선(오른쪽)', + robotis_icon_vehicle_number_21: '우주선(윗쪽)', + robotis_icon_vehicle_number_22: '주사위(1)', + robotis_icon_vehicle_number_23: '주사위(2)', + robotis_icon_vehicle_number_24: '주사위(3)', + robotis_icon_vehicle_number_25: '주사위(4)', + robotis_icon_vehicle_number_26: '주사위(5)', + robotis_icon_vehicle_number_27: '주사위(6)', + robotis_icon_vehicle_number_28: '0', + robotis_icon_vehicle_number_29: '1', + robotis_icon_vehicle_number_30: '2', + robotis_icon_vehicle_number_31: '3', + robotis_icon_vehicle_number_32: '4', + robotis_icon_vehicle_number_33: '5', + robotis_icon_vehicle_number_34: '6', + robotis_icon_vehicle_number_35: '7', + robotis_icon_vehicle_number_36: '8', + robotis_icon_vehicle_number_37: '9', + robotis_icon_vehicle_number_38: '10', + robotis_speed_fast: '빠른 속도', + robotis_speed_midium: '중간 속도', + robotis_speed_slow: '느린 속도', + robotis_clockwise: '시계방향', + robotis_counterclockwise: '반시계방향', + robotis_up: '들기', + robotis_down: '내리기', + robotis_if_greater: '크면', + robotis_if_smaller: '작으면', + robotis_if_equal: '같으면', + robotis_front_right: '앞 오른쪽', + robotis_front_left: '앞 왼쪽', + robotis_bottom_right: '아래 오른쪽', + robotis_bottom_left: '아래 왼쪽', + robotis_side_right: '우측', + robotis_side_left: '좌측', + robotis_front_ir_sensor: '적외선센서', + robotis_distance_sensor: '거리센서', + robotis_front: '앞', + robotis_right: '오른쪽', + robotis_left_wheel: '왼쪽바퀴', + robotis_right_wheel: '오른쪽바퀴', + // https://namu.wiki/w/%EC%9D%8C%ED%91%9C + robotis_beat_sound_8th_note: '8분음표 (♪)', + robotis_beat_sound_dotted_8th_note: '점8분음표 (♪.)', + robotis_beat_sound_quarter_note: '4분음표 (♩)', + robotis_beat_sound_dotted_quarter_note: '점4분음표 (♩.)', + robotis_beat_sound_half_note: '2분음표 (𝅗𝅥)', + robotis_beat_sound_dotted_half_note: '점2분음표 (𝅗𝅥.)', + robotis_beat_sound_whole_note: '온음표 (𝅝)', + robotis_beat_sound_dotted_note: '점온음표 (𝅝.)', + robotis_beat_rest_8th_note: '8분쉼표 (𝄾)', + robotis_beat_rest_dotted_8th_note: '점8분쉼표 (𝄾.)', + robotis_beat_rest_quarter_note: '4분쉼표 (𝄽)', + robotis_beat_rest_dotted_quarter_note: '점4분쉼표 (𝄽.)', + robotis_beat_rest_half_note: '2분쉼표 (𝄼)', + robotis_beat_rest_dotted_half_note: '점2분쉼표 (𝄼˙)', + robotis_beat_rest_whole_note: '온쉼표 (𝄻)', + robotis_beat_rest_dotted_note: '점온쉼표 (𝄻˙)', + robotis_line_cross_type_0: '|', + robotis_line_cross_type_1: ' (공백)', + robotis_line_cross_type_5: '🞣', + robotis_line_cross_type_6: '⏉', + robotis_line_cross_type_7: '⊣', + robotis_line_cross_type_8: '⊢', + robotis_line_cross_type_9: '⏋', + robotis_line_cross_type_10: '⎾', + robotis_line_cross_type_11: '¦', + robotis_line_cross_type_12: '︙', + + robotis_dxl_mode_joint: '관절', + robotis_dxl_mode_wheel: '바퀴', + robotis_dxl_mode_multi_turn: '여러바퀴회전', + robotis_dxl_move_rotate: '회전', + robotis_dxl_move_stop: '정지', + robotis_dxl_rotate_cw: '시계방향', + robotis_dxl_rotate_ccw: '반시계방향', + robotis_dxl_value_angle: '각도', + robotis_dxl_value_velocity: '속도', + robotis_dxl_value_moving: '움직임', + + robotis_connected: '연결', + robotis_disconnected: '없음', + robotis_ai_camera_mode_face_recognition: '얼굴인식', + robotis_ai_camera_mode_object_tracking: '물체추적', + robotis_ai_camera_mode_object_recognition: '물체인식', + robotis_ai_camera_mode_line_tracking: '라인인식', + robotis_ai_camera_mode_color_recognition: '색상인식', + robotis_ai_camera_mode_tag_recognition: '태그인식', + robotis_ai_camera_mode_object_classification: '물체분류', + robotis_ai_camera_target_face: '얼굴', + robotis_ai_camera_target_object: '사물', + robotis_ai_camera_target_color: '색상', + robotis_ai_camera_target_tag: '태그', + robotis_ai_camera_target_qr: 'QR코드', + robotis_ai_camera_target_block: '사각형', + robotis_ai_camera_target_arrow: '화살표', + robotis_ai_camera_center_block_center_x: '중심 X좌표', + robotis_ai_camera_center_block_center_y: '중심 Y좌표', + robotis_ai_camera_center_block_width: '너비', + robotis_ai_camera_center_block_height: '높이', + robotis_ai_camera_center_leared_id: '학습ID', + robotis_ai_camera_center_arrow_origin_x: '시작점 X좌표', + robotis_ai_camera_center_arrow_origin_y: '시작점 Y좌표', + robotis_ai_camera_center_arrow_target_x: '끝점 X좌표', + robotis_ai_camera_center_arrow_target_y: '끝점 Y좌표', + + robotis_plant_ripe: '빨간색으로 잘 익은', + robotis_plant_unripe: '초록색으로 덜 익은', + robotis_harvest: '수확하고', + robotis_not_harvest: '수확하지 않고', + }, + }, + en: { + template: { + // 주행 제어 + robotis_robotai_lite_drive_simple: 'Move %2 with velocity %1 %3', + robotis_robotai_lite_drive_advanced: + 'Left wheel %2 with velocity %1, right wheel %4 with velocity %3 %5', + robotis_robotai_lite_drive_seperate: + '%1 wheel rotate %3 with velocity %2 %4', + robotis_robotai_lite_drive_angle: 'Rotate %1 wheel %2 degree %3 %4', + robotis_robotai_lite_go_distance: 'Moves %2 %1 cm %3', + robotis_robotai_lite_turn_angle: 'Rotates %1 degree(s) %2 in place %3', + robotis_robotai_lite_follow_line: 'Follow line with %1 speed %2', + robotis_robotai_lite_stop_at_cross: 'Stop at cross %1 %2', + robotis_robotai_lite_turn_at_line: '%1 at cross and stop %2', + robotis_robotai_lite_drive_stop: 'Stop %1', + + robotis_robotai_lite_securitybot_init: 'Security robot init %1', + robotis_robotai_lite_securitybot_hi: 'Security robot shake up and down %1', + robotis_robotai_lite_securitybot_alert: + 'Security robot shake left and right %1', + + robotis_robotai_lite_petbot_happy: 'Petbot laugh %1', + robotis_robotai_lite_petbot_sad: 'Petbot angry %1', + + robotis_robotai_lite_farmbot_init: 'SmartFarm Robot init %1', + robotis_robotai_lite_farmbot_seek: 'Look for plant %1', + robotis_robotai_lite_farmbot_plant_type: 'If it is %1 plant', + robotis_robotai_lite_farmbot_harvest_or_not_and_go: + '%1 the plant and go back %2', + + // 값 블록 + robotis_robotai_lite_cm_ir_value: 'Value of %1 IR Sensor', + robotis_robotai_lite_cm_ir_compare: + 'If the number %1 IR sensor value is %3 than %2', + robotis_robotai_lite_detectFrontObj: 'If %1 IR sensor detected an object', + robotis_robotai_lite_cm_btn_value: + "When the controller's %1 button is clicked", + robotis_robotai_lite_cm_joystick_value: + "If the controller's yellow joystick position is %1", + robotis_robotai_lite_mic: 'MIC volume(dB)', + robotis_robotai_lite_detectSound_compare: + 'If sound is detected from %1 of the robot', + robotis_robotai_lite_imu: "%1 axis' %2 value", + robotis_robotai_lite_roll_pitch: '%1 value of the controller', + robotis_robotai_lite_environment_value: '%1 value', + robotis_robotai_lite_environment_compare: 'If %1 value is %3 than %2', + robotis_robotai_lite_line_cross_compare: 'If the type of cross is %1', + robotis_robotai_lite_dxl_value: 'The angle of ID %1', + + // 소리 + robotis_robotai_lite_scale_simple: 'Play the note %2 as %3 in octave %1 %4', + robotis_robotai_lite_scale_advanced: + 'Play the note %2 in octave %1 for %3 beat %4', + robotis_robotai_lite_rest_simple: '%1 %2', + robotis_robotai_lite_rest_advanced: 'Rest %1 beat %2', + robotis_robotai_lite_beat_per_minute: 'Set playing speed to %1 %2', + robotis_robotai_lite_Hello: 'Robot speaks %1 %2', + robotis_robotai_lite_effectSound: 'Play sound effect %1 %2', + robotis_robotai_lite_record: 'Record to sound slot %1 %2', + robotis_robotai_lite_playRecord: 'Play sound from slot %1 %2', + + // LCD 제어 + robotis_robotai_lite_screen: 'Set screen expression to %1 %2 %3', + robotis_robotai_lite_anim_screen: 'Set screen animation to %1 %2 %3', + robotis_robotai_lite_icon_screen_food_plant: + 'Display %1 from [Food/Plants] at position (%2, %3) in size %4 %5', + robotis_robotai_lite_icon_screen_animal_human: + 'Display %1 from [Animal/Human] at position (%2, %3) in size %4 %5', + robotis_robotai_lite_icon_screen_object_tool: + 'Display %1 from [Object/Tool] at position (%2, %3) in size %4 %5', + robotis_robotai_lite_icon_screen_vehicle_number: + 'Display %1 from [Vehicle/Number] at position (%2, %3) in size %4 %5', + robotis_robotai_lite_text_screen: + 'Display %1 in %5 in %4 at (%2, %3) on the screen %6', + robotis_robotai_lite_text_screen_redraw: + 'Newly display %1 in %4 at (%2, %3) %5', + robotis_robotai_lite_pixel: 'Display %3 colored dot at (%1, %2) %4', + robotis_robotai_lite_LCDColor: 'Set screen color as %1 %2', + robotis_robotai_lite_LCD_Flash: + 'Blink the screen with %1 and %2 at intervals of %3 seconds %4', + robotis_robotai_lite_LCDBright: 'Set screen brightness as %1 %2', + + // LED 제어 + robotis_robotai_lite_cm_led: "%2 the robot's %1 LED %3", + robotis_robotai_lite_cm_led_pattern: 'LED %1 blinks at a %2 speed %3', + + // DXL 제어 + robotis_robotai_lite_dxl_set_mode: 'Set ID %1 motor as %2 mode %3', + robotis_robotai_lite_dxl_each_control: 'Move %1th motor %2° for %3 second', + robotis_robotai_lite_dxl_set_position: + 'Rotate ID %1 motor to angle %3° at speed %2 %4', + robotis_robotai_lite_dxl_set_rotate: '%4 ID %1 motor %3 at speed %2 %4', + robotis_robotai_lite_dxl_set_multiturn_round: + 'Rotate ID %1 motor %3 times %4 at speed %2 %5', + + // AI Camera 값 블록 + robotis_robotai_lite_ai_camera_connection_status: 'AI Camera: If %1', + robotis_robotai_lite_ai_camera_if_detected: 'AI Camera: If %1 is displayed', + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: + 'AI Camera: %2 of the %1 closest to the center of the screen', + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: + 'AI Camera: %1 of the arrow closest to the center of the screen', + robotis_robotai_lite_ai_camera_number_of_learned_id: + 'AI Camera: the number of learned ID', + robotis_robotai_lite_ai_camera_block_value_of_id: + 'AI Camera: %3 of %2 with detected ID %1', + robotis_robotai_lite_ai_camera_arrow_value_of_id: + 'AI Camera: %2 of arrow with detected ID %1', + + robotis_robotai_lite_ai_camera_if_learned_id: + 'AI Camera: If learned data with ID %1', + robotis_robotai_lite_ai_camera_if_detected_id_type: + 'AI Camera: If learned %2 data with ID %1', + + // AI 카메라 제어 + robotis_robotai_lite_ai_camera_set_mode: 'AI Camera: Set mode to %1 %2', + robotis_robotai_lite_ai_camera_print_custom_text: + 'AI Camera: Display %3 at screen position (%1, %2) %4', + robotis_robotai_lite_ai_camera_clear_custom_text: + 'AI Camera: Clear screen text %1', + }, + Blocks: { + // 주행 제어 + robotis_robotai_lite_drive_simple: + 'Drive the robot at the specified speed and direction\nSpeed range: -100 ~ 100\nSpeed unit: %', + robotis_robotai_lite_drive_advanced: + 'Rotate the left and right wheels of the robot at the specified speed and direction\nSpeed range: -100 ~ 100\nSpeed unit: %', + robotis_robotai_lite_drive_seperate: + 'Rotate the specified wheel of the robot at the specified speed and direction\nSpeed range: -100 ~ 100\nSpeed unit: %', + robotis_robotai_lite_drive_angle: + 'Rotate the specified wheel of the robot in the specified direction and by the specified angle\nAngle range: -5760 ~ 5760\nAngle unit: degrees', + robotis_robotai_lite_go_distance: + 'Move forward or backward by the specified distance\nDistance range: -1000 ~ 1000\nDistance unit: mm', + robotis_robotai_lite_turn_angle: + 'Rotate in place by the specified angle and direction\nAngle range: -360 ~ 360\nAngle unit: degrees', + robotis_robotai_lite_follow_line: + 'Start following the line at the specified speed', + robotis_robotai_lite_stop_at_cross: 'Stop at the specified intersection', + robotis_robotai_lite_turn_at_line: + 'Make the specified turn at the intersection and stop', + robotis_robotai_lite_drive_stop: 'Stop the robot', + + robotis_robotai_lite_securitybot_init: + 'Initializes the security robot. Sets both motors to joint mode and the camera to face recognition mode.', + robotis_robotai_lite_securitybot_hi: + 'The security robot displays the message "User identified" on the screen and waves its arms up and down.', + robotis_robotai_lite_securitybot_alert: + 'The security robot displays the message "Not a user" on the screen and shakes its body from side to side.', + + robotis_robotai_lite_petbot_happy: + 'The pet robot makes a smiling face, says "I’m happy," and spins around in place.', + robotis_robotai_lite_petbot_sad: + 'The pet robot makes an angry face, says "I’m scared," and moves 5cm backward.', + + robotis_robotai_lite_farmbot_init: + 'Initializes the smart farm robot. Moves motor 1 to the starting position and sets the camera to color recognition mode.', + robotis_robotai_lite_farmbot_seek: 'Moves closer when it detects crops.', + robotis_robotai_lite_farmbot_plant_type: 'Identifies the type of crop.', + robotis_robotai_lite_farmbot_harvest_or_not_and_go: + 'Decides whether to harvest the crop or not, then rotates to the right.', + + // 값 블록 + robotis_robotai_lite_cm_ir_value: + 'IR sensor value of the specified number (range: 0 ~ 200)', + robotis_robotai_lite_cm_ir_compare: + "If the IR sensor value of the specified number matches the specified value, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_detectFrontObj: + "It returns 'true' if an object is detected by the infrared sensor in the specified direction; otherwise, it returns 'false'.", + robotis_robotai_lite_cm_btn_value: + "If the specified button is clicked, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_cm_joystick_value: + "If the joystick position is in the specified state, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_mic: + 'Displays the intensity of the sound detected by the microphone in decibels (dB).', + robotis_robotai_lite_detectSound_compare: + "If the direction of the sound matches the specified direction, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_imu: + 'Value of the specified accelerometer/gyro sensor on the specified axis\nRange: -100 ~ 100', + robotis_robotai_lite_roll_pitch: + 'roll/pitch value\nroll: -180° ~ 180°, pitch: -90° ~ 90°', + robotis_robotai_lite_environment_value: + 'Value of the specified sensor\nMotion sensor: 0 (no movement) / 1 (movement)\nBrightness range: 0 ~ 100%\nTemperature range: -25°C ~ 85°C', + robotis_robotai_lite_environment_compare: + "If the specified equation of the specified sensor value is correct, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_line_cross_compare: + "If the specified intersection shape is correct, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_dxl_value: + 'Position angle value of the specified motor\nRange: -180° ~ 180°', + + // 소리 + robotis_robotai_lite_scale_simple: + 'Play with the specified octave, scale, and note', + robotis_robotai_lite_scale_advanced: + 'Play with the specified octave, scale, and beat', + robotis_robotai_lite_rest_simple: 'Rest for the specified rest note', + robotis_robotai_lite_rest_advanced: 'Rest for the specified beat', + robotis_robotai_lite_beat_per_minute: + 'Set the playing speed (BPM)\nRange: 10 ~ 600', + robotis_robotai_lite_Hello: 'Play the specified voice of the robot', + robotis_robotai_lite_effectSound: + 'Play the specified sound effect of the robot', + robotis_robotai_lite_record: + 'Record and save to the specified number storage', + robotis_robotai_lite_playRecord: + 'Play the recorded voice in the specified number storage', + + // LCD 제어 + robotis_robotai_lite_screen: + 'Set the character and expression of the controller screen background', + robotis_robotai_lite_anim_screen: + 'Set the character and expression of the controller screen animation', + robotis_robotai_lite_icon_screen_food_plant: + 'Set the position and size of a specific icon in [food/plant] on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_icon_screen_animal_human: + 'Set the position and size of a specific icon in [animal/human] on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_icon_screen_object_tool: + 'Set the position and size of a specific icon in [object/tool] on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_icon_screen_vehicle_number: + 'Set the position and size of a specific icon in [vehicle/number] on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_text_screen: + 'Set the position, font size, and color of the specified text on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120', + robotis_robotai_lite_text_screen_redraw: + 'Set the position and color of the specified text to be newly displayed (clearing the background of the text) on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_pixel: + 'Set the position and color of the dot to be displayed on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120', + robotis_robotai_lite_LCDBright: + 'Set the screen brightness\nBrightness range: 0% ~ 100%', + robotis_robotai_lite_LCDColor: 'Set the screen color', + robotis_robotai_lite_LCD_Flash: + 'Specify two colors and the interval for the screen to blink.', + + // LED 제어 + robotis_robotai_lite_cm_led: + 'Turn the specified LED of the controller on or off', + robotis_robotai_lite_cm_led_pattern: + 'Set the blinking pattern of LEDs of the controller', + + // DXL 제어 + robotis_robotai_lite_dxl_set_mode: + 'Set the operating mode of the motor with the specified ID', + robotis_robotai_lite_dxl_each_control: + 'Set the motor with the specified ID to move to the specified angle for the specified time (seconds)', + robotis_robotai_lite_dxl_set_position: + 'Set the motor with the specified ID to move to the specified angle at the specified speed', + robotis_robotai_lite_dxl_set_rotate: + 'Set the rotation speed and direction of the motor with the specified ID', + robotis_robotai_lite_dxl_set_multiturn_round: + 'Set the motor with the specified ID to rotate the specified number of turns at the specified speed and direction', + + // AI Camera 값 블록 + robotis_robotai_lite_ai_camera_connection_status: + "If the AI camera is connected, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_ai_camera_if_detected: + "If the selected symbol (rectangle/arrow) is displayed on the LCD screen of the AI camera, it is determined as 'true'; otherwise, 'false'.", + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: + 'X coordinate/Y coordinate/width/height/learning ID of the rectangle closest to the center of the AI camera screen', + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: + 'Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate/learning ID of the arrow closest to the center of the AI camera screen', + robotis_robotai_lite_ai_camera_number_of_learned_id: + 'Number of IDs learned by the AI camera', + robotis_robotai_lite_ai_camera_block_value_of_id: + 'X coordinate/Y coordinate/width/height of the rectangle with the specified ID detected by the AI camera', + robotis_robotai_lite_ai_camera_arrow_value_of_id: + 'Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate of the arrow with the specified ID detected by the AI camera', + + robotis_robotai_lite_ai_camera_if_learned_id: + "If the AI camera has learned the data of the specified ID, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_ai_camera_if_detected_id_type: + "If the AI camera has learned the specified data (rectangle/arrow) of the specified ID, it is determined as 'true'; otherwise, 'false'.", + + // AI 카메라 제어 + robotis_robotai_lite_ai_camera_set_mode: 'Set the mode of the AI camera', + robotis_robotai_lite_ai_camera_print_custom_text: + 'Print the specified text at the specified position on the AI camera screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120', + robotis_robotai_lite_ai_camera_clear_custom_text: + 'Clear all the text displayed on the AI camera screen', + }, + + Blocks: { + robotis_red: 'Red', + robotis_orange: 'Orange', + robotis_yellow: 'Yellow', + robotis_green: 'Green', + robotis_blue: 'Blue', + robotis_brown: 'Brown', + robotis_black: 'Black', + robotis_white: 'White', + robotis_left: 'Left', + robotis_center: 'Center', + robotis_right: 'Right', + robotis_both: 'Both', + robotis_rgee: 'R-GEE', + robotis_rla: 'KODALA', + robotis_kkokdu: 'TIG', + robotis_korean1: 'Hello!', + robotis_korean2: 'Great to see you.', + robotis_korean3: 'Okay ~', + robotis_korean4: 'No!', + robotis_korean5: "I don't know.", + robotis_korean6: 'I like it.', + robotis_korean7: "I don't like it.", + robotis_korean8: 'What is your name? ', + robotis_korean9: 'How can I help you? ', + robotis_korean10: 'Great job! ', + robotis_korean11: "It's alright.", + robotis_korean12: "Let's do it again! ", + robotis_korean13: 'Thank you! ', + robotis_korean14: 'Can you say that one more time?', + robotis_korean15: 'Awesome!', + robotis_korean16: "I'm excited! ", + robotis_korean17: "I'm having a great time! ", + robotis_korean18: "I'm sorry.", + robotis_korean19: "I'm angry! ", + robotis_korean20: "I'm embarassed.", + robotis_korean21: "I'm scared.", + robotis_korean22: "I'm upset.", + robotis_korean23: 'I love you.', + robotis_korean24: 'Very pretty! ', + robotis_korean25: 'Interesting.', + robotis_korean26: "I'm nervous.", + robotis_korean27: "Let's move forward! ", + robotis_korean28: "Let's move backward! ", + robotis_korean29: "Let's stand up! ", + robotis_korean30: 'Did you fall down? ', + robotis_korean31: 'Oh Yeah~', + robotis_korean32: 'Sweet! ', + robotis_korean33: 'Oh no', + robotis_korean34: 'My My ', + robotis_korean35: 'Whoo hoo! ', + robotis_korean36: 'Ha Ha Ha', + robotis_korean37: 'Ho Ho Ho ', + robotis_korean38: "I'm sleepy.", + robotis_korean39: 'Sing me a bedtime song! ', + robotis_korean40: 'Hello!', + robotis_korean41: "I'm hungry.", + robotis_korean42: "I'm craving an acorn! ", + robotis_korean43: 'I want to take a bath! ', + robotis_korean44: 'Time for a bath! ', + robotis_korean45: "I'm bored. ", + robotis_korean46: 'Do you want a snack? ', + robotis_korean47: "I'm sick.", + robotis_korean48: 'Do you have any medicine? ', + robotis_korean49: 'Where do we have to go? ', + robotis_korean50: "We're here! ", + robotis_korean51: "Let's go to the left side! ", + robotis_korean52: "Let's go to the right side! ", + robotis_korean53: 'Oh my, you scared me! ', + robotis_korean54: 'Found you! ', + robotis_korean55: "There's nothing here. ", + robotis_korean56: 'Did you call me?', + robotis_korean57: 'Please let me down. ', + robotis_korean58: 'Oops! ', + robotis_korean59: 'Hmmph! ', + robotis_korean60: 'Eek! ', + robotis_dog: 'Dog', + robotis_frog: 'Frog', + robotis_cat: 'Cat', + robotis_chicken: 'Rooster', + robotis_tiger: 'Tiger', + robotis_mouse: 'Mouse', + robotis_ambul: 'Ambulance', + robotis_Horn: 'CarHorn', + robotis_siren: 'Siren', + robotis_whistle: 'Whistle', + robotis_gun: 'Gunshot', + robotis_clap: 'Clap', + robotis_melody1: 'Melody1', + robotis_melody2: 'Melody2', + robotis_melody3: 'Melody3', + robotis_melody4: 'Melody4', + robotis_forward: 'Forward', + robotis_backward: 'Backward', + robotis_acceleration: 'acceleration', + robotis_gyro: 'gyro', + robotis_run: 'Run', + robotis_cancel: 'Cancel', + robotis_push: 'Pressed', + robotis_notPush: 'Unpressed', + robotis_play: 'Play', + robotis_rest: 'Rest', + robotis_face01: 'Haha', + robotis_face02: 'Smile', + robotis_face03: 'Laugh', + robotis_face04: 'Yum Yum', + robotis_face05: 'Scared', + robotis_face06: 'Uncomfortable', + robotis_face07: 'Confused', + robotis_face08: 'Dazed', + robotis_face09: 'Yell', + robotis_face10: 'Angry', + robotis_face11: 'Sniff (Left)', + robotis_face12: 'Sniff (Right)', + robotis_face13: 'Sniff (Down)', + robotis_face14: 'Whew', + robotis_face15: 'Faint', + robotis_face16: 'Dizzy', + robotis_face17: 'Yawn', + robotis_face18: 'Sleepy', + robotis_face19: 'Sleep', + robotis_face20: 'Sad', + robotis_face21: 'Cry', + robotis_face22: 'Bath', + robotis_face23: 'Heart-Eyes', + robotis_flashing1: 'Flashing1', + robotis_flashing2: 'Flashing2', + robotis_flashing3: 'Flashing3', + robotis_flashing4: 'Flashing4', + robotis_flashing5: 'Flashing5', + robotis_flashing6: 'Flashing6', + robotis_flashing7: 'Flashing7', + robotis_flashing8: 'Flashing8', + robotis_flashing9: 'Flashing9', + robotis_moveF: 'Forward', + robotis_moveB: 'Backward', + robotis_moveL: 'LeftTurn', + robotis_moveR: 'RightTurn', + robotis_moveU: 'U-turn', + robotis_moveL_in_place: 'Turn left in place', + robotis_moveR_in_place: 'Trun right in place', + robotis_moveU_in_place: 'U-turn in place', + robotis_moveRG1: 'Stand', + robotis_moveRG2: 'Sit', + robotis_moveRG3: 'Struggle', + robotis_moveRG4: 'RaiseFeet', + robotis_stop: 'Stop', + robotis_roll: 'Left-right rotate angle (roll)', + robotis_pitch: 'Forward-backward rotate angle (pitch)', + robotis_direction_forward: 'Forward', + robotis_direction_backward: 'Backward', + robotis_stMotion1: 'Standard', + robotis_stMotion2: 'Forward', + robotis_stMotion3: 'TurnRight', + robotis_stMotion4: 'TurnLeft', + robotis_stMotion5: 'Backward', + robotis_stMotion6: 'ToRight', + robotis_stMotion7: 'ToLeft', + robotis_stMotion8: 'TurnAroundRight', + robotis_stMotion9: 'TurnAroundLeft', + robotis_spMotion1: 'RightHandUp', + robotis_spMotion2: 'RightHandDown', + robotis_spMotion3: 'LeftHandUp', + robotis_spMotion4: 'LeftHandDown', + robotis_spMotion5: 'BothHandsUp', + robotis_spMotion6: 'BothHandsDown', + robotis_spMotion7: 'FallBackward', + robotis_spMotion8: 'FallForward', + robotis_spMotion9: 'StandForward', + robotis_spMotion10: 'StandBackward', + robotis_spMotion11: 'Defence', + robotis_spMotion12: 'Offense1', + robotis_spMotion13: 'Offense2', + robotis_spMotion14: 'Offense3', + robotis_spMotion15: 'Offense4', + robotis_screen1: 'Sissor', + robotis_screen2: 'Rock', + robotis_screen3: 'Paper', + robotis_dxl_mode_joint: 'Joint', + robotis_dxl_mode_wheel: 'Wheel', + robotis_dxl_mode_multi_turn: 'Multi-turn', + robotis_dxl_move_rotate: 'Rotate', + robotis_dxl_move_stop: 'Stop', + robotis_dxl_rotate_cw: 'clockwise', + robotis_dxl_rotate_ccw: 'counter clockwise', + robotis_dxl_value_angle: 'angle', + robotis_dxl_value_velocity: 'velocity', + robotis_dxl_value_moving: 'moving', + robotis_icon_food_plant_1: 'Milk', + robotis_icon_food_plant_2: 'Tree', + robotis_icon_food_plant_3: 'Soup', + robotis_icon_food_plant_4: 'Cake', + robotis_icon_food_plant_5: 'Water', + robotis_icon_food_plant_6: 'Juice', + robotis_icon_food_plant_7: 'Carrot', + robotis_icon_food_plant_8: 'Apple', + robotis_icon_food_plant_9: 'Orange', + robotis_icon_food_plant_10: 'Meat', + robotis_icon_food_plant_11: 'Flowerpot', + robotis_icon_food_plant_12: 'Rose', + robotis_icon_food_plant_13: 'Grape', + robotis_icon_food_plant_14: 'Potato', + robotis_icon_food_plant_15: 'Candy', + robotis_icon_food_plant_16: 'Cheese', + robotis_icon_food_plant_17: 'Bread', + robotis_icon_food_plant_18: 'Flowers', + robotis_icon_food_plant_19: 'Coffee', + robotis_icon_food_plant_20: 'Tulip', + robotis_icon_food_plant_21: 'Banana', + robotis_icon_food_plant_22: 'Fruits', + robotis_icon_food_plant_23: 'Hamburger', + robotis_icon_food_plant_24: 'Pizza', + robotis_icon_animal_human_1: 'Shiba Dog', + robotis_icon_animal_human_2: 'Puppy', + robotis_icon_animal_human_3: 'Bear', + robotis_icon_animal_human_4: 'Bird', + robotis_icon_animal_human_5: 'Duck', + robotis_icon_animal_human_6: 'Lion', + robotis_icon_animal_human_7: 'Tiger', + robotis_icon_animal_human_8: 'Horse', + robotis_icon_animal_human_9: 'Sheep', + robotis_icon_animal_human_10: 'Shark 1 (Left)', + robotis_icon_animal_human_11: 'Shark 1 (Right)', + robotis_icon_animal_human_12: 'Shark 2 (Left)', + robotis_icon_animal_human_13: 'Shark 2 (Right)', + robotis_icon_animal_human_14: 'Fish 1', + robotis_icon_animal_human_15: 'Fish 2', + robotis_icon_animal_human_16: 'Fish 3', + robotis_icon_animal_human_17: 'Octopus', + robotis_icon_animal_human_18: 'Monkey', + robotis_icon_animal_human_19: 'Chicken', + robotis_icon_animal_human_20: 'Pig', + robotis_icon_animal_human_21: 'Person (Chubby)', + robotis_icon_animal_human_22: 'Person (Swimsuit)', + robotis_icon_animal_human_23: 'Baby', + robotis_icon_animal_human_24: 'Person (Running)', + robotis_icon_animal_human_25: 'Person (Singing)', + robotis_icon_animal_human_26: 'Person (Sitting)', + robotis_icon_animal_human_27: 'Person (Angry)', + robotis_icon_animal_human_28: 'Person (Cheering)', + robotis_icon_animal_human_29: 'King', + robotis_icon_animal_human_30: 'Prince', + robotis_icon_animal_human_31: 'Princess', + robotis_icon_animal_human_32: 'Chef', + robotis_icon_animal_human_33: 'Doctor', + robotis_icon_animal_human_34: 'Nurse', + robotis_icon_object_tool_1: 'Bag', + robotis_icon_object_tool_2: 'Box', + robotis_icon_object_tool_3: 'Mug', + robotis_icon_object_tool_4: 'Hat (Fedora)', + robotis_icon_object_tool_5: 'Hat (Cap)', + robotis_icon_object_tool_6: 'Key', + robotis_icon_object_tool_7: 'Toy', + robotis_icon_object_tool_8: 'Book', + robotis_icon_object_tool_9: 'Teddy Bear', + robotis_icon_object_tool_10: 'Drum', + robotis_icon_object_tool_11: 'Notebook', + robotis_icon_object_tool_12: 'Pen', + robotis_icon_object_tool_13: 'Desk', + robotis_icon_object_tool_14: 'Table', + robotis_icon_object_tool_15: 'Chair', + robotis_icon_object_tool_16: 'Bed', + robotis_icon_object_tool_17: 'Tent', + robotis_icon_object_tool_18: 'Plate', + robotis_icon_object_tool_19: 'Soccer Ball', + robotis_icon_object_tool_20: 'Bell', + robotis_icon_object_tool_21: 'Watch', + robotis_icon_object_tool_22: 'Shoes', + robotis_icon_object_tool_23: 'Lamp', + robotis_icon_object_tool_24: 'Radio', + robotis_icon_object_tool_25: 'Banknote', + robotis_icon_object_tool_26: 'Ruler', + robotis_icon_object_tool_27: 'Camera', + robotis_icon_object_tool_28: 'Spoon', + robotis_icon_object_tool_29: 'Keyboard', + robotis_icon_object_tool_30: 'Calendar', + robotis_icon_object_tool_31: 'Knife', + robotis_icon_object_tool_32: 'Balloon', + robotis_icon_object_tool_33: 'Water Bottle', + robotis_icon_object_tool_34: 'Wooden Stick (Horizontal)', + robotis_icon_object_tool_35: 'Wooden Stick (Vertical)', + robotis_icon_object_tool_36: 'Fishing Hook', + robotis_icon_vehicle_number_1: 'Car', + robotis_icon_vehicle_number_2: 'Bus', + robotis_icon_vehicle_number_3: 'Truck', + robotis_icon_vehicle_number_4: 'Jeep', + robotis_icon_vehicle_number_5: 'Bicycle', + robotis_icon_vehicle_number_6: 'Subway', + robotis_icon_vehicle_number_7: 'Train', + robotis_icon_vehicle_number_8: 'Airplane', + robotis_icon_vehicle_number_9: 'Fighter Jet (Vertical)', + robotis_icon_vehicle_number_10: 'Fighter Jet (Horizontal)', + robotis_icon_vehicle_number_11: 'Rocket', + robotis_icon_vehicle_number_12: 'Fishing Boat', + robotis_icon_vehicle_number_13: 'Passenger Ship', + robotis_icon_vehicle_number_14: 'Submarine (Left)', + robotis_icon_vehicle_number_15: 'Submarine (Right)', + robotis_icon_vehicle_number_16: 'Airplane (Left)', + robotis_icon_vehicle_number_17: 'Airplane (Right)', + robotis_icon_vehicle_number_18: 'Airplane (Top)', + robotis_icon_vehicle_number_19: 'Spaceship (Left)', + robotis_icon_vehicle_number_20: 'Spaceship (Right)', + robotis_icon_vehicle_number_21: 'Spaceship (Top)', + robotis_icon_vehicle_number_22: 'Dice (1)', + robotis_icon_vehicle_number_23: 'Dice (2)', + robotis_icon_vehicle_number_24: 'Dice (3)', + robotis_icon_vehicle_number_25: 'Dice (4)', + robotis_icon_vehicle_number_26: 'Dice (5)', + robotis_icon_vehicle_number_27: 'Dice (6)', + robotis_icon_vehicle_number_28: '0', + robotis_icon_vehicle_number_29: '1', + robotis_icon_vehicle_number_30: '2', + robotis_icon_vehicle_number_31: '3', + robotis_icon_vehicle_number_32: '4', + robotis_icon_vehicle_number_33: '5', + robotis_icon_vehicle_number_34: '6', + robotis_icon_vehicle_number_35: '7', + robotis_icon_vehicle_number_36: '8', + robotis_icon_vehicle_number_37: '9', + robotis_icon_vehicle_number_38: '10', + robotis_speed_fast: 'Fast Speed', + robotis_speed_midium: 'Medium Speed', + robotis_speed_slow: 'Slow Speed', + robotis_clockwise: 'Clockwise', + robotis_counterclockwise: 'Counterclockwise', + robotis_up: 'Lift', + robotis_down: 'Lower', + robotis_if_greater: 'If Greater', + robotis_if_smaller: 'If Smaller', + robotis_if_equal: 'If Equal', + robotis_front_right: 'Front Right', + robotis_front_left: 'Front Left', + robotis_bottom_right: 'Bottom Right', + robotis_bottom_left: 'Bottom Left', + robotis_side_right: 'Right Edge', + robotis_side_left: 'Left Edge', + robotis_front_ir_sensor: 'Infrared Sensor', + robotis_distance_sensor: 'Distance Sensor', + robotis_front: 'Front', + robotis_right: 'Right', + robotis_left_wheel: 'Left Wheel', + robotis_right_wheel: 'Right Wheel', + robotis_beat_sound_8th_note: 'Eighth Note (♪)', + robotis_beat_sound_dotted_8th_note: 'Dotted Eighth Note (♪.)', + robotis_beat_sound_quarter_note: 'Quarter Note (♩)', + robotis_beat_sound_dotted_quarter_note: 'Dotted Quarter Note (♩.)', + robotis_beat_sound_half_note: 'Half Note (𝅗𝅥)', + robotis_beat_sound_dotted_half_note: 'Dotted Half Note (𝅗𝅥.)', + robotis_beat_sound_whole_note: 'Whole Note (𝅝)', + robotis_beat_sound_dotted_note: 'Dotted Whole Note (𝅝.)', + robotis_beat_rest_8th_note: 'Eighth Rest (𝄾)', + robotis_beat_rest_dotted_8th_note: 'Dotted Eighth Rest (𝄾.)', + robotis_beat_rest_quarter_note: 'Quarter Rest (𝄽)', + robotis_beat_rest_dotted_quarter_note: 'Dotted Quarter Rest (𝄽.)', + robotis_beat_rest_half_note: 'Half Rest (𝄼)', + robotis_beat_rest_dotted_half_note: 'Dotted Half Rest (𝄼˙)', + robotis_beat_rest_whole_note: 'Whole Rest (𝄻)', + robotis_beat_rest_dotted_note: 'Dotted Whole Rest (𝄻˙)', + robotis_line_cross_type_0: '|', + robotis_line_cross_type_1: ' (Blank)', + robotis_line_cross_type_5: '🞣', + robotis_line_cross_type_6: '⏉', + robotis_line_cross_type_7: '⊣', + robotis_line_cross_type_8: '⊢', + robotis_line_cross_type_9: '⏋', + robotis_line_cross_type_10: '⎾', + robotis_line_cross_type_11: '¦', + robotis_line_cross_type_12: '︙', + robotis_connected: 'Connected', + robotis_disconnected: 'Not connected', + robotis_ai_camera_mode_face_recognition: 'Face recognition', + robotis_ai_camera_mode_object_tracking: 'Object tracking', + robotis_ai_camera_mode_object_recognition: 'Object recognition', + robotis_ai_camera_mode_line_recognition: 'Line tracking', + robotis_ai_camera_mode_color_recognition: 'Color recognition', + robotis_ai_camera_mode_tag_recognition: 'Tag recognition', + robotis_ai_camera_mode_object_classification: 'Object classification', + robotis_ai_camera_target_block: 'Rectangle', + robotis_ai_camera_target_arrow: 'Arrow', + robotis_ai_camera_center_block_center_x: 'Center X', + robotis_ai_camera_center_block_center_y: 'Center Y', + robotis_ai_camera_center_block_width: 'Width', + robotis_ai_camera_center_block_height: 'Height', + robotis_ai_camera_center_leared_id: 'Learned ID', + robotis_ai_camera_center_arrow_origin_x: 'Origin X', + robotis_ai_camera_center_arrow_origin_y: 'Origin Y', + robotis_ai_camera_center_arrow_target_x: 'Target X', + robotis_ai_camera_center_arrow_target_y: 'Target Y', + + robotis_plant_ripe: 'ripe in red', + robotis_plant_unripe: 'green and unripe', + robotis_harvest: 'Harvest', + robotis_not_harvest: 'Skip harvesting', + }, + }, + }; + } + getBlocks() { + return { + robotis_robotai_lite_drive_simple: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveF, '1'], + [Lang.Blocks.robotis_moveB, '2'], + [Lang.Blocks.robotis_moveL_in_place, '3'], + [Lang.Blocks.robotis_moveR_in_place, '4'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [5, null, null], + type: 'robotis_robotai_lite_drive_simple', + }, + paramsKeyMap: { + SPEED: 0, + DIRECTION: 1, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + const speed = script.getNumberValue('SPEED', script); + const direction = script.getField('DIRECTION', script); + + const data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + const data_address = 710; + const data_length = 2; + let data_value = 0; + + switch (direction) { + case '1': + data_value = speed * 256 + speed; + break; + case '2': + data_value = (256 - speed) * 256 + (256 - speed); + break; + case '3': + data_value = speed * 256 + (256 - speed); + break; + case '4': + data_value = (256 - speed) * 256 + speed; + break; + default: + data_value = 0; + break; + } + + const data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.go_simple(%1, %2)'], + }, + }, + robotis_robotai_lite_drive_stop: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_drive_stop', + }, + paramsKeyMap: { + DIRECTION: 0, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 710; + let data_length = 2; + let data_value = 0; + + let data_sendqueue = [ + [data_instruction, 5200, 1, 0], + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.stop(%1, %2)'], + }, + }, + robotis_robotai_lite_drive_advanced: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveF, '1'], + [Lang.Blocks.robotis_moveB, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveF, '1'], + [Lang.Blocks.robotis_moveB, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['5'], + }, + null, + { + type: 'number', + params: ['5'], + }, + null, + ], + type: 'robotis_robotai_lite_drive_advanced', + }, + paramsKeyMap: { + LEFT_SPEED: 0, + LEFT_DIRECTION: 1, + RIGHT_SPEED: 2, + RIGHT_DIRECTION: 3, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let leftSpeed = script.getNumberValue('LEFT_SPEED', script); + const leftDirection = script.getField('LEFT_DIRECTION', script); + let rightSpeed = script.getNumberValue('RIGHT_SPEED', script); + const rightDirection = script.getField('RIGHT_DIRECTION', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 710; + let data_length = 2; + let data_value = 0; + + if (leftSpeed < -100) { + leftSpeed = -100; + } else if (leftSpeed > 100) { + leftSpeed = 100; + } + + if (rightSpeed < -100) { + rightSpeed = -100; + } else if (rightSpeed > 100) { + rightSpeed = 100; + } + + if (leftDirection == '2') { + leftSpeed = -leftSpeed; + } + if (rightDirection == '2') { + rightSpeed = -rightSpeed; + } + + if (leftSpeed < 0) { + leftSpeed = 256 + leftSpeed; + } + if (rightSpeed < 0) { + rightSpeed = 256 + rightSpeed; + } + + data_value = leftSpeed + rightSpeed * 256; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.go_advanced(%1, %2)'], + }, + }, + robotis_robotai_lite_drive_seperate: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left, '1'], + [Lang.Blocks.robotis_right, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_direction_forward, '1'], + [Lang.Blocks.robotis_direction_backward, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['5'], + }, + null, + ], + type: 'robotis_robotai_lite_drive_seperate', + }, + paramsKeyMap: { + WHEEL_SIDE: 0, + WHEEL_SPEED: 1, + WHEEL_DIRECTION: 2, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let wheelSide = script.getNumberValue('WHEEL_SIDE', script); + let wheelSpeed = script.getNumberValue('WHEEL_SPEED', script); + let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script); + + let leftSpeed = 0; + let rightSpeed = 0; + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 710; + let data_length = 2; + let data_value = 0; + + if (wheelSpeed < -100) { + wheelSpeed = -100; + } else if (wheelSpeed > 100) { + wheelSpeed = 100; + } + + wheelSpeed = (wheelSpeed + 256) % 256; + if (wheelDirection == '2') { + wheelSpeed = (256 - wheelSpeed) % 256; + } + + if (wheelSide == 1) { + leftSpeed = wheelSpeed; + rightSpeed = 127; // 속도제어 안함 + } else { + leftSpeed = 127; // 속도제어 안함 + rightSpeed = wheelSpeed; + } + + data_value = leftSpeed + rightSpeed * 256; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 25 //DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.go_seperate(%1, %2)'], + }, + }, + robotis_robotai_lite_drive_angle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left, '1'], + [Lang.Blocks.robotis_right, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_direction_forward, '1'], + [Lang.Blocks.robotis_direction_backward, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['15'], + }, + null, + ], + type: 'robotis_robotai_lite_drive_angle', + }, + paramsKeyMap: { + WHEEL_SIDE: 0, + WHEEL_ANGLE: 1, + WHEEL_DIRECTION: 2, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let wheelSide = script.getNumberValue('WHEEL_SIDE', script); + let wheelAngle = script.getNumberValue('WHEEL_ANGLE', script); + let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script); + + const data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 580; + let data_length = 8; + let angleValue = 0; + let id = 51 + wheelSide; + let data_buf = []; + let i = 0; + let speed = 150; + + if (wheelDirection == '2') { + wheelAngle = -wheelAngle; + } + + wheelAngle = Math.round((wheelAngle * 4096) / 360); + + if (wheelAngle > 65535) { + wheelAngle = 65535; + } else if (wheelAngle < -65535) { + wheelAngle = -65535; + } + + angleValue = wheelAngle; + if (wheelAngle < 0) { + angleValue = 65536 + angleValue; + } + + data_buf.push(id); + data_buf.push(0); + data_buf.push(speed % 256); + data_buf.push(Math.floor(speed / 256)); + data_buf.push(angleValue % 256); + data_buf.push(Math.floor(angleValue / 256) % 256); + if (wheelAngle >= 0) { + data_buf.push(0); + data_buf.push(0); + } else { + data_buf.push(0xff); + data_buf.push(0xff); + } + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.go_angle(%1, %2)'], + }, + }, + robotis_robotai_lite_go_distance: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveF, '1'], + [Lang.Blocks.robotis_moveB, '-1'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['10'], + }, + null, + ], + type: 'robotis_robotai_lite_go_distance', + }, + + paramsKeyMap: { + DISTANCE: 0, + DIRECTION: 1, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(entity, script) { + let distance = script.getNumberValue('DISTANCE', script); + let direction = script.getField('DIRECTION', script); + + if (distance > 1000) { + distance = 1000; + } else if (distance < -1000) { + distance = -1000; + } + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 270; + let data_length = 4; + let data_value = Math.floor(10 * distance * direction); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + data_sendqueue.push([data_instruction, 66, 2, 50491]); + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 150 * Math.abs(distance) + 1200 + //DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.dxl_each_control(%1)'] }, + }, + + robotis_robotai_lite_turn_angle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveL_in_place, '1'], + [Lang.Blocks.robotis_moveR_in_place, '-1'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['90'], + }, + null, + ], + type: 'robotis_robotai_lite_turn_angle', + }, + + paramsKeyMap: { + ANGLE: 0, + DIRECTION: 1, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(entity, script) { + let angle = script.getNumberValue('ANGLE', script); + let direction = script.getNumberValue('DIRECTION', script); + + angle *= direction; + + if (angle > 720) { + angle = 720; + } else if (angle < -720) { + angle = -720; + } + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 270; + let data_length = 4; + let data_value = Math.floor(angle); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + data_sendqueue.push([data_instruction, 66, 2, 50492]); + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + Math.abs(angle) * 16 + 1500 + //DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.dxl_each_control(%1)'] }, + }, + robotis_robotai_lite_follow_line: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['느린', '1'], + ['보통', '2'], + ['빠른', '3'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_follow_line', + }, + paramsKeyMap: { + SPEED: 0, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let speed_level = script.getNumberValue('SPEED', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 5200; + let data_length = 1; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, speed_level], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.follow_line(%1)'], + }, + }, + robotis_robotai_lite_stop_at_cross: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_line_cross_type_5, '5'], + [Lang.Blocks.robotis_line_cross_type_6, '6'], + [Lang.Blocks.robotis_line_cross_type_7, '7'], + [Lang.Blocks.robotis_line_cross_type_8, '8'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_stop_at_cross', + }, + paramsKeyMap: { + CROSS: 0, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + async func(sprite, script) { + // instruction / address / length / value / default length + let cross_type = script.getNumberValue('CROSS', script); + let data_address = 5201; + + // max 10 seconds + for (let i = 0; i < 100; i++) { + await Entry.Utils.sleep(100); + if (Entry.RobotisRobotaiLite.dataBuffer[data_address] == cross_type) { + break; + } + if (Entry.engine.isState('stop') == true) { + break; + } + } + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 5200, 1, 0]]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.stop_at_cross(%1)'], + }, + }, + robotis_robotai_lite_turn_at_line: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveL_in_place, '0'], + [Lang.Blocks.robotis_moveR_in_place, '1'], + [Lang.Blocks.robotis_moveU_in_place, '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_turn_at_line', + }, + paramsKeyMap: { + TURN_TYPE: 0, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let turn_type = script.getNumberValue('TURN_TYPE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 66; + let data_length = 2; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, 50045 + turn_type], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.follow_line(%1)'], + }, + }, + robotis_robotai_lite_securitybot_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_securitybot_init', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2110, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 1100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.securitybot_init()'], + }, + }, + robotis_robotai_lite_securitybot_hi: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_securitybot_hi', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2111, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotailite.securitybot_hi()'], + }, + }, + robotis_robotai_lite_securitybot_alert: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_securitybot_alert', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2112, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotailite.securitybot_alert()'], + }, + }, + robotis_robotai_lite_petbot_happy: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_petbot_happy', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2121, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 7100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.petbot_happy()'], + }, + }, + robotis_robotai_lite_petbot_sad: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_petbot_sad', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2122, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 2500 + ); + }, + syntax: { + js: [], + py: ['Robotailite.petbot_sad()'], + }, + }, + + robotis_robotai_lite_farmbot_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_farmbot_init', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2130, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_init()'], + }, + }, + robotis_robotai_lite_farmbot_seek: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_farmbot_seek', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2131, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn(script, data_sendqueue, 200); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_seek()'], + }, + }, + robotis_robotai_lite_farmbot_plant_type: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_plant_ripe, '1'], + [Lang.Blocks.robotis_plant_unripe, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_farmbot_plant_type', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let compareValue = script.getNumberValue('TYPE'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[2134]; + + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotis.farmbot_is_type(%1)'], + }, + }, + robotis_robotai_lite_farmbot_harvest_or_not_and_go: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_harvest, '1'], + [Lang.Blocks.robotis_not_harvest, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_farmbot_harvest_or_not_and_go', + }, + paramsKeyMap: { + ACTION: 0, + }, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let action = script.getNumberValue('ACTION', script); + let address = 2132; + let wait_time = 6000; + + switch (action) { + case 1: + address = 2132; + wait_time = 6000; + break; + + case 2: + address = 2133; + wait_time = 1600; + break; + } + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, address, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + wait_time + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_harvest_or_not_and_go(%1)'], + }, + }, + + robotis_robotai_lite_cm_ir_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_front_right, '360'], + [Lang.Blocks.robotis_front_left, '362'], + [Lang.Blocks.robotis_bottom_right, '364'], + [Lang.Blocks.robotis_bottom_left, '366'], + [Lang.Blocks.robotis_side_right, '368'], + [Lang.Blocks.robotis_side_left, '370'], + ], + value: '360', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_cm_ir_value', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + const scope = script.executor.scope; + + const data_default_address = script.getNumberValue('VALUE'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_default_address]; + if (result == undefined) { + result = rb100_last_valid_value[data_default_address]; + } else { + rb100_last_valid_value[data_default_address] = result; + } + if (typeof result == 'undefined') { + return 0; + } + return Math.round((result % 65536) / 2); + }, + syntax: { + js: [], + py: ['Robotailite.ir_value(%1)'], + }, + }, + robotis_robotai_lite_cm_ir_compare: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_front_right, '360'], + [Lang.Blocks.robotis_front_left, '362'], + [Lang.Blocks.robotis_bottom_right, '364'], + [Lang.Blocks.robotis_bottom_left, '366'], + [Lang.Blocks.robotis_side_right, '368'], + [Lang.Blocks.robotis_side_left, '370'], + ], + value: '360', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_if_greater, '0'], + [Lang.Blocks.robotis_if_smaller, '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, 50, null], + type: 'robotis_robotai_lite_cm_ir_compare', + }, + paramsKeyMap: { + VALUE: 0, + COMPARE_VAL: 1, + COMPARE_OP: 2, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = script.getNumberValue('VALUE'); + let compareValue = script.getNumberValue('COMPARE_VAL'); + let compareOP = script.getNumberValue('COMPARE_OP'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (result == undefined) { + return false; + } + + result = Math.round((result % 65536) / 2); + + switch (compareOP) { + case 0: + return result > compareValue; + case 1: + return result < compareValue; + default: + return false; + } + }, + syntax: { + js: [], + py: ['Robotailite.ir_compare(%1)'], + }, + }, + robotis_robotai_lite_detectFrontObj: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_front, '0'], + [Lang.Blocks.robotis_right, '1'], + [Lang.Blocks.robotis_left, '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_detectFrontObj', + }, + paramsKeyMap: { + DIRECTION: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + // instruction / address / length / value / default length + let direction = script.getNumberValue('DIRECTION'); + let ir_1 = 0; + let ir_2 = 0; + + if (direction == 0) { + ir_1 = Entry.RobotisRobotaiLite.dataBuffer[360]; + ir_2 = Entry.RobotisRobotaiLite.dataBuffer[362]; + if (ir_1 == undefined) { + ir_1 = 0; + } + if (ir_2 == undefined) { + ir_2 = 0; + } + return ir_1 > 100 || ir_2 > 100; + } else if (direction == 1) { + ir_1 = Entry.RobotisRobotaiLite.dataBuffer[368]; + if (ir_1 == undefined) { + ir_1 = 0; + } + return ir_1 > 100; + } else if (direction == 2) { + ir_1 = Entry.RobotisRobotaiLite.dataBuffer[370]; + if (ir_1 == undefined) { + ir_1 = 0; + } + return ir_1 > 100; + } + }, + syntax: { + js: [], + py: ['Robotailite.detectFrontObj()'], + }, + }, + robotis_robotai_lite_cm_btn_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_blue, '47'], + [Lang.Blocks.robotis_red, '44'], + ], + value: '47', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_cm_btn_value', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = script.getNumberValue('VALUE'); + let compareValue = 1; + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.btn_value(%1)'], + }, + }, + robotis_robotai_lite_cm_joystick_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_center, '0'], + ['←', '1'], + ['→', '2'], + ['↑', '3'], + ['↓', '4'], + ['↖', '5'], + ['↗', '6'], + ['↙', '7'], + ['↘', '8'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_cm_joystick_value', + }, + paramsKeyMap: { + COMPARE_VAL: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 50; + let compareValue = script.getNumberValue('COMPARE_VAL', script); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.joystick_value()'], + }, + }, + robotis_robotai_lite_mic: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_mic', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + async func(sprite, script) { + let scope = script.executor.scope; + let data_address = 119; + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + return result; + }, + syntax: { + js: [], + py: ['Robotailite.mic()'], + }, + }, + robotis_robotai_lite_detectSound_compare: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left, '1'], + [Lang.Blocks.robotis_center, '0'], + [Lang.Blocks.robotis_right, '255'], + ], + value: '255', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_detectSound_compare', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 5031; + let compareValue = script.getNumberValue('VALUE'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.detectSound_compare(%1)'], + }, + }, + robotis_robotai_lite_imu: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['x', '78'], //72 + ['y', '80'], //74 + ['z', '82'], //76 + ], + value: '78', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_acceleration, '0'], //72 + [Lang.Blocks.robotis_gyro, '6'], //74 + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_imu', + }, + paramsKeyMap: { + AXIS: 0, + MODE: 1, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = + script.getField('AXIS', script) - script.getField('MODE', script); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + return result; + }, + syntax: { + js: [], + py: ['Robotailite.imu()'], + }, + }, + robotis_robotai_lite_roll_pitch: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_roll, '70'], //72 + [Lang.Blocks.robotis_pitch, '88'], //74 + ], + value: '70', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_roll_pitch', + }, + paramsKeyMap: { + AXIS: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = script.getNumberValue('AXIS'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + return result; + }, + syntax: { + js: [], + py: ['Robotailite.roll_pitch(%1)'], + }, + }, + robotis_robotai_lite_environment_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_sensing_temperature, '28'], + [Lang.Blocks.robotis_sensing_humidity, '29'], + [Lang.Blocks.robotis_sensing_brightness, '30'], + [Lang.Blocks.robotis_sensing_motion, '27'], + ], + value: '28', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_environment_value', + }, + paramsKeyMap: { + ADDR: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = script.getNumberValue('ADDR'); + + let result = 0; + + switch (data_address) { + case 28: + result = Entry.RobotisRobotaiLite.pirTemperature[0]; + break; + + case 29: + result = Entry.RobotisRobotaiLite.pirHumidity[0]; + break; + + case 30: + result = Entry.RobotisRobotaiLite.pirBrightness[0]; + break; + + case 27: + result = Entry.RobotisRobotaiLite.pirPir[0]; + break; + } + + if (typeof result == 'undefined') { + return 0; + } else { + // temperature + if (data_address == 28) { + result = result % 256; + if (result > 128) { + result = result - 256; + } + } + } + return result; + }, + syntax: { + js: [], + py: ['Robotailite.environment_value(%1)'], + }, + }, + robotis_robotai_lite_environment_compare: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_sensing_temperature, '28'], + [Lang.Blocks.robotis_sensing_humidity, '29'], + [Lang.Blocks.robotis_sensing_brightness, '30'], + [Lang.Blocks.robotis_sensing_motion, '27'], + ], + value: '28', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + value: 'asdfasdf', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_if_greater, '0'], + [Lang.Blocks.robotis_if_smaller, '1'], + [Lang.Blocks.robotis_if_equal, '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: [0], + }, + null, + ], + type: 'robotis_robotai_lite_environment_compare', + }, + paramsKeyMap: { + ADDR: 0, + COMPARE_VAL: 1, + COMPARE_OP: 2, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + let data_address = script.getNumberValue('ADDR'); + let compareValue = script.getNumberValue('COMPARE_VAL'); + let compareOP = script.getNumberValue('COMPARE_OP'); + + let result = 0; + + switch (data_address) { + case 28: + result = Entry.RobotisRobotaiLite.pirTemperature[0]; + break; + + case 29: + result = Entry.RobotisRobotaiLite.pirHumidity[0]; + break; + + case 30: + result = Entry.RobotisRobotaiLite.pirBrightness[0]; + break; + + case 27: + result = Entry.RobotisRobotaiLite.pirPir[0]; + break; + } + + if (typeof result == 'undefined') { + return false; + } + + switch (compareOP) { + case 0: + return result > compareValue; + case 1: + return result < compareValue; + case 2: + return result == compareValue; + default: + return false; + } + }, + syntax: { + js: [], + py: ['Robotailite.environment_compare(%1)'], + }, + }, + robotis_robotai_lite_dxl_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_value_angle, '1'], + [Lang.Blocks.robotis_dxl_value_velocity, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [52, null], + type: 'robotis_robotai_lite_dxl_value', + }, + paramsKeyMap: { + ID: 0, + TYPE: 1, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + let dxl_id = script.getNumberValue('ID'); + //var data_type = script.getNumberValue('TYPE'); + + let result = Entry.RobotisRobotaiLite.dxlPositions[dxl_id]; + + if (typeof result == 'undefined') { + return 0; + } + result = 180 - Math.round((result * 360) / 4096); + while (result < -180) { + result += 360; + } + while (result > 180) { + result -= 360; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.get_dxl_value(%1)'], + }, + }, + robotis_robotai_lite_line_cross_compare: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_line_cross_type_5, '5'], + [Lang.Blocks.robotis_line_cross_type_6, '6'], + [Lang.Blocks.robotis_line_cross_type_7, '7'], + [Lang.Blocks.robotis_line_cross_type_8, '8'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_line_cross_compare', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 5201; + let compareValue = script.getNumberValue('VALUE'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.line_cross_compare(%1)'], + }, + }, + + robotis_robotai_lite_screen: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_kkokdu, '3'], + [Lang.Blocks.robotis_rla, '2'], + [Lang.Blocks.robotis_rgee, '0'], + ], + value: '3', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_car_anim01, '2817'], + [Lang.Blocks.robotis_car_anim02, '2818'], + [Lang.Blocks.robotis_car_anim03, '2819'], + [Lang.Blocks.robotis_car_anim04, '2820'], + [Lang.Blocks.robotis_car_anim05, '2821'], + + [Lang.Blocks.robotis_car_anim06, '2822'], + //[Lang.Blocks.robotis_car_anim07, '2823'], + [Lang.Blocks.robotis_car_anim08, '2824'], + [Lang.Blocks.robotis_car_anim09, '2825'], + [Lang.Blocks.robotis_car_anim10, '2826'], + + [Lang.Blocks.robotis_car_anim11, '2827'], + [Lang.Blocks.robotis_car_anim12, '2828'], + //[Lang.Blocks.robotis_car_anim13, '2829'], + [Lang.Blocks.robotis_car_anim14, '2830'], + [Lang.Blocks.robotis_car_anim15, '2831'], + + [Lang.Blocks.robotis_car_anim16, '2832'], + [Lang.Blocks.robotis_car_anim17, '2833'], + [Lang.Blocks.robotis_car_anim18, '2834'], + [Lang.Blocks.robotis_car_anim19, '2835'], + ], + value: '2817', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_screen', + }, + paramsKeyMap: { + ROBOT_TYPE: 0, + BACKGROUND: 1, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let robotType = script.getNumberValue('ROBOT_TYPE', script); + let screenValue = script.getNumberValue('BACKGROUND', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 163; + let data_length = 2; + let data_value = screenValue + robotType * 256; + + if (robotType == 0) { + switch (screenValue) { + case 2817: + data_value = 2841; + break; + + case 2818: + data_value = 2842; + break; + + case 2819: + data_value = 2820; + break; + + case 2820: + data_value = 2817; + break; + + case 2821: + data_value = 2819; + break; + + case 2822: + data_value = 2818; + break; + + //case 2823: + // break; + + case 2824: + data_value = 2826; + break; + + case 2825: + data_value = 2836; + break; + + case 2826: + data_value = 2837; + break; + + case 2827: + data_value = 2843; + break; + + case 2828: + data_value = 2831; + break; + + //case 2829: + // break; + + case 2830: + data_value = 2833; + break; + + case 2831: + data_value = 2834; + break; + + case 2832: + data_value = 2828; + break; + + case 2833: + data_value = 2827; + break; + + case 2834: + data_value = 2829; + break; + + case 2835: + data_value = 2840; + break; + + default: + data_value = 2841; + break; + } + } + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + [3, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { js: [], py: ['Robotailite.screen(%1)'] }, + }, + + robotis_robotai_lite_anim_screen: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_kkokdu, '1'], + [Lang.Blocks.robotis_rla, '0'], + [Lang.Blocks.robotis_rgee, '-1'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_car_anim01, '30978'], + [Lang.Blocks.robotis_car_anim02, '30981'], + //[Lang.Blocks.robotis_car_anim03, '30982'], + [Lang.Blocks.robotis_car_anim04, '30983'], + [Lang.Blocks.robotis_car_anim05, '30984'], + + [Lang.Blocks.robotis_car_anim06, '30985'], + [Lang.Blocks.robotis_car_anim07, '30986'], + [Lang.Blocks.robotis_car_anim08, '30987'], + [Lang.Blocks.robotis_car_anim09, '30988'], + [Lang.Blocks.robotis_car_anim10, '30989'], + + [Lang.Blocks.robotis_car_anim11, '30990'], + [Lang.Blocks.robotis_car_anim12, '30991'], + //[Lang.Blocks.robotis_car_anim13, '30992'], + [Lang.Blocks.robotis_car_anim14, '30993'], + [Lang.Blocks.robotis_car_anim15, '30994'], + + [Lang.Blocks.robotis_car_anim16, '30995'], + [Lang.Blocks.robotis_car_anim17, '30996'], + [Lang.Blocks.robotis_car_anim18, '30997'], + [Lang.Blocks.robotis_car_anim19, '30998'], + ], + value: '30978', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_anim_screen', + }, + paramsKeyMap: { + ROBOT_TYPE: 0, + BACKGROUND: 1, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let robotType = script.getNumberValue('ROBOT_TYPE', script); + let screenValue = script.getNumberValue('BACKGROUND', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 163; + let data_length = 2; + let data_value = screenValue; + + if (robotType >= 0) { + data_value += 256 * robotType; + } else { + switch (screenValue) { + case 30978: + data_value = 30724; + break; + + case 30981: + data_value = 30761; + break; + + //case 30982: + // break; + + case 30983: + data_value = 30748; + break; + + case 30984: + data_value = 30750; + break; + + case 30985: + data_value = 30749; + break; + + //case 30986: + // break; + + case 30987: + data_value = 30739; + break; + + case 30988: + data_value = 30751; + break; + + case 30989: + data_value = 30752; + break; + + case 30990: + data_value = 30762; + break; + + case 30991: + data_value = 30736; + break; + + //case 30992: + // break; + + case 30993: + data_value = 30742; + break; + + case 30994: + data_value = 30743; + break; + + case 30995: + data_value = 30734; + break; + + case 30996: + data_value = 30733; + break; + + case 30997: + data_value = 30732; + break; + + case 30998: + data_value = 30760; + break; + + default: + data_value = 30724; + break; + } + } + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + [3, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY //+ 1000 + ); + }, + syntax: { js: [], py: ['Robotailite.animation_screen(%1)'] }, + }, + robotis_robotai_lite_icon_screen_food_plant: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_icon_food_plant_1, '10496'], + [Lang.Blocks.robotis_icon_food_plant_2, '10497'], + [Lang.Blocks.robotis_icon_food_plant_3, '10498'], + [Lang.Blocks.robotis_icon_food_plant_4, '10499'], + [Lang.Blocks.robotis_icon_food_plant_5, '10500'], + [Lang.Blocks.robotis_icon_food_plant_6, '10501'], + [Lang.Blocks.robotis_icon_food_plant_7, '10502'], + [Lang.Blocks.robotis_icon_food_plant_8, '10503'], + [Lang.Blocks.robotis_icon_food_plant_9, '10504'], + [Lang.Blocks.robotis_icon_food_plant_10, '10505'], + [Lang.Blocks.robotis_icon_food_plant_11, '10506'], + [Lang.Blocks.robotis_icon_food_plant_12, '10507'], + [Lang.Blocks.robotis_icon_food_plant_13, '10508'], + [Lang.Blocks.robotis_icon_food_plant_14, '10509'], + [Lang.Blocks.robotis_icon_food_plant_15, '10510'], + [Lang.Blocks.robotis_icon_food_plant_16, '10511'], + [Lang.Blocks.robotis_icon_food_plant_17, '10512'], + [Lang.Blocks.robotis_icon_food_plant_18, '10513'], + [Lang.Blocks.robotis_icon_food_plant_19, '10514'], + [Lang.Blocks.robotis_icon_food_plant_20, '10515'], + [Lang.Blocks.robotis_icon_food_plant_21, '10516'], + [Lang.Blocks.robotis_icon_food_plant_22, '10517'], + [Lang.Blocks.robotis_icon_food_plant_23, '10518'], + [Lang.Blocks.robotis_icon_food_plant_24, '10519'], + ], + value: '10496', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 50, + null, + ], + type: 'robotis_robotai_lite_icon_screen_food_plant', + }, + paramsKeyMap: { + ICON: 0, + X: 1, + Y: 2, + SIZE: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let iconNum = script.getField('ICON', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let size = script.getNumberValue('SIZE', script) * 2; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 166; + let data_length = 2; + let data_value = 10496; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + if (size < 0) { + size = 0; + } else if (size > 400) { + size = 400; + } + + data_value = iconNum; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size], + [data_instruction, data_address, data_length, data_value], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.icon_screen_food_and_plant(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_icon_screen_animal_human: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_icon_animal_human_1, '10752'], + [Lang.Blocks.robotis_icon_animal_human_2, '10753'], + [Lang.Blocks.robotis_icon_animal_human_3, '10754'], + [Lang.Blocks.robotis_icon_animal_human_4, '10755'], + [Lang.Blocks.robotis_icon_animal_human_5, '10756'], + [Lang.Blocks.robotis_icon_animal_human_6, '10757'], + [Lang.Blocks.robotis_icon_animal_human_7, '10758'], + [Lang.Blocks.robotis_icon_animal_human_8, '10759'], + [Lang.Blocks.robotis_icon_animal_human_9, '10760'], + [Lang.Blocks.robotis_icon_animal_human_10, '11787'], + [Lang.Blocks.robotis_icon_animal_human_11, '11788'], + [Lang.Blocks.robotis_icon_animal_human_12, '11789'], + [Lang.Blocks.robotis_icon_animal_human_13, '11790'], + [Lang.Blocks.robotis_icon_animal_human_14, '11805'], + [Lang.Blocks.robotis_icon_animal_human_15, '11806'], + [Lang.Blocks.robotis_icon_animal_human_16, '11807'], + [Lang.Blocks.robotis_icon_animal_human_17, '11808'], + [Lang.Blocks.robotis_icon_animal_human_18, '10761'], + [Lang.Blocks.robotis_icon_animal_human_19, '10762'], + [Lang.Blocks.robotis_icon_animal_human_20, '10763'], + [Lang.Blocks.robotis_icon_animal_human_21, '10764'], + [Lang.Blocks.robotis_icon_animal_human_22, '10765'], + [Lang.Blocks.robotis_icon_animal_human_23, '10766'], + [Lang.Blocks.robotis_icon_animal_human_24, '10767'], + [Lang.Blocks.robotis_icon_animal_human_25, '10768'], + [Lang.Blocks.robotis_icon_animal_human_26, '10769'], + [Lang.Blocks.robotis_icon_animal_human_27, '10770'], + [Lang.Blocks.robotis_icon_animal_human_28, '10771'], + [Lang.Blocks.robotis_icon_animal_human_29, '10772'], + [Lang.Blocks.robotis_icon_animal_human_30, '10773'], + [Lang.Blocks.robotis_icon_animal_human_31, '10774'], + [Lang.Blocks.robotis_icon_animal_human_32, '10775'], + [Lang.Blocks.robotis_icon_animal_human_33, '10776'], + [Lang.Blocks.robotis_icon_animal_human_34, '10777'], + ], + value: '10752', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 50, + null, + ], + type: 'robotis_robotai_lite_icon_screen_animal_human', + }, + paramsKeyMap: { + ICON: 0, + X: 1, + Y: 2, + SIZE: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let iconNum = script.getField('ICON', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let size = script.getNumberValue('SIZE', script) * 2; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 166; + let data_length = 2; + let data_value = 10496; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + if (size < 0) { + size = 0; + } else if (size > 400) { + size = 400; + } + + data_value = iconNum; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size], + [data_instruction, data_address, data_length, data_value], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.icon_screen_animal_and_human(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_icon_screen_object_tool: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_icon_object_tool_1, '11008'], + [Lang.Blocks.robotis_icon_object_tool_2, '11009'], + [Lang.Blocks.robotis_icon_object_tool_3, '11010'], + [Lang.Blocks.robotis_icon_object_tool_4, '11011'], + [Lang.Blocks.robotis_icon_object_tool_5, '11012'], + [Lang.Blocks.robotis_icon_object_tool_6, '11013'], + [Lang.Blocks.robotis_icon_object_tool_7, '11014'], + [Lang.Blocks.robotis_icon_object_tool_8, '11015'], + [Lang.Blocks.robotis_icon_object_tool_9, '11016'], + [Lang.Blocks.robotis_icon_object_tool_10, '11017'], + [Lang.Blocks.robotis_icon_object_tool_11, '11018'], + [Lang.Blocks.robotis_icon_object_tool_12, '11019'], + [Lang.Blocks.robotis_icon_object_tool_13, '11020'], + [Lang.Blocks.robotis_icon_object_tool_14, '11021'], + [Lang.Blocks.robotis_icon_object_tool_15, '11022'], + [Lang.Blocks.robotis_icon_object_tool_16, '11023'], + [Lang.Blocks.robotis_icon_object_tool_17, '11024'], + [Lang.Blocks.robotis_icon_object_tool_18, '11025'], + [Lang.Blocks.robotis_icon_object_tool_19, '11026'], + [Lang.Blocks.robotis_icon_object_tool_20, '11027'], + [Lang.Blocks.robotis_icon_object_tool_21, '11028'], + [Lang.Blocks.robotis_icon_object_tool_22, '11029'], + [Lang.Blocks.robotis_icon_object_tool_23, '11030'], + [Lang.Blocks.robotis_icon_object_tool_24, '11031'], + [Lang.Blocks.robotis_icon_object_tool_25, '11032'], + [Lang.Blocks.robotis_icon_object_tool_26, '11033'], + [Lang.Blocks.robotis_icon_object_tool_27, '11034'], + [Lang.Blocks.robotis_icon_object_tool_28, '11035'], + [Lang.Blocks.robotis_icon_object_tool_29, '11036'], + [Lang.Blocks.robotis_icon_object_tool_30, '11037'], + [Lang.Blocks.robotis_icon_object_tool_31, '11038'], + [Lang.Blocks.robotis_icon_object_tool_32, '11039'], + [Lang.Blocks.robotis_icon_object_tool_33, '11040'], + [Lang.Blocks.robotis_icon_object_tool_34, '11801'], + [Lang.Blocks.robotis_icon_object_tool_35, '11802'], + [Lang.Blocks.robotis_icon_object_tool_36, '11809'], + ], + value: '11008', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 50, + null, + ], + type: 'robotis_robotai_lite_icon_screen_object_tool', + }, + paramsKeyMap: { + ICON: 0, + X: 1, + Y: 2, + SIZE: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let iconNum = script.getField('ICON', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let size = script.getNumberValue('SIZE', script) * 2; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 166; + let data_length = 2; + let data_value = 10496; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + if (size < 0) { + size = 0; + } else if (size > 400) { + size = 400; + } + + data_value = iconNum; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size], + [data_instruction, data_address, data_length, data_value], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.icon_screen_object_and_tool(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_icon_screen_vehicle_number: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_icon_vehicle_number_1, '11264'], + [Lang.Blocks.robotis_icon_vehicle_number_2, '11265'], + [Lang.Blocks.robotis_icon_vehicle_number_3, '11266'], + [Lang.Blocks.robotis_icon_vehicle_number_4, '11267'], + [Lang.Blocks.robotis_icon_vehicle_number_5, '11268'], + [Lang.Blocks.robotis_icon_vehicle_number_6, '11269'], + [Lang.Blocks.robotis_icon_vehicle_number_7, '11270'], + [Lang.Blocks.robotis_icon_vehicle_number_8, '11271'], + [Lang.Blocks.robotis_icon_vehicle_number_9, '11272'], + [Lang.Blocks.robotis_icon_vehicle_number_10, '11273'], + [Lang.Blocks.robotis_icon_vehicle_number_11, '11274'], + [Lang.Blocks.robotis_icon_vehicle_number_12, '11275'], + [Lang.Blocks.robotis_icon_vehicle_number_13, '11276'], + [Lang.Blocks.robotis_icon_vehicle_number_14, '11776'], + [Lang.Blocks.robotis_icon_vehicle_number_15, '11777'], + [Lang.Blocks.robotis_icon_vehicle_number_16, '11778'], + [Lang.Blocks.robotis_icon_vehicle_number_17, '11779'], + [Lang.Blocks.robotis_icon_vehicle_number_18, '11780'], + [Lang.Blocks.robotis_icon_vehicle_number_19, '11781'], + [Lang.Blocks.robotis_icon_vehicle_number_20, '11782'], + [Lang.Blocks.robotis_icon_vehicle_number_21, '11783'], + [Lang.Blocks.robotis_icon_vehicle_number_22, '11277'], + [Lang.Blocks.robotis_icon_vehicle_number_23, '11278'], + [Lang.Blocks.robotis_icon_vehicle_number_24, '11279'], + [Lang.Blocks.robotis_icon_vehicle_number_25, '11280'], + [Lang.Blocks.robotis_icon_vehicle_number_26, '11281'], + [Lang.Blocks.robotis_icon_vehicle_number_27, '11282'], + [Lang.Blocks.robotis_icon_vehicle_number_28, '11283'], + [Lang.Blocks.robotis_icon_vehicle_number_29, '11284'], + [Lang.Blocks.robotis_icon_vehicle_number_30, '11285'], + [Lang.Blocks.robotis_icon_vehicle_number_31, '11286'], + [Lang.Blocks.robotis_icon_vehicle_number_32, '11287'], + [Lang.Blocks.robotis_icon_vehicle_number_33, '11288'], + [Lang.Blocks.robotis_icon_vehicle_number_34, '11289'], + [Lang.Blocks.robotis_icon_vehicle_number_35, '11290'], + [Lang.Blocks.robotis_icon_vehicle_number_36, '11291'], + [Lang.Blocks.robotis_icon_vehicle_number_37, '11292'], + [Lang.Blocks.robotis_icon_vehicle_number_38, '11293'], + ], + value: '11264', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 50, + null, + ], + type: 'robotis_robotai_lite_icon_screen_vehicle_number', + }, + paramsKeyMap: { + ICON: 0, + X: 1, + Y: 2, + SIZE: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let iconNum = script.getField('ICON', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let size = script.getNumberValue('SIZE', script) * 2; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 166; + let data_length = 2; + let data_value = 10496; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + if (size < 0) { + size = 0; + } else if (size > 400) { + size = 400; + } + + data_value = iconNum; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size], + [data_instruction, data_address, data_length, data_value], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.icon_screen_vehicle_and_number(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_text_screen: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_screen_text_font_small, '0'], + [Lang.Blocks.robotis_screen_text_font_big, '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + ' ', + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + null, + null, + ], + type: 'robotis_robotai_lite_text_screen', + }, + paramsKeyMap: { + TEXT: 0, + X: 1, + Y: 2, + FONT: 3, + COLOR: 4, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let text = script.getStringValue('TEXT', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let font = script.getNumberValue('FONT', script); + let color = script.getNumberValue('COLOR', script); + let data_buf = []; + let i = 0; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 900; + let data_length = 2; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + let encoder = new TextEncoder('utf-8'); + let byteArray = encoder.encode(text); + + data_buf.push(x % 256); + data_buf.push(Math.floor(x / 256)); + data_buf.push(y % 256); + data_buf.push(Math.floor(y / 256)); + data_buf.push(font); + data_buf.push(0); + data_buf.push(0); + data_buf.push(color); + data_buf.push(byteArray.length); + for (i = 0; i < byteArray.length; i++) { + data_buf.push(byteArray[i]); + } + + data_length = 9 + byteArray.length; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.text_screen(%1,%2,%3,%4,%5)'], + }, + }, + robotis_robotai_lite_pixel: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + null, + ], + type: 'robotis_robotai_lite_pixel', + }, + paramsKeyMap: { + X: 0, + Y: 1, + COLOR: 2, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let color = script.getNumberValue('COLOR', script); + let data_buf = []; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 130; + let data_length = 11; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + data_buf.push(x % 256); + data_buf.push(Math.floor(x / 256)); + data_buf.push(y % 256); + data_buf.push(Math.floor(y / 256)); + data_buf.push(0); + data_buf.push(0); + data_buf.push(0); + data_buf.push(0); + data_buf.push(0); + data_buf.push(0); + data_buf.push(color); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 161, 2, 1 * 256 + 8], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.pixel(%1,%2,%3)'], + }, + }, + robotis_robotai_lite_text_screen_redraw: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + ' ', + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + null, + ], + type: 'robotis_robotai_lite_text_screen_redraw', + }, + paramsKeyMap: { + TEXT: 0, + X: 1, + Y: 2, + COLOR: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let text = script.getStringValue('TEXT', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let font = 0; + let color = script.getNumberValue('COLOR', script); + let data_buf = []; + let i = 0; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + let encoder = new TextEncoder('utf-8'); + let byteArray = encoder.encode(text); + + data_buf.push(x % 256); + data_buf.push(Math.floor(x / 256)); + data_buf.push(y % 256); + data_buf.push(Math.floor(y / 256)); + data_buf.push(font); + data_buf.push(1); + data_buf.push(bg_color); + data_buf.push(color); + data_buf.push(byteArray.length); + for (i = 0; i < byteArray.length; i++) { + data_buf.push(byteArray[i]); + } + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 900; + let data_length = 9 + byteArray.length; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.text_screen_redraw(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_LCDBright: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [50], + type: 'robotis_robotai_lite_LCDBright', + }, + paramsKeyMap: { + BRIGHT: 0, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let bright = script.getNumberValue('BRIGHT', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 180; + let data_length = 1; + let data_value = 0; + + bright = Math.min(Math.max(bright, 0), 100); + + data_value = bright; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.LCDBright(%1)'], + }, + }, + robotis_robotai_lite_LCDColor: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '224', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_LCDColor', + }, + paramsKeyMap: { + COLOR: 0, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let color = script.getNumberValue('COLOR', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 163; + let data_length = 2; + let data_value = 0; + + data_value = color; + bg_color = color; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 2817], + [data_instruction, data_address, data_length, data_value], + [3, 162, 1, 1], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.LCDColor(%1)'], + }, + }, + robotis_robotai_lite_LCD_Flash: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '224', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [0.3, '3'], + [0.4, '4'], + [0.5, '5'], + [0.6, '6'], + [0.7, '7'], + [0.8, '8'], + [0.9, '9'], + [1.0, '10'], + [1.1, '11'], + [1.2, '12'], + [1.3, '13'], + [1.4, '14'], + [1.5, '15'], + [1.6, '16'], + [1.7, '17'], + [1.8, '18'], + [1.9, '19'], + [2.0, '20'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_LCD_Flash', + }, + paramsKeyMap: { + COLOR_ON: 0, + COLOR_OFF: 1, + PERIOD: 2, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + const color_on = script.getNumberValue('COLOR_ON', script); + const color_off = script.getNumberValue('COLOR_OFF', script); + const period = script.getNumberValue('PERIOD', script); + const colors = color_on + (color_off << 8); + + // 0x8000: use flashing mode, + // (period << 8): on time (0.1 sec) + // period: off time (0.1 sec) + const time_parameter = 0x8000 + (period << 8) + period; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 158, 2, colors], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, time_parameter], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.LCD_Flash(%1, %2, %3)'], + }, + }, + + robotis_robotai_lite_cm_led: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left, '1'], + [Lang.Blocks.robotis_right, '2'], + [Lang.Blocks.robotis_both, '3'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_common_on, '1'], + [Lang.Blocks.robotis_common_off, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null, null], + type: 'robotis_robotai_lite_cm_led', + }, + paramsKeyMap: { + RB_LED: 0, + VALUE: 1, + }, + class: 'robotis_robotai_lite_led', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmLed = script.getField('RB_LED', script); + let value = script.getField('VALUE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 40; + let data_length = 1; + let data_value = 0; + + if (cmLed == 1) { + data_value = 200 * value; + } else if (cmLed == 2) { + data_address = 41; + data_value = 200 * value; + } else if (cmLed == 3) { + data_address = 40; + data_length = 2; + data_value = 200 * 257 * value; + } else { + data_value = value * cmLed; + } + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.led(%1, %2)'] }, + }, + robotis_robotai_lite_cm_led_pattern: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_pattern1, '11'], + [Lang.Blocks.robotis_pattern2, '21'], + [Lang.Blocks.robotis_pattern3, '31'], + ], + value: '11', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_speed_fast, '0'], + [Lang.Blocks.robotis_speed_midium, '1'], + [Lang.Blocks.robotis_speed_slow, '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null, null], + type: 'robotis_robotai_lite_cm_led_pattern', + }, + paramsKeyMap: { + PATTERN: 0, + SPEED: 1, + }, + class: 'robotis_robotai_lite_led', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let pattern = script.getNumberValue('PATTERN', script); + let speed = script.getNumberValue('SPEED', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 40; + let data_length = 1; + let data_value = 0; + + data_value = pattern + speed; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.led_pattern(%1, %2)'] }, + }, + + robotis_robotai_lite_dxl_set_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_mode_joint, '3'], + [Lang.Blocks.robotis_dxl_mode_wheel, '1'], + [Lang.Blocks.robotis_dxl_mode_multi_turn, '4'], + ], + value: '3', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: ['52', null, null], + type: 'robotis_robotai_lite_dxl_set_mode', + }, + paramsKeyMap: { + DXL_ID: 0, + DXL_MODE: 1, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let dxl_id = script.getNumberValue('DXL_ID', script); + let dxl_mode = script.getField('DXL_MODE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE; + let data_address = 0; + let data_length = 0; + let data_value = 0; + + data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[0]; + data_length = Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[1]; + + data_value = dxl_mode; + + let data_sendqueue = [ + [ + data_instruction, + Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0], + Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1], + dxl_id, + 0, + ], + [data_instruction, data_address, data_length, dxl_id, data_value], + [ + data_instruction, + Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0], + Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1], + dxl_id, + 1, + ], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_dxl_mode(%1, %2)'], + }, + }, + robotis_robotai_lite_dxl_each_control: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + '52', + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['1'], + }, + ], + type: 'robotis_robotai_lite_dxl_each_control', + }, + + paramsKeyMap: { + DXLNUM: 0, + ANGLE: 1, + TIME: 2, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(entity, script) { + let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE; + let data_address = 0; + let data_length = 0; + + data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0]; + data_length = + Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] + + Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1]; + + let dxlID = script.getField('DXLNUM', script); + let angle = script.getNumberValue('ANGLE', script); + let time = script.getNumberValue('TIME', script) * 1000; + let data_buf = []; + + let engValue = 2048; + engValue = Math.floor(2048 - Math.round(angle * 4096) / 360); + let velocity = 0; + + if (time == 0) { + velocity = 0; + } else { + velocity = Math.round( + Math.floor( + (60 * + Math.abs( + engValue - Entry.RobotisRobotaiLite.dxlPositions[dxlID] + ) * + 1000) / + 4096 / + time + ) / 0.229 + ); + } + + data_buf.push(velocity % 256); + data_buf.push(Math.floor(velocity / 256)); + data_buf.push(0); + data_buf.push(0); + + data_buf.push(engValue % 256); + data_buf.push(Math.floor(engValue / 256)); + data_buf.push(0); + data_buf.push(0); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, dxlID, data_buf], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + time + DEFAULT_DELAY + //DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.dxl_each_control(%1,%2,%3)'] }, + }, + robotis_robotai_lite_dxl_set_position: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: ['52', '50', '0', null], + type: 'robotis_robotai_lite_dxl_set_position', + }, + paramsKeyMap: { + DXL_ID: 0, + DXL_SPEED: 1, + DXL_ANGLE: 2, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let dxl_id = script.getNumberValue('DXL_ID', script); + let dxl_speed = script.getNumberValue('DXL_SPEED', script); + let dxl_angle = script.getNumberValue('DXL_ANGLE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE; + let data_address = 0; + let data_length = 0; + let data_buf = []; + + data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0]; + data_length = + Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] + + Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1]; + + if (dxl_speed < 0) { + dxl_speed = 0; + } else if (dxl_speed > 100) { + dxl_speed = 100; + } + + data_buf.push((dxl_speed * 10) % 256); + data_buf.push(Math.floor((dxl_speed * 10) / 256)); + data_buf.push(0); + data_buf.push(0); + + if (dxl_angle < -179) { + dxl_angle = -179; + } else if (dxl_angle > 180) { + dxl_angle = 180; + } + + dxl_angle = 180 - dxl_angle; + + data_buf.push(Math.floor((dxl_angle * 4096) / 360) % 256); + data_buf.push(Math.floor((dxl_angle * 4096) / 360 / 256)); + data_buf.push(0); + data_buf.push(0); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, dxl_id, data_buf], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_dxl_position(%1, %2, %3)'], + }, + }, + robotis_robotai_lite_dxl_set_rotate: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_rotate_cw, '1'], + [Lang.Blocks.robotis_dxl_rotate_ccw, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_move_rotate, '1'], + [Lang.Blocks.robotis_dxl_move_stop, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: ['52', '50', null, null, null], + type: 'robotis_robotai_lite_dxl_set_rotate', + }, + paramsKeyMap: { + DXL_ID: 0, + DXL_SPEED: 1, + DXL_DIRECTION: 2, + DXL_MOVE: 3, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let dxl_id = script.getNumberValue('DXL_ID', script); + let dxl_speed = script.getNumberValue('DXL_SPEED', script); + let dxl_direction = script.getNumberValue('DXL_DIRECTION', script); + let dxl_move = script.getNumberValue('DXL_MOVE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE; + let data_address = 0; + let data_length = 0; + let data_value = 0; + + data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[0]; + data_length = Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[1]; + + if (dxl_speed < 0) { + dxl_speed = 0; + } else if (dxl_speed > 100) { + dxl_speed = 100; + } + + data_value = dxl_speed * 10; + + // cw일 경우 음수처리 + if (dxl_direction == 1) { + data_value = -data_value; + } + + // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대 + if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) { + data_value = -data_value; + } + + data_value = data_value * dxl_move; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, dxl_id, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_dxl_rotate(%1, %2, %3, %4)'], + }, + }, + robotis_robotai_lite_dxl_set_multiturn_round: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_rotate_cw, '1'], + [Lang.Blocks.robotis_dxl_rotate_ccw, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: ['52', '50', '1', null, null], + type: 'robotis_robotai_lite_dxl_set_multiturn_round', + }, + paramsKeyMap: { + DXL_ID: 0, + DXL_SPEED: 1, + DXL_ROUND: 2, + DXL_DIRECTION: 3, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let dxl_id = script.getNumberValue('DXL_ID', script); + let dxl_speed = script.getNumberValue('DXL_SPEED', script); + let dxl_round = script.getNumberValue('DXL_ROUND', script); + let dxl_direction = script.getNumberValue('DXL_DIRECTION', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address_1 = 0; + let data_length_1 = 0; + let data_value_1 = 0; + let data_address_2 = 0; + let data_length_2 = 0; + let data_value_2 = 0; + let data_address_3 = 0; + let data_length_3 = 0; + let data_value_3 = 0; + + let data_sendqueue = []; + let result = undefined; + + if (dxl_id == 0 || dxl_speed == 0 || dxl_round == 0) { + return; + } + + data_address_1 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[0]; + data_length_1 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[1]; + + data_address_2 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[0]; + data_length_2 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[1]; + + if (dxl_speed < 0) { + dxl_speed = 0; + } else if (dxl_speed > 100) { + dxl_speed = 100; + } + + data_value_2 = dxl_speed * 10; + + data_address_3 = + Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[0]; + data_length_3 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[1]; + + if (dxl_round < 0) { + dxl_round = 0; + } else if (dxl_round > 100) { + dxl_round = 100; + } + + // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대 + if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) { + dxl_round = -dxl_round; + } + + data_value_3 = dxl_round * 4096; + + if (dxl_direction == 1) { + data_value_3 = -data_value_3; + } + + data_sendqueue = [ + [data_instruction, data_address_1, data_length_1, dxl_id], + [data_instruction, data_address_2, data_length_2, data_value_2], + [data_instruction, data_address_3, data_length_3, data_value_3], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_dxl_multiturn_round(%1, %2, %3, %4)'], + }, + }, + + robotis_robotai_lite_scale_simple: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ], + value: '4', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.General.note_c + '', '1'], + [Lang.General.note_c + '#', '2'], + [Lang.General.note_d + '', '3'], + [Lang.General.note_d + '#', '4'], + [Lang.General.note_e + '', '5'], + [Lang.General.note_f + '', '6'], + [Lang.General.note_f + '#', '7'], + [Lang.General.note_g + '', '8'], + [Lang.General.note_g + '#', '9'], + [Lang.General.note_a + '', '10'], + [Lang.General.note_a + '#', '11'], + [Lang.General.note_b + '', '12'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_beat_sound_8th_note, '3'], + [Lang.Blocks.robotis_beat_sound_dotted_8th_note, '4'], + [Lang.Blocks.robotis_beat_sound_quarter_note, '5'], + [Lang.Blocks.robotis_beat_sound_dotted_quarter_note, '6'], + [Lang.Blocks.robotis_beat_sound_half_note, '7'], + [Lang.Blocks.robotis_beat_sound_dotted_half_note, '8'], + [Lang.Blocks.robotis_beat_sound_whole_note, '9'], + [Lang.Blocks.robotis_beat_sound_dotted_note, '10'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null, null, null], + type: 'robotis_robotai_lite_scale_simple', + }, + paramsKeyMap: { + CM_BUZZER_OCTAV: 0, + CM_BUZZER_INDEX: 1, + CM_BUZZER_NOTE: 2, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script); + let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script); + let cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script); + let cmBuzzerTime = 0; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 0; + let data_value = 0; + let interval = 0; + let data_buf = []; + + switch (cmBuzzerNote) { + case 3: + cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute / 2); + break; + + case 4: + cmBuzzerTime = Math.round( + ((60 * 1000) / beat_per_minute / 2) * 1.5 + ); + break; + + case 5: + cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute); + break; + + case 6: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 1.5); + break; + + case 7: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 2); + break; + + case 8: + cmBuzzerTime = Math.round( + ((60 * 1000) / beat_per_minute) * 2 * 1.5 + ); + break; + + case 9: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 4); + break; + + case 10: + cmBuzzerTime = Math.round( + ((60 * 1000) / beat_per_minute) * 4 * 1.5 + ); + break; + } + + data_address = 740; + // data_value_1 = cmBuzzerTime * 10; + // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력 - console.log(parseInt(0.59 * 10)); max 는 5초 + data_value = cmBuzzerTime; + if (data_value < 0) { + data_value = 0; + } + if (data_value > 50000) { + data_value = 50000; + } + + data_buf.push(data_value % 256); + data_buf.push(Math.floor(data_value / 256)); + + data_value = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12; + data_buf.push(Math.floor(data_value)); + + // console.log("buzzer send"); + let data_sendqueue = [[data_instruction, data_address, 3, data_buf]]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + cmBuzzerTime + interval + ); + }, + syntax: { + js: [], + py: ['Robotailite.scale_simple(%1, %2, %3)'], + }, + }, + robotis_robotai_lite_scale_advanced: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ], + value: '4', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.General.note_c + '', '1'], + [Lang.General.note_c + '#', '2'], + [Lang.General.note_d + '', '3'], + [Lang.General.note_d + '#', '4'], + [Lang.General.note_e + '', '5'], + [Lang.General.note_f + '', '6'], + [Lang.General.note_f + '#', '7'], + [Lang.General.note_g + '', '8'], + [Lang.General.note_g + '#', '9'], + [Lang.General.note_a + '', '10'], + [Lang.General.note_a + '#', '11'], + [Lang.General.note_b + '', '12'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null, 1, null], + type: 'robotis_robotai_lite_scale_advanced', + }, + paramsKeyMap: { + CM_BUZZER_OCTAV: 0, + CM_BUZZER_INDEX: 1, + CM_BUZZER_BEAT: 2, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script); + let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script); + let cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script); + let cmBuzzerTime = 0; + + cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address_1 = 0; + let data_length_1 = 0; + let data_value_1 = 0; + let data_address_2 = 0; + let data_length_2 = 0; + let data_value_2 = 0; + let interval = 0; + + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * cmBuzzerBeat); + + data_address_1 = 740; + data_length_1 = 2; + // data_value_1 = cmBuzzerTime * 10; + // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력 - console.log(parseInt(0.59 * 10)); max 는 5초 + data_value_1 = cmBuzzerTime; + if (data_value_1 < 0) { + data_value_1 = 0; + } + if (data_value_1 > 50000) { + data_value_1 = 50000; + } + + data_address_2 = 742; + data_length_2 = 1; + data_value_2 = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12; + + // console.log("buzzer send"); + let data_sendqueue = [ + [data_instruction, data_address_1, data_length_1, data_value_1], + [data_instruction, data_address_2, data_length_2, data_value_2], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + cmBuzzerTime + interval + ); + }, + syntax: { + js: [], + py: ['Robotailite.scale_advanced(%1, %2, %3)'], + }, + }, + robotis_robotai_lite_rest_simple: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_beat_rest_8th_note, '3'], + [Lang.Blocks.robotis_beat_rest_quarter_note, '5'], + [Lang.Blocks.robotis_beat_rest_half_note, '7'], + [Lang.Blocks.robotis_beat_rest_whole_note, '9'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_rest_simple', + }, + paramsKeyMap: { + CM_BUZZER_NOTE: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script); + let cmBuzzerTime = 0; + + let interval = 0; + + switch (cmBuzzerNote) { + case 3: + cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute / 2); + break; + + case 5: + cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute); + break; + + case 7: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 2); + break; + + case 9: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 4); + break; + } + + let data_sendqueue = []; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + cmBuzzerTime + interval + ); + }, + syntax: { + js: [], + py: ['Robotailite.rest_simple(%1)'], + }, + }, + robotis_robotai_lite_rest_advanced: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [1, null], + type: 'robotis_robotai_lite_rest_advanced', + }, + paramsKeyMap: { + CM_BUZZER_BEAT: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script); + let cmBuzzerTime = 0; + + let interval = 0; + + cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100); + + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * cmBuzzerBeat); + + let data_sendqueue = []; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + cmBuzzerTime + interval + ); + }, + syntax: { + js: [], + py: ['Robotailite.rest_advanced(%1)'], + }, + }, + robotis_robotai_lite_beat_per_minute: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [75, null], + type: 'robotis_robotai_lite_beat_per_minute', + }, + paramsKeyMap: { + CM_BUZZER_BPM: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerBpm = script.getNumberValue('CM_BUZZER_BPM', script); + + beat_per_minute = Math.min(Math.max(cmBuzzerBpm, 10), 600); + + // console.log("buzzer send"); + let data_sendqueue = []; + + return Entry.RobotisRobotaiLite.postCallReturn(script, data_sendqueue, 0); + }, + syntax: { + js: [], + py: ['Robotailite.set_bpm(%1)'], + }, + }, + + robotis_robotai_lite_Hello: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_korean1, '0'], + [Lang.Blocks.robotis_korean2, '1'], + [Lang.Blocks.robotis_korean3, '2'], + [Lang.Blocks.robotis_korean4, '3'], + [Lang.Blocks.robotis_korean5, '4'], + [Lang.Blocks.robotis_korean6, '5'], + [Lang.Blocks.robotis_korean7, '6'], + [Lang.Blocks.robotis_korean8, '7'], + [Lang.Blocks.robotis_korean9, '8'], + [Lang.Blocks.robotis_korean10, '9'], + [Lang.Blocks.robotis_korean11, '10'], + [Lang.Blocks.robotis_korean12, '11'], + [Lang.Blocks.robotis_korean13, '12'], + [Lang.Blocks.robotis_korean14, '13'], + [Lang.Blocks.robotis_korean15, '14'], + [Lang.Blocks.robotis_korean16, '15'], + [Lang.Blocks.robotis_korean17, '16'], + [Lang.Blocks.robotis_korean18, '17'], + [Lang.Blocks.robotis_korean19, '18'], + [Lang.Blocks.robotis_korean20, '19'], + [Lang.Blocks.robotis_korean21, '20'], + [Lang.Blocks.robotis_korean22, '21'], + [Lang.Blocks.robotis_korean23, '22'], + [Lang.Blocks.robotis_korean24, '23'], + [Lang.Blocks.robotis_korean25, '24'], + [Lang.Blocks.robotis_korean26, '25'], + [Lang.Blocks.robotis_korean27, '26'], + [Lang.Blocks.robotis_korean28, '27'], + [Lang.Blocks.robotis_korean29, '28'], + [Lang.Blocks.robotis_korean30, '29'], + [Lang.Blocks.robotis_korean31, '30'], + [Lang.Blocks.robotis_korean32, '31'], + [Lang.Blocks.robotis_korean33, '32'], + [Lang.Blocks.robotis_korean34, '33'], + [Lang.Blocks.robotis_korean35, '34'], + [Lang.Blocks.robotis_korean36, '35'], + [Lang.Blocks.robotis_korean37, '36'], + [Lang.Blocks.robotis_korean38, '37'], + [Lang.Blocks.robotis_korean39, '38'], + [Lang.Blocks.robotis_korean40, '39'], + [Lang.Blocks.robotis_korean41, '40'], + [Lang.Blocks.robotis_korean42, '41'], + [Lang.Blocks.robotis_korean43, '42'], + [Lang.Blocks.robotis_korean44, '43'], + [Lang.Blocks.robotis_korean45, '44'], + [Lang.Blocks.robotis_korean46, '45'], + [Lang.Blocks.robotis_korean47, '46'], + [Lang.Blocks.robotis_korean48, '47'], + [Lang.Blocks.robotis_korean49, '48'], + [Lang.Blocks.robotis_korean50, '49'], + [Lang.Blocks.robotis_korean51, '50'], + [Lang.Blocks.robotis_korean52, '51'], + [Lang.Blocks.robotis_korean53, '52'], + [Lang.Blocks.robotis_korean54, '53'], + [Lang.Blocks.robotis_korean55, '54'], + [Lang.Blocks.robotis_korean56, '55'], + [Lang.Blocks.robotis_korean57, '56'], + [Lang.Blocks.robotis_korean58, '57'], + [Lang.Blocks.robotis_korean59, '58'], + [Lang.Blocks.robotis_korean60, '59'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_Hello', + }, + paramsKeyMap: { + HELLO: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmHello = script.getField('HELLO', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 110; + let data_length = 2; + let data_value = 0; + + data_value = 25601 + Number(cmHello); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + [data_instruction, 0, 2, 0], + ]; + + let extraTime = 0; + + if (cmHello == '38' || cmHello == '55') { + extraTime = 2000; + } + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 2000 + extraTime + ); + }, + syntax: { + js: [], + py: ['Robotailite.speak(%1)'], + }, + }, + robotis_robotai_lite_effectSound: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dog, '0'], + [Lang.Blocks.robotis_frog, '1'], + [Lang.Blocks.robotis_cat, '2'], + [Lang.Blocks.robotis_chicken, '7'], + [Lang.Blocks.robotis_tiger, '19'], + [Lang.Blocks.robotis_mouse, '17'], + + [Lang.Blocks.robotis_ambul, '773'], + [Lang.Blocks.robotis_Horn, '781'], + [Lang.Blocks.robotis_siren, '774'], + [Lang.Blocks.robotis_whistle, '274'], + [Lang.Blocks.robotis_gun, '775'], + [Lang.Blocks.robotis_clap, '260'], + + [Lang.Blocks.robotis_melody1, '786'], + [Lang.Blocks.robotis_melody2, '787'], + [Lang.Blocks.robotis_melody3, '788'], + [Lang.Blocks.robotis_melody4, '789'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_effectSound', + }, + paramsKeyMap: { + HELLO: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmHello = script.getField('HELLO', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 110; + let data_length = 2; + let data_value = 0; + + data_value = Number(cmHello); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + [data_instruction, 0, 2, 0], + ]; + + let extraTime = 0; + if ( + cmHello == '272' || + cmHello == '786' || + cmHello == '787' || + cmHello == '788' || + cmHello == '789' + ) { + //오리 + extraTime = 0; + if (cmHello == '788' || cmHello == '789') { + extraTime += 500; + } + } + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 3000 + extraTime + ); + }, + syntax: { + js: [], + py: ['Robotailite.effect_sound(%1)'], + }, + }, + robotis_robotai_lite_record: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['1', '0'], + ['2', '1'], + ['3', '2'], + ['4', '3'], + ['5', '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_record', + }, + paramsKeyMap: { + ROOM: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let roomNum = script.getField('ROOM', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 115; + let data_length = 1; + let data_value = 0; + + data_value = roomNum; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 6000 + ); + }, + syntax: { + js: [], + py: ['Robotailite.record(%1)'], + }, + }, + robotis_robotai_lite_playRecord: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['1', '0'], + ['2', '1'], + ['3', '2'], + ['4', '3'], + ['5', '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_playRecord', + }, + paramsKeyMap: { + ROOM: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let roomNum = script.getField('ROOM', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 116; + let data_length = 1; + let data_value = 0; + + data_value = roomNum; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 6000 + ); + }, + syntax: { + js: [], + py: ['Robotailite.playRecord(%1)'], + }, + }, + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_target_face, '0'], + [Lang.Blocks.robotis_ai_camera_target_object, '1'], + [Lang.Blocks.robotis_ai_camera_target_color, '2'], + [Lang.Blocks.robotis_ai_camera_target_tag, '3'], + [Lang.Blocks.robotis_ai_camera_target_qr, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'], + [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'], + [Lang.Blocks.robotis_ai_camera_center_block_width, '2'], + [Lang.Blocks.robotis_ai_camera_center_block_height, '3'], + [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_ai_camera_block_value_closest_to_center', + }, + paramsKeyMap: { + TARGET: 0, + DATA_TYPE: 1, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4009; + let data_type = script.getNumberValue('DATA_TYPE'); + data_address += data_type * 2; + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_block_value_closest_to_center(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'], + [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'], + [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'], + [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'], + [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_ai_camera_arrow_value_closest_to_center', + }, + paramsKeyMap: { + DATA_TYPE: 0, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4019; + let data_type = script.getNumberValue('DATA_TYPE'); + data_address += data_type * 2; + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_arrow_value_closest_to_center(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_number_of_learned_id: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [], + events: {}, + def: { + params: [], + type: 'robotis_robotai_lite_ai_camera_number_of_learned_id', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4003; + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_number_of_learned_id()'], + }, + }, + robotis_robotai_lite_ai_camera_block_value_of_id: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_target_face, '0'], + [Lang.Blocks.robotis_ai_camera_target_object, '1'], + [Lang.Blocks.robotis_ai_camera_target_color, '2'], + [Lang.Blocks.robotis_ai_camera_target_tag, '3'], + [Lang.Blocks.robotis_ai_camera_target_qr, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'], + [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'], + [Lang.Blocks.robotis_ai_camera_center_block_width, '2'], + [Lang.Blocks.robotis_ai_camera_center_block_height, '3'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, null, null], + type: 'robotis_robotai_lite_ai_camera_block_value_of_id', + }, + paramsKeyMap: { + ID: 0, + TARGET: 1, + TYPE: 2, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + // instruction / address / length / value / default length + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4029; // ID_FOR_USE + let data_length = 2; + let data_value = script.getNumberValue('ID'); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + + data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER + + data_address += script.getNumberValue('TYPE') * 2; + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_block_value_of_id(%1, %2)'], + }, + }, + robotis_robotai_lite_ai_camera_arrow_value_of_id: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'], + [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'], + [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'], + [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_ai_camera_arrow_value_of_id', + }, + paramsKeyMap: { + ID: 0, + TYPE: 1, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + // instruction / address / length / value / default length + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4029; // ID_FOR_USE + let data_length = 2; + let data_value = script.getNumberValue('ID'); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + + data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN + + data_address += script.getNumberValue('TYPE') * 2; + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_arrow_value_of_id(%1, %2)'], + }, + }, + robotis_robotai_lite_ai_camera_connection_status: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_connected, '1'], + [Lang.Blocks.robotis_disconnected, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_ai_camera_connection_status', + }, + paramsKeyMap: { + STATUS: 0, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4000; + let compareValue = script.getNumberValue('STATUS'); + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_connection_status(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_if_detected: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_target_face, '0'], + [Lang.Blocks.robotis_ai_camera_target_object, '1'], + [Lang.Blocks.robotis_ai_camera_target_color, '2'], + [Lang.Blocks.robotis_ai_camera_target_tag, '3'], + [Lang.Blocks.robotis_ai_camera_target_qr, '4'], + [Lang.Blocks.robotis_ai_camera_target_arrow, '5'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_ai_camera_if_detected', + }, + paramsKeyMap: { + DETECT_TYPE: 0, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4005; // block + let detect_type = script.getNumberValue('DETECT_TYPE'); + + if (detect_type == 5) { + data_address = 4006; + } // arrow + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (result == undefined) { + return false; + } + + return result == 1; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_if_detected(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_set_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_mode_face_recognition, '0'], + [Lang.Blocks.robotis_ai_camera_mode_object_tracking, '1'], + [Lang.Blocks.robotis_ai_camera_mode_object_recognition, '2'], + [Lang.Blocks.robotis_ai_camera_mode_line_tracking, '3'], + [Lang.Blocks.robotis_ai_camera_mode_color_recognition, '4'], + [Lang.Blocks.robotis_ai_camera_mode_tag_recognition, '5'], + [Lang.Blocks.robotis_ai_camera_mode_object_classification, '6'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_ai_camera_set_mode', + }, + paramsKeyMap: { + AI_CAMERA_MODE: 0, + }, + class: 'robotis_robotai_lite_ai_camera_set', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let ai_camera_mode = script.getField('AI_CAMERA_MODE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4001; + let data_length = 1; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, ai_camera_mode], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_ai_camera_mode(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_print_custom_text: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 'Hello!', + ], + type: 'robotis_robotai_lite_ai_camera_print_custom_text', + }, + paramsKeyMap: { + X: 0, + Y: 1, + TEXT: 2, + }, + class: 'robotis_robotai_lite_ai_camera_set', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let text = script.getStringValue('TEXT', script); + let text_len = text.length; + let data_buf = []; + let i = 0; + + if (x < -160) { + x = 160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = 120; + } else if (y > 120) { + y = 120; + } + + if (x < 0) { + x = 65536 + x; + } + if (y < 0) { + y = 65536 + y; + } + + data_buf.push(x % 256); + data_buf.push(Math.floor(x / 256)); + data_buf.push(y % 256); + data_buf.push(Math.floor(y / 256)); + data_buf.push(0); + data_buf.push(0); + for (i = 0; i < text_len; i++) { + data_buf.push(text[i]); + } + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4200; + let data_length = 6 + text_len; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_print_custom_text(%1,%2,%3)'], + }, + }, + robotis_robotai_lite_ai_camera_clear_custom_text: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [], + type: 'robotis_robotai_lite_ai_camera_clear_custom_text', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_ai_camera_set', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4250; + let data_length = 1; + + let data_sendqueue = [[data_instruction, data_address, data_length, 1]]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_clear_custom_text()'], + }, + }, + }; + } + + requestLocalData() { + let packet = null; + if (this.robotisBuffer.length > 0) { + const data = this.robotisBuffer.shift(); + const instruction = data[0]; + const address = data[1]; + const length = data[2]; + const value = data[3]; + const dataBuffer = data[4]; + let id = 0; + + switch (instruction) { + case INST_WRITE: + id = 200; + packet = this.writePacket(id, address, length, value); + break; + case INST_BYPASS_WRITE: + id = value; + packet = this.writePacket(id, address, length, dataBuffer); + break; + } + } + return packet; + } + + handleLocalData(data) { + let stuffLength = 0; + //console.log(`length: ${data.length}`); + for (let i = 0; i < data.length; i++) { + //this.receiveBuffer.push(data[i]); + const dataIn = data[i]; + + switch (this.packetReceiveState) { + case PACKET_STATE_IDLE: + if (this.headerCount >= 2) { + rxPacket.header[2] = dataIn; + + if ( + rxPacket.header[0] == 0xff && + rxPacket.header[1] == 0xff && + rxPacket.header[2] == 0xfd + ) { + this.headerCount = 0; + this.packetReceiveState = PACKET_STATE_RESERVED; + } else { + rxPacket.header[0] = rxPacket.header[1]; + rxPacket.header[1] = rxPacket.header[2]; + rxPacket.header[2] = 0; + } + } else { + rxPacket.header[this.headerCount] = dataIn; + this.headerCount++; + } + break; + + case PACKET_STATE_RESERVED: + if (dataIn == 0xfd) { + this.packetReceiveState = PACKET_STATE_IDLE; + } else { + rxPacket.reserved = dataIn; + this.packetReceiveState = PACKET_STATE_ID; + } + break; + + case PACKET_STATE_ID: + rxPacket.id = dataIn; + this.packetReceiveState = PACKET_STATE_LENGTH_L; + break; + + case PACKET_STATE_LENGTH_L: + rxPacket.packetLength = dataIn; + this.packetReceiveState = PACKET_STATE_LENGTH_H; + break; + + case PACKET_STATE_LENGTH_H: + rxPacket.packetLength |= dataIn << 8; + if (rxPacket.packetLength < 1000) { + this.packetReceiveState = PACKET_STATE_DATA; + } else { + this.packetReceiveState = PACKET_STATE_IDLE; + } + rxPacket.index = 0; + break; + + case PACKET_STATE_DATA: + rxPacket.data[rxPacket.index] = dataIn; + rxPacket.index++; + + if (rxPacket.index >= rxPacket.packetLength - 2) { + this.packetReceiveState = PACKET_STATE_CRC_L; + } + break; + + case PACKET_STATE_CRC_L: + rxPacket.crcReceived = dataIn; + this.packetReceiveState = PACKET_STATE_CRC_H; + break; + + case PACKET_STATE_CRC_H: + rxPacket.crcReceived |= dataIn << 8; + + stuffLength = this.removeStuffing(rxPacket.data, rxPacket.packetLength); + rxPacket.packetLength -= stuffLength; + + rxPacket.cmd = rxPacket.data[0]; + rxPacket.error = rxPacket.data[1]; + + if (rxPacket.cmd == INST_STATUS) { + //console.log(`rx length: ${rxPacket.packetLength}`); + if (rxPacket.packetLength >= 147) { + let tempValue = 0; + for (let i = 0; i < addrMap.length; i++) { + switch (addrMap[i][1]) { + case 1: + this.dataBuffer[addrMap[i][2]] = + rxPacket.data[2 + addrMap[i][0]]; + break; + + case 2: + tempValue = + rxPacket.data[2 + addrMap[i][0]] + + (rxPacket.data[2 + addrMap[i][0] + 1] << 8); + if (tempValue >= 32768) { + tempValue = tempValue - 65536; + } + this.dataBuffer[addrMap[i][2]] = tempValue; + break; + + case 4: + this.dataBuffer[addrMap[i][2]] = + rxPacket.data[2 + addrMap[i][0]] + + (rxPacket.data[2 + addrMap[i][0] + 1] << 8) + + (rxPacket.data[2 + addrMap[i][0] + 2] << 16) + + (rxPacket.data[2 + addrMap[i][0] + 3] << 24); + break; + } + } + + const dxlPositionStartAddr = + addrMap[addrMap.length - 1][0] + addrMap[addrMap.length - 1][1]; + + // DXL Position + for (let i = 0; i < 20; i++) { + const currentId = + rxPacket.data[2 + dxlPositionStartAddr + 3 * i]; + const currentPos = + rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 1] + + (rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 2] << 8); + if (currentId != 0xff && currentPos != 0xffff) { + this.dxlPositions[currentId] = currentPos; + } + } + + const lineCategoryStartAddr = dxlPositionStartAddr + 3 * 20; + // line category + this.dataBuffer[5201] = rxPacket.data[2 + lineCategoryStartAddr]; + + const sensorStartAddr = lineCategoryStartAddr + 1; + + // 온습도+조도+동작감지센서값 + this.pirPir[0] = rxPacket.data[2 + sensorStartAddr]; + this.pirTemperature[0] = rxPacket.data[2 + sensorStartAddr + 1]; + this.pirHumidity[0] = rxPacket.data[2 + sensorStartAddr + 2]; + this.pirBrightness[0] = rxPacket.data[2 + sensorStartAddr + 3]; + + // 거리+버튼+조도센서값 + this.distanceDistance[0] = + rxPacket.data[2 + sensorStartAddr + 4] + + (rxPacket.data[2 + sensorStartAddr + 5] << 8); + this.distanceButton[0] = rxPacket.data[2 + sensorStartAddr + 6]; + this.distanceBrightness[0] = rxPacket.data[2 + sensorStartAddr + 7]; + + for (let i = 0; i < addrMap2.length; i++) { + switch (addrMap2[i][1]) { + case 1: + this.dataBuffer[addrMap2[i][2]] = + rxPacket.data[2 + addrMap2[i][0]]; + break; + + case 2: + tempValue = + rxPacket.data[2 + addrMap2[i][0]] + + (rxPacket.data[2 + addrMap2[i][0] + 1] << 8); + if (tempValue >= 32768) { + tempValue = tempValue - 65536; + } + this.dataBuffer[addrMap2[i][2]] = tempValue; + break; + + case 4: + this.dataBuffer[addrMap2[i][2]] = + rxPacket.data[2 + addrMap2[i][0]] + + (rxPacket.data[2 + addrMap2[i][0] + 1] << 8) + + (rxPacket.data[2 + addrMap2[i][0] + 2] << 16) + + (rxPacket.data[2 + addrMap2[i][0] + 3] << 24); + break; + } + } + } + } + + this.packetReceiveState = PACKET_STATE_IDLE; + break; + + default: + // code block + } + } + } + + requestInitialData() { + this.robotisBuffer = []; + this.robotisBuffer.push([INST_WRITE, 21, 2, 20]); + this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기 + this.robotisBuffer.push([INST_WRITE, 20, 1, 0]); // bypass port를 BLE로 설정 + this.robotisBuffer.push([INST_WRITE, 23, 1, 1]); // auto report 기능 켜기 + this.robotisBuffer.push([INST_WRITE, 4250, 1, 1]); // ai_camera 텍스트 지우기 + this.robotisBuffer.push([INST_WRITE, 722, 1, 0]); // dxl 토크 끄기 + //this.robotisBuffer.push([INST_WRITE, 63, 1, 1]); // 부저음 시간 설정 + //this.robotisBuffer.push([INST_WRITE, 60, 1, 70]); // 부저음 발생 + this.robotisBuffer.push([INST_WRITE, 113, 2, 1040]); // "띵" 효과음 발생 + /* + //const ping = [0xff, 0xff, 0xfd, 0x00, 0xc8, 0x03, 0x00, 0x01, 0x3b, 0xfa]; + // run entry mode + const packet = [ + 0xff, 0xff, 0xfd, 0x00, 0xc8, 0x07, 0x00, 0x03, 0x15, 0x00, 0x14, 0x00, 0xc1, 0xb3, + ]; + return packet; + */ + } + + async initialHandshake() { + const status = true; + let sendBuffer = null; + this.requestInitialData(); + while (this.robotisBuffer.length) { + const data = this.robotisBuffer.shift(); + const instruction = data[0]; + const address = data[1]; + const length = data[2]; + const value = data[3]; + const dataBuffer = data[4]; + let id = 0; + + switch (instruction) { + case INST_WRITE: + id = 200; + sendBuffer = this.writePacket(id, address, length, value); + break; + case INST_BYPASS_WRITE: + id = value; + sendBuffer = this.writePacket(id, address, length, dataBuffer); + break; + } + Entry.hwLite.serial.sendAsciiAsBuffer(sendBuffer); + if (instruction == INST_WRITE && address == 2100 && length == 1 && value == 1) { + this.robotisBuffer = []; + } + } + return status; + } + })(); +})(); + +module.exports = Entry.RobotisRobotaiLite; diff --git a/src/playground/blocks/hardwareLite/metadata_robotis_robotai_lite.json b/src/playground/blocks/hardwareLite/metadata_robotis_robotai_lite.json new file mode 100644 index 0000000000..e04525c172 --- /dev/null +++ b/src/playground/blocks/hardwareLite/metadata_robotis_robotai_lite.json @@ -0,0 +1,9 @@ +{ + "name": "RobotisRobotaiLite", + "version": "1.0.0", + "type": "hardware", + "title": "로봇아이(AI)", + "description": "로보티즈", + "imageName": "robotis_robotai_lite", + "moduleId": "070B01" +} From 1c89384541a46e5598e9d82777642c4bc751bd48 Mon Sep 17 00:00:00 2001 From: Jason Kim Date: Wed, 4 Sep 2024 16:10:17 +0900 Subject: [PATCH 04/21] =?UTF-8?q?Dynamixel=20=EC=A0=9C=EC=96=B4=20?= =?UTF-8?q?=EB=B8=94=EB=A1=9D=20=EB=AC=B8=EA=B5=AC=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block_robotisRBPracticalAssembly.js | 130 +++++++++--------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js index d5d4c99576..b029069fbb 100644 --- a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js +++ b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js @@ -232,11 +232,11 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { // DXL 제어 - robotis_Practice_dxl_set_mode: "%1 번 모터 %2 모드로 설정 %3", - robotis_Practice_dxl_each_control: "%1 번 모터 %2°로 %3 초 동안 움직이기 %4", - robotis_Practice_dxl_set_position: "%1 번 모터 %2 속도로 %3° 위치로 회전 %4", - robotis_Practice_dxl_set_rotate: "%1 번 모터 %2 속도로 %3 으로 %4 %5", - robotis_Practice_dxl_set_multiturn_round: "%1 번 모터 %2 속도로 %3 바퀴 %4으로 회전 %5", + robotis_Practice_dxl_set_mode: "%1 모터 %2 모드로 설정 %3", + robotis_Practice_dxl_each_control: "%1 모터 %2°로 %3 초 동안 움직이기 %4", + robotis_Practice_dxl_set_position: "%1 모터 %2 속도로 %3° 위치로 회전 %4", + robotis_Practice_dxl_set_rotate: "%1 모터 %2 속도로 %3 으로 %4 %5", + robotis_Practice_dxl_set_multiturn_round: "%1 모터 %2 속도로 %3 바퀴 %4으로 회전 %5", @@ -5088,18 +5088,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5125,7 +5125,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - '1', + '52', null, null, ], @@ -5198,18 +5198,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5231,7 +5231,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - null, + '52', { type: 'number', params: ['0'], @@ -5316,18 +5316,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5349,7 +5349,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - '1', + '52', '50', '0', null, @@ -5427,18 +5427,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5478,7 +5478,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - '1', + '52', '50', null, null, @@ -5554,18 +5554,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5598,7 +5598,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - '1', + '52', '50', '1', null, From c218b6f798a5d18a19a0040164f502b5e0f24d4d Mon Sep 17 00:00:00 2001 From: Jason Kim Date: Wed, 4 Sep 2024 16:11:02 +0900 Subject: [PATCH 05/21] =?UTF-8?q?AI=20Camera=20UTF-8=20=ED=85=8D=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EB=AC=B8=EA=B5=AC=ED=91=9C=EC=8B=9C=20=EC=A7=80?= =?UTF-8?q?=EC=9B=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../hardware/block_robotisRBPracticalAssembly.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js index b029069fbb..4c0362137d 100644 --- a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js +++ b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js @@ -7150,10 +7150,17 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { var x = script.getNumberValue('X', script); var y = script.getNumberValue('Y', script); var text = script.getStringValue('TEXT', script); - var text_len = text.length; var data_buf = []; var i = 0; + // Encode the text as UTF-8 + let encoder = new TextEncoder(); + let utf8Array = encoder.encode(text); + + // utf8Array is now a Uint8Array containing the UTF-8 bytes of the text + let text_len = utf8Array.length; + + if (text_len > 45) text_len = 45; if (x < -160) x = 160; else if (x > 160) x = 160; @@ -7171,7 +7178,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { data_buf.push(0); data_buf.push(0); for (i = 0; i < text_len; i++) { - data_buf.push(text[i]); + data_buf.push(utf8Array[i]); } var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; From 9a10380b1c9f35ad787eb388d1704f0c672895af Mon Sep 17 00:00:00 2001 From: Jason Kim Date: Wed, 4 Sep 2024 16:11:52 +0900 Subject: [PATCH 06/21] =?UTF-8?q?Dynamixel=20=EC=A0=9C=EC=96=B4=EB=B8=94?= =?UTF-8?q?=EB=A1=9D=20=EB=B2=84=EA=B7=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block_robotisRBPracticalAssembly.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js index 4c0362137d..80d4358b05 100644 --- a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js +++ b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js @@ -1364,6 +1364,13 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { if (rightDirection == '2') { rightSpeed = -rightSpeed; } + + if (leftSpeed < 0) { + leftSpeed = 256 + leftSpeed; + } + if (rightSpeed < 0) { + rightSpeed = 256 + rightSpeed; + } data_value = leftSpeed + rightSpeed * 256; @@ -1561,7 +1568,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { let data_address = 580; let data_length = 8; let angleValue = 0; - let id = 33 + wheelSide; + let id = 51 + wheelSide; let data_buf = []; let i = 0; let speed = 150; @@ -5519,8 +5526,8 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { // cw일 경우 음수처리 if (dxl_direction == 1) data_value = -data_value; - // 알쥐나 알라 우측 바퀴인 경우 reverse mode이므로 방향 반대 - if (dxl_id == 33 || dxl_id == 35) data_value = -data_value; + // 바퀴형 로봇인 경우 reverse mode이므로 방향 반대 + if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) data_value = -data_value; data_value = data_value * dxl_move; @@ -5663,6 +5670,11 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { if (dxl_round < 0) dxl_round = 0; else if (dxl_round > 100) dxl_round = 100; + // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대 + if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) { + dxl_round = -dxl_round; + } + data_value_3 = dxl_round * 4096; if (dxl_direction == 1) data_value_3 = -data_value_3; From fabdd1d90288555702e0f2f8a33bcd9f67cb1910 Mon Sep 17 00:00:00 2001 From: Jason Kim Date: Wed, 4 Sep 2024 16:12:11 +0900 Subject: [PATCH 07/21] =?UTF-8?q?=EC=8A=A4=EB=A7=88=ED=8A=B8=ED=8C=9C=20?= =?UTF-8?q?=EC=A0=84=EC=9A=A9=EB=B8=94=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block_robotisRBPracticalAssembly.js | 242 ++++++++++++++++++ 1 file changed, 242 insertions(+) diff --git a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js index 80d4358b05..561ff6a015 100644 --- a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js +++ b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js @@ -71,12 +71,19 @@ Entry.Robotis_rb_P_Assembly.blockMenuBlocks = [ 'robotis_Practice_stop_at_cross', 'robotis_Practice_turn_at_line', 'robotis_Practice_drive_stop', + 'robotis_Practice_securitybot_init', 'robotis_Practice_securitybot_hi', 'robotis_Practice_securitybot_alert', + 'robotis_Practice_petbot_happy', 'robotis_Practice_petbot_sad', + 'robotis_Practice_farmbot_init', + 'robotis_Practice_farmbot_seek', + 'robotis_Practice_farmbot_plant_type', + 'robotis_Practice_farmbot_harvest_or_not_and_go', + // 값 블록 'robotis_Practice_cm_ir_value', 'robotis_Practice_detectFrontObj', @@ -173,12 +180,19 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_Practice_stop_at_cross: "교차로 %1 에서 멈추기 %2", robotis_Practice_turn_at_line: "교차로에서 %1 하고 멈추기 %2", robotis_Practice_drive_stop: "정지하기 %1", + robotis_Practice_securitybot_init: "보안로봇 초기화 %1", robotis_Practice_securitybot_hi: "보안로봇 위아래로 흔들기 %1", robotis_Practice_securitybot_alert: "보안로봇 좌우로 흔들기 %1", + robotis_Practice_petbot_happy: "반려로봇 웃음 %1", robotis_Practice_petbot_sad: "반려로봇 화남 %1", + robotis_Practice_farmbot_init: "스마트팜 로봇 초기화 %1", + robotis_Practice_farmbot_seek: "농작물 찾기 %1", + robotis_Practice_farmbot_plant_type: "%1 농작물이면", + robotis_Practice_farmbot_harvest_or_not_and_go: "농작물 %1 돌아가기 %2", + // 값 블록 robotis_Practice_cm_ir_value: "%1 적외선센서 값", @@ -739,6 +753,11 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_huskylens_center_arrow_origin_y: "시작점 Y좌표", robotis_huskylens_center_arrow_target_x: "끝점 X좌표", robotis_huskylens_center_arrow_target_y: "끝점 Y좌표", + + robotis_plant_ripe: "빨간색으로 잘 익은", + robotis_plant_unripe: "초록색으로 덜 익은", + robotis_harvest: "수확하고", + robotis_not_harvest: "수확하지 않고", }, }, en: { @@ -754,6 +773,18 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_Practice_stop_at_cross: "Stop at cross %1 %2", robotis_Practice_turn_at_line: "%1 at cross and stop %2", robotis_Practice_drive_stop: "Stop %1", + + robotis_Practice_securitybot_init: "Security robot init %1", + robotis_Practice_securitybot_hi: "Security robot shake up and down %1", + robotis_Practice_securitybot_alert: "Security robot shake left and right %1", + + robotis_Practice_petbot_happy: "Petbot laugh %1", + robotis_Practice_petbot_sad: "Petbot angry %1", + + robotis_Practice_farmbot_init: "SmartFarm Robot init %1", + robotis_Practice_farmbot_seek: "Look for plant %1", + robotis_Practice_farmbot_plant_type: "If it is %1 plant", + robotis_Practice_farmbot_harvest_or_not_and_go: "%1 the plant and go back %2", @@ -1110,6 +1141,11 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_huskylens_center_arrow_origin_y: "Origin Y", robotis_huskylens_center_arrow_target_x: "Target X", robotis_huskylens_center_arrow_target_y: "Target Y", + + robotis_plant_ripe: "ripe in red", + robotis_plant_unripe: "green and unripe", + robotis_harvest: "Harvest", + robotis_not_harvest: "Skip harvesting", }, } } @@ -2200,6 +2236,212 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { }, + robotis_Practice_farmbot_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_farmbot_init', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2130, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_init()'], + }, + }, + robotis_Practice_farmbot_seek: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_farmbot_seek', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2131, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 200 + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_seek()'], + }, + }, + robotis_Practice_farmbot_plant_type: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_plant_ripe, '1'], + [Lang.Blocks.robotis_plant_unripe, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_farmbot_plant_type', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + var scope = script.executor.scope; + var compareValue = script.getNumberValue('TYPE'); + + var result = Entry.hw.portData[2134]; + + if(result == undefined) { + return false; + } + + return (result == compareValue); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_is_type(%1)'], + }, + }, + robotis_Practice_farmbot_harvest_or_not_and_go: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_harvest, '1'], + [Lang.Blocks.robotis_not_harvest, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + null, + ], + type: 'robotis_Practice_farmbot_harvest_or_not_and_go', + }, + paramsKeyMap: { + ACTION: 0, + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + let action = script.getNumberValue('ACTION', script); + let address = 2132; + let wait_time = 6000; + + switch (action) + { + case 1: + address = 2132; + wait_time = 6000; + break; + + case 2: + address = 2133; + wait_time = 1600; + break; + } + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, address, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + wait_time + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_harvest_or_not_and_go(%1)'], + }, + }, + + robotis_Practice_cm_ir_value: { From 829d9a7b7ec9bdb2c8a7a385072eabc8721f3f2d Mon Sep 17 00:00:00 2001 From: Tnks2U Date: Thu, 5 Sep 2024 15:24:34 +0900 Subject: [PATCH 08/21] =?UTF-8?q?fix:=20=EB=A1=9C=EB=B4=87=EC=95=84?= =?UTF-8?q?=EC=9D=B4=20=EC=9B=B9=EC=97=B0=EA=B2=B0=20=EC=9D=B4=EB=AF=B8?= =?UTF-8?q?=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- images/hw_lite/robotis_robotai_lite.png | Bin 16871 -> 24920 bytes .../blocks/hardwareLite/block_codewiz_lite.js | 18 +++++++----------- .../block_robotis_robotai_lite.js | 2 +- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/images/hw_lite/robotis_robotai_lite.png b/images/hw_lite/robotis_robotai_lite.png index fb603c39ea28e266c4fa1039305ad6c6068ccb6a..ad983b52d7c4b5a6bb3019055730bad501f4a68b 100644 GIT binary patch literal 24920 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

%sG?dGngC;55I5k3#$A`$ ze|~Fxq2!Hby|PDqL53HCZ|`?N*^=X;6qG;#jsw>LVTeSLj3A^#08#Lr)j@zaN%uA!DI}_81$AijmP--SLDK zmAVDp0HL51TtEUKpnyi9Q)mQCK>|Yc#FpQcooiOqm%jA%&wlZ{HP;J#-!R5~$5F!L zenY1u9JXVzNG6qRZAnafR-zD9c8Z%B5o%FZN@xkGN0c5?%mNrBAQhAZlnjLHOIJw< z2_bx?KnY=lQu5gy4j82r2H}=QN^X0474aykSGcNkXn>)a2}78aS9L%^*Pxo$!ICkz zTN04Vn~OTP9_)!Hp8ViPJ{bhQrZL+}+Obxtl+NHdHOKWl-}79@bsA2irht?jX6@nyK{$2nxhb)C1o z^<9rV_N1YkT-jSL9lB_3Vs1Kj@|17b5r9*s8HOpiF9e8ga3PdbN-6GpPNU}gPTr{Os@;XB;-gzpA^od=HK9#M)gCIO;bFv7x!rusGxUiNYo9V|Mu=+VWh ztW_ie3PKQxA{m9HFS#hP^bM&X1rz}QM!^UaAfW~7wu{*Vzx8Xim~%L-s2cGTFO@jxV={gY%fFeXHRd;>P11SO}C4pp=>4s?< zRwR;$g(K25G+l?LE8UQuBRp41NTmYbaT-pOQz(Ayu0)!Gu2?1jaN+>`9Tq+d=J{Jwwvm1_L z)RpKl^+;)UR?;An2XxPROcIP z_7*DQjq+Ddj{Qrg8o%tFh3KHR_lNE79;z|lbu24lS>YgXIQMnKE*2JrtO8I5)$Jigp;TQ@uB6>3f(`?$kJBDd~sN`r`BGW+N!I_giDcF1>K(+oicoClhQcp_aa z=LjGKuheQ^`_}y({cAOyHGDBzr0;!1x)li!ma)z9bg*+TuDccK1PXH~JG3%2F#4$< z?y`5cw1;i8R+>$xdqA_O7iUDqOR+UxyG@PdTVD?Hhf5_ zgrvmXyMI34poyfAN~2P$rezQ!C6`JnDF7&_W(*>Q@PznqSKE7uC-zO}1(7y99*nDc zIozhWLal^ID0u0IXSPQ>OAi}{DTVL45R%ub)krkq)N7h%`I2}vc5r0wsXhC8d%B!j z{7~Nf(`#EPqq8OXqj@>8br>fPqjM$FoAKm!OwCm;UH`CAqIG3NW8;4+t+^#uEzhXLZfa-F9i~HQlkDqb|4! z(?G3)VhN5wP@@51iFP{_)~M1Lk{yF?qnb>mnNIt=&tc>8xniYQE*48=5ZD%b=*j8# zf7pD_o4R6lZED>4`c`#3YsOMhB_#-L@<0iNY6jR+K}pfP$)gg26GF>UJyLJHf$D+F zWSMIr=5tYj48pD899+N;U~%Z0xa5ub2Of(!b0P>pXegYZL`%feTu8_DT)zgv=H@1e z@^iVxiGys>Yu|IAm1H_pdrH$Orwp2bTppZ&G6bHkG24#lx@m{V%GDQXnyy5^g=$GB z&ynhI4q3_PDwQfBL@A{k`09g`5AIm7SaoKh<|#9t>7tZKB?tjkN+}^B6q<9slu8mn zNq`WkBvA^Wf9lqV6?;v}s4|TZ-pIOTkRZ~Ih65pB*|1DVg5sQ4%Q3H_6dz)UB7IiPs8@d6TCgi13tYqgKO-9oYXR zHoMEz13RAZ>b0gnq?$%3QIb$fEz{1V(}`%Py|XtvO4ei;#gzXV6e)XB$6x zSSGtkYp0n?@B_Oc#r*6zB{UpKGCNEOkszjN)GOtg8EP12OUti(7vx`vbH&R1+(Hlp zgfy>s1&H<*>;M1IV0)`sEX!=(n_Ki}7u@NrH@g@t#@caH<&q7-gDHbzL(J zvw0U`N~y^hm-6p@Z>t>{i<@&nDt+=R%Bq!*Y!@fDnkd`xgsvwPlvEOgKq;nalu$|} zC^Ky{m57@rZE0(-k9D2cALmz_{gJ%MXpj{X5pP+FLlQg9)1xh!Q? zET$Ad8ErJ2&wcp;B}AiM?(E3C=2b7b?9z>AQG4f#mD$-jC&6wRFVR1=p?zW?pFz2w@nrM+{*ic<3n^8k5)7C?5knDMZ#>x?l11*I`vDN7*| zR+*$Z2n9e0$+_|a<+!3;3l?(0e9oI*@Mac*=>=~#>*fkUp;E7v^FcsB2&GKZwUBMu zwyglAI6$S8N-02r5KYsX_R6^*irJx1mwX|U|E2Hz^+(?mi=2gXc+Uwdj?*aQiy%#{H}yvR+V9(!dXVuGz_S`@mHfZ+Y~Ae-E|vcBNB<2+Im{&Xtmrqle~aPCfki zme;=WmNQr2IjMt|O2ty83W66*fDqE2F&X>i&U;iZ`UwyUN(iNd=~UCHVKCERmZ^tB zdOT*fW$a8`ZxY{(c$5@MNhnatD4~jwXrfh08Hq%6rg^R_xhJLa0uIKY04wU|bDFGX z61oBu=R_IM!zhkRr>qpX?+3)9cJlHou0L^bd%@%Vo!!qp`{TLUal^Evl=VvK$f2jl z$4+c}VqdM{oVfze2`hzsp;2!vbyyJsDAUkdGse$y(zJ*hh?KXWimzyu(0TODh8_s z^{lP}NWm48My#uMAQjd3A9`l6f0b9SOihfI%S9e=p=3Tc7jREO&dkmqJUo2n3OpyQ zEM&6{$0sl9GzwXIOH%(SRtQ{A1VZA>j)sy-EfhRI5Y0EGL@CJuC@98s5W+dO{H^&O{Knf^$J_%d)S$^y(w~b{LUV z#107|;;nt@wtm-b=#(^SWk6BJ2xI#Xo;VY6nm8w{WV1Qn^U5Exm zWWMNs@{1?yzQixH$(IuRr|nxxK}eO&drc2UDB&Uqc+d=1G)-?-2ZR)mDiVoFrCg^j zICq^u1bk_Pkz`qh_wG6D)V&iU`G0@LK}RnPg8VT}x4R9Cgt-L zECArDzb|shhSXpG(@{sM|B4s|7>p~mSoD6TOIRszt`>40(5#n1DcQ{NC_vKqDs}Q;x))aL;{5qp$p*PrvFNUs;&SLp3n*2ytc@(?JcU z>8n<)A3yb6D4I@0Vw5tbX@+$7{P@1bg{jl0hjqg=LXi!duF@GTNfW8Ed$FY^wfK{>l|EyRG};4avXz>~Wz{Xg_Z-3J7b(n*Y0hzWY!56rUxM3q_z?v3RmIl{_(gxTB+oQ3xq~&mB2=aB6CFAv>4u8tU#_ zwegZ0l931jX*h17SUE!lo)cCU7xOPveE|UChRf4``{$ch_C*m$03bkEM^uMWulvox zwzT<)e>zfixRC0nnqCzU(+{2~{ozOUzvR01H~vN+8XQ0MxN<#_FZ#`99Rk{HOi=)# znx^Xjb!w%F)6f0r2mkTO|L=e9+y5+}2&Ik_fG_|cI_%_SL-f{;xp%yIW7|va#Mnca zcnC@;1)-Q>SRJjM#q3PO@lwgO@B5zTIgNTgp9KKj>>u3F-PRqqB8Ly`1Z5)Nxx)F! z3J<)+?4m+b`^}((J+^E9z8_42sHJt6Nx%8+V}JIseP90fk>b4bd%w4a5&Yf%K1K|N z7t>;~$F|RZ>R(U%!8_Ny{&fTJ#m{_}l5jm)toXoEz}oygN+_cmW15tlD+$7&8JZoo zBMHx~6G9v>0Hc5eF~f<-Tl#9Byu1AiznT2QE6X@~A4CmIS2AFRX_|T}m6@I#iN#Zl zX?_q$!3Fny-vhvfy!!eZ`NkXeU-tIJS|GT~m{G3O&QOPEKZ>l?YT4W(lxl81XwEBZ zhN59xg91R5K|cPe6HgxL-TTb`N@?WZ?i>65m#+WdyVso_tx(l$CI$c)^yFw|&))2( z{_>JUtA&dHGa)Ak(Ia}L7G(1t06VO1l~Oj` z08E2Yup+v2wm&}c(m%Kgz{Tk@P=N}8b3&=6n>u3}rTJoR<(iA36l3i8p*@Nkp;*SL z<>QIeKu5=}_Df3{bA92s#;5#7sa$ECp$^Z!t<)R!VzG#&Y%x(%YMTDm-{`&l`V51D z$)4Fi|GjPW(MNvx$M63=0K4|*zwotFT0~p5G6wM?#Rsyt)&9r_HparNG+h^rAoQYZ zh>~(G_{^7w-}oob%q@D&rVB!;A`pTL$qA#B5-Eg~k^q`+hQl$_FnJItFvsJd8Wdo~ z{M=mJa$A#j0C29rJ#Y`aK`3KPHw@EhR6^mnLGkqV@8+{pr$>+ZzHjJyyscmP-gkE$ z*ym6fVCiUs6d+>pP-@i`q~}KT-;VUvvx{1}RD9oi-@9keo@QK0$cr4;3kb0%cTRrp zdx<~&t9z)?@yL$(-+a&RBgc!d7ytyar!Vs14{!P(Z(6Z5zk^UhUue)}j448-l0pbV zh=NKaTNtBGqgJkzg;byv0E}qFqUo5e=^()NC!PXaKtXZKj!{NTJLJ|Y2BkBz(*XQH zwDqiQYiV1vYExxlGMa4Z=ox?xRH~I@JIZdbX5+Qt(3zeDd-hpb$j*D7M<`K{&1of_ zjwWIzqy#fztQ*TMo&WeksNdTahE9KK+8_WUU;Nrgd-wWR-+kxcKreuN$^XLFN1>5s z!gpxLpPZSVm69wad*ZG0 zh2XKRk2I?8liQws=&>URZ-(7Y2sB-X5|mQctw{pcZ2%}1i|aODLOND#yW*XNG2x7f}MB zuQRk%hpSyB$UL4%<<&hKnckkZaY|J=xyv!Y`5rC3J(%k)Qe%qcbpaYT+N-6Vw zx49J4m`(ttq~M%T=DThvnk;4~_wV|?Fb80*2Pl+6BvA{s+`ISK*qi@#_L*apUnc#&k#xhXzz%drbd=h$ZX4&70*A?baB|UIs_^Z*Add7(`FjqsR#49 zpj6Cl+qRAKr7$HGr;Pd#9z1vBityJydFeGXi z%m9EMZQdRP%s@1Qg_Ah+Js2@`U5eT$X0}2!pr{m*5*B!M)3#&rlx{>ix`((|uPGwq zEudH!KDPbgduL}S9B9-EZ`gcII+2u8hV3&wo9yg+u*GZ+cp)z$0kpQp7<++!-qDeI z;DL{P<}(ir56^De)c?Nsy~>QXee_?pe&O>^188rxHmr<)@l&@(TQf}G2?WiTH7Oie ze=)*WB3uWcgjdczTdeMBCP4`S=e`gEAW|wuHKv({0nT}LVb;Qe}BtA{KGq& zH?0S_=ami~7;Qc_pLOT6?zSVzxBkv6ue@sSgAeY1;mviOU2*wJpbq!|l$2#2ueeKm zD@BA{s+UnpHC zsfkcA+n=Q}Jmpm^3(A$#& z_{To>#uF!IMn~tHFZwxklm#o~r{S)`zyCa*e zTz&PLyY9NYX(f2R?;@A4x~~8HHabca6ch-dnno#A&+mJT#p0T-JB?bcRsc*86NG{g zm|^&J=t)Q)(t{QTF~J?k1_YsuNhLMLLZL7NF^o|E+N;*A+2l2(Qw8XBwYGp@zA0V0rQLk5HG4p-zdmWZSANNI7VkM=@W~YED|dSP1Ap}v6#?UJjobsG^$R$4jKZ{pcE8fg`uy5aRQwICD`aL;hGdKJ?(62 zL`ToSnn*mI&rVxiD?}s-3Z9!C9XS+s7D3 zI1;r1{+~ZcDaEP7C zybRC$Gs>fgw7}5dW{Gqu3lT!4l7?Xt!1uXRuPn^Z07N&ffz_9!;|V`Edwh2MmRnv~ zj98}$aAcPV8f|T7;XcP_nUxhQR&Kob(rrI_IG#v(o*M)Kp-M@S&sX#L%8|np_uu~v zz*6bZz(C93K->EDJsU3S8R&0mYm3F>;nvnLV=t6gnstBxpg-F;1}LRGk1u3j$j*{x zvI|gzkY>dm1e7w}w4$*X7ou7z2nkRNL<1zK0V@JRKmlhKUIC#5SRA54nyWaCK}t>2 zgcMBEs+CfsQ3Bu#e#aem(n#vrp_|C`LT+X>ncm+b_1qKxVMbCzLjz~7#y*fQVt zuJ=55_(Z*!GYrGDETsq`%n!W4cO~aiawt*A*9!US{(YzKy?3`|ndx+NXsBiN>aNwR zJ65gg?CHt0w#Fh6OVb!3V653HyyT~vAEXo<$6J_RvK2xIqfCG|E7F=~5JI@`YKCo@ zb|exB0$$25C;%)10E$2}5sD)}fw6tiqA=qCgVbPmkVb(#-}%9qrW8D<=DBrH1}Ug+ zZ5kMSvi*wDhP63ApC}$Z{^-}b)Hh4@{NQERZ&-Eyu>#=kyKXr>{%7}o`@2rPFgd(0 z@Lb&p8K$M#A;xs25OAOSt`J;s4@$YNKQoh?naOS6ejGq3WVW=#d;2o$*LJPn(7k$f zXLolxnT&+PhNfwhHtShb2wAB(`FssPGu^UeD})e2n;xuLaMKOL4ux_H^TS7<1_-q0 zS*pqQN=89ChEv%-vLZn*yDbmA=Bxb^I_V(aV=-|^aXBKpMkJyMFh+~YMM~MyoDV|TQpMi1B7x`I;V99Ip4FBei)T8yQ<+iBH9{7Jzc6y> z$TMcVrEln>z7-d5zG&@PIo$f3^clyaq2GV&-LJai##3W6qvO-ZPK+KuesXeRtX?bB zE9Fc_pWh(&s zQmj>qZlmhC4a%63X0wQe~SuWQPAFdxhJo%IH69NTBse)2al#oa) zscXy)JnlP`V(iqhlgIXXPJuB-l!?>;3>$6@(G2oqFk%oM2t}wJz6T=;XEF#}rW=F+ zl=!|IPql8o^v2dq%k0GP%+#@U8#bq+HVH#Ly<1Ej(g)V`b@euC)p#bkc2)0LQQfcU zgu`?)+TWc#acqCNTs2K2WJf~bSSS*Y#?z_ZAwsDi1g_Jl)ymaMpTkj_RBE^_@F8Ju_dc*Q?c1rR+-)m_~$X8c~SGlJR6Z z9#4lNiI!w*M|+P@vf z38C@<_<)3v096Q~ekl(LXevlRLXBFe`pUy`5**vH&-VFokKNnn%tceVe~@3-@x*_r>$7+pQqC-g_e00G2A5JW|f#KV%p0-ph{$QnY3QW}jV z0b`zHT4s(Qm}Svfr5mE0PmnCgIG^^WZz#HkZAxp_fvsNv)7P-AL}Sf{;Kfw&;Fph_ zcy{-9zWuF{(Q#eJf#-Ry12x0Q;tcvB+-K6MzQ3AgF*d-}g*2YnoXwbpt{qOL9#^+rSftT3cEt(^Dg( zWAh7zz;&77V?iid1=lXxc9BDg$j128+;qmpau)`Tu9XCW2zUTo1~>;1t)^ZVC2spg z&dsk4whZ>SMs$S`!U04GBLp4SpPkQd+^}8}1xkHFgnVwUKGlQ?PLJQrn^_`=O>Ld2 zx+c4jyEc5Wp|yK+s&4m=jVs92>Z#J--=At~pB%fEnHl-XkAFZJA)?4Q<(%Cf=f5@M zm;=B74A=eyoKxGerYFa)3=MP2YwK(G?Ch6BGMkwh8J*0VPCh5mz>CL>_O_;u_LlJ+ zdHaGjHd@GLiT*Yi-nUNgO376kf{Y0mrII>=Ae%3ST?Pmtgb>D7_`Zr!V{r&1>?WN(%p6hFx!5MRl1xjzn=OK(BgW;@jhzI}>Fvw$s3Y|acQl|@0LUmvaae3D-t(Lc;_B z%HZNe0cbl;XeUHT6-sF=X6)Oy=chk=Egq}RE~L#u9!KMx2oMR8Xp$gdetuSxq_v%! zx9!+=aNpLI%prj>#;7CYHsSV}@Tw!44d?%%xr2IWjr^_iLRXuL|6bq-Kh&o+S& zQIr6Ob# z2nqlIVL??@>id)fBFY34&Zt_II{4HJjkPtprgpAdA60~NfB##uu`N~KAd5jVruYF3 z=h&Bg2#See2xYum12CB2gH3R7H(w zQOENmvDm4T&ptWO7YGR`@rlrzRS(^av5Yj1yFuPBKUk$(Qm zUx_MRv!*eTFa!a5t`8tu)7)GYkLL1ujIb;sRaO16E$`qmPqLh{CAUhdV2qat3!tJSUPVyHOZ>B<`lt*1_8KJ;{jm-p8gfYL)(9) zoU&5*O9{Rg3?A5fa_G4?e*4F3!N>v(jd4UvQyE-gOan#`+Aj|D^)P%Cm|@M2q8fr zlj-T{nR%ZZMVBFrr)RSlKK{rqdL8Yl!QJa)QQZ%Mij0&uF3KNRQf|PV^-W2YF^PN(zOe!bQu@72I6Goz2=K<1>(ZkMHP8CJe{*?`!M6d@ZkLDgsn; zeV@?8r^UnE18=!D;7*aiqC6oj5CX=y>jsiUAcR4%G)U~zqQqvYp7A4f%5Z;es85RP$5eXSCw+yJ147_&wJDTUlrrF mmH!=8?uLhz!_^U>BK`wjc}BarUN{2)0000 있으면 지금과 비교해서 속도는? - return ( - Date.now() - .toString() - .substring(6) + opcode - ); + return Date.now().toString().substring(6) + opcode; } // 코드위즈에 보낼 데이터를 만드는 함수입니다. @@ -954,7 +950,7 @@ }, isNotFor: ['CodeWizLite'], class: 'CodeWizLite_default_sensor', - func: function(sprite, script) { + func: function (sprite, script) { var sensor = script.getField('SENSOR', script); var hw_sensorData = Entry.CodeWizLite.sensorData; return hw_sensorData[sensor] ?? 0; @@ -989,7 +985,7 @@ }, isNotFor: ['CodeWizLite'], class: 'CodeWizLite_default_sensor', - func: function(sprite, script) { + func: function (sprite, script) { var sensor = script.getField('GYRO_TYPE', script); var hw_sensorData = Entry.CodeWizLite.sensorData; return hw_sensorData[sensor] ?? 0; @@ -1025,7 +1021,7 @@ }, isNotFor: ['CodeWizLite'], class: 'CodeWizLite_default_sensor', - func: function(sprite, script) { + func: function (sprite, script) { var sensor = script.getField('SWITCH', script); var hw_sensorData = Entry.CodeWizLite.sensorData; return hw_sensorData[sensor] ?? false; @@ -1065,7 +1061,7 @@ }, isNotFor: ['CodeWizLite'], class: 'CodeWizLite_default_sensor', - func: function(sprite, script) { + func: function (sprite, script) { var sensor = script.getField('SWITCH', script); var hw_sensorData = Entry.CodeWizLite.sensorData; return hw_sensorData[sensor] ?? 0; diff --git a/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js b/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js index 5dbfc6e418..a283bfe877 100644 --- a/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js +++ b/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js @@ -162,7 +162,7 @@ let beat_per_minute = 75; constructor() { this.id = '070B01'; this.url = 'http://www.robotis.com'; - this.imageName = 'robotis_robotai.png'; + this.imageName = 'robotis_robotai_lite.png'; this.name = 'RobotisRobotaiLite'; this.blockMenuBlocks = [ // 주행 제어 From 8fd2c1ef0dd0ba3549b0bf4910e9f23547566445 Mon Sep 17 00:00:00 2001 From: Tnks2U Date: Tue, 10 Sep 2024 16:25:42 +0900 Subject: [PATCH 09/21] =?UTF-8?q?feat:=20=ED=8E=8C=EC=9B=A8=EC=96=B4=20?= =?UTF-8?q?=ED=94=8C=EB=9E=98=EC=8B=B1=20=EC=BD=9C=EB=B0=B1=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/class/hardware/webUsbFlasher.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/class/hardware/webUsbFlasher.ts b/src/class/hardware/webUsbFlasher.ts index a18e779ec9..32c5b16309 100644 --- a/src/class/hardware/webUsbFlasher.ts +++ b/src/class/hardware/webUsbFlasher.ts @@ -31,7 +31,7 @@ export default class WebUsbFlasher { // INFO: 연결된 기기에 파라미터로 넘어온 펌웨어를 플래싱 // TODO: 현재 유일한 지원기종인 microbitble에 맞춰져있음, 추후 지원기기가 늘어나면 로직수정 필요 - async flashFirmware(firmwareUrl: string, moduleId: string) { + async flashFirmware(firmwareUrl: string, percentCallback: Function) { try { if (!this.device) { throw Error('device undefined'); @@ -57,14 +57,14 @@ export default class WebUsbFlasher { // TODO: 퍼센트 로직도 분리 if (sentPages % 128 == 0) { this.flashingPercent = (offset / data.length) * 100; - console.log(this.flashingPercent); + percentCallback && percentCallback(this.flashingPercent); } await this.writeBuffer(cmdData); sentPages++; offset = end; } this.flashingPercent = (offset / data.length) * 100; - console.log(this.flashingPercent); + percentCallback && percentCallback(this.flashingPercent); this.flashState = 'end'; // INFO: close From 5e3020c56f62ec3a65c87165e6b2b8fbea909283 Mon Sep 17 00:00:00 2001 From: hksong Date: Thu, 19 Sep 2024 08:22:16 +0900 Subject: [PATCH 10/21] =?UTF-8?q?=EC=97=90=EC=9D=B4=EB=9F=AD=EC=8A=A4=20?= =?UTF-8?q?=EB=84=A4=EB=AA=A8=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocks/hardware/block_alux_nemo.js | 2488 +++++++++++++++++ 1 file changed, 2488 insertions(+) create mode 100644 src/playground/blocks/hardware/block_alux_nemo.js diff --git a/src/playground/blocks/hardware/block_alux_nemo.js b/src/playground/blocks/hardware/block_alux_nemo.js new file mode 100644 index 0000000000..61377e3020 --- /dev/null +++ b/src/playground/blocks/hardware/block_alux_nemo.js @@ -0,0 +1,2488 @@ +'use strict'; + +Entry.nemo = { + id: ['63.1'], + name: 'nemo', + url: 'https://www.aluxonline.com', + imageName: 'alux_nemo.png', + title: { + ko: '네모', + en: 'NEMO', + }, + delayTime: 0.001, + setZero: function() { + Entry.hw.sendQueue['NEMO_INIT'] = { + id: Math.random(), + setZero: 1, + }; + Entry.hw.update(); + this.setCount = 0; + }, + numToMS(num) { + let ms = 0; + if (num < 0) { + ms = 0; + } else if (0 <= num && num <= 5) { + switch(num) { + case 0: + ms = 0; + break; + case 1: + ms = 500; + break; + case 2: + ms = 200; + break; + case 3: + ms = 100; + break; + case 4: + ms = 50; + break; + case 5: + ms = 20; + break; + } + } else { + ms = 500; + } + return ms; + }, + afterReceive(portData) { + const motion = portData['NEMO_EVENT_MOTION']; + const button = portData['NEMO_EVENT_BUTTON']; + const temp = Entry.hw.portData['NEMO_DEVICE'].anSwitch; + if (button === true) { + Entry.engine.fireEvent('aluxNemoButtonEventReceived'); + } + if (motion === true) { + Entry.engine.fireEvent('aluxNemoMotionEventReceived'); + } + }, + setProcessor(script, delayTime, code) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const fps = Entry.FPS || 60; + const timeValue = (60 / fps) * delayTime * 1000; + Entry.TimeWaitManager.add( + Math.random(), + () => { + script.timeFlag = 0; + }, + timeValue + ); + Entry.toybot.scoreFlag = code(); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, +}; + +Entry.nemo.setLanguage = function() { + return { + ko: { + template: { + title_namo_input: '네모 입력', + title_namo_output: '네모 출력', + title_namo_extension: '네모 확장', + line_emtpy: ' ', + + list_s1: 'S1', + list_s2: 'S2', + list_s3: 'S3', + list_s4: 'S4', + list_motion_1: '앞으로 기울임', + list_motion_2: '뒤로 기울임', + list_motion_3: '왼쪽으로 기울임', + list_motion_4: '오른쪽으로 기울임', + list_motion_5: '위로 놓음', + list_motion_6: '아래로 놓음', + list_motion_7: '세워 놓음', + list_motion_8: '충격 받음', + list_smile: '웃음', + list_not_much: '별로', + list_good: '좋음', + list_bad: '나쁨', + list_wink: '윙크', + list_cry: '울음', + list_absurd: '어이없음', + list_peck: '뽀뽀', + list_arrow_1: '화살표 1', + list_arrow_2: '화살표 2', + list_arrow_3: '화살표 3', + list_arrow_4: '화살표 4', + list_arrow_5: '화살표 5', + list_arrow_6: '화살표 6', + list_arrow_7: '화살표 7', + list_arrow_8: '화살표 8', + list_spade: '스페이드', + list_club: '클럽', + list_diamond: '다이아몬드', + list_heart: '하트', + list_circle: '원', + list_x: '엑스', + list_triangle: '세모', + list_square: '네모', + list_note_1: '음표 1', + list_note_2: '음표 2', + list_note_3: '음표 3', + list_dice_1: '주사위 1', + list_dice_2: '주사위 2', + list_dice_3: '주사위 3', + list_dice_4: '주사위 4', + list_dice_5: '주사위 5', + list_dice_6: '주사위 6', + list_is_pressing: '눌려 있을 때', + list_pressed: '눌렀을 때', + list_released: '뗐을 때', + list_has_prssing: '눌려 있는가', + list_has_pressed: '눌렀는가', + list_has_released: '뗐는가', + list_axis_x: 'X축', + list_axis_y: 'Y축', + list_axis_z: 'Z축', + list_linear_acceleration: '선형 가속도', + list_off1: '끄기', + list_on1: '켜기', + list_off2: '□', + list_on2: '■', + list_toggle: '토글', + list_do_re_mi_song: '도레미송', + list_an_island_baby: '섬집아기', + list_twinkle_twinkle_little_star: '작은별', + list_spring_in_my_hometown: '고향의 봄', + list_for_elise: '엘리제를 위하여', + list_celebrated_chop_waltz: '젓가락 행진곡', + list_happy_birthday_to_you: '생일 축하곡', + list_lc: 'C(0)', + list_lcs: 'C#(1)', + list_ld: 'D(2)', + list_lds: 'D#(3)', + list_le: 'E(4)', + list_lf: 'F(5)', + list_lfs: 'F#(6)', + list_lg: 'G(7)', + list_lgs: 'G#(8)', + list_la: 'A(9)', + list_las: 'A#(10)', + list_lb: 'B(11)', + list_mc: 'C(12)', + list_mcs: 'C#(13)', + list_md: 'D(14)', + list_mds: 'D#(15)', + list_me: 'E(16)', + list_mf: 'F(17)', + list_mfs: 'F#(18)', + list_mg: 'G(19)', + list_mgs: 'G#(20)', + list_ma: 'A(21)', + list_mas: 'A#(22)', + list_mb: 'B(23)', + list_hc: 'C(24)', + list_switch: '스위치', + list_infrared_ray: '적외선', + list_magnet: '자석', + list_rotation: '회전', + list_brightness: '밝기', + list_sound: '소리', + list_tilt: '기울기', + list_pressure: '압력', + list_heart_rate: '심박', + list_value: '값', + list_angle: '각도', + list_absolute_angle: '절대 각도', + list_rotation_value: '회전 수', + list_east: '동쪽', + list_west: '서쪽', + list_south: '남쪽', + list_north: '북쪽', + + input_event_button_state: '%1 %2 버튼 %3', + input_event_motion_sensing: '%1 %2 이 감지되었을 때', + input_bool_button_state: '%1 버튼 %2 ?', + input_bool_motion_sensing: '%1 이 감지되었는가?', + input_bool_led_state_value: 'LED X: %1 Y: %2 상태값', + input_field_button_analog_value: '%1 버튼의 아날로그 값', + input_field_acceleration_value: '가속도 센서 %1 의 값', + input_field_brightness_value: '밝기 센서의 값', + input_field_convert_value: '%1 의 값 %2 ~ %3 을 %4 ~ %5 으(로) 변환', + + output_basic_display_led_icon: 'LED 아이콘 %1 을 %2 속도로 출력 %3', + output_basic_diplay_led_custom_icon: 'LED %1 줄의 %2%3%4%5%6%7%8 을 %9 속도로 출력 %10', + output_basic_display_led_string: 'LED %1 문자열을 %2 속도로 출력 %3', + output_basic_delete_all_led: 'LED 출력 지우기 %1', + output_basic_coordinate_value: 'LED X: %1 Y: %2 %3 %4', + output_basic_play_melody: '멜로디 %1 재생하기 %2', + output_basic_play_melody_to_the_end: '멜로디 %1 끝까지 재생하기 %2', + output_basic_play_note: '%1 음을 재생하기 %2', + output_basic_play_note_for_seconds: '%1 음을 %2 초동안 재생하기 %3', + output_basic_stop_all_sound: '모든 소리 정지 %1', + + extension_basic_set_expension: '확장센서를 %1 (으)로 설정 %2', + extension_basic_set_expension_value: '확장센서를 %1 값으로 정하기', + extension_bool_expension_state: '확장센서 %1 ? %2', + extension_field_expension_anlog_value: '확장센서의 아날로그 값 %1', + extension_field_expension_custom_value: '확장센서의 %1', + extension_basic_set_compass_value: '나침반센서를 %1 값으로 정하기', + extension_field_compass_analog_value: '나침반센서의 아날로그 값 %1', + extension_field_compass_custom_value: '나침반센서의 %1', + extension_bool_compass_state: '나침반센서의 방향이 %1 인가 ?', + }, + }, + en: { + template: { + title_namo_input: 'NAMO INPUT', + title_namo_output: 'NAMO OUTPUT', + title_namo_extension: 'NAMO EXTENSION', + line_emtpy: ' ', + + list_s1: 'S1', + list_s2: 'S2', + list_s3: 'S3', + list_s4: 'S4', + list_motion_1: 'Tilting forward', + list_motion_2: 'Tilting back', + list_motion_3: 'Tilting to the left', + list_motion_4: 'Tilting to the right', + list_motion_5: 'Put it up', + list_motion_6: 'Put it down', + list_motion_7: 'Standing up', + list_motion_8: 'Impacted', + list_smile: 'Smile', + list_not_much: 'Not much', + list_good: 'Good', + list_bad: 'Bad', + list_wink: 'Wink', + list_cry: 'Cry', + list_absurd: 'Absurd', + list_peck: 'Peck', + list_arrow_1: 'Arrow 1', + list_arrow_2: 'Arrow 2', + list_arrow_3: 'Arrow 3', + list_arrow_4: 'Arrow 4', + list_arrow_5: 'Arrow 5', + list_arrow_6: 'Arrow 6', + list_arrow_7: 'Arrow 7', + list_arrow_8: 'Arrow 8', + list_spade: 'Spade', + list_club: 'Club', + list_diamond: 'Diamond', + list_heart: 'heart', + list_circle: 'Circle', + list_x: 'X', + list_triangle: 'Triangle', + list_square: 'Square', + list_note_1: 'note 1', + list_note_2: 'note 2', + list_note_3: 'note 3', + list_dice_1: 'dice 1', + list_dice_2: 'dice 2', + list_dice_3: 'dice 3', + list_dice_4: 'dice 4', + list_dice_5: 'dice 5', + list_dice_6: 'dice 6', + list_is_pressing: 'Is pressing', + list_pressed: 'Pressed', + list_released: 'released', + list_has_prssing: 'has be pressing', + list_has_pressed: 'has pressed', + list_has_released: 'has released', + list_axis_x: 'X axis', + list_axis_y: 'Y axis', + list_axis_z: 'Z axis', + list_linear_acceleration: 'Linear acceleration', + list_off1: 'Off', + list_on1: 'On', + list_off2: '□', + list_on2: '■', + list_toggle: 'Toggle', + list_do_re_mi_song: 'Do Re Mi Song', + list_an_island_baby: 'An Island Baby', + list_twinkle_twinkle_little_star: 'Twinkle Twinkle Little Star', + list_spring_in_my_hometown: 'Spring in My Hometwon', + list_for_elise: 'For Elise', + list_celebrated_chop_waltz: 'Celebrate Chop Waltz', + list_happy_birthday_to_you: 'Happy Birthday To You', + list_lc: 'C(0)', + list_lcs: 'C#(1)', + list_ld: 'D(2)', + list_lds: 'D#(3)', + list_le: 'E(4)', + list_lf: 'F(5)', + list_lfs: 'F#(6)', + list_lg: 'G(7)', + list_lgs: 'G#(8)', + list_la: 'A(9)', + list_las: 'A#(10)', + list_lb: 'B(11)', + list_mc: 'C(12)', + list_mcs: 'C#(13)', + list_md: 'D(14)', + list_mds: 'D#(15)', + list_me: 'E(16)', + list_mf: 'F(17)', + list_mfs: 'F#(18)', + list_mg: 'G(19)', + list_mgs: 'G#(20)', + list_ma: 'A(21)', + list_mas: 'A#(22)', + list_mb: 'B(23)', + list_hc: 'C(24)', + list_switch: 'Switch', + list_infrared_ray: 'Infrared ray', + list_magnet: 'Magnet', + list_rotation: 'Rotation', + list_brightness: 'Brightness', + list_sound: 'Sound', + list_tilt: 'Tilt', + list_pressure: 'Pressure', + list_heart_rate: 'Heart rate', + list_value: 'Value', + list_angle: 'Angle', + list_absolute_angle: 'Absolute angle', + list_rotation_value: 'Rotation value', + list_east: 'East', + list_west: 'West', + list_south: 'South', + list_north: 'North', + + input_event_button_state: 'When %1 button %2', + input_event_button_motion_sensing: 'When %1 motion is detected', + input_bool_button_state: 'Is %1 button %2 ?', + input_bool_motion_sensing: 'Is %1 motion detected', + input_bool_led_state_value: ' LED X: %1 Y: %2 status', + input_field_button_analog_value: 'Analog value of %1 button', + input_field_acceleration_value: 'Acceleration sensor %1 value', + input_field_brightness_value: 'Value of illuminance sensor', + input_field_convert_value: 'change the value of %1 from %2 ~ %3 to %4 ~ %5', + + output_basic_display_led_icon: 'LED icon %1 output %2 speed %3', + output_basic_diplay_led_custom_icon: 'LED %1 line %2%3%4%5%6%7%8 at %9 speed %10', + output_basic_display_led_string: 'LED %1 string output %2 speed %3', + output_basic_delete_all_led: 'Clear LED output %1', + output_basic_coordinate_value: 'LED X: %1 Y: %2 %3 %4', + output_basic_play_melody: 'Play melody %1 %2', + output_basic_play_melody_to_the_end: 'melody %1 play to the end %2', + output_basic_play_note: 'Playing note %1 %2', + output_basic_play_note_for_seconds: 'Play note %1 for %2 second(s) %3', + output_basic_stop_all_sound: 'Stop all sound %1', + + extension_basic_set_expension: 'Expansion type set %1 %2', + extension_basic_set_expension_value: 'Expansion sensor set %1 value ? %2', + extension_bool_expension_state: 'Is extended sensor %1', + extension_field_expension_anlog_value: 'Value of extended sensor %1', + extension_field_expension_custom_value: 'Exansion sensor value of %1', + extension_basic_set_compass_value: 'Compass sensor value Set %1', + extension_field_compass_analog_value: 'Value of compass sensor %1', + extension_field_compass_custom_value: 'compass sensor value of %1', + extension_bool_compass_state: 'Does the rotation sensor point %1 ?', + }, + }, + }; +}; + +Entry.nemo.blockMenuBlocks = [ + 'nemo_dropdown_button', + 'nemo_dropdown_button_now_state', + 'nemo_dropdown_button_state_question', + 'nemo_dropdown_motion', + 'nemo_dropdown_coordinate_acceleration', + 'nemo_dropdown_led_icon', + 'nemo_dropdown_switch', + 'nemo_dropdown_melody', + 'nemo_dropdown_keyboard', + 'nemo_dropdown_expension_sensor_mode', + 'nemo_dropdown_compass_sensor_mode', + 'nemo_dropdown_direction', + 'nemo_dropdown_index_0_5', + 'nemo_dropdown_index_1_5', + 'nemo_dropdown_index_1_7', + 'nemo_dropdown_toggle', + 'nemo_dropdown_toggle2', + + 'nemo_title_namo_input', + 'nemo_block_input_event_button_state', + 'nemo_block_input_event_motion_sensing', + 'nemo_block_input_bool_button_state', + 'nemo_block_input_bool_motion_sensing', + 'nemo_block_input_bool_led_state_value', + 'nemo_block_input_field_button_analog_value', + 'nemo_block_input_field_acceleration_value', + 'nemo_block_input_field_brightness_value', + 'nemo_block_input_field_convert_value', + + 'nemo_title_namo_output', + 'nemo_block_output_basic_display_led_icon', + 'nemo_block_output_basic_diplay_led_custom_icon', + 'nemo_block_output_basic_display_led_string', + 'nemo_block_output_basic_delete_all_led', + 'nemo_block_output_basic_coordinate_value', + 'nemo_block_output_basic_play_melody', + 'nemo_block_output_basic_play_melody_to_the_end', + 'nemo_block_output_basic_play_note', + 'nemo_block_output_basic_play_note_for_seconds', + 'nemo_block_output_basic_stop_all_sound', + + 'nemo_title_namo_extension', + 'nemo_block_extension_basic_set_expension', + 'nemo_block_extension_basic_set_expension_value', + 'nemo_block_extension_bool_expension_state', + 'nemo_block_extension_field_expension_anlog_value', + 'nemo_block_extension_field_expension_custom_value', + 'nemo_block_extension_basic_set_compass_value', + 'nemo_block_extension_field_compass_analog_value', + 'nemo_block_extension_field_compass_custom_value', + 'nemo_block_extension_bool_compass_state', +]; + +Entry.nemo.getBlocks = function() { + return { + ///======================================================================================== + /// Dropdown block + ///======================================================================================== + nemo_dropdown_button: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_s1, 0], + [Lang.template.list_s2, 1], + [Lang.template.list_s3, 2], + [Lang.template.list_s4, 3], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_button_now_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_is_pressing, 0], + [Lang.template.list_pressed, 1], + [Lang.template.list_released, 2], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_button_state_question: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_has_prssing, 0], + [Lang.template.list_has_pressed, 1], + [Lang.template.list_has_released, 2], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_motion: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_motion_1, 0], + [Lang.template.list_motion_2, 1], + [Lang.template.list_motion_3, 2], + [Lang.template.list_motion_4, 3], + [Lang.template.list_motion_5, 4], + [Lang.template.list_motion_6, 5], + [Lang.template.list_motion_7, 6], + [Lang.template.list_motion_8, 7], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_coordinate_acceleration: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_axis_x, 0], + [Lang.template.list_axis_y, 1], + [Lang.template.list_axis_z, 2], + [Lang.template.list_linear_acceleration, 3], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_led_icon: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'DropdownExtra', + options: [ + [Lang.template.list_smile, 1], + [Lang.template.list_not_much, 2], + [Lang.template.list_good, 3], + [Lang.template.list_bad, 4], + [Lang.template.list_wink, 5], + [Lang.template.list_cry, 6], + [Lang.template.list_absurd, 7], + [Lang.template.list_peck, 8], + [Lang.template.list_arrow_1, 9], + [Lang.template.list_arrow_2, 10], + [Lang.template.list_arrow_3, 11], + [Lang.template.list_arrow_4, 12], + [Lang.template.list_arrow_5, 13], + [Lang.template.list_arrow_6, 14], + [Lang.template.list_arrow_7, 15], + [Lang.template.list_arrow_8, 16], + [Lang.template.list_spade, 17], + [Lang.template.list_club, 18], + [Lang.template.list_diamond, 19], + [Lang.template.list_heart, 20], + [Lang.template.list_circle, 21], + [Lang.template.list_x, 22], + [Lang.template.list_triangle, 23], + [Lang.template.list_square, 24], + [Lang.template.list_note_1, 25], + [Lang.template.list_note_2, 26], + [Lang.template.list_note_3, 27], + [Lang.template.list_dice_1, 28], + [Lang.template.list_dice_2, 29], + [Lang.template.list_dice_3, 30], + [Lang.template.list_dice_4, 31], + [Lang.template.list_dice_5, 32], + [Lang.template.list_dice_6, 33], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_switch: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_off1, 1], + [Lang.template.list_on1, 2], + [Lang.template.list_toggle, 3], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_melody: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_do_re_mi_song, 1], + [Lang.template.list_an_island_baby, 2], + [Lang.template.list_twinkle_twinkle_little_star, 3], + [Lang.template.list_spring_in_my_hometown, 4], + [Lang.template.list_for_elise, 5], + [Lang.template.list_celebrated_chop_waltz, 6], + [Lang.template.list_happy_birthday_to_you, 7], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_keyboard: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'DropdownExtra', + options: [ + [Lang.template.list_lc, 0], + [Lang.template.list_lcs, 1], + [Lang.template.list_ld, 2], + [Lang.template.list_lds, 3], + [Lang.template.list_le, 4], + [Lang.template.list_lf, 5], + [Lang.template.list_lfs, 6], + [Lang.template.list_lg, 7], + [Lang.template.list_lgs, 8], + [Lang.template.list_la, 9], + [Lang.template.list_las, 10], + [Lang.template.list_lb, 11], + [Lang.template.list_mc, 12], + [Lang.template.list_mcs, 13], + [Lang.template.list_md, 14], + [Lang.template.list_mds, 15], + [Lang.template.list_me, 16], + [Lang.template.list_mf, 17], + [Lang.template.list_mfs, 18], + [Lang.template.list_mg, 19], + [Lang.template.list_mgs, 20], + [Lang.template.list_ma, 21], + [Lang.template.list_mas, 22], + [Lang.template.list_mb, 23], + [Lang.template.list_hc, 24] + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_expension_sensor_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_switch, 0], + [Lang.template.list_infrared_ray, 1], + [Lang.template.list_magnet, 2], + [Lang.template.list_rotation, 3], + [Lang.template.list_brightness, 4], + [Lang.template.list_sound, 5], + [Lang.template.list_tilt, 6], + [Lang.template.list_pressure, 7], + [Lang.template.list_heart_rate, 8] + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_compass_sensor_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_value, 0], + [Lang.template.list_angle, 1], + [Lang.template.list_absolute_angle, 2], + [Lang.template.list_rotation_value, 3], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_direction: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_east, 0], + [Lang.template.list_west, 1], + [Lang.template.list_south, 2], + [Lang.template.list_north, 3], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_index_0_5: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0', 0], + ['1', 1], + ['2', 2], + ['3', 3], + ['4', 4], + ['5', 5], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_index_1_5: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 1], + ['2', 2], + ['3', 3], + ['4', 4], + ['5', 5], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_index_1_7: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 0], + ['2', 1], + ['3', 2], + ['4', 3], + ['5', 4], + ['6', 5], + ['7', 6], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_toggle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_off1, 0], + [Lang.template.list_on1, 1], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_toggle2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_off2, 0], + [Lang.template.list_on2, 1], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + ///======================================================================================== + /// Input block + ///======================================================================================== + nemo_title_namo_input: { + skeleton: 'basic_text', + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#333333', + template: Lang.template.title_namo_input, + skeletonOptions: { + box: { + offsetX: 20, + }, + }, + def: { + type: 'nemo_title_namo_input', + }, + isNotFor: ['nemo'], + class : 'inputBlock', + }, + nemo_block_input_event_button_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_event', + statements: [], + template: Lang.template.input_event_button_state, + params: [ + { + type: 'Indicator', + img: 'block_icon/start_icon_hardware.svg', + size: 14, + position: { + x: 0, + y: -2, + }, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'nemo_dropdown_button', + }, + { + type: 'nemo_dropdown_button_now_state', + }, + ], + type: 'nemo_block_input_event_button_state', + }, + paramsKeyMap: { + DUMMY: 0, + INDEX: 1, + STATE: 2, + }, + event: 'aluxNemoButtonEventReceived', + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const state = script.getNumberValue('STATE'); + const getState = Entry.hw.portData['NEMO_DEVICE_EX'].button[index].state[state]; + return getState === true ? script.callReturn() : this.die(); + } + }, + nemo_block_input_event_motion_sensing: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_event', + statements: [], + template: Lang.template.input_event_motion_sensing, + params: [ + { + type: 'Indicator', + img: 'block_icon/start_icon_hardware.svg', + size: 14, + position: { + x: 0, + y: -2, + }, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + } + ], + events: {}, + def: { + params: [ + null, + { + type: 'nemo_dropdown_motion', + }, + ], + type: 'nemo_block_input_event_motion_sensing', + }, + paramsKeyMap: { + DUMMY: 0, + INDEX: 1, + }, + event: 'aluxNemoMotionEventReceived', + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const motion = Entry.hw.portData['NEMO_DEVICE'].accelD; + if (motion[index] === true) { + return script.callReturn(); + } else { + return this.die(); + } + } + }, + nemo_block_input_bool_button_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.input_bool_button_state, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_button', + }, + { + type: 'nemo_dropdown_button_state_question', + }, + ], + type: 'nemo_block_input_bool_button_state', + }, + paramsKeyMap: { + INDEX: 0, + STATE: 1, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const state = script.getNumberValue('STATE'); + const getState = Entry.hw.portData['NEMO_DEVICE_EX'].button[index].state[state]; + return getState; + } + }, + nemo_block_input_bool_motion_sensing: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.input_bool_motion_sensing, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_motion', + }, + ], + type: 'nemo_block_input_bool_motion_sensing', + }, + paramsKeyMap: { + INDEX: 0, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const motion = Entry.hw.portData['NEMO_DEVICE'].accelD; + return motion[index]; + } + }, + nemo_block_input_bool_led_state_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.input_bool_led_state_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + ], + type: 'nemo_block_input_bool_led_state_value', + }, + paramsKeyMap: { + X: 0, + Y: 1, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const x = script.getNumberValue('X'); + const y = script.getNumberValue('Y'); + const index = x * 7 + y + 1; + + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 10, + readLED: { + index: index + }, + }; + Entry.hw.update(); + + const led = Entry.hw.portData['NEMO_DEVICE'].ledRead; + return led.state; + } + }, + nemo_block_input_field_button_analog_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.input_field_button_analog_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_button', + }, + ], + type: 'nemo_block_input_field_button_analog_value', + }, + paramsKeyMap: { + INDEX: 0, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const button = Entry.hw.portData['NEMO_DEVICE'].anSwitch; + return button[index]; + } + }, + nemo_block_input_field_acceleration_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.input_field_acceleration_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_coordinate_acceleration', + }, + ], + type: 'nemo_block_input_field_acceleration_value', + }, + paramsKeyMap: { + INDEX: 0, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const accel = Entry.hw.portData['NEMO_DEVICE'].accelA; + return accel[index]; + } + }, + nemo_block_input_field_brightness_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.input_field_brightness_value, + params: [ + ], + events: {}, + def: { + params: [null], + type: 'nemo_block_input_field_brightness_value', + }, + paramsKeyMap: {}, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const illuminance = Entry.hw.portData['NEMO_DEVICE'].illumi; + return illuminance; + } + }, + nemo_block_input_field_convert_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.input_field_convert_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + ], + type: 'nemo_block_input_field_convert_value', + }, + paramsKeyMap: { + VALUE: 0, + IN_MIN: 1, + IN_MAX: 2, + OUT_MIN: 3, + OUT_MAX: 4, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const value = script.getNumberValue('VALUE'); + const inMin = script.getNumberValue('IN_MIN'); + const inMax = script.getNumberValue('IN_MAX'); + const outMin = script.getNumberValue('OUT_MIN'); + const outMax = script.getNumberValue('OUT_MAX'); + let result = Math.round(((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin); + if (result < outMin) { + result = outMin; + } else if (result > outMax) { + result = outMax; + } + return result; + } + }, + ///======================================================================================== + /// Output block + ///======================================================================================== + nemo_title_namo_output: { + skeleton: 'basic_text', + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#333333', + template: Lang.template.title_namo_output, + skeletonOptions: { + box: { + offsetX: 20, + }, + }, + def: { + type: 'nemo_title_namo_output', + }, + isNotFor: ['nemo'], + class : 'outputBlock', + }, + nemo_block_output_basic_display_led_icon: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_display_led_icon, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_led_icon', + }, + { + type: 'nemo_dropdown_index_0_5', + }, + null, + ], + type: 'nemo_block_output_basic_display_led_icon', + }, + paramsKeyMap: { + INDEX: 0, + SPEED: 1, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const index = script.getNumberValue('INDEX'); + const speed = script.getNumberValue('SPEED'); + const time = Entry.nemo.numToMS(speed); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 0, + iconLED: { + index: index, + time: time, + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_diplay_led_custom_icon: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_diplay_led_custom_icon, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_index_1_7', + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'nemo_dropdown_index_0_5', + }, + null, + ], + type: 'nemo_block_output_basic_diplay_led_custom_icon', + }, + paramsKeyMap: { + INDEX: 0, + VALUE1: 1, + VALUE2: 2, + VALUE3: 3, + VALUE4: 4, + VALUE5: 5, + VALUE6: 6, + VALUE7: 7, + SPEED: 8, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const index = script.getNumberValue('INDEX'); + const value1 = script.getNumberValue('VALUE1'); + const value2 = script.getNumberValue('VALUE2'); + const value3 = script.getNumberValue('VALUE3'); + const value4 = script.getNumberValue('VALUE4'); + const value5 = script.getNumberValue('VALUE5'); + const value6 = script.getNumberValue('VALUE6'); + const value7 = script.getNumberValue('VALUE7'); + const speed = script.getNumberValue('SPEED'); + const time = Entry.nemo.numToMS(speed); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 1, + customLED: { + icon: index, + value: [value1, value2, value3, value4, value5, value6, value7], + time: time, + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_display_led_string: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_display_led_string, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'text', + params: [ 'Hello' ], + }, + { + type: 'nemo_dropdown_index_1_5', + }, + null, + ], + type: 'nemo_block_output_basic_display_led_string', + }, + paramsKeyMap: { + TEXT: 0, + SPEED: 1, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const text = script.getValue('TEXT'); + const speed = script.getNumberValue('SPEED'); + const time = Entry.nemo.numToMS(speed); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 2, + textLED: { + text: text, + time: time, + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_delete_all_led: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_delete_all_led, + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'nemo_block_output_basic_delete_all_led', + }, + paramsKeyMap: {}, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 3, + deleteLED: { + value: true, + }, + }; + + return script.callReturn(); + } + }, + nemo_block_output_basic_coordinate_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_coordinate_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'nemo_dropdown_switch', + }, + null, + ], + type: 'nemo_block_output_basic_coordinate_value', + }, + paramsKeyMap: { + X: 0, + Y: 1, + STATE: 2, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const x = script.getNumberValue('X'); + const y = script.getNumberValue('Y'); + const index = x * 7 + y + 1; + const state = script.getNumberValue('STATE'); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 4, + coordinateLED: { + index: index, + state: state, + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_play_melody: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_play_melody, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_melody', + }, + null, + ], + type: 'nemo_block_output_basic_play_melody', + }, + paramsKeyMap: { + TITLE: 0, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const title = script.getNumberValue('TITLE'); + + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 5, + playMelody: { + title: title, + }, + }; + + return script.callReturn(); + } + }, + nemo_block_output_basic_play_melody_to_the_end: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_play_melody_to_the_end, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_melody', + }, + null, + ], + type: 'nemo_block_output_basic_play_melody_to_the_end', + }, + paramsKeyMap: { + TITLE: 0, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const title = script.getNumberValue('TITLE'); + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 6, + playMelody: { + title: title, + }, + }; + return script; + } else if (script.timeFlag == 1) { + const finished = Entry.hw.portData['NEMO_DEVICE_EX'].timeCheck[1]; + if (finished.state) { + script.timeFlag = 2; + } + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + } + }, + nemo_block_output_basic_play_note: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_play_note, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_keyboard', + }, + null, + ], + type: 'nemo_block_output_basic_play_note', + }, + paramsKeyMap: { + PITCH: 0, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const pitch = script.getNumberValue('PITCH'); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 7, + playNote: { + pitch: pitch + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_play_note_for_seconds: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_play_note_for_seconds, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_keyboard', + }, + { + type: 'number', + params: ['1'], + }, + null, + ], + type: 'nemo_block_output_basic_play_note_for_seconds', + }, + paramsKeyMap: { + PITCH: 0, + TIME: 1, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const pitch = script.getNumberValue('PITCH'); + const time = script.getNumberValue('TIME'); + + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const fps = Entry.FPS || 60; + const timeValue = (60 / fps) * time * 1000; + Entry.TimeWaitManager.add( + Math.random(), + () => { + script.timeFlag = 0; + }, + timeValue + ); + + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 7, + playNote: { + pitch: pitch + }, + }; + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + } + }, + nemo_block_output_basic_stop_all_sound: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_stop_all_sound, + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'nemo_block_output_basic_stop_all_sound', + }, + paramsKeyMap: {}, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 9, + playNote: { + pitch: -1, + }, + playMelody: { + title: 0, + }, + }; + return false; + }); + } + }, + ///======================================================================================== + /// Extension block + ///======================================================================================== + nemo_title_namo_extension: { + skeleton: 'basic_text', + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#333333', + template: Lang.template.title_namo_extension, + skeletonOptions: { + box: { + offsetX: 20, + }, + }, + def: { + type: 'nemo_title_namo_extension', + }, + isNotFor: ['nemo'], + class : 'extensionBlock', + }, + nemo_block_extension_basic_set_expension: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.extension_basic_set_expension, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_expension_sensor_mode', + }, + null, + ], + type: 'nemo_block_extension_basic_set_expension', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const type = script.getNumberValue('TYPE'); + Entry.hw.sendQueue['NEMO_EXTENSION'] = { + id: Math.random(), + index: 0, + setExpansion: { + type: type, + }, + }; + return false; + }); + } + }, + nemo_block_extension_basic_set_expension_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.extension_basic_set_expension_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + null, + ], + type: 'nemo_block_extension_basic_set_expension_value', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const value = script.getNumberValue('VALUE'); + Entry.hw.sendQueue['NEMO_EXTENSION'] = { + id: Math.random(), + index: 1, + setExpansionValue: { + value: value, + }, + }; + return false; + }); + } + }, + nemo_block_extension_bool_expension_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.extension_bool_expension_state, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_button_state_question', + }, + null + ], + type: 'nemo_block_extension_bool_expension_state', + }, + paramsKeyMap: { + STATE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const state = script.getNumberValue('STATE') + 4; + const expansion = Entry.hw.portData['NEMO_DEVICE_EX'].expansion; + return expansion.state[state]; + } + }, + nemo_block_extension_field_expension_anlog_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.extension_field_expension_anlog_value, + params: [], + events: {}, + def: { + params: [], + type: 'nemo_block_extension_field_expension_anlog_value', + }, + paramsKeyMap: {}, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const value = Entry.hw.portData['NEMO_DEVICE'].exPort; + return value; + } + }, + nemo_block_extension_field_expension_custom_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.extension_field_expension_custom_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_compass_sensor_mode', + }, + ], + type: 'nemo_block_extension_field_expension_custom_value', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const type = script.getNumberValue('TYPE'); + const expansion = Entry.hw.portData['NEMO_DEVICE_EX'].expansion; + return expansion.state[type]; + } + }, + nemo_block_extension_basic_set_compass_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.extension_basic_set_compass_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + ], + type: 'nemo_block_extension_basic_set_compass_value', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const value = script.getNumberValue('VALUE'); + Entry.hw.sendQueue['NEMO_EXTENSION'] = { + id: Math.random(), + index: 2, + setCompassValue: { + value: value, + }, + }; + return false; + }); + } + }, + + nemo_block_extension_field_compass_analog_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.extension_field_compass_analog_value, + params: [], + events: {}, + def: { + params: [], + type: 'nemo_block_extension_field_compass_analog_value', + }, + paramsKeyMap: {}, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const value = Entry.hw.portData['NEMO_DEVICE'].compass; + return value; + } + }, + nemo_block_extension_field_compass_custom_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.extension_field_compass_custom_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_compass_sensor_mode', + }, + ], + type: 'nemo_block_extension_field_compass_custom_value', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const type = script.getNumberValue('TYPE'); + const compass = Entry.hw.portData['NEMO_DEVICE_EX'].compass; + return compass.state[type]; + } + }, + nemo_block_extension_bool_compass_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.extension_bool_compass_state, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + },], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_direction', + }, + ], + type: 'nemo_block_extension_bool_compass_state', + }, + paramsKeyMap: { + DIRECTION: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const direction = script.getNumberValue('DIRECTION'); + const compass = Entry.hw.portData['NEMO_DEVICE_EX'].compass; + return compass.state[4] === direction ? true : false; + } + }, + }; +}; + +module.exports = Entry.nemo; \ No newline at end of file From 09128890f0ecc48e44f40f9aeea3b36336ca4b0a Mon Sep 17 00:00:00 2001 From: Hagwon <50008047+hagwon@users.noreply.github.com> Date: Thu, 19 Sep 2024 08:53:41 +0900 Subject: [PATCH 11/21] =?UTF-8?q?=ED=94=84=EB=A1=9C=EB=B3=B4=EC=BB=A4?= =?UTF-8?q?=EB=84=A5=ED=8A=B8=20=EB=B8=94=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocks/hardware/block_proboconnect.js | 6633 ++++++++++------- 1 file changed, 3970 insertions(+), 2663 deletions(-) diff --git a/src/playground/blocks/hardware/block_proboconnect.js b/src/playground/blocks/hardware/block_proboconnect.js index 18fd0f21dd..d670bb0d10 100644 --- a/src/playground/blocks/hardware/block_proboconnect.js +++ b/src/playground/blocks/hardware/block_proboconnect.js @@ -1,2663 +1,3970 @@ -'use strict'; - - -Entry.ProboConnect = { - afterReceive(pd) { - if(Entry.engine.isState('run')){ - Entry.engine.fireEvent('event_remote_input'); - Entry.engine.fireEvent('event_digital_input'); - } - - }, - - id: '27.1', - name: 'ProboConnect', // isNotFor 속성과 대소문자까지 정확하게 매치되어야 합니다. - url: 'http://www.probo.kr/', // 생략 가능합니다. 엔트리 사이트에서 홍보시 사용됩니다. - imageName: 'ProboConnect.png', // images/hardware 폴더 내에 존재하는 이미지입니다. 엔트리 사이트에서 홍보시 사용됩니다. - title: { - ko: '프로보커넥트', - en: 'ProboConnect', - }, - Color: [ - /*레드*/ [13, 37], - /*그린*/ [38, 62], - /*블루*/ [63, 87], - /*옐로우*/ [88, 112], - /*블랙*/ [113, 137], - /*화이트*/ [138, 162], - ], - - Note:{ - n32 : 48,// = 1*3*4*4, - n16 : 96,// = 2*3*4*4, - n16d: 144,// = 3*3*4*4, - n16t: 64,// = 2*2*4*4, - n8 : 192,// = 4*3*4*4, - n8d : 288,// = 6*3*4*4, - n8t : 128,// = 4*2*4*4, - n4 : 384,// = 8*3*4*4, - n4d : 576,// = 12*3*4*4, - n4t : 256,// = 8*2*4*4, - n2 : 768,// = 16*3*4*4, - n2d : 1152,// = 24*3*4*4, - n2t : 512,// = 16*2*4*4, - n1 : 1536,// = 32*3*4*4 - }, - - RGB_LED:{ - red : 1, //RED ON - red1: 2, //RED 0.05 ON -> OFF 반복 - red2: 3, //RED 0.1 ON -> OFF 반복 - red3: 4, //RED 0.2 ON -> OFF 반복 - red4: 5, //RED 0.5 ON -> OFF 반복 - red5: 6, //RED 1 ON -> OFF 반복 - _red1: 7, //RED 0.05 OFF -> ON 반복 - _red2: 8, //RED 0.1 OFF -> ON 반복 - _red3: 9, //RED 0.2 OFF -> ON 반복 - _red4: 10, //RED 0.5 OFF -> ON 반복 - _red5: 11, //RED 1 OFF -> ON 반복 - - yellow: 12, //YELLOW ON - yellow1: 13, //YELLOW 0.05 ON -> OFF 반복 - yellow2: 14, //YELLOW 0.1 ON -> OFF 반복 - yellow3: 15, //YELLOW 0.2 ON -> OFF 반복 - yellow4: 16, //YELLOW 0.5 ON -> OFF 반복 - yellow5: 17, //YELLOW 1 ON -> OFF 반복 - _yellow1: 18, //YELLOW 0.05 OFF -> ON 반복 - _yellow2: 19, //YELLOW 0.1 OFF -> ON 반복 - _yellow3: 20, //YELLOW 0.2 OFF -> ON 반복 - _yellow4: 21, //YELLOW 0.5 OFF -> ON 반복 - _yellow5: 22, //YELLOW 1 OFF -> ON 반복 - - green : 23, //GREEN ON - green1: 24, //GREEN 0.05 ON -> OFF 반복 - green2: 25, //GREEN 0.1 ON -> OFF 반복 - green3: 26, //GREEN 0.2 ON -> OFF 반복 - green4: 27, //GREEN 0.5 ON -> OFF 반복 - green5: 28, //GREEN 1 ON -> OFF 반복 - _green1: 29, //GREEN 0.05 OFF -> ON 반복 - _green2: 30, //GREEN 0.1 OFF -> ON 반복 - _green3: 31, //GREEN 0.2 OFF -> ON 반복 - _green4: 32, //GREEN 0.5 OFF -> ON 반복 - _green5: 33, //GREEN 1 OFF -> ON 반복 - - cyan : 34, //CYAN ON - cyan1: 35, //CYAN 0.05 ON -> OFF 반복 - cyan2: 36, //CYAN 0.1 ON -> OFF 반복 - cyan3: 37, //CYAN 0.2 ON -> OFF 반복 - cyan4: 38, //CYAN 0.5 ON -> OFF 반복 - cyan5: 39, //CYAN 1 ON -> OFF 반복 - _cyan1: 40, //CYAN 0.05 OFF -> ON 반복 - _cyan2: 41, //CYAN 0.1 OFF -> ON 반복 - _cyan3: 42, //CYAN 0.2 OFF -> ON 반복 - _cyan4: 43, //CYAN 0.5 OFF -> ON 반복 - _cyan5: 44, //CYAN 1 OFF -> ON 반복 - - blue: 45, //BLUE ON - blue1: 46, //BLUE 0.05 ON -> OFF 반복 - blue2: 47, //BLUE 0.1 ON -> OFF 반복 - blue3: 48, //BLUE 0.2 ON -> OFF 반복 - blue4: 49, //BLUE 0.5 ON -> OFF 반복 - blue5: 50, //BLUE 1 ON -> OFF 반복 - _blue1: 51, //BLUE 0.05 OFF -> ON 반복 - _blue2: 52, //BLUE 0.1 OFF -> ON 반복 - _blue3: 53, //BLUE 0.2 OFF -> ON 반복 - _blue4: 54, //BLUE 0.5 OFF -> ON 반복 - _blue5: 55, //BLUE 1 OFF -> ON 반복 - - magenta: 56, //MAGENTA ON - magenta1: 57, //MAGENTA 0.05 ON -> OFF 반복 - magenta2: 58, //MAGENTA 0.1 ON -> OFF 반복 - magenta3: 59, //MAGENTA 0.2 ON -> OFF 반복 - magenta4: 60, //MAGENTA 0.5 ON -> OFF 반복 - magenta5: 61, //MAGENTA 1 ON -> OFF 반복 - _magenta1: 62, //MAGENTA 0.05 OFF -> ON 반복 - _magenta2: 63, //MAGENTA 0.1 OFF -> ON 반복 - _magenta3: 64, //MAGENTA 0.2 OFF -> ON 반복 - _magenta4: 65, //MAGENTA 0.5 OFF -> ON 반복 - _magenta5: 66, //MAGENTA 1 OFF -> ON 반복 - - white: 67, //WHITE ON - white1: 68, //WHITE 0.05 ON -> OFF 반복 - white2: 69, //WHITE 0.1 ON -> OFF 반복 - white3: 70, //WHITE 0.2 ON -> OFF 반복 - white4: 71, //WHITE 0.5 ON -> OFF 반복 - white5: 72, //WHITE 1 ON -> OFF 반복 - _white1: 73, //WHITE 0.05 OFF -> ON 반복 - _white2: 74, //WHITE 0.1 OFF -> ON 반복 - _white3: 75, //WHITE 0.2 OFF -> ON 반복 - _white4: 76, //WHITE 0.5 OFF -> ON 반복 - _white5: 77, //WHITE 1 OFF -> ON 반복 - - rgbrnd1: 78, //RANDOM 1 - rgbrnd2: 79, //RANDOM 2 - - red_d: 90, //RED - yellow_d: 91, //YELLOW - green_d: 92, //GREEN - cyan_d: 93, //CYAN - blue_d: 94, //BLUE - magenta_d: 95, //MAGENTA - white_d: 96, //WHITE - - rgboff: 100 //RGB LED OFF - }, - - Melody: [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748], - Melody_S: [0, 35391, 31530, 28090, 26513, 23621, 21044, 18748], - - Track:[ - [0x451F,0x3D95,0x36DD,0x33C8,0x2E22,0x291A,0x249E],// Start : size 7, - [0x228F,0x249E,0x291A,0x2E22,0x33C8,0x36DD,0x3D95,0x451F],// End : size 8, - [0x228F,0x1B6E,0x1711,0x1147],// LevelUp : size 4, - [0x1147,0x1711,0x1B6E,0x228F],// LevelDwon : size 4, - ], - - Infinite_Buff: { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - Infinite_Count: { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - Infinite_Start: { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - - SenserSet:{AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - - InputData: { - Analog: { - AA1: 0, - AA2: 0, - AA3: 0, - AA4: 0, - }, - Digital: { - A1: 0, - A2: 0, - A3: 0, - A4: 0, - FEA1: 0, - FEA2: 0, - FEA3: 0, - FEA4: 0, - REA1: 0, - REA2: 0, - REA3: 0, - REA4: 0, - BEA1: 0, - BEA2: 0, - BEA3: 0, - BEA4: 0, - }, - Remote: { - R_1: 0, - R_2: 0, - R_3: 0, - R_4: 0, - R_5: 0, - R_6: 0, - R_7: 0, - R_8: 0, - R_L1: 0, - R_L2: 0, - R_R1: 0, - R_R2: 0, - }, - EEPROM: { - EC: 0, - EEPR2: 0, - EEPR1: 0, - }, - Infinite:{ - ROTATION_1:0, - ROTATION_2:0, - ROTATION_3:0, - ROTATION_4:0 - }, - Acceler:{ - AXIS_X1:0, - AXIS_X2:0, - AXIS_X3:0, - AXIS_X4:0, - AXIS_Y1:0, - AXIS_Y2:0, - AXIS_Y3:0, - AXIS_Y4:0, - AXIS_Z1:0, - AXIS_Z2:0, - AXIS_Z3:0, - AXIS_Z4:0, - } - }, - RemoteData: { - B1: 0, - B2: 0, - B3: 0, - B4: 0, - Servo1: 0, - Servo2: 0, - Servo3: 0, - Servo4: 0, - DC1: 0, - DC2: 0, - DC3: 0, - DC4: 0, - MEL2: 0, - MEL1: 0, - FND: 100, - EEPR4: 0, - EEPR3: 0, - EEPR2: 0, - EEPR1: 0, - ASET2: 0, - ASET1: 0, - }, - EdgeFlag: { - FEA1: 0, - FEA2: 0, - FEA3: 0, - FEA4: 0, - REA1: 0, - REA2: 0, - REA3: 0, - REA4: 0, - BEA1: 0, - BEA2: 0, - BEA3: 0, - BEA4: 0, - }, - EEPROM: { - EEPROM_Buff: 0, - EEPROM_Count: 0, - }, - - setZero: function() { - for (var key in this.EdgeFlag) this.EdgeFlag[key] = 0; - for (var key in this.RemoteData) Entry.hw.sendQueue[key] = this.RemoteData[key]; - // for (var key in this.Infinite_Start) this.Infinite_Start[key] = 0; - // for (var key in this.Infinite_Count) this.Infinite_Count[key] = 0; - // for (var key in this.Infinite_Buff) this.Infinite_Buff[key] = 0; - for (var key in this.SenserSet) this.SenserSet[key] = 0; - Entry.hw.update(); - }, -}; - -// 언어 적용 -Entry.ProboConnect.setLanguage = function() { - return { - ko: { - // ko.js에 작성하던 내용 - template: { - connect_remote_event: '%1 리모컨 %2 키를 눌렀을 때 %3', - connect_digital_event: '%1 디지털 입력 %2 이(가) 들어왔을 때 %3', - - connect_senser_setting: '센서 설정 A1:%1 A2:%2 A3:%3 A4:%4 %5', - - connect_remote_input: '리모컨 입력 %1', - connect_digital_input: '디지털 센서 %1', - connect_analog_input: '아날로그 센서 %1', - connect_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환', - //connect_ultrasonic_cm: '초음파 센서 %1 의 거리(cm)', - connect_color_input_b: '컬러 센서 %1 이(가) %2 색 인가?', - connect_color_input_r: '컬러 센서 %1 의 색상', - connect_infinite_reset: '%1 센서 %2 초기화 %3', - connect_infinite_setting: '%1 센서 %2 의 값을 %3 값으로 정하기 %4', - connect_infinite_transform_input: '%1 센서 %2 의 %3', - connect_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값', - connect_3axis_acceler_x: '3가속도 %1의 X축', - connect_3axis_acceler_y: '3가속도 %1의 Y축', - connect_3axis_acceler_z: '3가속도 %1의 Z축', - connect_multi_sensor: '멀티키 센서 %1의 %2', - - - connect_port_output: '출력포트 %1 을(를) %2 %3', - connect_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3', - connect_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3', - connect_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3', - connect_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3', - connect_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4', - connect_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3', - connect_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2', - connect_mel_sec_output: '멜로디 %1 을(를) %2 초 동안 소리내기 %3', - connect_melody_output: '멜로디 %1 을(를) 소리내기 %2', - connect_mel_number_sec_output: '멜로디 %1 을(를) %2 초 동안 소리내기 %3', - connect_melody_number_output: '멜로디 %1 을(를) 소리내기 %2', - connect_melody_number_note_output: '멜로디 %1 을(를) %2음표로 소리내기 %3', - connect_value_output: '멜로디 %1 값을 소리내기 %2', - connect_melody_track_output: '멜로디 %1 을(를) %2초 간격으로 소리내기 %3', - connect_melody_off: '멜로디 소리끄기 %1', - connect_fnd_output: 'FND를 %1 (으)로 켜기 %2', - connect_fnd_off: 'FND를 끄기 %1', - - connect_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3', - connect_eeprom_buffset: 'EEPROM %1 주소의 값 임시저장소로 호출하기 %2', - connect_buff_read: 'EEPROM 임시저장소의 값', - }, - }, - en: { - // en.js에 작성하던 내용 - template: { - connect_remote_event: '%1 when remote control %2 key pressed %3', - connect_digital_event: '%1 when digital input %2 is on %3', - - connect_senser_setting: 'senser setting A1:%1 A2:%2 A3:%3 A4:%4 %5', - - connect_remote_input: 'remote input %1', - connect_digital_input: 'digital senser %1', - connect_analog_input: 'analog senser %1', - connect_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5', - //connect_ultrasonic_cm: 'Distance(cm) of ultrasonic sensor %1', - connect_color_input_b: 'is color sensor %1 to %2 ?', - connect_color_input_r: 'color of color sensor %1', - connect_infinite_reset: '%1 rotation sensor %2 reset %3', - connect_infinite_setting: '%1 rotation sensor %2 setting the %3 %4', - connect_infinite_transform_input: '%1 rotation sensor %2 to %3', - connect_infinite_mm_diameter: 'mm value of %1 rotation sensor %2 diameter %3', - connect_3axis_acceler_x: 'acceleration %1 of X-axis', - connect_3axis_acceler_y: 'acceleration %1 of Y-axis', - connect_3axis_acceler_z: 'acceleration %1 of Z-axis', - connect_multi_sensor: 'multi sensor %1 key %2', - - connect_port_output: 'output %1 port %2 %3', - connect_servo_output: 'move position of servo motor %1 to %2 %3', - connect_s_dc_output: 'rotate S motor %1 at %2 speed %3', - connect_dc_output: 'rotate dc motor %1 at %2 speed %3', - connect_rgbled_on_output: 'RGB LED %1 at %2 on %3', - connect_rgbled_flashing_output: 'RGB LED %1 %2 with %3 second interval %4', - connect_rgbled_dimming_output: 'RGB LED %1 at %2 Dimming %3', - connect_rgbled_off_output: 'RGB LED %1 off %2', - connect_mel_sec_output: 'melody %1 sounds for %2 seconds %3', - connect_melody_output: 'off melody sound %1', - connect_mel_number_sec_output: 'play melody %1 sounds for %2 seconds %3', - connect_melody_number_output: 'play the melody %1 %2', - connect_melody_number_note_output: 'play melody %1 with %2 notes %2', - connect_value_output: 'play the melody %1 value %2', - connect_melody_track_output: 'play the melody %1 at intervals of %2 second %3', - connect_melody_off: 'off melody sound %1', - connect_fnd_output: 'FND on %1 %2', - connect_fnd_off: 'FND off %1', - connect_eeprom_write: 'setting the EEPROM %1 address to a value of %2 %3', - connect_eeprom_buffset: - 'calling the value of the EEPROM %1 address into the temporary store %2', - connect_buff_read: 'value of EEPROM temporary store', - }, - }, - }; -}; - -Entry.ProboConnect.blockMenuBlocks = [ - //region proboconnect - ////Start - 'connect_remote_event', - 'connect_digital_event', - - ////input - 'connect_senser_setting', - 'connect_remote_input', - 'connect_digital_input', - 'connect_analog_input', - 'connect_value_mapping', - //"connect_ultrasonic_cm", - 'connect_color_input_b', - 'connect_color_input_r', - 'connect_infinite_reset', - 'connect_infinite_setting', - 'connect_infinite_transform_input', - 'connect_infinite_mm_diameter', - 'connect_3axis_acceler_x', - 'connect_3axis_acceler_y', - 'connect_3axis_acceler_z', - 'connect_multi_sensor', - - - ////output - 'connect_port_output', - 'connect_servo_output', - 'connect_s_dc_output', - 'connect_dc_output', - 'connect_rgbled_on_output', - 'connect_rgbled_flashing_output', - 'connect_rgbled_dimming_output', - 'connect_rgbled_off_output', - 'connect_mel_sec_output', - 'connect_melody_output', - 'connect_mel_number_sec_output', - 'connect_melody_number_output', - 'connect_melody_number_note_output', - 'connect_value_output', - 'connect_melody_track_output', - 'connect_melody_off', - 'connect_fnd_output', - 'connect_fnd_off', - - //// EEPROM - 'connect_eeprom_write', - 'connect_eeprom_buffset', - 'connect_buff_read', - //endregion proboconnect -]; - -// 블록 생성 -Entry.ProboConnect.getBlocks = function() { - return { - // 리모컨 입력 이벤트 - connect_remote_event: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_event', - params: [ - { - type: 'Indicator', - img: 'block_icon/start_icon_play.svg', - size: 14, - position: { - x: 0, - y: -2, - }, - }, - { - type: 'Dropdown', - options: [ - ['R_1', 'R_1'], - ['R_2', 'R_2'], - ['R_3', 'R_3'], - ['R_4', 'R_4'], - ['R_5', 'R_5'], - ['R_6', 'R_6'], - ['R_7', 'R_7'], - ['R_8', 'R_8'], - ['R_L1', 'R_L1'], - ['R_L2', 'R_L2'], - ['R_R1', 'R_R1'], - ['R_R2', 'R_R2'], - ], - fontSize: 11, - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - events: {}, - def: { - params: [null,'R_1',null], - type: 'connect_remote_event', - }, - paramsKeyMap: { - BUTTON: 1, - }, - class: 'event', - isNotFor: ['ProboConnect'], - event: 'event_remote_input', - func(sprite, script) { - const btn = script.getStringField('BUTTON', script); - if(Entry.hw.portData.InputData.Remote[btn] == 1 ) - return script.callReturn(); - - return this.die(); - }, - }, - // 디지털 입력 이벤트 - connect_digital_event: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_event', - params: [ - { - type: 'Indicator', - img: 'block_icon/start_icon_play.svg', - size: 14, - position: { - x: 0, - y: -2, - }, - }, - { - type: 'Dropdown', - options: [ - ['A1', 'A1'], - ['A2', 'A2'], - ['A3', 'A3'], - ['A4', 'A4'], - ['FEA1', 'FEA1'], - ['FEA2', 'FEA2'], - ['FEA3', 'FEA3'], - ['FEA4', 'FEA4'], - ['REA1', 'REA1'], - ['REA2', 'REA2'], - ['REA3', 'REA3'], - ['REA4', 'REA4'], - ['BEA1', 'BEA1'], - ['BEA2', 'BEA2'], - ['BEA3', 'BEA3'], - ['BEA4', 'BEA4'], - ], - fontSize: 11, - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - events: {}, - def: { - params: [null,'A1',null], - type: 'connect_digital_event', - }, - paramsKeyMap: { - PORT: 1, - }, - class: 'event', - isNotFor: ['ProboConnect'], - event: 'event_digital_input', - func(sprite, script) { - const port = script.getStringField('PORT', script); - var rt = false; - if ( - port == 'FEA1' || - port == 'FEA2' || - port == 'FEA3' || - port == 'FEA4' || - port == 'REA1' || - port == 'REA2' || - port == 'REA3' || - port == 'REA4' || - port == 'BEA1' || - port == 'BEA2' || - port == 'BEA3' || - port == 'BEA4' - ) { - if (Entry.hw.portData.InputData.Digital[port] == 1) { - if (Entry.ProboConnect.EdgeFlag[port] == 0) { - Entry.ProboConnect.EdgeFlag[port] = 1; - return script.callReturn(); - } - } else { - Entry.ProboConnect.EdgeFlag[port] = 0; - } - } else if(Entry.hw.portData.InputData.Digital[port] == 1 ){ - return script.callReturn(); - } - return this.die(); - }, - }, - // 리모컨 입력 - connect_remote_input: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_boolean_field', - params: [ - { - type: 'Dropdown', - // Dropdown 생성 기준은 - // [["key1", "value1"], - // ["key2", "value2"]] - options: [ - ['R_1', 'R_1'], - ['R_2', 'R_2'], - ['R_3', 'R_3'], - ['R_4', 'R_4'], - ['R_5', 'R_5'], - ['R_6', 'R_6'], - ['R_7', 'R_7'], - ['R_8', 'R_8'], - ['R_L1', 'R_L1'], - ['R_L2', 'R_L2'], - ['R_R1', 'R_R1'], - ['R_R2', 'R_R2'], - ], - fontSize: 11, - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['R_1'], - type: 'connect_remote_input', - }, - paramsKeyMap: { - BUTTON: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const btn = script.getStringField('BUTTON', script); - - return Entry.hw.portData.InputData.Remote[btn] == 1 ? true : false; - }, - }, - // 디지털 입력 - connect_digital_input: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_boolean_field', - params: [ - { - type: 'Dropdown', - - options: [ - ['A1', 'A1'], - ['A2', 'A2'], - ['A3', 'A3'], - ['A4', 'A4'], - ['FEA1', 'FEA1'], - ['FEA2', 'FEA2'], - ['FEA3', 'FEA3'], - ['FEA4', 'FEA4'], - ['REA1', 'REA1'], - ['REA2', 'REA2'], - ['REA3', 'REA3'], - ['REA4', 'REA4'], - ['BEA1', 'BEA1'], - ['BEA2', 'BEA2'], - ['BEA3', 'BEA3'], - ['BEA4', 'BEA4'], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['A1'], - type: 'connect_digital_input', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var rt = false; - - if ( - port == 'FEA1' || - port == 'FEA2' || - port == 'FEA3' || - port == 'FEA4' || - port == 'REA1' || - port == 'REA2' || - port == 'REA3' || - port == 'REA4' || - port == 'BEA1' || - port == 'BEA2' || - port == 'BEA3' || - port == 'BEA4' - ) { - if (Entry.hw.portData.InputData.Digital[port] == 1) { - if (Entry.ProboConnect.EdgeFlag[port] == 0) { - Entry.ProboConnect.EdgeFlag[port] = 1; - rt = true; - } - } else { - Entry.ProboConnect.EdgeFlag[port] = 0; - } - } else rt = Entry.hw.portData.InputData.Digital[port] == 1 ? true : false; - - return rt; - }, - }, - // 아날로그 입력 - connect_analog_input: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - // Dropdown 생성 기준은 - // [["key1", "value1"], - // ["key2", "value2"]] - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ - // Dropdown 값의 경우 Value를 세팅하면 초기값이 처리 됩니다. - 'AA1', - ], - type: 'connect_analog_input', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - - // Port 라는 key값을 가진 정보를 읽는다. - var value = 0; - - if(Entry.ProboConnect.SenserSet[port]==5) - value = 255 - Entry.hw.portData.InputData.Analog[port]; - else - value = Entry.hw.portData.InputData.Analog[port]; - - return value; - }, - }, - // 아날로그 입력 값 맵핑 블럭 - connect_value_mapping: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { type: 'Block', accept: 'string' }, - { type: 'Block', accept: 'string' }, - { type: 'Block', accept: 'string' }, - { type: 'Block', accept: 'string' }, - { type: 'Block', accept: 'string' }, - ], - def: { - params: [ - // Dropdown 값의 경우 Value를 세팅하면 초기값이 처리 됩니다. - '0', - '0', - '0', - '0', - '0', - ], - type: 'connect_value_mapping', - }, - paramsKeyMap: { - DATA: 0, - SOURCE1: 1, - SOURCE2: 2, - TARGET1: 3, - TARGET2: 4, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const data = script.getNumberValue('DATA', script); - const source1 = script.getNumberValue('SOURCE1', script); - const source2 = script.getNumberValue('SOURCE2', script); - const target1 = script.getNumberValue('TARGET1', script); - const target2 = script.getNumberValue('TARGET2', script); - - var value = 0; - var rate = (data - source1) / (source2 - source1); - var num = 0; - - if (target1 < target2) { - value = (target2 - target1) * rate; - - num = value % 1; - - if (num < 0.5) value -= num; - else value += 1 - num; - - value = target1 + value; - - if (value < target1) value = target1; - else if (value > target2) value = target2; - } else { - value = (target1 - target2) * rate; - - num = value % 1; - - if (num < 0.5) value -= num; - else value += 1 - num; - - value = target1 - value; - - if (value > target1) value = target1; - else if (value < target2) value = target2; - } - - return value; - }, - }, - // 컬러센서 bool - connect_color_input_b: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_boolean_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['빨강', '0'], - ['초록', '1'], - ['파랑', '2'], - ['노랑', '3'], - ['검정', '4'], - ['하양', '5'], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['AA1', '0'], - type: 'connect_color_input_b', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const target = script.getNumberField('COLOR', script); - const value = Entry.hw.portData.InputData.Analog[port]; - var color = Entry.ProboConnect.Color; - - return color[target][0] <= value && value <= color[target][1]; - }, - }, - // 컬러센서 value - connect_color_input_r: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['AA1'], - type: 'connect_color_input_r', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const value = Entry.hw.portData.InputData.Analog[port]; - var color = Entry.ProboConnect.Color; - - for (var i = 0; i < 6; i++) { - if (color[i][0] <= value && value <= color[i][1]) { - switch (i) { - case 0: - return '빨강'; - case 1: - return '초록'; - case 2: - return '파랑'; - case 3: - return '노랑'; - case 4: - return '검정'; - case 5: - return '하양'; - } - } - } - return 0; - }, - }, - // 무한회전 센서 값 초기화 - connect_infinite_reset: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['무한회전', '0'], ['나침반', '1']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [0,'AA1', null], - type: 'connect_infinite_reset', - }, - paramsKeyMap: { - PORT: 1, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const value = Entry.hw.portData.InputData.Analog[port]; - Entry.ProboConnect.Infinite_Start[port] = value; - Entry.ProboConnect.Infinite_Buff[port] = value; - Entry.ProboConnect.Infinite_Count[port] = 0; - }, - }, - // 무한회전 센서 값 설정 - connect_infinite_setting: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['무한회전', '0'], ['나침반', '1']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - } - ], - def: { - params: [0, 'AA1', '0', null], - type: 'connect_infinite_setting', - }, - paramsKeyMap: { - NAME: 0, - PORT: 1, - VALUE: 2, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = script.getNumberValue('VALUE', script); - var count = 0; - // console.log("Start",Entry.ProboConnect.Infinite_Start[port]); - // console.log("Buff",Entry.ProboConnect.Infinite_Buff[port]); - // console.log("Count",Entry.ProboConnect.Infinite_Count[port]); - - if (value!=0){ - count = Number(value / 255).toFixed(0); - value = value % 255; - }else{ - value = 0; - count = 0; - } - console.log("count",count); - console.log("value",value); - console.log("Infinite_Buff",Entry.ProboConnect.Infinite_Buff[port]); - - - Entry.ProboConnect.Infinite_Buff[port] = Entry.hw.portData.InputData.Analog[port]; - Entry.ProboConnect.Infinite_Start[port] = Entry.hw.portData.InputData.Analog[port]-value; - Entry.ProboConnect.Infinite_Count[port] = count; - - console.log("Infinite_Start",Entry.ProboConnect.Infinite_Start[port]); - console.log("Infinite_Buff",Entry.ProboConnect.Infinite_Buff[port]); - console.log("Infinite_Count",Entry.ProboConnect.Infinite_Count[port]); - - }, - }, - // 무한회전 센서 - connect_infinite_transform_input: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['무한회전', '0'], ['나침반', '1']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['값', '1'], ['각도', '2'], ['회전 수', '3'], ['절대각도', '4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [0,'AA1', '1'], - type: 'connect_infinite_transform_input', - }, - paramsKeyMap: { - PORT: 1, - SELECT: 2, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = Entry.hw.portData.InputData.Analog[port]; - const select = script.getNumberField('SELECT', script); - - if (value < (Entry.ProboConnect.Infinite_Buff[port] - 150)) - Entry.ProboConnect.Infinite_Count[port]++; - else if (value > (Entry.ProboConnect.Infinite_Buff[port] + 150)) - Entry.ProboConnect.Infinite_Count[port]--; - - Entry.ProboConnect.Infinite_Buff[port] = value; - - console.log("-Infinite_Start",Entry.ProboConnect.Infinite_Start[port]); - console.log("-Infinite_Buff",Entry.ProboConnect.Infinite_Buff[port]); - console.log("-Infinite_Count",Entry.ProboConnect.Infinite_Count[port]); - - value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255); - - switch (select) { - case 2: - if(value > 0) - return Math.floor((value%255) * 1.41732); - else - return Math.ceil((value%255) * 1.41732); - case 3: - if(value > 0) - return Math.floor(value / 255); - else - return Math.ceil(value / 255); - case 4: - return Number((360/255) * Entry.hw.portData.InputData.Analog[port]).toFixed(0); - default: - return value; - } - }, - }, - // 무한회전 센서 지름 설정 - connect_infinite_mm_diameter: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['무한회전', '0'], ['나침반', '1']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - ], - def: { - params: [0,'AA1', 53.5], - type: 'connect_infinite_mm_diameter', - }, - paramsKeyMap: { - PORT: 1, - DIAMETER: 2, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = Entry.hw.portData.InputData.Analog[port]; - const diameter = script.getNumberValue('DIAMETER', script); - - if (value < Entry.ProboConnect.Infinite_Buff[port] - 150) - Entry.ProboConnect.Infinite_Count[port]++; - else if (value > Entry.ProboConnect.Infinite_Buff[port] + 150) - Entry.ProboConnect.Infinite_Count[port]--; - - Entry.ProboConnect.Infinite_Buff[port] = value; - - value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255); - - return Number( - 2 * - 3.141592 * - (diameter / 2) / - 255 * - value - ).toFixed(3); - }, - }, - // 3가속도 X - connect_3axis_acceler_x: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AXIS_X1'], ['AA2', 'AXIS_X2'], ['AA3', 'AXIS_X3'], ['AA4', 'AXIS_X4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ - 'AXIS_X1', - ], - type: 'connect_3axis_acceler_x', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = (Entry.hw.portData.InputData.Acceler[port]) - if(value & 0x80) value = (value - 255); - return Number(value / 10).toFixed(1); - }, - }, - // 3가속도 Y - connect_3axis_acceler_y: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AXIS_Y1'], ['AA2', 'AXIS_Y2'], ['AA3', 'AXIS_Y3'], ['AA4', 'AXIS_Y4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ - 'AXIS_Y1', - ], - type: 'connect_3axis_acceler_y', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = (Entry.hw.portData.InputData.Acceler[port]) - if(value & 0x80) value = (value - 255); - return Number(value / 10).toFixed(1); - }, - }, - // 3가속도 Z - connect_3axis_acceler_z: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AXIS_Z1'], ['AA2', 'AXIS_Z2'], ['AA3', 'AXIS_Z3'], ['AA4', 'AXIS_Z4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ - 'AXIS_Z1', - ], - type: 'connect_3axis_acceler_z', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = (Entry.hw.portData.InputData.Acceler[port]) - if(value & 0x80) value = (value - 255); - return Number(value / 10).toFixed(1); - }, - }, - // 멀티키 센서 - connect_multi_sensor: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_boolean_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['키1', 0], - ['키2', 1], - ['키3', 2], - ['키4', 3], - ['키5', 4], - ['키6', 5], - ['키7', 6], - ['키8', 7], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['AA1', '0'], - type: 'connect_multi_sensor', - }, - paramsKeyMap: { - PORT: 0, - KEY: 1, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const key = script.getNumberField('KEY', script); - const value = Entry.hw.portData.InputData.Analog[port] & (0x1<100) value = 100; - - Entry.hw.sendQueue[servo] = value; - }, - }, - connect_dc_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['M1', 'DC1'], ['M2', 'DC2'], ['M3', 'DC3'], ['M4', 'DC4'], ['M1,M2', 'DC5'], ['M3,M4', 'DC6'], ['ALL', 'DC7']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['DC1', { type: 'number', params: ['0'] }, null], - type: 'connect_dc_output', - }, - paramsKeyMap: { - MOTOR: 0, - VALUE: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const motor = script.getStringField('MOTOR', script); - const value = script.getNumberValue('VALUE', script); - if(motor=='DC5'){ - Entry.hw.sendQueue['DC1'] = value; - Entry.hw.sendQueue['DC2'] = value; - }else if(motor=='DC6'){ - Entry.hw.sendQueue['DC3'] = value; - Entry.hw.sendQueue['DC4'] = value; - }else if(motor=='DC7'){ - Entry.hw.sendQueue['DC1'] = value; - Entry.hw.sendQueue['DC2'] = value; - Entry.hw.sendQueue['DC3'] = value; - Entry.hw.sendQueue['DC4'] = value; - }else{ - Entry.hw.sendQueue[motor] = value; - } - }, - }, - connect_s_dc_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['S1', 'Servo1'], ['S2', 'Servo2'], ['S3', 'Servo3'], ['S4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', { type: 'number', params: ['0'] }, null], - type: 'connect_s_dc_output', - }, - paramsKeyMap: { - MOTOR: 0, - VALUE: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const motor = script.getStringField('MOTOR', script); - var value = script.getNumberValue('VALUE', script); - - if(value > 20) value = 20; - else if(value < -20) value = -20; - value += 148; - - console.log(value); - - if(motor=='Servo5'){ - Entry.hw.sendQueue['Servo1'] = value; - Entry.hw.sendQueue['Servo2'] = value; - }else if(motor=='Servo6'){ - Entry.hw.sendQueue['Servo3'] = value; - Entry.hw.sendQueue['Servo4'] = value; - }else{ - Entry.hw.sendQueue[motor] = value; - } - }, - }, - connect_rgbled_on_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['B1', 'Servo1'], ['B2', 'Servo2'], ['B3', 'Servo3'], ['B4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['빨강', '1'], - ['노랑', '12'], - ['초록', '23'], - ['청록', '34'], - ['파랑', '45'], - ['자홍', '56'], - ['하양', '67'],], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', '1', null], - type: 'connect_rgbled_on_output', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const color = script.getNumberValue('COLOR', script); - console.log(port); - console.log(color); - Entry.hw.sendQueue[port] = color; - }, - }, - connect_rgbled_flashing_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['B1', 'Servo1'], ['B2', 'Servo2'], ['B3', 'Servo3'], ['B4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['빨강', '1'], - ['노랑', '12'], - ['초록', '23'], - ['청록', '34'], - ['파랑', '45'], - ['자홍', '56'], - ['하양', '67'],], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['0.05', '1'], - ['0.1', '2'], - ['0.2', '3'], - ['0.5', '4'], - ['1', '5'],], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', '1', '3', null], - type: 'connect_rgbled_flashing_output', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - SEC: 2, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const color = script.getNumberValue('COLOR', script); - const sec = script.getNumberField('SEC', script); - const value = color+sec; - console.log("color",color); - console.log("sec",sec); - console.log("color+sec",value); - - Entry.hw.sendQueue[port] = value; - - }, - }, - connect_rgbled_dimming_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['B1', 'Servo1'], ['B2', 'Servo2'], ['B3', 'Servo3'], ['B4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['빨강', '90'], - ['노랑', '91'], - ['초록', '92'], - ['청록', '93'], - ['파랑', '94'], - ['자홍', '95'], - ['하양', '96'],], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', '90', null], - type: 'connect_rgbled_dimming_output', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const color = script.getNumberValue('COLOR', script); - Entry.hw.sendQueue[port] = color; - }, - }, - connect_rgbled_off_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['B1', 'Servo1'], ['B2', 'Servo2'], ['B3', 'Servo3'], ['B4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', null], - type: 'connect_rgbled_off_output', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const color = script.getNumberValue('COLOR', script); - Entry.hw.sendQueue[port] = color; - }, - }, - connect_mel_sec_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [ - ['[1]도', 1], - ['[1]레', 3], - ['[1]미', 5], - ['[1]파', 6], - ['[1]솔', 8], - ['[1]라', 10], - ['[1]시', 12], - ['[2]도', 13], - ['[2]레', 15], - ['[2]미', 17], - ['[2]파', 18], - ['[2]솔', 20], - ['[2]라', 22], - ['[2]시', 24], - ['[3]도', 25], - ['[3]레', 27], - ['[3]미', 29], - ['[3]파', 30], - ['[3]솔', 32], - ['[3]라', 34], - ['[3]시', 36], - ['[4]도', 37], - ['[4]레', 39], - ['[4]미', 41], - ['[4]파', 42], - ['[4]솔', 44], - ['[4]라', 46], - ['[4]시', 48], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [1, { type: 'number', params: ['1'] }, null], - type: 'connect_mel_sec_output', - }, - paramsKeyMap: { - MELODY: 0, - SEC: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - if (!script.isStart) { - script.isStart = true; - script.timeFlag = 1; - const mel = script.getNumberField('MELODY', script); - var timeValue = script.getNumberValue('SEC', script); - var melody = 0; - - if (mel > 0 && mel < 13) melody = Entry.ProboConnect.Melody[mel]; - else if (mel < 25) melody = Entry.ProboConnect.Melody[mel - 12] / 2; - else if (mel < 37) melody = Entry.ProboConnect.Melody[mel - 24] / 4; - else if (mel < 49) melody = Entry.ProboConnect.Melody[mel - 36] / 8; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue * 1000; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - connect_melody_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [ - ['[1]도', 1], - ['[1]레', 3], - ['[1]미', 5], - ['[1]파', 6], - ['[1]솔', 8], - ['[1]라', 10], - ['[1]시', 12], - ['[2]도', 13], - ['[2]레', 15], - ['[2]미', 17], - ['[2]파', 18], - ['[2]솔', 20], - ['[2]라', 22], - ['[2]시', 24], - ['[3]도', 25], - ['[3]레', 27], - ['[3]미', 29], - ['[3]파', 30], - ['[3]솔', 32], - ['[3]라', 34], - ['[3]시', 36], - ['[4]도', 37], - ['[4]레', 39], - ['[4]미', 41], - ['[4]파', 42], - ['[4]솔', 44], - ['[4]라', 46], - ['[4]시', 48], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [1, null], - type: 'connect_melody_output', - }, - paramsKeyMap: { - MELODY: 0, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const mel = script.getNumberField('MELODY', script); - var melody = 0; - - if (mel > 0 && mel < 13) melody = Entry.ProboConnect.Melody[mel]; - else if (mel < 25) melody = Entry.ProboConnect.Melody[mel - 12] / 2; - else if (mel < 37) melody = Entry.ProboConnect.Melody[mel - 24] / 4; - else if (mel < 49) melody = Entry.ProboConnect.Melody[mel - 36] / 8; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - }, - }, - connect_mel_number_sec_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [ - { type: 'number', params: ['1'] }, - { type: 'number', params: ['1'] }, - null], - type: 'connect_mel_number_sec_output', - }, - paramsKeyMap: { - MELODY: 0, - SEC: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - if (!script.isStart) { - script.isStart = true; - script.timeFlag = 1; - const mel = script.getNumberValue('MELODY', script); - var timeValue = script.getNumberValue('SEC', script); - var melody = 0; - - if (mel > 0 && mel < 8) melody = Entry.ProboConnect.Melody_S[mel]; - else if (mel < 15) melody = Entry.ProboConnect.Melody_S[mel - 7] / 2; - else if (mel < 22) melody = Entry.ProboConnect.Melody_S[mel - 14] / 4; - else if (mel < 29) melody = Entry.ProboConnect.Melody_S[mel - 21] / 8; - else melody = 0; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - - console.log(melody); - console.log(timeValue); - - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue * 1000; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - connect_melody_number_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [{ type: 'number', params: ['1'] }, null], - type: 'connect_melody_number_output', - }, - paramsKeyMap: { - MELODY: 0, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const mel = script.getNumberValue('MELODY', script); - - if (mel > 0 && mel < 8) melody = Entry.ProboConnect.Melody_S[mel]; - else if (mel < 15) melody = Entry.ProboConnect.Melody_S[mel - 7] / 2; - else if (mel < 22) melody = Entry.ProboConnect.Melody_S[mel - 14] / 4; - else if (mel < 29) melody = Entry.ProboConnect.Melody_S[mel - 21] / 8; - else melody = 0; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - }, - }, - connect_melody_number_note_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Dropdown', - options: [ - ['온', 'n1'], - ['2분','n2'], - ['4분','n4'], - ['8분','n8'], - ['16분','n16'], - ['32분','n32'], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [{ type: 'number', params: ['1'] }, 'n1', null], - type: 'connect_melody_number_note_output', - }, - paramsKeyMap: { - MELODY: 0, - NOTE: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - if (!script.isStart) { - script.isStart = true; - script.timeFlag = 1; - var mel = script.getNumberValue('MELODY', script); - const note = script.getStringField('NOTE', script); - var timeValue = Entry.ProboConnect.Note[note]; - var melody = 0; - - if (mel > 0 && mel < 8) melody = Entry.ProboConnect.Melody_S[mel]; - else if (mel < 15) melody = Entry.ProboConnect.Melody_S[mel - 7] / 2; - else if (mel < 22) melody = Entry.ProboConnect.Melody_S[mel - 14] / 4; - else if (mel < 29) melody = Entry.ProboConnect.Melody_S[mel - 21] / 8; - else melody = 0; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - connect_value_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [35391, null], - type: 'connect_value_output', - }, - paramsKeyMap: { - MELODY: 0, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - var melody = script.getNumberValue('MELODY', script); - - Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; - Entry.hw.sendQueue['MEL1'] = melody & 0xff; - }, - }, - connect_melody_track_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [ - ['시작음', 0], - ['종료음', 1], - ['레벨업', 2], - ['레벨다운', 3]], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['0.1', 100], - ['0.3', 300], - ['0.5', 500], - ['0.7', 700], - ['1', 1000], - ['2', 2000]], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [0, 1000, null], - type: 'connect_melody_track_output', - }, - paramsKeyMap: { - MELODY: 0, - SEC: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - function getTrackStep(track,script){ - if(!script.isStart){ - script.isStart = true; - script.trackStep = 0; - } - else - script.trackStep++; - - var timeValue = script.getNumberValue('SEC', script); - - script.timeFlag = 1; - var melody = Entry.ProboConnect.Track[track][script.trackStep]; - Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; - Entry.hw.sendQueue['MEL1'] = melody & 0xff; - - var fps = Entry.FPS || 60; - var timeValue = 60 / fps * timeValue; - - Entry.TimeWaitManager.add( - script.block.id, - function() { - script.timeFlag = 0; - }, - timeValue - ); - } - - const TR = script.getNumberValue('MELODY', script); - if (!script.isStart) { - switch(TR){ - case 0 : - script.maxStep = 6; - break; - case 1 : - script.maxStep = 7; - break; - case 2 : - script.maxStep = 3; - break; - case 3 : - script.maxStep = 3; - break; - } - getTrackStep(TR,script); - return script; - } else if (script.timeFlag == 1) { - console.log('timeFlag',script.timeFlag); - return script; - } else if (script.trackStep < script.maxStep){ - getTrackStep(TR,script); - return script; - } else { - - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - - delete script.trackStep; - delete script.maxStep; - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - - connect_melody_off: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [null], - type: 'connect_melody_off', - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - }, - }, - connect_fnd_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['0', null], - type: 'connect_fnd_output', - }, - paramsKeyMap: { - FND: 0, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const fnd = script.getNumberValue('FND', script); - Entry.hw.sendQueue['FND'] = fnd; - }, - }, - connect_fnd_off: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [null], - type: 'connect_fnd_off', - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - Entry.hw.sendQueue['FND'] = 100; - }, - }, - - //============================================ EEPROM ===================================================== - connect_eeprom_buffset: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [{ type: 'number', params: ['0'] }, null], - type: 'connect_eeprom_buffset', - }, - paramsKeyMap: { - ADDRESS: 0, - }, - class: 'EEPROM', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const address = script.getNumberValue('ADDRESS', script); - if (!script.isStart) { - Entry.ProboConnect.EEPROM.EEPROM_Count = Entry.hw.portData.InputData.EEPROM.EC; - Entry.hw.sendQueue['EEPR4'] = 0x40; - Entry.hw.sendQueue['EEPR3'] = address; - - script.isStart = true; - script.timeFlag = 1; - var timeValue = 0.05; - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue * 1000; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - Entry.ProboConnect.EEPROM.EEPROM_Buff = - (Entry.hw.portData.InputData.EEPROM.EEPR2 << 8) + - Entry.hw.portData.InputData.EEPROM.EEPR1; - Entry.hw.sendQueue['EEPR4'] = 0; - - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - connect_buff_read: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - def: { - type: 'connect_buff_read', - }, - class: 'EEPROM', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - var value = 0; - const count = Entry.ProboConnect.EEPROM.EEPROM_Count; - if (Entry.hw.portData.InputData.EEPROM.EC != count) { - value = Entry.ProboConnect.EEPROM.EEPROM_Buff; - } - return value; - }, - }, - connect_eeprom_write: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [ - { type: 'number', params: ['0'] }, - { type: 'number', params: ['0'] }, - null, - ], - type: 'connect_eeprom_write', - }, - paramsKeyMap: { - ADDRESS: 0, - VALUE: 1, - }, - class: 'EEPROM', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const address = script.getNumberValue('ADDRESS', script); - const value = script.getNumberValue('VALUE', script); - if (!script.isStart) { - Entry.hw.sendQueue['EEPR4'] = 0x80; - Entry.hw.sendQueue['EEPR3'] = address; - Entry.hw.sendQueue['EEPR2'] = value >> 8; - Entry.hw.sendQueue['EEPR1'] = value & 0xff; - - script.isStart = true; - script.timeFlag = 1; - var timeValue = 0.05; - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue * 1000; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - }; -}; - -module.exports = Entry.ProboConnect; +'use strict'; + +Entry.ProboConnect = { + afterReceive(pd) { + if(Entry.engine.isState('run')) { + Entry.engine.fireEvent('event_remote_input'); + Entry.engine.fireEvent('event_digital_input'); + } + }, + + id: '27.1', + name: 'ProboConnect', + url: 'https://www.aluxonline.com', + imageName: 'ProboConnect.png', + blockIndex: 0, + title: { + ko: '프로보커넥트', + en: 'ProboConnect', + }, + Color: [ + [13, 37], // 빨강 + [38, 62], // 초록 + [63, 87], // 파랑 + [88, 112], // 노랑 + [113, 137], // 검정 + [138, 162], // 하양 + ], + + Note:{ + n32 : 48, // = 1*3*4*4, + n16 : 96, // = 2*3*4*4, + n16d: 144, // = 3*3*4*4, + n16t: 64, // = 2*2*4*4, + n8 : 192, // = 4*3*4*4, + n8d : 288, // = 6*3*4*4, + n8t : 128, // = 4*2*4*4, + n4 : 384, // = 8*3*4*4, + n4d : 576, // = 12*3*4*4, + n4t : 256, // = 8*2*4*4, + n2 : 768, // = 16*3*4*4, + n2d : 1152, // = 24*3*4*4, + n2t : 512, // = 16*2*4*4, + n1 : 1536, // = 32*3*4*4 + }, + + RGB_LED:{ + red : 1, //RED ON + red1: 2, //RED 0.05 ON -> OFF 반복 + red2: 3, //RED 0.1 ON -> OFF 반복 + red3: 4, //RED 0.2 ON -> OFF 반복 + red4: 5, //RED 0.5 ON -> OFF 반복 + red5: 6, //RED 1 ON -> OFF 반복 + _red1: 7, //RED 0.05 OFF -> ON 반복 + _red2: 8, //RED 0.1 OFF -> ON 반복 + _red3: 9, //RED 0.2 OFF -> ON 반복 + _red4: 10, //RED 0.5 OFF -> ON 반복 + _red5: 11, //RED 1 OFF -> ON 반복 + + yellow: 12, //YELLOW ON + yellow1: 13, //YELLOW 0.05 ON -> OFF 반복 + yellow2: 14, //YELLOW 0.1 ON -> OFF 반복 + yellow3: 15, //YELLOW 0.2 ON -> OFF 반복 + yellow4: 16, //YELLOW 0.5 ON -> OFF 반복 + yellow5: 17, //YELLOW 1 ON -> OFF 반복 + _yellow1: 18, //YELLOW 0.05 OFF -> ON 반복 + _yellow2: 19, //YELLOW 0.1 OFF -> ON 반복 + _yellow3: 20, //YELLOW 0.2 OFF -> ON 반복 + _yellow4: 21, //YELLOW 0.5 OFF -> ON 반복 + _yellow5: 22, //YELLOW 1 OFF -> ON 반복 + + green : 23, //GREEN ON + green1: 24, //GREEN 0.05 ON -> OFF 반복 + green2: 25, //GREEN 0.1 ON -> OFF 반복 + green3: 26, //GREEN 0.2 ON -> OFF 반복 + green4: 27, //GREEN 0.5 ON -> OFF 반복 + green5: 28, //GREEN 1 ON -> OFF 반복 + _green1: 29, //GREEN 0.05 OFF -> ON 반복 + _green2: 30, //GREEN 0.1 OFF -> ON 반복 + _green3: 31, //GREEN 0.2 OFF -> ON 반복 + _green4: 32, //GREEN 0.5 OFF -> ON 반복 + _green5: 33, //GREEN 1 OFF -> ON 반복 + + cyan : 34, //CYAN ON + cyan1: 35, //CYAN 0.05 ON -> OFF 반복 + cyan2: 36, //CYAN 0.1 ON -> OFF 반복 + cyan3: 37, //CYAN 0.2 ON -> OFF 반복 + cyan4: 38, //CYAN 0.5 ON -> OFF 반복 + cyan5: 39, //CYAN 1 ON -> OFF 반복 + _cyan1: 40, //CYAN 0.05 OFF -> ON 반복 + _cyan2: 41, //CYAN 0.1 OFF -> ON 반복 + _cyan3: 42, //CYAN 0.2 OFF -> ON 반복 + _cyan4: 43, //CYAN 0.5 OFF -> ON 반복 + _cyan5: 44, //CYAN 1 OFF -> ON 반복 + + blue: 45, //BLUE ON + blue1: 46, //BLUE 0.05 ON -> OFF 반복 + blue2: 47, //BLUE 0.1 ON -> OFF 반복 + blue3: 48, //BLUE 0.2 ON -> OFF 반복 + blue4: 49, //BLUE 0.5 ON -> OFF 반복 + blue5: 50, //BLUE 1 ON -> OFF 반복 + _blue1: 51, //BLUE 0.05 OFF -> ON 반복 + _blue2: 52, //BLUE 0.1 OFF -> ON 반복 + _blue3: 53, //BLUE 0.2 OFF -> ON 반복 + _blue4: 54, //BLUE 0.5 OFF -> ON 반복 + _blue5: 55, //BLUE 1 OFF -> ON 반복 + + magenta: 56, //MAGENTA ON + magenta1: 57, //MAGENTA 0.05 ON -> OFF 반복 + magenta2: 58, //MAGENTA 0.1 ON -> OFF 반복 + magenta3: 59, //MAGENTA 0.2 ON -> OFF 반복 + magenta4: 60, //MAGENTA 0.5 ON -> OFF 반복 + magenta5: 61, //MAGENTA 1 ON -> OFF 반복 + _magenta1: 62, //MAGENTA 0.05 OFF -> ON 반복 + _magenta2: 63, //MAGENTA 0.1 OFF -> ON 반복 + _magenta3: 64, //MAGENTA 0.2 OFF -> ON 반복 + _magenta4: 65, //MAGENTA 0.5 OFF -> ON 반복 + _magenta5: 66, //MAGENTA 1 OFF -> ON 반복 + + white: 67, //WHITE ON + white1: 68, //WHITE 0.05 ON -> OFF 반복 + white2: 69, //WHITE 0.1 ON -> OFF 반복 + white3: 70, //WHITE 0.2 ON -> OFF 반복 + white4: 71, //WHITE 0.5 ON -> OFF 반복 + white5: 72, //WHITE 1 ON -> OFF 반복 + _white1: 73, //WHITE 0.05 OFF -> ON 반복 + _white2: 74, //WHITE 0.1 OFF -> ON 반복 + _white3: 75, //WHITE 0.2 OFF -> ON 반복 + _white4: 76, //WHITE 0.5 OFF -> ON 반복 + _white5: 77, //WHITE 1 OFF -> ON 반복 + + rgbrnd1: 78, //RANDOM 1 + rgbrnd2: 79, //RANDOM 2 + + red_d: 90, //RED + yellow_d: 91, //YELLOW + green_d: 92, //GREEN + cyan_d: 93, //CYAN + blue_d: 94, //BLUE + magenta_d: 95, //MAGENTA + white_d: 96, //WHITE + + rgboff: 100 //RGB LED OFF + }, + + Melody: [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748], + Melody_S: [0, 35391, 31530, 28090, 26513, 23621, 21044, 18748], + + Track:[ + [0x451F, 0x3D95, 0x36DD, 0x33C8, 0x2E22, 0x291A, 0x249E],// Start : size 7, + [0x228F, 0x249E, 0x291A, 0x2E22, 0x33C8, 0x36DD, 0x3D95, 0x451F],// End : size 8, + [0x228F, 0x1B6E, 0x1711, 0x1147 ],// LevelUp : size 4, + [0x1147, 0x1711, 0x1B6E, 0x228F ],// LevelDwon : size 4, + ], + + Infinite_Buff: { + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + Infinite_Count: { + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + Infinite_Start: { + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + + SenserSet:{ + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + + InputData: { + Analog: { + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0, + }, + Digital: { + A1: 0, + A2: 0, + A3: 0, + A4: 0, + FEA1: 0, + FEA2: 0, + FEA3: 0, + FEA4: 0, + REA1: 0, + REA2: 0, + REA3: 0, + REA4: 0, + BEA1: 0, + BEA2: 0, + BEA3: 0, + BEA4: 0, + }, + Remote: { + R_1: 0, + R_2: 0, + R_3: 0, + R_4: 0, + R_5: 0, + R_6: 0, + R_7: 0, + R_8: 0, + R_L1: 0, + R_L2: 0, + R_R1: 0, + R_R2: 0, + }, + EEPROM: { + EC: 0, + EEPR2: 0, + EEPR1: 0, + }, + Infinite:{ + ROTATION_1: 0, + ROTATION_2: 0, + ROTATION_3: 0, + ROTATION_4: 0 + }, + Acceler:{ + AXIS_X1: 0, + AXIS_X2: 0, + AXIS_X3: 0, + AXIS_X4: 0, + AXIS_Y1: 0, + AXIS_Y2: 0, + AXIS_Y3: 0, + AXIS_Y4: 0, + AXIS_Z1: 0, + AXIS_Z2: 0, + AXIS_Z3: 0, + AXIS_Z4: 0, + } + }, + RemoteData: { + B1: 0, + B2: 0, + B3: 0, + B4: 0, + Servo1: 0, + Servo2: 0, + Servo3: 0, + Servo4: 0, + DC1: 0, + DC2: 0, + DC3: 0, + DC4: 0, + MEL2: 0, + MEL1: 0, + FND: 100, + EEPR4: 0, + EEPR3: 0, + EEPR2: 0, + EEPR1: 0, + ASET2: 0, + ASET1: 0, + }, + EdgeFlag: { + FEA1: 0, + FEA2: 0, + FEA3: 0, + FEA4: 0, + REA1: 0, + REA2: 0, + REA3: 0, + REA4: 0, + BEA1: 0, + BEA2: 0, + BEA3: 0, + BEA4: 0, + }, + EEPROM: { + EEPROM_Buff: 0, + EEPROM_Count: 0, + }, + + setZero: function() { + for (let key in this.EdgeFlag) { + this.EdgeFlag[key] = 0; + } + for (let key in this.RemoteData) { + Entry.hw.sendQueue[key] = this.RemoteData[key]; + } + for (let key in this.SenserSet) { + this.SenserSet[key] = 0; + } + Entry.hw.update(); + }, + convertDropdownRemote(value) { + switch (value) { + case '1': + return 'R_1'; + case '2': + return 'R_2'; + case '3': + return 'R_3'; + case '4': + return 'R_4'; + case '5': + return 'R_5'; + case '6': + return 'R_6'; + case '7': + return'R_7'; + case '8': + return'R_8'; + case '9': + return 'R_L1'; + case '10': + return 'R_L2'; + case '11': + return 'R_R1'; + case '12': + return 'R_R2'; + default: + return value; + } + }, + convertDropdownDigital(value) { + switch (value) { + case '1': + return 'A1'; + case '2': + return 'A2'; + case '3': + return 'A3'; + case '4': + return 'A4'; + case '5': + return 'FEA1'; + case '6': + return 'FEA2'; + case '7': + return 'FEA3'; + case '8': + return 'FEA4'; + case '9': + return 'REA1'; + case '10': + return 'REA2'; + case '11': + return 'REA3'; + case '12': + return 'REA4'; + case '13': + return 'BEA1'; + case '14': + return 'BEA2'; + case '15': + return 'BEA3'; + case '16': + return 'BEA4'; + default: + return value; + } + }, + convertDropdownAnalog(value) { + switch (value) { + case '1': + case '2': + case '3': + case '4': + return 'AA' + value; + default: + return value; + } + }, + convertDropdownAxis(value, axis) { + switch (value) { + case 'AA1': + case 'AA2': + case 'AA3': + case 'AA4': + value = value.substr(2, 2); + break; + } + return "AXIS_" + axis + value; + }, + convertDropdownSensor1(value) { + switch (value) { + case Lang.template.item_switch: + case '1': + return 1; + case Lang.template.item_infrared: + case '2': + return 2; + case Lang.template.item_magnetic: + case '3': + return 3; + case Lang.template.item_rotation: + case '4': + return 4; + case Lang.template.item_color: + case '5': + return 5; + case Lang.template.item_acceleration: + case '6': + return 6; + case Lang.template.item_ultrasonic: + case '7': + return 7; + case Lang.template.item_heart_rate: + case '8': + return 8; + case Lang.template.item_illuminance: + case '9': + return 9; + case Lang.template.item_sound: + case '10': + return 10; + case Lang.template.item_tilt: + case '11': + return 11; + case Lang.template.item_pressure: + case '12': + return 12; + case Lang.template.item_multi_touch: + case '13': + return 13; + case Lang.template.item_compass: + case '14': + return 14; + case Lang.template.item_3acceleration: + case '15': + return 15; + case Lang.template.item_multi_switch: + case '16': + return 16; + } + }, + convertDropdownSensor2(value) { + switch (value) { + case Lang.template.item_infinite_rotation: + case '1': + return 1; + case Lang.template.item_compass: + case '2': + return 2; + default: + return value; + } + }, + convertDropdownKey(value) { + switch (value) { + case Lang.template.item_key_1: + case '1': + return 0; + case Lang.template.item_key_2: + case '2': + return 1; + case Lang.template.item_key_3: + case '3': + return 2; + case Lang.template.item_key_4: + case '4': + return 3; + case Lang.template.item_key_5: + case '5': + return 4; + case Lang.template.item_key_6: + case '6': + return 5; + case Lang.template.item_key_7: + case '7': + return 6; + case Lang.template.item_key_8: + case '8': + return 7; + default: + return value; + } + }, + convertDropdownOnOff(value) { + switch (value) { + case Lang.template.item_on: + case '1': + return 1; + case Lang.template.item_off: + case '0': + return 0; + default: + return value + } + + }, + convertDropdownDC(value) { + switch (value) { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + return 'DC' + value; + default: + return value; + } + }, + convertDropdownServo(value) { + switch (value) { + case '1': + case '2': + case '3': + case '4': + return 'Servo' + value; + default: + return value; + } + }, + convertDropdownPort(value) { + switch (value) { + case '1': + case '2': + case '3': + case '4': + return 'B' + value; + default: + return value; + } + }, + convertDropdownSensorTransfer(value) { + switch (value) { + case Lang.template.item_value: + return '1'; + case Lang.template.item_angle: + return '2'; + case Lang.template.item_absolute_angle: + return '3'; + case Lang.template.item_number_of_rotations: + return '4'; + default: + value; + } + }, + convertDropdownPitch(pitch) { + // 배열의 인덱스 1번부터 음표 + const index = (pitch % 12) + 1; + + let value = 0; + if (36 <= pitch && pitch <= 47) { + value = Entry.ProboConnect.Melody[index]; + } else if (48 <= pitch && pitch <= 59) { + value = Entry.ProboConnect.Melody[index] >> 1; + } else if (60 <= pitch && pitch <= 71) { + value = Entry.ProboConnect.Melody[index] >> 2; + } else if (72 <= pitch && pitch <= 83) { + value = Entry.ProboConnect.Melody[index] >> 3; + } else { + value = Entry.ProboConnect.Melody[0]; + } + return value; + }, + convertDropdownNote(value) { + switch (value) { + case Lang.template.item_note_whole: + case '1': + return 'n1'; + case Lang.template.item_note_half: + case '2': + return 'n2'; + case Lang.template.item_note_quarter: + case '4': + return 'n4'; + case Lang.template.item_note_eighth: + case '8': + return 'n8'; + case Lang.template.item_note_sixteenth: + case '16': + return 'n16'; + case Lang.template.item_note_thirty_second: + case '32': + return 'n32'; + default: + return value; + } + }, + convertDropdownMelody(value) { + switch (value) { + case Lang.template.item_melody_start: + case '1': + return 1; + case Lang.template.item_melody_end: + case '2': + return 2; + case Lang.template.item_melody_level_up: + case '3': + return 3; + case Lang.template.item_melody_level_down: + case '4': + return 4; + } + }, + convertDropdownColor1(value) { + switch (value) { + case Lang.template.item_color_red: + return 0; + case Lang.template.item_color_green: + return 1; + case Lang.template.item_color_blue: + return 2; + case Lang.template.item_color_yellow: + return 3; + case Lang.template.item_color_black: + return 4; + case Lang.template.item_color_white: + return 5; + default: + return value - 1; + } + }, + convertDropdownColor2(value) { + switch (value) { + case Lang.template.item_color_red: + case '1': + return 1; + case Lang.template.item_color_green: + case '2': + return 23; + case Lang.template.item_color_blue: + case '3': + return 45; + case Lang.template.item_color_cyan: + case '4': + return 34; + case Lang.template.item_color_magenta: + case '5': + return 56; + case Lang.template.item_color_yellow: + case '6': + return 12; + case '7': + case Lang.template.item_color_white: + return 67; + default: + return value; + } + }, +}; + +Entry.ProboConnect.setLanguage = function() { + return { + ko: { + template: { + item_switch: '스위치', + item_infrared: '적외선', + item_magnetic: '자석', + item_rotation: '회전', + item_color: '컬러', + item_acceleration: '가속도', + item_ultrasonic: '초음파', + item_heart_rate: '심박', + item_illuminance: '조도', + item_temperature: '온도', + item_sound: '소리', + item_tilt: '기울기', + item_pressure: '압력', + item_multi_touch: '멀티키', + item_compass: '나침반', + item_3acceleration: '3가속', + item_multi_switch: '분배기', + item_infinite_rotation: '무한회전', + item_color_red: '빨간색', + item_color_green: '초록색', + item_color_blue: '파란색', + item_color_cyan: '청녹색', + item_color_magenta: '자홍색', + item_color_yellow: '노란색', + item_color_black: '검정색', + item_color_white: '하얀색', + item_value: '값', + item_angle: '각도', + item_absolute_angle: '절대각도', + item_number_of_rotations: '회전 수', + item_key_1: '키1', + item_key_2: '키2', + item_key_3: '키3', + item_key_4: '키4', + item_key_5: '키5', + item_key_6: '키6', + item_key_7: '키7', + item_key_8: '키8', + item_all: '모두', + item_on: '켜기', + item_off: '끄기', + item_note_whole: '온', + item_note_half: '2분', + item_note_quarter: '4분', + item_note_eighth: '8분', + item_note_sixteenth: '16분', + item_note_thirty_second: '32분', + item_pitch_do: '도', + item_pitch_do_sharp: '도#', + item_pitch_re: '레', + item_pitch_re_sharp: '레#', + item_pitch_mi: '미', + item_pitch_fa: '파', + item_pitch_fa_sharp: '파#', + item_pitch_sol: '솔', + item_pitch_sol_sharp: '솔#', + item_pitch_ra: '라', + item_pitch_ra_sharp: '라#', + item_pitch_si: '시', + item_melody_start: '시작음', + item_melody_end: '종료음', + item_melody_level_up: '레벨 업', + item_melody_level_down: '레벨 다운', + + connect_remote_event: '%1 리모컨 %2 키를 눌렀을 때', + connect_digital_event: '%1 디지털 입력 %2 이(가) 들어왔을 때', + + connect_senser_setting: '입력포트 %1 을(를) %2 센서로 설정 %3', + + connect_remote_input: '리모컨 입력 %1', + connect_digital_input: '디지털 입력 %1', + connect_analog_input: '아날로그 입력 %1', + connect_3axis_acceler_x: '3가속도 %1의 X축', + connect_3axis_acceler_y: '3가속도 %1의 Y축', + connect_3axis_acceler_z: '3가속도 %1의 Z축', + connect_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환', + connect_color_input_b: '컬러 센서 %1 이(가) %2 인가?', + connect_color_input_r: '컬러 센서 %1 의 색상', + connect_infinite_setting: '%1 센서 %2 을 %3 값으로 정하기 %4', + connect_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값', + connect_infinite_transform_input: '%1 센서 %2 의 %3', + connect_multi_sensor: '멀티키 센서 %1의 %2', + connect_multi_switch: '분배 스위치 %1의 %2', + connect_eeprom_buffset: 'EEPROM %1 주소의 값 호출하기 %2', + connect_eeprom_address_value: 'EEPROM 주소의 값', + + connect_port_output: '출력핀 %1 을(를) %2 %3', + connect_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3', + connect_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3', + connect_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3', + connect_melody_note_output: '%1 을(를) %2 음표로 연주하기 %3', + connect_melody_sec_output: '%1 을(를) %2 초 동안 연주하기 %3', + connect_melody_output: '%1 을(를) 연주하기 %2', + connect_value_sec_output: '%1 값을(를) %2 초 동안 연주하기 %3', + connect_value_output: '%1 값을(를) 연주하기 %2', + connect_melody_track_output: '%1 을(를) %2초 간격으로 재생하기 %3', + connect_melody_off: '멜로디 중지 %1', + connect_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3', + connect_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2', + connect_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3', + connect_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4', + connect_fnd_output: 'FND를 %1 (으)로 설정 %2', + connect_fnd_off: 'FND 끄기 %1', + connect_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3', + }, + }, + en: { + template: { + item_switch: 'Switch', + item_infrared: 'Infrared', + item_magnetic: 'Magnetic', + item_rotation: 'Rotation', + item_color: 'Color', + item_acceleration: 'Acceleration', + item_ultrasonic: 'Ultrasonic', + item_heart_rate: 'Heart Rate', + item_illuminance: 'Illuminance', + item_temperature: 'Temperature', + item_sound: 'Sound', + item_tilt: 'Tilt', + item_pressure: 'Pressure', + item_multi_touch: 'Multi Touch', + item_compass: 'Compass', + item_3acceleration: '3Acceleration', + item_multi_switch: 'Multi Switch', + item_infinite_rotation: 'Infinite Rotation', + item_color_red: 'Red', + item_color_green: 'Green', + item_color_blue: 'Blue', + item_color_cyan: 'Cyan', + item_color_magenta: 'Magenta', + item_color_yellow: 'Yellow', + item_color_black: 'Black', + item_color_white: 'White', + item_value: 'Value', + item_angle: 'Angle', + item_absolute_angle: 'Absolute Angle', + item_number_of_rotations: 'Number of Rotations', + item_key_1: 'Key1', + item_key_2: 'Key2', + item_key_3: 'Key3', + item_key_4: 'Key4', + item_key_5: 'Key5', + item_key_6: 'Key6', + item_key_7: 'Key7', + item_key_8: 'Key8', + item_all: 'All', + item_on: 'On', + item_off: 'Off', + item_note_whole: 'Whole', + item_note_half: 'Half', + item_note_quarter: 'Quarter', + item_note_eighth: 'Eighth', + item_note_sixteenth: 'Sixteenth', + item_note_thirty_second: 'Thirty-Second', + item_pitch_do: 'do', + item_pitch_do_sharp: 'xdo', + item_pitch_re: 're', + item_pitch_re_sharp: 'xre', + item_pitch_mi: 'mi', + item_pitch_fa: 'fa', + item_pitch_fa_sharp: 'xfa', + item_pitch_sol: 'sol', + item_pitch_sol_sharp: 'xsol', + item_pitch_ra: 'ra', + item_pitch_ra_sharp: 'xra', + item_pitch_si: 'si', + item_melody_start: 'Start', + item_melody_end: 'End', + item_melody_level_up: 'Level up', + item_melody_level_down: 'Level down', + + connect_remote_event: '%1 When %2 remote control key pressed', + connect_digital_event: '%1 When %2 digital pin input', + + connect_senser_setting: 'Set input port %1 to %2 sensor %3', + + connect_remote_input: 'Remote control %1', + connect_digital_input: 'Read digital pin %1', + connect_analog_input: 'Read analog pin %1', + connect_3axis_acceler_x: '3acceleration %1 and X', + connect_3axis_acceler_y: '3acceleration %1 and Y', + connect_3axis_acceler_z: '3acceleration %1 and Z', + connect_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5', + connect_color_input_b: 'Is color sensor %1 %2 ?', + connect_color_input_r: 'Color of color sensor %1', + connect_infinite_setting: 'Set %1 sensor %2 to %3 value %4', + connect_infinite_mm_diameter: 'The move distance(in mm) when the %1 sensor %2 is %3 mm in diameter', + connect_infinite_transform_input: '%1 rotation sensor %2 to %3', + connect_multi_sensor: 'Multi sensor %1 key %2', + connect_multi_switch: 'A key number of the multi-switch sensor %1 = %2', + connect_eeprom_buffset:'Calling the value of EEPROM %1 address', + connect_eeprom_address_value: 'Value of EEPROM address', + + connect_dc_output: 'DC motor %1 velocity %2 %3', + connect_servo_output: 'Servo motor %1 position %2 %3', + connect_s_dc_output: 'Servo motor %1 speed %2 %3', + connect_port_output: 'Set digital pint %1 as %2 %3', + connect_melody_note_output: 'Play key %1 for %2 note %3', + connect_melody_sec_output: 'Play key %1 for %2 secs %3', + connect_melody_output: 'Play key %1 %2', + connect_value_sec_output: 'Play value %1 for %2 secs %3', + connect_value_output: 'Play value %1 %2', + connect_melody_track_output: 'Play sound %1 for %2 secs %3', + connect_melody_off: 'Stop tone %1', + connect_rgbled_on_output: 'Turn on RGB LED %1 to %2 %3', + connect_rgbled_off_output: 'Turn off RGB LED %1 %2', + connect_rgbled_dimming_output: 'Dimming RGB LED %1 to %2 %3', + connect_rgbled_flashing_output: 'RGB LED %1 Blinking %2 at %3 second intervals %4', + connect_fnd_output: 'Set FND to %1 %2', + connect_fnd_off: 'Turn off FND %1', + connect_eeprom_write: 'Set EEPROM %1 address to %2 %3', + }, + }, + }; +}; + +Entry.ProboConnect.blockMenuBlocks = [ + 'connect_dropdown_remote', + 'connect_dropdown_digital', + 'connect_dropdown_analog', + 'connect_dropdown_sensor_1', + 'connect_dropdown_sensor_2', + 'connect_dropdown_color_1', + 'connect_dropdown_color_2', + 'connect_dropdown_sensor_transfer', + 'connect_dropdown_key', + 'connect_dropdown_dc_1_all', + 'connect_dropdown_servo_1_4', + 'connect_dropdown_port_1_4', + 'connect_dropdown_on_off', + 'connect_dropdown_velocity', + 'connect_dropdown_servo_position', + 'connect_dropdown_note', + 'connect_dropdown_time_1', + 'connect_dropdown_time_2', + 'connect_dropdown_time_3', + 'connect_dropdown_pitch', + 'connect_dropdown_melody', + + //event + 'connect_remote_event', + 'connect_digital_event', + + //input + 'connect_senser_setting', + 'connect_remote_input', + 'connect_digital_input', + 'connect_analog_input', + 'connect_3axis_acceler_x', + 'connect_3axis_acceler_y', + 'connect_3axis_acceler_z', + 'connect_value_mapping', + 'connect_color_input_b', + 'connect_color_input_r', + 'connect_infinite_setting', + 'connect_infinite_mm_diameter', + 'connect_infinite_transform_input', + 'connect_multi_sensor', + 'connect_multi_switch', + 'connect_eeprom_buffset', + 'connect_eeprom_address_value', + + //output + 'connect_dc_output', + 'connect_servo_output', + 'connect_s_dc_output', + 'connect_port_output', + 'connect_melody_note_output', + 'connect_melody_sec_output', + 'connect_melody_output', + 'connect_value_sec_output', + 'connect_value_output', + 'connect_melody_track_output', + 'connect_melody_off', + 'connect_rgbled_on_output', + 'connect_rgbled_off_output', + 'connect_rgbled_flashing_output', + 'connect_rgbled_dimming_output', + 'connect_fnd_output', + 'connect_fnd_off', + // EEPROM + 'connect_eeprom_write', +]; + +// 블록 생성 +Entry.ProboConnect.getBlocks = function() { + return { + ///======================================================================================== + /// Dropdown block + ///======================================================================================== + connect_dropdown_remote: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['R_1', '1'], + ['R_2', '2'], + ['R_3', '3'], + ['R_4', '4'], + ['R_5', '5'], + ['R_6', '6'], + ['R_7', '7'], + ['R_8', '8'], + ['R_L1', '9'], + ['R_L2', '10'], + ['R_R1', '11'], + ['R_R2', '12'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_digital: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['A1', '1'], + ['A2', '2'], + ['A3', '3'], + ['A4', '4'], + ['FEA1', '5'], + ['FEA2', '6'], + ['FEA3', '7'], + ['FEA4', '8'], + ['REA1', '9'], + ['REA2', '10'], + ['REA3', '11'], + ['REA4', '12'], + ['BEA1', '13'], + ['BEA2', '14'], + ['BEA3', '15'], + ['BEA4', '16'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_analog: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['AA1', '1'], + ['AA2', '2'], + ['AA3', '3'], + ['AA4', '4'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_sensor_1: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_switch, '1'], + [Lang.template.item_infrared, '2'], + [Lang.template.item_magnetic, '3'], + [Lang.template.item_rotation, '4'], + [Lang.template.item_color, '5'], + [Lang.template.item_acceleration, '6'], + [Lang.template.item_ultrasonic, '7'], + [Lang.template.item_heart_rate, '8'], + [Lang.template.item_illuminance, '9'], + [Lang.template.item_sound, '10'], + [Lang.template.item_tilt, '11'], + [Lang.template.item_pressure, '12'], + [Lang.template.item_multi_touch, '13'], + [Lang.template.item_compass, '14'], + [Lang.template.item_3acceleration, '15'], + [Lang.template.item_multi_switch, '16'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_sensor_2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_infinite_rotation, '1'], + [Lang.template.item_compass, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_color_1: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_color_red, '1'], + [Lang.template.item_color_green, '2'], + [Lang.template.item_color_blue, '3'], + [Lang.template.item_color_yellow, '4'], + [Lang.template.item_color_black, '5'], + [Lang.template.item_color_white, '6'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_color_2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_color_red, '1'], + [Lang.template.item_color_green, '2'], + [Lang.template.item_color_blue, '3'], + [Lang.template.item_color_cyan, '4'], + [Lang.template.item_color_magenta, '5'], + [Lang.template.item_color_yellow, '6'], + [Lang.template.item_color_white, '7'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_sensor_transfer: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_value, '1'], + [Lang.template.item_angle, '2'], + [Lang.template.item_absolute_angle, '3'], + [Lang.template.item_number_of_rotations, '4'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_key: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_key_1, '1'], + [Lang.template.item_key_2, '2'], + [Lang.template.item_key_3, '3'], + [Lang.template.item_key_4, '4'], + [Lang.template.item_key_5, '5'], + [Lang.template.item_key_6, '6'], + [Lang.template.item_key_7, '7'], + [Lang.template.item_key_8, '8'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_dc_1_all: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 'DC1'], + ['2', 'DC2'], + ['3', 'DC3'], + ['4', 'DC4'], + ['1,2', 'DC5'], + ['3,4', 'DC6'], + [Lang.template.item_all, 'DC7'], + ], + value: 'DC1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_servo_1_4: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 'Servo1'], + ['2', 'Servo2'], + ['3', 'Servo3'], + ['4', 'Servo4'], + ], + value: 'Servo1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_velocity: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['20', '20'], + ['15', '15'], + ['10', '10'], + ['5', '5'], + ['0', '0'], + ['-5', '-5'], + ['-10', '-10'], + ['-15', '-15'], + ['-20', '-20'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_servo_position: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', '1'], + ['20', '20'], + ['40', '40'], + ['60', '60'], + ['80', '80'], + ['100', '100'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_port_1_4: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 'B1'], + ['2', 'B2'], + ['3', 'B3'], + ['4', 'B4'], + ], + value: 'B1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_on_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_on, '1'], + [Lang.template.item_off, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_note: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_note_whole, '1'], + [Lang.template.item_note_half, '2'], + [Lang.template.item_note_quarter, '4'], + [Lang.template.item_note_eighth, '8'], + [Lang.template.item_note_sixteenth, '16'], + [Lang.template.item_note_thirty_second, '32'], + ], + value: 'n4', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_time_1: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0.1', '0.1'], + ['0.3', '0.3'], + ['0.5', '0.5'], + ['0.7', '0.7'], + ['1', '1'], + ['2', '2'], + ], + value: '0.5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_time_2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0.1', '0.1'], + ['0.3', '0.3'], + ['0.5', '0.5'], + ['0.7', '0.7'], + ['1', '1'], + ['2', '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_time_3: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0.05', '0.05'], + ['0.1', '0.1'], + ['0.2', '0.2'], + ['0.5', '0.5'], + ['1', '1'], + ], + value: '0.5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_pitch: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'DropdownExtra', + options: [ + [Lang.template.item_pitch_do + ' (36)', '36'], + [Lang.template.item_pitch_do_sharp + ' (37)', '37'], + [Lang.template.item_pitch_re + ' (38)', '38'], + [Lang.template.item_pitch_re_sharp + ' (39)', '39'], + [Lang.template.item_pitch_mi + ' (40)', '40'], + [Lang.template.item_pitch_fa + ' (41)', '41'], + [Lang.template.item_pitch_fa_sharp + ' (42)', '42'], + [Lang.template.item_pitch_sol + ' (43)', '43'], + [Lang.template.item_pitch_sol_sharp + ' (44)', '44'], + [Lang.template.item_pitch_ra + ' (45)', '45'], + [Lang.template.item_pitch_ra_sharp + ' (46)', '46'], + [Lang.template.item_pitch_si + ' (47)', '47'], + + [Lang.template.item_pitch_do + ' (48)', '48'], + [Lang.template.item_pitch_do_sharp + ' (49)', '49'], + [Lang.template.item_pitch_re + ' (50)', '50'], + [Lang.template.item_pitch_re_sharp + ' (51)', '51'], + [Lang.template.item_pitch_mi + ' (52)', '52'], + [Lang.template.item_pitch_fa + ' (53)', '53'], + [Lang.template.item_pitch_fa_sharp + ' (54)', '54'], + [Lang.template.item_pitch_sol + ' (55)', '55'], + [Lang.template.item_pitch_sol_sharp + ' (56)', '56'], + [Lang.template.item_pitch_ra + ' (57)', '57'], + [Lang.template.item_pitch_ra_sharp + ' (58)', '58'], + [Lang.template.item_pitch_si + ' (59)', '59'], + + [Lang.template.item_pitch_do + ' (60)', '60'], + [Lang.template.item_pitch_do_sharp + ' (61)', '61'], + [Lang.template.item_pitch_re + ' (62)', '62'], + [Lang.template.item_pitch_re_sharp + ' (63)', '63'], + [Lang.template.item_pitch_mi + ' (64)', '64'], + [Lang.template.item_pitch_fa + ' (65)', '65'], + [Lang.template.item_pitch_fa_sharp + ' (66)', '66'], + [Lang.template.item_pitch_sol + ' (67)', '67'], + [Lang.template.item_pitch_sol_sharp + ' (68)', '68'], + [Lang.template.item_pitch_ra + ' (69)', '69'], + [Lang.template.item_pitch_ra_sharp + ' (70)', '70'], + [Lang.template.item_pitch_si + ' (71)', '71'], + + [Lang.template.item_pitch_do + ' (72)', '72'], + [Lang.template.item_pitch_do_sharp + ' (73)', '73'], + [Lang.template.item_pitch_re + ' (74)', '74'], + [Lang.template.item_pitch_re_sharp + ' (75)', '75'], + [Lang.template.item_pitch_mi + ' (76)', '76'], + [Lang.template.item_pitch_fa + ' (77)', '77'], + [Lang.template.item_pitch_fa_sharp + ' (78)', '78'], + [Lang.template.item_pitch_sol + ' (79)', '79'], + [Lang.template.item_pitch_sol_sharp + ' (80)', '80'], + [Lang.template.item_pitch_ra + ' (81)', '81'], + [Lang.template.item_pitch_ra_sharp + ' (82)', '82'], + [Lang.template.item_pitch_si + ' (83)', '83'], + ], + value: '60', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + const value = script.getField('PARAM0'); + return value; + } + }, + connect_dropdown_melody: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_melody_start, '1'], + [Lang.template.item_melody_end, '2'], + [Lang.template.item_melody_level_up, '3'], + [Lang.template.item_melody_level_down, '4'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + ///======================================================================================== + /// Event block + ///======================================================================================== + // 리모컨 R_1 키를 눌렀을 때 + connect_remote_event: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_event', + params: [ + { + type: 'Indicator', + img: 'block_icon/start_icon_hardware.svg', + size: 14, + position: { + x: 0, + y: -2, + }, + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'connect_dropdown_remote', + }, + ], + type: 'connect_remote_event', + }, + paramsKeyMap: { + PARAM1: 1, + }, + class: 'event', + isNotFor: ['ProboConnect'], + event: 'event_remote_input', + func(sprite, script) { + const btn = Entry.ProboConnect.convertDropdownRemote( + script.getStringValue('PARAM1') + ); + if (Entry.hw.portData.InputData.Remote[btn] == 1 ) { + return script.callReturn(); + } + return this.die(); + }, + }, + // 디지털 입력 A1 이(가) 들어왔을 때 + connect_digital_event: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_event', + params: [ + { + type: 'Indicator', + img: 'block_icon/start_icon_hardware.svg', + size: 14, + position: { + x: 0, + y: -2, + }, + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'connect_dropdown_digital', + }, + ], + type: 'connect_digital_event', + }, + paramsKeyMap: { + PARAM1: 1, + }, + class: 'event', + isNotFor: ['ProboConnect'], + event: 'event_digital_input', + func(sprite, script) { + const port = Entry.ProboConnect.convertDropdownDigital( + script.getStringValue('PARAM1') + ); + switch(port) { + case 'FEA1': + case 'FEA2': + case 'FEA3': + case 'FEA4': + case 'REA1': + case 'REA2': + case 'REA3': + case 'REA4': + case 'BEA1': + case 'BEA2': + case 'BEA3': + case 'BEA4': + if (Entry.hw.portData.InputData.Digital[port] == 1) { + if (Entry.ProboConnect.EdgeFlag[port] == 0) { + Entry.ProboConnect.EdgeFlag[port] = 1; + return script.callReturn(); + } + } else { + Entry.ProboConnect.EdgeFlag[port] = 0; + } + break; + default: + if (Entry.hw.portData.InputData.Digital[port] == 1 ) { + return script.callReturn(); + } + break; + } + + return this.die(); + }, + }, + ///======================================================================================== + /// Input block + ///======================================================================================== + // 입력포트 AA1 을(를) 스위치 센서로 설정 + connect_senser_setting: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_sensor_1', + }, + null, + ], + type: 'connect_senser_setting', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'setting', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const sensor = Entry.ProboConnect.convertDropdownSensor1( + script.getStringValue('PARAM1') + ); + let index = 0; + switch (port) { + case 'AA1': + index = 0; + break; + case 'AA2': + index = 1; + break; + case 'AA3': + index = 2; + break; + case 'AA4': + index = 3; + break; + } + + let Aset = [0, 0, 0, 0]; + let value = [0, 0, 0, 0]; + + Aset[index] = sensor; + for (let i = 0; i < 4; i++) { + switch (Aset[i]) { + case 1: // 스위치 + case 2: // 적외선 + case 3: // 자석 + case 16: // 분배기 + value[i] = 1; + break; + case 4: // 회전 + case 9: // 조도 + case 7: // 초음파 + value[i] = 2; + break; + case 10: // 소리 + value[i] = 3; + break; + case 11: // 기울기 + value[i] = 4; + break; + case 12: // 압력 + value[i] = 5; + break; + case 8: // 심박 + value[i] = 6; + break; + case 5: // 컬러 + value[i] = 7; + break; + case 6: // 가속도 + value[i] = 8; + break; + case 14: // 나침반 + case 15: // 3가속 + value[i] = 9; + break; + case 13: // 멀티터치(멀티키) + value[i] = 11; + break; + } + } + + Entry.ProboConnect.SenserSet.AA1 = value[0]; + Entry.ProboConnect.SenserSet.AA2 = value[1]; + Entry.ProboConnect.SenserSet.AA3 = value[2]; + Entry.ProboConnect.SenserSet.AA4 = value[3]; + + Entry.hw.sendQueue['ASET2'] = (value[0] << 4) | value[1]; + Entry.hw.sendQueue['ASET1'] = (value[2] << 4) | value[3]; + + let fps = Entry.FPS || 60; + let timeValue = 60 / fps * 200; // 0.2초 + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + + }, + }, + // 리모컨 입력 R_1 + connect_remote_input: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_remote', + }, + ], + type: 'connect_remote_input', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const btn = Entry.ProboConnect.convertDropdownRemote( + script.getStringValue('PARAM0') + ); + return Entry.hw.portData.InputData.Remote[btn] == 1 ? true : false; + }, + }, + // 디지털 입력 A1 + connect_digital_input: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_digital', + }, + ], + type: 'connect_digital_input', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownDigital( + script.getStringValue('PARAM0') + ); + let rt = false; + switch(port) { + case 'FEA1': + case 'FEA2': + case 'FEA3': + case 'FEA4': + case 'REA1': + case 'REA2': + case 'REA3': + case 'REA4': + case 'BEA1': + case 'BEA2': + case 'BEA3': + case 'BEA4': + if (Entry.hw.portData.InputData.Digital[port] == 1) { + if (Entry.ProboConnect.EdgeFlag[port] == 0) { + Entry.ProboConnect.EdgeFlag[port] = 1; + rt = true; + } + } else { + Entry.ProboConnect.EdgeFlag[port] = 0; + } + break; + default: + rt = Entry.hw.portData.InputData.Digital[port] == 1 ? true : false; + break; + } + return rt; + }, + }, + // 아날로그 입력 AA1 + connect_analog_input: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_analog_input', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + let value = Entry.ProboConnect.SenserSet[port] == 5 + ? 255 - Entry.hw.portData.InputData.Analog[port] + : Entry.hw.portData.InputData.Analog[port]; + return value; + }, + }, + // 3가속도 AA1 의 X축 + connect_3axis_acceler_x: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_3axis_acceler_x', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const axis = Entry.ProboConnect.convertDropdownAxis( + script.getStringValue('PARAM0'), + "X" + ); + let value = (Entry.hw.portData.InputData.Acceler[axis]); + if (value & 0x80) { + value = (value - 255); + } + return Number(value / 10).toFixed(1); + }, + }, + // 3가속도 AA1의 Y축 + connect_3axis_acceler_y: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_3axis_acceler_y', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const axis = Entry.ProboConnect.convertDropdownAxis( + script.getStringValue('PARAM0'), + "Y" + ); + let value = (Entry.hw.portData.InputData.Acceler[axis]); + if (value & 0x80) { + value = (value - 255); + } + return Number(value / 10).toFixed(1); + }, + }, + // 3가속도 AA1 의 Z축 + connect_3axis_acceler_z: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_3axis_acceler_z', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const axis = Entry.ProboConnect.convertDropdownAxis( + script.getStringValue('PARAM0'), + "Z" + ); + let value = (Entry.hw.portData.InputData.Acceler[axis]); + if (value & 0x80) { + value = (value - 255); + } + return Number(value / 10).toFixed(1); + }, + }, + // AA1의 0 ~ 255 값을 0 ~ 100 (으)로 변환 + connect_value_mapping: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 255 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 100 ], + }, + ], + type: 'connect_value_mapping', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + PARAM2: 2, + PARAM3: 3, + PARAM4: 4, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const source1 = script.getNumberValue('PARAM1'); + const source2 = script.getNumberValue('PARAM2'); + const target1 = script.getNumberValue('PARAM3'); + const target2 = script.getNumberValue('PARAM4'); + + // Port 라는 key값을 가진 정보를 읽는다. + let data = 0; + if (Entry.ProboConnect.SenserSet[port] == 5) { + data = 255 - Entry.hw.portData.InputData.Analog[port]; + } else { + data = Entry.hw.portData.InputData.Analog[port]; + } + let value = 0; + let rate = (data - source1) / (source2 - source1); + let num = 0; + + if (target1 < target2) { + value = (target2 - target1) * rate; + num = value % 1; + if (num < 0.5) { + value -= num; + } + else { + value += 1 - num; + } + value = target1 + value; + if (value < target1) { + value = target1; + } else if (value > target2) { + value = target2; + } + } else { + value = (target1 - target2) * rate; + num = value % 1; + if (num < 0.5) { + value -= num; + } else { + value += 1 - num; + } + value = target1 - value; + if (value > target1) { + value = target1; + } else if (value < target2) { + value = target2; + } + } + return value; + }, + }, + // 컬러센서 AA1 이(가) 빨간색 색인가? + connect_color_input_b: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_color_1', + }, + ], + type: 'connect_color_input_b', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const target = Entry.ProboConnect.convertDropdownColor1( + script.getNumberValue('PARAM1') + ); + const value = Entry.hw.portData.InputData.Analog[port]; + const color = Entry.ProboConnect.Color; + return color[target][0] <= value && value <= color[target][1]; + }, + }, + // 컬러센서 AA1 의 색상 + connect_color_input_r: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_color_input_r', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const value = Entry.hw.portData.InputData.Analog[port]; + const color = Entry.ProboConnect.Color; + let colorName = ''; + for (let i = 0; i < 6; i++) { + if (color[i][0] <= value && value <= color[i][1]) { + switch (i) { + case 0: + colorName = Lang.template.item_color_red; + break; + case 1: + colorName = Lang.template.item_color_green; + break; + case 2: + colorName = Lang.template.item_color_blue; + break; + case 3: + colorName = Lang.template.item_color_yellow; + break; + case 4: + colorName = Lang.template.item_color_black; + break; + case 5: + colorName = Lang.template.item_color_white; + break; + } + } + } + return colorName; + }, + }, + // 무한회전 센서 AA1 을 0 값으로 정하기 + connect_infinite_setting: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + } + ], + def: { + params: [ + { + type: 'connect_dropdown_sensor_2', + }, + { + type: 'connect_dropdown_analog', + }, + { + type: 'number', + params: [ 0 ], + }, + null + ], + type: 'connect_infinite_setting', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + PARAM2: 2, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM1') + ); + let value = script.getNumberValue('PARAM2'); + let count = 0; + + if (value != 0) { + count = Number(value / 255).toFixed(0); + value = value % 255; + } else { + value = 0; + count = 0; + } + + Entry.ProboConnect.Infinite_Buff[port] = Entry.hw.portData.InputData.Analog[port]; + Entry.ProboConnect.Infinite_Start[port] = Entry.hw.portData.InputData.Analog[port]-value; + Entry.ProboConnect.Infinite_Count[port] = count; + + return script.callReturn(); + }, + }, + // 무한회전 센서 AA1 지름 53.5 의 mm 값 + connect_infinite_mm_diameter: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_sensor_2', + }, + { + type: 'connect_dropdown_analog', + }, + { + type: 'number', + params: [ 53.5 ], + }, + ], + type: 'connect_infinite_mm_diameter', + }, + paramsKeyMap: { + PARAM1: 1, + PARAM2: 2, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM1') + ); + const diameter = script.getNumberValue('PARAM2'); + let value = Entry.hw.portData.InputData.Analog[port]; + + if (value < Entry.ProboConnect.Infinite_Buff[port] - 150) { + + Entry.ProboConnect.Infinite_Count[port]++; + } else if (value > Entry.ProboConnect.Infinite_Buff[port] + 150) { + Entry.ProboConnect.Infinite_Count[port]--; + } + Entry.ProboConnect.Infinite_Buff[port] = value; + value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255); + + return Number( + 2 * + 3.141592 * + (diameter / 2) / + 255 * + value + ).toFixed(3); + }, + }, + // 무한회전 센서 AA1 의 값 + connect_infinite_transform_input: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_sensor_2', + }, + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_sensor_transfer', + }, + ], + type: 'connect_infinite_transform_input', + }, + paramsKeyMap: { + PARAM1: 1, + PARAM2: 2, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM1') + ); + const select = Entry.ProboConnect.convertDropdownSensorTransfer( + script.getStringValue('PARAM2') + ); + let value = Entry.hw.portData.InputData.Analog[port]; + + if (value < (Entry.ProboConnect.Infinite_Buff[port] - 150)) { + Entry.ProboConnect.Infinite_Count[port]++; + } else if (value > (Entry.ProboConnect.Infinite_Buff[port] + 150)) { + Entry.ProboConnect.Infinite_Count[port]--; + } + Entry.ProboConnect.Infinite_Buff[port] = value; + value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255); + + switch (select) { + case 2: + if (value > 0) { + return Math.floor((value%255) * 1.41732); + } else { + return Math.ceil((value%255) * 1.41732); + } + case 3: + return Number((360/255) * Entry.hw.portData.InputData.Analog[port]).toFixed(0); + case 4: + if (value > 0) { + return Math.floor(value / 255); + } else { + return Math.ceil(value / 255); + } + default: + return value; + } + }, + }, + // 멀티키 센서 AA1 의 키1 + connect_multi_sensor: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_key', + }, + ], + type: 'connect_multi_sensor', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const key = Entry.ProboConnect.convertDropdownKey( + script.getStringValue('PARAM1') + ); + const value = Entry.hw.portData.InputData.Analog[port] & (0x1 << key)? 1 : 0; + return value; + }, + }, + // 분배스위치 센서 AA1의 키1 + connect_multi_switch: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_key', + }, + ], + type: 'connect_multi_switch', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const key = Entry.ProboConnect.convertDropdownKey( + script.getStringValue('PARAM1') + ); + const analog = Entry.hw.portData.InputData.Analog[port]; + let value = -1; + if (1 <= analog && analog <= 19) { + value = 0; + } else if (26 <= analog && analog <= 44) { + value = 1; + } else if (53 <= analog && analog <= 77) { + value = 2; + } else if (83 <= analog && analog <= 101) { + value = 3; + } else if (107 <= analog && analog <= 125) { + value = 4; + } else if (139 <= analog && analog <= 157) { + value = 5; + } else if (160 <= analog && analog <= 178) { + value = 6; + } else if (191 <= analog && analog <= 209) { + value = 7; + } + return key === value ? 1 : 0; + }, + }, + connect_eeprom_buffset: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [{ type: 'number', params: ['0'] }, null], + type: 'connect_eeprom_buffset', + }, + paramsKeyMap: { + ADDRESS: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const address = script.getNumberValue('ADDRESS', script); + if (!script.isStart) { + Entry.ProboConnect.EEPROM.EEPROM_Count = Entry.hw.portData.InputData.EEPROM.EC; + Entry.hw.sendQueue['EEPR4'] = 0x40; + Entry.hw.sendQueue['EEPR3'] = address; + + script.isStart = true; + script.timeFlag = 1; + var timeValue = 0.05; + var fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + var blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.ProboConnect.EEPROM.EEPROM_Buff = + (Entry.hw.portData.InputData.EEPROM.EEPR2 << 8) + + Entry.hw.portData.InputData.EEPROM.EEPR1; + Entry.hw.sendQueue['EEPR4'] = 0; + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // EEPROM 주소의 값 + connect_eeprom_address_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + def: { + type: 'connect_eeprom_address_value', + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + var value = 0; + const count = Entry.ProboConnect.EEPROM.EEPROM_Count; + if (Entry.hw.portData.InputData.EEPROM.EC != count) { + value = Entry.ProboConnect.EEPROM.EEPROM_Buff; + } + return value; + }, + }, + ///======================================================================================== + /// output block + ///======================================================================================== + // DC 모터 1을(를) 0 속도로 회전 + connect_dc_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_dc_1_all', + }, + { + type: 'connect_dropdown_velocity', + }, + null, + ], + type: 'connect_dc_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const motor = Entry.ProboConnect.convertDropdownDC( + script.getStringValue('PARAM0') + ); + const value = script.getNumberValue('PARAM1'); + switch (motor) { + case 'DC5': + Entry.hw.sendQueue['DC1'] = value; + Entry.hw.sendQueue['DC2'] = value; + break; + case 'DC6': + Entry.hw.sendQueue['DC3'] = value; + Entry.hw.sendQueue['DC4'] = value; + break; + case 'DC7': + Entry.hw.sendQueue['DC1'] = value; + Entry.hw.sendQueue['DC2'] = value; + Entry.hw.sendQueue['DC3'] = value; + Entry.hw.sendQueue['DC4'] = value; + break; + default: + Entry.hw.sendQueue[motor] = value; + break; + } + return script.callReturn(); + }, + }, + // 서보모터 1 의 위치를 1 로 이동 + connect_servo_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_servo_position', + }, + null, + ], + type: 'connect_servo_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const servo = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + let value = script.getNumberValue('PARAM1'); + if (value < 1) { + value = 0; + } else if (value > 100) { + value = 100; + } + + Entry.hw.sendQueue[servo] = value; + return script.callReturn(); + }, + }, + // S 모터 1 을(를) 0 속도로 회전 + connect_s_dc_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_velocity', + }, + null, + ], + type: 'connect_s_dc_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const motor = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + let value = script.getNumberValue('PARAM1'); + + if (value > 20) { + value = 20; + } else if (value < -20) { + value = -20; + } + value += 148; + + switch (motor) { + case 'Servo5': + Entry.hw.sendQueue['Servo1'] = value; + Entry.hw.sendQueue['Servo2'] = value; + break; + case 'Servo6': + Entry.hw.sendQueue['Servo3'] = value; + Entry.hw.sendQueue['Servo4'] = value; + break; + default: + Entry.hw.sendQueue[motor] = value; + break; + } + return script.callReturn(); + }, + }, + // 출력핀 1 을(를) 켜기 + connect_port_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_port_1_4', + }, + { + type: 'connect_dropdown_on_off', + }, + null + ], + type: 'connect_port_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const motor = Entry.ProboConnect.convertDropdownPort( + script.getStringValue('PARAM0') + ); + const value = Entry.ProboConnect.convertDropdownOnOff( + script.getNumberValue('PARAM1') + ); + + Entry.hw.sendQueue[motor] = value; + return script.callReturn(); + }, + }, + // 도(60) 을(를) 4분 음표로 연주하기 + connect_melody_note_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_pitch', + }, + { + type: 'connect_dropdown_note', + }, + null + ], + type: 'connect_melody_note_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const pitch = Entry.ProboConnect.convertDropdownPitch( + script.getNumberValue('PARAM0') + ); + const note = Entry.ProboConnect.convertDropdownNote( + script.getStringValue('PARAM1') + ); + + let timeValue = Entry.ProboConnect.Note[note]; + + Entry.hw.sendQueue['MEL2'] = pitch >> 8; + Entry.hw.sendQueue['MEL1'] = pitch; + + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue; + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // 도(60) 을(를) 0.5 초 동안 연주하기 + connect_melody_sec_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_pitch', + }, + { + type: 'connect_dropdown_time_1', + }, + null + ], + type: 'connect_melody_sec_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const pitch = Entry.ProboConnect.convertDropdownPitch( + script.getNumberValue('PARAM0') + ); + let timeValue = script.getNumberValue('PARAM1'); + + Entry.hw.sendQueue['MEL2'] = pitch >> 8; + Entry.hw.sendQueue['MEL1'] = pitch; + + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // 도(60) 을(를) 연주하기 + connect_melody_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_pitch', + }, + null + ], + type: 'connect_melody_output', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const pitch = Entry.ProboConnect.convertDropdownPitch( + script.getNumberValue('PARAM0') + ); + + Entry.hw.sendQueue['MEL2'] = pitch >> 8; + Entry.hw.sendQueue['MEL1'] = pitch; + return script.callReturn(); + }, + }, + // 35391 값을 0.5 초 동안 연주하기 + connect_value_sec_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'number', + params: [ 35391 ], + }, + { + type: 'connect_dropdown_time_1', + }, + null + ], + type: 'connect_value_sec_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + + let melody = script.getNumberValue('PARAM0'); + let timeValue = script.getNumberValue('PARAM1'); + + Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; + Entry.hw.sendQueue['MEL1'] = melody & 0xff; + + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // 35391 값을(를) 연주하기 + connect_value_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'number', + params: [ 35391 ], + }, + null + ], + type: 'connect_value_output', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + let melody = script.getNumberValue('PARAM0'); + Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; + Entry.hw.sendQueue['MEL1'] = melody & 0xff; + return script.callReturn(); + }, + }, + // 시작음 을(를) 1 초 간격으로 재생하기 + connect_melody_track_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_melody', + }, + { + type: 'connect_dropdown_time_2', + }, + null + ], + type: 'connect_melody_track_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + function getTrackStep(track,script){ + if(!script.isStart){ + script.isStart = true; + script.trackStep = 0; + } + else { + script.trackStep++; + } + let timeValue = script.getNumberValue('PARAM1'); + script.timeFlag = 1; + let melody = Entry.ProboConnect.Track[track][script.trackStep]; + Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; + Entry.hw.sendQueue['MEL1'] = melody & 0xff; + + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + Entry.TimeWaitManager.add( + script.block.id, + function() { + script.timeFlag = 0; + }, + timeValue + ); + } + const param0 = script.getNumberValue('PARAM0'); + const TR = Entry.ProboConnect.convertDropdownMelody(param0); + if (!script.isStart) { + switch(TR) { + case 0 : + script.maxStep = 6; + break; + case 1 : + script.maxStep = 7; + break; + case 2 : + script.maxStep = 3; + break; + case 3 : + script.maxStep = 3; + break; + } + getTrackStep(TR,script); + return script; + } else if (script.timeFlag == 1) { + return script; + } else if (script.trackStep < script.maxStep){ + getTrackStep(TR,script); + return script; + } else { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + + delete script.trackStep; + delete script.maxStep; + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // 멜로디 중지 + connect_melody_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + null + ], + type: 'connect_melody_off', + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + return script.callReturn(); + }, + }, + // RGB LED 1 을(를) 빨간색 으로 켜기 + connect_rgbled_on_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_color_2', + }, + null + ], + type: 'connect_rgbled_on_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + const color = Entry.ProboConnect.convertDropdownColor2( + script.getStringValue('PARAM1') + ); + Entry.hw.sendQueue[port] = color; + return script.callReturn(); + }, + }, + // RGB LED 을(를) 끄기 + connect_rgbled_off_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + null + ], + type: 'connect_rgbled_off_output', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + Entry.hw.sendQueue[port] = 0; + }, + }, + // RGB LED 1 빨간색으로 0.5초 간격 + connect_rgbled_flashing_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_color_2', + }, + { + type: 'connect_dropdown_time_3', + }, + null + ], + type: 'connect_rgbled_flashing_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + PARAM2: 2, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + const color = Entry.ProboConnect.convertDropdownColor2( + script.getStringValue('PARAM1') + ); + const sec = script.getNumberValue('PARAM2'); + let value = 0; + switch (sec) { + case 0.05: + value = color + 0; + break; + case 0.1: + value = color + 1; + break; + case 0.2: + value = color + 2; + break; + case 0.5: + value = color + 3; + break; + case 1: + value = color + 4; + break; + } + Entry.hw.sendQueue[port] = value; + return script.callReturn(); + }, + }, + // RGB LED 1을(를) 빨간색으로 디밍 + connect_rgbled_dimming_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_color_2', + }, + null + ], + type: 'connect_rgbled_dimming_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + let color = 0; + switch (script.getStringValue('PARAM1')) { + case '1': + color = 90; + break; + case '2': + color = 92; + break; + case '3': + color = 94; + break; + case '4': + color = 93; + break; + case '5': + color = 95; + break; + case '6': + color = 91; + break; + case '7': + color = 96; + break; + } + Entry.hw.sendQueue[port] = color; + return script.callReturn(); + }, + }, + // FND를 0 (으)로 설정 + connect_fnd_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'number', + params: [ 0 ], + }, + null + ], + type: 'connect_fnd_output', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const fnd = script.getNumberValue('PARAM0'); + Entry.hw.sendQueue['FND'] = fnd; + return script.callReturn(); + }, + }, + // FND 끄기 + connect_fnd_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + null + ], + type: 'connect_fnd_off', + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + Entry.hw.sendQueue['FND'] = 100; + return script.callReturn(); + }, + }, + // EEPROM 0 주소에 0 값 설정하기 + connect_eeprom_write: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'number', + params: [ 0 ] + }, + { + type: 'number', + params: [ 0 ] + }, + null, + ], + type: 'connect_eeprom_write', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const address = script.getNumberValue('PARAM0'); + const value = script.getNumberValue('PARAM1'); + if (!script.isStart) { + Entry.hw.update(); + Entry.hw.sendQueue['EEPR4'] = 0x80; + Entry.hw.sendQueue['EEPR3'] = address; + Entry.hw.sendQueue['EEPR2'] = (value >> 8) & 0xff; + Entry.hw.sendQueue['EEPR1'] = value & 0xff; + script.isStart = true; + script.timeFlag = 1; + let timeValue = 0.05; + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.hw.update(); + Entry.hw.sendQueue['EEPR4'] = 0x40; + Entry.hw.sendQueue['EEPR3'] = address; + Entry.hw.sendQueue['EEPR2'] = 0; + Entry.hw.sendQueue['EEPR1'] = 0; + + setTimeout(function() { + Entry.hw.update(); + Entry.hw.sendQueue['EEPR4'] = 0; + Entry.hw.sendQueue['EEPR3'] = 0; + Entry.hw.sendQueue['EEPR2'] = 0; + Entry.hw.sendQueue['EEPR1'] = 0; + }, 100); + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + }; +}; + +module.exports = Entry.ProboConnect; From a7f9776aee323daddabcaa97c86fdc141e95ac69 Mon Sep 17 00:00:00 2001 From: Jason Kim Date: Thu, 19 Sep 2024 18:47:22 +0900 Subject: [PATCH 12/21] =?UTF-8?q?=EC=8A=A4=EB=A7=88=ED=8A=B8=ED=8C=9C=20?= =?UTF-8?q?=EB=8F=99=EC=9E=91=EB=B8=94=EB=A1=9D=20=EB=8C=80=EA=B8=B0?= =?UTF-8?q?=EC=8B=9C=EA=B0=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocks/hardware/block_robotisRBPracticalAssembly.js | 4 ++-- .../blocks/hardwareLite/block_robotis_robotai_lite.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js index 561ff6a015..cab0b58a01 100644 --- a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js +++ b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js @@ -2415,12 +2415,12 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { case 1: address = 2132; - wait_time = 6000; + wait_time = 6500; break; case 2: address = 2133; - wait_time = 1600; + wait_time = 2100; break; } diff --git a/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js b/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js index 5dbfc6e418..42e535e7df 100644 --- a/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js +++ b/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js @@ -2925,12 +2925,12 @@ let beat_per_minute = 75; switch (action) { case 1: address = 2132; - wait_time = 6000; + wait_time = 6500; break; case 2: address = 2133; - wait_time = 1600; + wait_time = 2100; break; } From 51e6a3c2df55230316f6c846979f81d8bbf16426 Mon Sep 17 00:00:00 2001 From: Jason Kim Date: Thu, 19 Sep 2024 18:48:17 +0900 Subject: [PATCH 13/21] =?UTF-8?q?=EC=B9=B4=EB=A9=94=EB=9D=BC=20=ED=83=80?= =?UTF-8?q?=EA=B2=9F=20ID=20=EC=84=A4=EC=A0=95=20=EC=A1=B0=EA=B1=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block_robotisRBPracticalAssembly.js | 64 +++++++++++-------- .../block_robotis_robotai_lite.js | 40 +++++++----- 2 files changed, 60 insertions(+), 44 deletions(-) diff --git a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js index cab0b58a01..4128d7b09c 100644 --- a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js +++ b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js @@ -45,6 +45,7 @@ Entry.Robotis_rb_P_Assembly = { Entry.Robotis_carCont.setRobotisData([ [Entry.Robotis_rb.INSTRUCTION.WRITE, 2100, 1, 1], // PracticeBot Finish ]); + camera_id_for_use = 0; Entry.Robotis_carCont.update(); }, id: ['7.A', '7.B'], @@ -1155,6 +1156,7 @@ let dxl_last_valid_value = []; let rb100_last_valid_value = []; let bg_color = 0; let beat_per_minute = 75; +let camera_id_for_use = 0; const _doevent = ms => new Promise(res => setTimeout(res, ms)); async function wait(nTime) { await _doevent(nTime); } @@ -7056,20 +7058,23 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { var data_length = 2; var data_value = script.getNumberValue('ID'); - var data_sendqueue = [ - [ - data_instruction, - data_address, - data_length, - data_value, - ], - ]; - - Entry.Robotis_carCont.postCallReturn( - script, - data_sendqueue, - Entry.Robotis_openCM70.delay - ); + if (camera_id_for_use != data_value) { + var data_sendqueue = [ + [ + data_instruction, + data_address, + data_length, + data_value, + ], + ]; + + Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + Entry.Robotis_openCM70.delay + ); + camera_id_for_use = data_value; + } data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER @@ -7149,20 +7154,23 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { var data_length = 2; var data_value = script.getNumberValue('ID'); - var data_sendqueue = [ - [ - data_instruction, - data_address, - data_length, - data_value, - ], - ]; - - Entry.Robotis_carCont.postCallReturn( - script, - data_sendqueue, - Entry.Robotis_openCM70.delay - ); + if (camera_id_for_use != data_value) { + var data_sendqueue = [ + [ + data_instruction, + data_address, + data_length, + data_value, + ], + ]; + + Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + Entry.Robotis_openCM70.delay + ); + camera_id_for_use = data_value; + } data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN diff --git a/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js b/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js index 42e535e7df..22c6766381 100644 --- a/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js +++ b/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js @@ -156,6 +156,7 @@ const crcTable = [ const rb100_last_valid_value = []; let bg_color = 0; let beat_per_minute = 75; +let camera_id_for_use = 0; (function () { Entry.RobotisRobotaiLite = new (class RobotisRobotaiLite { @@ -296,6 +297,7 @@ let beat_per_minute = 75; this.__removeAllTimeouts(); this.robotisBuffer = []; this.robotisBuffer.push([INST_WRITE, 2100, 1, 1]); + camera_id_for_use = 0; if (Entry.hwLite && Entry.hwLite.serial) { Entry.hwLite.serial.update(); } @@ -6995,15 +6997,18 @@ let beat_per_minute = 75; let data_length = 2; let data_value = script.getNumberValue('ID'); - let data_sendqueue = [ - [data_instruction, data_address, data_length, data_value], - ]; + if (data_value != camera_id_for_use) { + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; - Entry.RobotisRobotaiLite.postCallReturn( - script, - data_sendqueue, - DEFAULT_DELAY - ); + Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + camera_id_for_use = data_value; + } data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER @@ -7080,15 +7085,18 @@ let beat_per_minute = 75; let data_length = 2; let data_value = script.getNumberValue('ID'); - let data_sendqueue = [ - [data_instruction, data_address, data_length, data_value], - ]; + if (data_value != camera_id_for_use) { + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; - Entry.RobotisRobotaiLite.postCallReturn( - script, - data_sendqueue, - DEFAULT_DELAY - ); + Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + camera_id_for_use = data_value; + } data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN From 1f51aaf882b65d8ad0aa2cda350b9fc71f421807 Mon Sep 17 00:00:00 2001 From: Hagwon <50008047+hagwon@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:56:19 +0900 Subject: [PATCH 14/21] =?UTF-8?q?=EB=A9=9C=EB=A1=9C=EB=94=94=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocks/hardware/block_proboconnect.js | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/playground/blocks/hardware/block_proboconnect.js b/src/playground/blocks/hardware/block_proboconnect.js index d670bb0d10..22c801b615 100644 --- a/src/playground/blocks/hardware/block_proboconnect.js +++ b/src/playground/blocks/hardware/block_proboconnect.js @@ -590,16 +590,18 @@ Entry.ProboConnect = { switch (value) { case Lang.template.item_melody_start: case '1': - return 1; + return 0; case Lang.template.item_melody_end: case '2': - return 2; + return 1; case Lang.template.item_melody_level_up: case '3': - return 3; + return 2; case Lang.template.item_melody_level_down: case '4': - return 4; + return 3; + default: + return value; } }, convertDropdownColor1(value) { @@ -3511,8 +3513,10 @@ Entry.ProboConnect.getBlocks = function() { timeValue ); } - const param0 = script.getNumberValue('PARAM0'); - const TR = Entry.ProboConnect.convertDropdownMelody(param0); + const TR = Entry.ProboConnect.convertDropdownMelody( + script.getStringValue('PARAM0') + ); + console.log("TR ", TR); if (!script.isStart) { switch(TR) { case 0 : From 279460c17f94dbb34f4d4b0e46e28ea1cfb0616d Mon Sep 17 00:00:00 2001 From: Hagwon <50008047+hagwon@users.noreply.github.com> Date: Fri, 20 Sep 2024 14:59:57 +0900 Subject: [PATCH 15/21] =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/playground/blocks/hardware/block_proboconnect.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/playground/blocks/hardware/block_proboconnect.js b/src/playground/blocks/hardware/block_proboconnect.js index 22c801b615..5c25091284 100644 --- a/src/playground/blocks/hardware/block_proboconnect.js +++ b/src/playground/blocks/hardware/block_proboconnect.js @@ -3516,7 +3516,6 @@ Entry.ProboConnect.getBlocks = function() { const TR = Entry.ProboConnect.convertDropdownMelody( script.getStringValue('PARAM0') ); - console.log("TR ", TR); if (!script.isStart) { switch(TR) { case 0 : From c58f42f165938504955e101bae686ef61b81e0ff Mon Sep 17 00:00:00 2001 From: Hagwon <50008047+hagwon@users.noreply.github.com> Date: Fri, 20 Sep 2024 16:29:18 +0900 Subject: [PATCH 16/21] =?UTF-8?q?=EC=97=B0=EC=A3=BC=ED=95=98=EA=B8=B0=20?= =?UTF-8?q?=EB=B8=94=EB=A1=9D=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/playground/blocks/hardware/block_proboconnect.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/playground/blocks/hardware/block_proboconnect.js b/src/playground/blocks/hardware/block_proboconnect.js index 5c25091284..e2ae834493 100644 --- a/src/playground/blocks/hardware/block_proboconnect.js +++ b/src/playground/blocks/hardware/block_proboconnect.js @@ -1520,7 +1520,7 @@ Entry.ProboConnect.getBlocks = function() { [Lang.template.item_note_sixteenth, '16'], [Lang.template.item_note_thirty_second, '32'], ], - value: 'n4', + value: '4', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, From dac2020a68600b726675824b1166194f48e31ac4 Mon Sep 17 00:00:00 2001 From: Tnks2U Date: Mon, 23 Sep 2024 15:39:34 +0900 Subject: [PATCH 17/21] eslint --- .../blocks/hardwareLite/block_microbit2ble_lite.js | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/playground/blocks/hardwareLite/block_microbit2ble_lite.js b/src/playground/blocks/hardwareLite/block_microbit2ble_lite.js index 09131be989..c470255b31 100644 --- a/src/playground/blocks/hardwareLite/block_microbit2ble_lite.js +++ b/src/playground/blocks/hardwareLite/block_microbit2ble_lite.js @@ -15,7 +15,7 @@ const convertPresetImageToLedState = (preset) => { return result; }; -(function() { +(function () { Entry.Microbit2BleLite = new (class Microbit2LiteBle { constructor() { this.webapiType = 'ble'; @@ -1100,7 +1100,7 @@ const convertPresetImageToLedState = (preset) => { }; } - getBlocks = function() { + getBlocks = function () { return { microbit2blelite_common_title: { skeleton: 'basic_text', @@ -2053,7 +2053,8 @@ const convertPresetImageToLedState = (preset) => { func: async (sprite, script) => { const axis = script.getField('AXIS'); // eslint-disable-next-line max-len - const deviceAccData = await this.services.AccelerometerService.readAccelerometerData(); + const deviceAccData = + await this.services.AccelerometerService.readAccelerometerData(); if (axis === 'mag') { return deviceAccData.x + deviceAccData.y + deviceAccData.z; } else { @@ -2164,7 +2165,8 @@ const convertPresetImageToLedState = (preset) => { func: async (sprite, script) => { const axis = script.getField('AXIS'); // eslint-disable-next-line max-len - const deviceMagnetData = await this.services.MagnetometerService.readMagnetometerData(); + const deviceMagnetData = + await this.services.MagnetometerService.readMagnetometerData(); if (axis === 'mag') { return deviceMagnetData.x + deviceMagnetData.y + deviceMagnetData.z; } else { @@ -2209,7 +2211,8 @@ const convertPresetImageToLedState = (preset) => { paramsKeyMap: {}, func: async (sprite, script) => { // eslint-disable-next-line max-len - const temperature = await this.services.TemperatureService.readTemperature(); + const temperature = + await this.services.TemperatureService.readTemperature(); return temperature; }, }, From 6d35799cc5c54a9b9d4fb8d3dfdd633e6f0dc025 Mon Sep 17 00:00:00 2001 From: Hagwon <50008047+hagwon@users.noreply.github.com> Date: Mon, 23 Sep 2024 15:49:17 +0900 Subject: [PATCH 18/21] =?UTF-8?q?=ED=94=84=EB=A1=9C=EB=B3=B4=20=EC=BB=A4?= =?UTF-8?q?=EB=84=A5=ED=8A=B8=20=EB=82=98=EC=B9=A8=EB=B0=98=20=EB=B8=94?= =?UTF-8?q?=EB=A1=9D=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocks/hardware/block_proboconnect.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/playground/blocks/hardware/block_proboconnect.js b/src/playground/blocks/hardware/block_proboconnect.js index e2ae834493..7ce9ede862 100644 --- a/src/playground/blocks/hardware/block_proboconnect.js +++ b/src/playground/blocks/hardware/block_proboconnect.js @@ -532,14 +532,18 @@ Entry.ProboConnect = { }, convertDropdownSensorTransfer(value) { switch (value) { + case '1': case Lang.template.item_value: - return '1'; + return 1; + case '2': case Lang.template.item_angle: - return '2'; + return 2; + case '3': case Lang.template.item_absolute_angle: - return '3'; + return 3; + case '4': case Lang.template.item_number_of_rotations: - return '4'; + return 4; default: value; } @@ -2675,6 +2679,7 @@ Entry.ProboConnect.getBlocks = function() { const select = Entry.ProboConnect.convertDropdownSensorTransfer( script.getStringValue('PARAM2') ); + let value = Entry.hw.portData.InputData.Analog[port]; if (value < (Entry.ProboConnect.Infinite_Buff[port] - 150)) { From 2173a7b50761edae7855e9989b56cd15cc969e35 Mon Sep 17 00:00:00 2001 From: Tnks2U Date: Mon, 23 Sep 2024 16:10:05 +0900 Subject: [PATCH 19/21] =?UTF-8?q?feat:=20=EB=A7=88=EC=9D=B4=ED=81=AC?= =?UTF-8?q?=EB=A1=9C=EB=B9=84=ED=8A=B82=20=EB=B8=94=EB=A1=9D=ED=83=80?= =?UTF-8?q?=EC=9D=B4=ED=8B=80=EC=95=84=EB=9E=98=20=EC=84=A0=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../blocks/hardware/block_microbit2.js | 19 ++++++++++++------- .../hardwareLite/block_microbit2_lite.js | 8 ++++---- .../hardwareLite/block_microbit2ble_lite.js | 4 ++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/playground/blocks/hardware/block_microbit2.js b/src/playground/blocks/hardware/block_microbit2.js index 730618110c..fadceb23dc 100644 --- a/src/playground/blocks/hardware/block_microbit2.js +++ b/src/playground/blocks/hardware/block_microbit2.js @@ -259,9 +259,13 @@ Entry.Microbit2 = new (class Microbit2 { 'microbit2_get_sound_level', ]; this.version = '2'; - this.firePressedBtnEventWithThrottle = _throttle((pressedBtn) => { - Entry.engine.fireEventWithValue('microbit_btn_pressed', pressedBtn); - }, EVENT_INTERVAL, { leading: true, trailing: false }); + this.firePressedBtnEventWithThrottle = _throttle( + (pressedBtn) => { + Entry.engine.fireEventWithValue('microbit_btn_pressed', pressedBtn); + }, + EVENT_INTERVAL, + { leading: true, trailing: false } + ); } setZero() { @@ -735,7 +739,8 @@ Entry.Microbit2 = new (class Microbit2 { 'Plays the entered melody for the entered beat. You can choose a scale between 1 and 5 octaves.', microbit2_play_preset_music: 'Plays preset music.', microbit2_play_sound_effect: 'Plays preset sound.', - microbit2_btn_event: 'When the selected button is pressed, the connected blocks below will run', + microbit2_btn_event: + 'When the selected button is pressed, the connected blocks below will run', microbit2_get_btn: "If the selected button is pressed, it is judged as 'True'.", microbit2_get_logo: "If the logo is touched, it is judged as 'True'.", microbit2_get_gesture: @@ -978,7 +983,7 @@ Entry.Microbit2 = new (class Microbit2 { def: { type: 'microbit2_common_title', }, - class: 'microbit2_title', + class: 'microbit2Pin', isNotFor: ['microbit2'], events: {}, }, @@ -997,7 +1002,7 @@ Entry.Microbit2 = new (class Microbit2 { def: { type: 'microbit2_v2_title', }, - class: 'microbit2_title', + class: 'microbit2v2', isNotFor: ['microbit2'], events: {}, }, @@ -1971,7 +1976,7 @@ Entry.Microbit2 = new (class Microbit2 { }, ], def: { - type: 'microbit2_btn_event' + type: 'microbit2_btn_event', }, paramsKeyMap: { VALUE: 1, diff --git a/src/playground/blocks/hardwareLite/block_microbit2_lite.js b/src/playground/blocks/hardwareLite/block_microbit2_lite.js index 42c1f9a50d..bd5d510738 100644 --- a/src/playground/blocks/hardwareLite/block_microbit2_lite.js +++ b/src/playground/blocks/hardwareLite/block_microbit2_lite.js @@ -4,7 +4,7 @@ const _throttle = require('lodash/throttle'); const EVENT_INTERVAL = 150; -(function() { +(function () { Entry.Microbit2lite = new (class Microbit2Lite { constructor() { this.commandStatus = {}; @@ -1018,7 +1018,7 @@ const EVENT_INTERVAL = 150; }; } - getBlocks = function() { + getBlocks = function () { return { microbit2lite_common_title: { skeleton: 'basic_text', @@ -1035,7 +1035,7 @@ const EVENT_INTERVAL = 150; def: { type: 'microbit2lite_common_title', }, - class: 'microbit2lite_title', + class: 'microbit2litePin', isNotFor: ['Microbit2lite'], events: {}, }, @@ -2292,7 +2292,7 @@ const EVENT_INTERVAL = 150; def: { type: 'microbit2lite_v2_title', }, - class: 'microbit2lite_title', + class: 'microbit2litev2', isNotFor: ['Microbit2lite'], events: {}, }, diff --git a/src/playground/blocks/hardwareLite/block_microbit2ble_lite.js b/src/playground/blocks/hardwareLite/block_microbit2ble_lite.js index c470255b31..588fc8dd8f 100644 --- a/src/playground/blocks/hardwareLite/block_microbit2ble_lite.js +++ b/src/playground/blocks/hardwareLite/block_microbit2ble_lite.js @@ -1117,7 +1117,7 @@ const convertPresetImageToLedState = (preset) => { def: { type: 'microbit2blelite_common_title', }, - class: 'microbit2blelite_title', + class: 'microbit2bleliteLed', isNotFor: ['Microbit2BleLite'], events: {}, }, @@ -2344,7 +2344,7 @@ const convertPresetImageToLedState = (preset) => { def: { type: 'microbit2blelite_v2_title', }, - class: 'microbit2blelite_title', + class: 'microbit2blelitev2', isNotFor: ['Microbit2BleLite'], events: {}, }, From 6796fcdb33a34aa59c84c4b0f8b3b0c80425cd84 Mon Sep 17 00:00:00 2001 From: Tnks2U Date: Mon, 23 Sep 2024 16:10:24 +0900 Subject: [PATCH 20/21] =?UTF-8?q?feat:=20'=EC=97=B0=EA=B2=B0=ED=95=9C=20?= =?UTF-8?q?=ED=95=98=EB=93=9C=EC=9B=A8=EC=96=B4'=20bold=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/playground/block_entry.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/playground/block_entry.js b/src/playground/block_entry.js index c539a3465b..5a36582c73 100644 --- a/src/playground/block_entry.js +++ b/src/playground/block_entry.js @@ -427,7 +427,7 @@ function getBlocks() { }, }, hardware_device_name_title: { - skeleton: 'basic_text', + skeleton: 'basic_text_light', color: EntryStatic.colorSet.common.TRANSPARENT, template: '%1', params: [ From 668b6cf8fee80e1ee67902e0bd1b9a17a11f7aae Mon Sep 17 00:00:00 2001 From: Tnks2U Date: Tue, 24 Sep 2024 15:34:08 +0900 Subject: [PATCH 21/21] =?UTF-8?q?lang:=20=EB=8B=A4=EA=B5=AD=EC=96=B4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- extern/lang/ko.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extern/lang/ko.js b/extern/lang/ko.js index e2d9f9028d..328dbf5eaa 100644 --- a/extern/lang/ko.js +++ b/extern/lang/ko.js @@ -5546,6 +5546,8 @@ Lang.Workspace = { progress_firmware_hwlite_step2_title: '펌웨어 설치', progress_firmware_hwlite_step2_content1: '펌웨어를 설치하고 있습니다.\n잠시만 기다려 주세요.', progress_firmware_hwlite_step2_content_complete: '펌웨어 설치가 완료되었습니다.', + usbconnect_fail_alert: + "기기 연결에 실패했습니다. 연결 상태를 확인하고 '다시 선택'을 눌러 주세요.", progress_firmware_hwlite_step2_content_fail: '펌웨어 설치에 실패했습니다.', progress_firmware_hwlite_step2_content_select: '설치할 펌웨어 버전을 선택해 주세요', select_hwlite_block_duplicated: '1개의 하드웨어만 선택해 주세요.',