diff --git a/images/hardware/neo_cannon.png b/images/hardware/neo_cannon.png new file mode 100644 index 0000000000..837debcfa6 Binary files /dev/null and b/images/hardware/neo_cannon.png differ diff --git a/images/hw/neo_cannon.png b/images/hw/neo_cannon.png new file mode 100644 index 0000000000..837debcfa6 Binary files /dev/null and b/images/hw/neo_cannon.png differ diff --git a/src/class/learning/Cluster.js b/src/class/learning/Cluster.js index 7aacd6e428..e6a4e1ae15 100644 --- a/src/class/learning/Cluster.js +++ b/src/class/learning/Cluster.js @@ -2,6 +2,7 @@ import { kmpp } from 'skmeans/kinit'; // import { kmpp } from 'skmeans/dist/node/kinit'; import floor from 'lodash/floor'; import _toNumber from 'lodash/toNumber'; +import _isNaN from 'lodash/isNaN'; import LearningView from './LearningView'; import Chart from './Chart'; import DataTable from '../DataTable'; @@ -155,7 +156,7 @@ class Cluster { this.#isTrained = false; const { data, select } = this.#table; const filtered = data.filter( - (row) => !select.flat().some((selected) => !_toNumber(row[selected])) + (row) => !select.flat().some((selected) => _isNaN(_toNumber(row[selected]))) ); const [attr] = select; diff --git a/src/class/learning/DecisionTree.js b/src/class/learning/DecisionTree.js index 2a30f47045..848ea10dbe 100644 --- a/src/class/learning/DecisionTree.js +++ b/src/class/learning/DecisionTree.js @@ -4,6 +4,7 @@ import _max from 'lodash/max'; import _sum from 'lodash/sum'; import _mean from 'lodash/mean'; import _toNumber from 'lodash/toNumber'; +import _isNaN from 'lodash/isNaN'; import LearningBase from './LearningBase'; import { DecisionTreeClassifier as DTClassifier } from 'ml-cart'; import Utils from './Utils'; @@ -159,7 +160,7 @@ function getData(testRate = 0.2, data) { const { select = [[0], [1]], data: table, fields } = data; const [attr, predict] = select; const filtered = table.filter( - (row) => !select[0].some((selected) => !_toNumber(row[selected])) + (row) => !select[0].some((selected) => _isNaN(_toNumber(row[selected]))) ); const dataArray = filtered .map((row) => ({ diff --git a/src/class/learning/LearningView.js b/src/class/learning/LearningView.js index 4d38534e21..ae748ba343 100644 --- a/src/class/learning/LearningView.js +++ b/src/class/learning/LearningView.js @@ -15,7 +15,7 @@ const STATUS = { export default class LearningView { constructor({ name = 'model name', status = STATUS.NO_MODEL, value = 0} = {}) { - this.id = Entry.generateHash(); + this.id = Entry.generateHash(); this.visible = true; this.value = value; const fontFamily = EntryStatic.fontFamily || 'NanumGothic'; diff --git a/src/class/learning/LogisticRegression.js b/src/class/learning/LogisticRegression.js index 492fb17af0..b7725af055 100644 --- a/src/class/learning/LogisticRegression.js +++ b/src/class/learning/LogisticRegression.js @@ -4,6 +4,7 @@ import _max from 'lodash/max'; import _sum from 'lodash/sum'; import _mean from 'lodash/mean'; import _toNumber from 'lodash/toNumber'; +import _isNaN from 'lodash/isNaN'; import LearningBase from './LearningBase'; import Utils from './Utils'; @@ -184,7 +185,7 @@ function getData(validationRate, testRate, data, trainParam) { const { select = [[0], [1]], data: table, fields } = data; const [attr, predict] = select; const filtered = table.filter( - (row) => !select[0].some((selected) => !_toNumber(row[selected])) + (row) => !select[0].some((selected) => _isNaN(_toNumber(row[selected]))) ); const dataArray = filtered .map((row) => ({ diff --git a/src/class/learning/NumberClassification.js b/src/class/learning/NumberClassification.js index cbcd83b865..c2d5148616 100644 --- a/src/class/learning/NumberClassification.js +++ b/src/class/learning/NumberClassification.js @@ -6,6 +6,7 @@ import _floor from 'lodash/floor'; import _sum from 'lodash/sum'; import _mean from 'lodash/mean'; import _toNumber from 'lodash/toNumber'; +import _isNaN from 'lodash/isNaN'; import DataTable from '../DataTable'; export const classes = [ @@ -334,7 +335,7 @@ function convertTableToKnnData(tableData = {}) { const { select = [[0], [1]], data: table = [] } = tableData; const [attr, predict] = select; const filtered = table.filter( - (row) => !select[0].some((selected) => !_toNumber(row[selected])) + (row) => !select[0].some((selected) => _isNaN(_toNumber(row[selected]))) ); return filtered.reduce( (accumulator, row) => { diff --git a/src/class/learning/Regression.js b/src/class/learning/Regression.js index af29bc2340..a3c6bc3c8a 100644 --- a/src/class/learning/Regression.js +++ b/src/class/learning/Regression.js @@ -5,6 +5,7 @@ import Chart from './Chart'; import _sum from 'lodash/sum'; import _mean from 'lodash/mean'; import _toNumber from 'lodash/toNumber'; +import _isNaN from 'lodash/isNaN'; import LearningBase from './LearningBase'; import Utils from './Utils'; @@ -224,7 +225,7 @@ function convertToTfData(data, trainParam) { const [attr, predict] = select; const { epochs = 1, batchSize = 1 } = trainParam; const filtered = table.filter( - (row) => !select.flat().some((selected) => !_toNumber(row[selected])) + (row) => !select.flat().some((selected) => _isNaN(_toNumber(row[selected]))) ); const totalDataSize = Math.ceil(filtered.length / batchSize) * epochs; return filtered.reduce( diff --git a/src/class/learning/Svm.js b/src/class/learning/Svm.js index 22cb4a79b7..acf7f6360c 100644 --- a/src/class/learning/Svm.js +++ b/src/class/learning/Svm.js @@ -4,6 +4,7 @@ import _max from 'lodash/max'; import _sum from 'lodash/sum'; import _mean from 'lodash/mean'; import _toNumber from 'lodash/toNumber'; +import _isNaN from 'lodash/isNaN'; import Utils from './Utils'; const { callApi } = require('../../util/common'); const SVM = require('libsvm-js/asm'); @@ -168,7 +169,7 @@ class Svm extends LearningBase { const { select = [[0], [1]], data: table, fields } = data; const [attr, predict] = select; const filtered = table.filter( - (row) => !select[0].some((selected) => !_toNumber(row[selected])) + (row) => !select[0].some((selected) => _isNaN(_toNumber(row[selected]))) ); const dataArray = filtered .map((row) => ({ diff --git a/src/playground/blocks/block_ai_utilize_tts.js b/src/playground/blocks/block_ai_utilize_tts.js index 92574e8b63..5068d87d44 100644 --- a/src/playground/blocks/block_ai_utilize_tts.js +++ b/src/playground/blocks/block_ai_utilize_tts.js @@ -37,6 +37,10 @@ Entry.AI_UTILIZE_BLOCK.tts.getBlocks = function() { [Lang.Blocks.tts_echo, 'brown'], [Lang.Blocks.tts_mischievous, 'minions'], [Lang.Blocks.tts_dainty, 'sally'], + [Lang.Blocks.tts_sabina, 'nsabina'], + [Lang.Blocks.tts_mammon, 'nmammon'], + [Lang.Blocks.tts_kitty, 'nmeow'], + [Lang.Blocks.tts_doggy, 'nwoof'], ], value: 'kyuri', fontSize: 11, diff --git a/src/playground/blocks/hardware/block_0uboard.js b/src/playground/blocks/hardware/block_0uboard.js index cf6d7c1fc1..ff18cf9bbe 100644 --- a/src/playground/blocks/hardware/block_0uboard.js +++ b/src/playground/blocks/hardware/block_0uboard.js @@ -313,43 +313,6 @@ Entry.pyocoding.getBlocks = function() { return ANALOG ? ANALOG[port] || 0 : 0; }, }, - pyocoding_get_touch_value: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - skeleton: 'basic_string_field', - statements: [], - events: {}, - params: [ - { - "type": "Dropdown", - "options": [ - [ "A3", "3" ], - //[ "A5", "5" ], - ], - "value": "3", - "fontSize": 11, - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ null ], - "type": "pyocoding_get_touch_value" - }, - isNotFor: [ '0uboard' ], - class: "SENSOR", - paramsKeyMap: { - "PORT": 0, - }, - func: function (sprite, script) { - var port = script.getValue("PORT", script); - var ANALOG = Entry.hw.portData.ANALOG; - console.log(port,ANALOG) - if (port[0] === "A") - port = port.substring(1) - return ANALOG ? ANALOG[5] || 0 : 0; - }, - }, pyocoding_change_4095to255_value: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, diff --git a/src/playground/blocks/hardware/block_KKMOO.js b/src/playground/blocks/hardware/block_KKMOO.js index 5602970083..61f6182c42 100644 --- a/src/playground/blocks/hardware/block_KKMOO.js +++ b/src/playground/blocks/hardware/block_KKMOO.js @@ -158,7 +158,7 @@ Entry.kkmoo.getBlocks = function() { isNotFor: ['kkmoo'], func: async function(sprite,script){ const wait = (timeToDelay) => new Promise((resolve) => setTimeout(resolve, timeToDelay)) - await wait(100); + await wait(300); await Entry.hw.update(); if(Entry.hw.portData.data == 'true'){ Entry.kkmoo.isMotionRunning = true; diff --git a/src/playground/blocks/hardware/block_dalgona.js b/src/playground/blocks/hardware/block_dalgona.js new file mode 100644 index 0000000000..28e6430187 --- /dev/null +++ b/src/playground/blocks/hardware/block_dalgona.js @@ -0,0 +1,6285 @@ +'use strict'; + +Entry.Dalgona = { + id: '54.1', + name: 'Dalgona', + url: 'https://dalgonaedu.co.kr/', + imageName: 'dalgona.png', + title: { + ko: '달고나 제어보드', + en: 'dalgona', + }, + Static: { + BUTTON_PRESS_VALUE: 0, + }, + + //정지시 초기화 함수 + setZero: function() { + if (!Entry.hw.sendQueue.SET) { + Entry.hw.sendQueue = { + GET: {}, + SET: {}, + }; + } else { + var keySet = Object.keys(Entry.hw.sendQueue.SET); + keySet.forEach((key) => { + if (Entry.hw.sendQueue.SET[key].type == Entry.Dalgona.sensorTypes.SERVO) { + Entry.hw.sendQueue.SET[key].data = 200; + Entry.hw.sendQueue.SET[key].time = new Date().getTime(); + } + else if (Entry.hw.sendQueue.SET[key].type == Entry.Dalgona.sensorTypes.SERVO2) { + Entry.hw.sendQueue.SET[key].data.value1 = 200; + Entry.hw.sendQueue.SET[key].time = new Date().getTime(); + } + else { + Entry.hw.sendQueue.SET[key].data = 0; + Entry.hw.sendQueue.SET[key].time = new Date().getTime(); + } + }); + } + Entry.hw.update(); + }, + sensorTypes: { + ALIVE: 0, + DIGITAL: 1, + ANALOG: 2, + PWM: 3, + SERVO: 4, + TONE: 5, + PULSEIN: 6, + ULTRASONIC: 7, + TIMER: 8, + READ_BLUETOOTH: 9, + WRITE_BLUETOOTH: 10, + LCD: 11, + LCDCLEAR: 12, + RGBLED: 13, + DCMOTOR: 14, + OLED: 15, + PIR: 16, + LCDINIT: 17, + DHTHUMI: 18, + DHTTEMP: 19, + NEOPIXELINIT: 20, + NEOPIXELBRIGHT: 21, + NEOPIXEL: 22, + NEOPIXELALL: 23, + NEOPIXELCLEAR: 24, + DOTMATRIXINIT: 25, + DOTMATRIXBRIGHT: 26, + DOTMATRIX: 27, + DOTMATRIXEMOJI: 28, + DOTMATRIXCLEAR: 29, + MP3INIT: 30, + MP3PLAY1: 31, + MP3PLAY2: 32, + MP3VOL: 33, + RESET_: 34, + LOADINIT: 35, + LOADSCALE: 36, + LOADVALUE: 37, + DUST: 38, + JOYINIT: 39, + JOYX: 40, + JOYY: 41, + JOYZ: 42, + JOYMOVE: 43, + RFIDINIT: 44, + RFIDTAP: 45, + RFIDVALUE: 46, + STEPINIT: 47, + STEPSPEED: 48, + STEPROTATE: 49, + STEPROTATE2: 50, + STEPROTATE3: 51, + MLXOBJ: 52, + MLXAMB: 53, + SERVO2: 54, + GYROX: 55, + GYROY: 56, + GYROZ: 57, + PULLUP: 58, + }, + toneTable: { + '0': 0, + C: 1, + CS: 2, + D: 3, + DS: 4, + E: 5, + F: 6, + FS: 7, + G: 8, + GS: 9, + A: 10, + AS: 11, + 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, 311, 622, 1245, 2849, 4978], + '5': [41, 82, 165, 330, 659, 1319, 2637, 5274], + '6': [44, 87, 175, 349, 698, 1397, 2794, 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], + }, + direction: { + CENTER: 0, + UP: 1, + LEFT: 2, + RIGHT: 3, + DOWN: 4, + LEFT_UP: 5, + LEFT_DOWN: 6, + RIGHT_UP: 7, + RIGHT_DOWN: 8, + }, + highList: ['high', '1', 'on'], + lowList: ['low', '0', 'off'], + getOffsetX(str) { + return this.getByteLength(str) * 1.5 - 5; + }, + getByteLength(s, b, i, c) { + for (b = i = 0; (c = s.charCodeAt(i++)); b += c >> 11 ? 3 : c >> 7 ? 2 : 1); + return b; + }, + BlockState: {}, +}; +Entry.Dalgona.setLanguage = function() { + return { + ko: { + template: { + dalgona_digital_title:'달고나 디지털 블럭', + dalgona_analog_title:'달고나 아날로그 블럭', + dalgona_pwm_title:'달고나 PWM 블럭', + dalgona_library_title:'달고나 라이브러리 블럭', + dalgona_neopixel_title:'달고나 네오픽셀 블럭', + dalgona_ultrasonic_title: '달고나 초음파센서 블럭', + dalgona_buzzer_title: '달고나 피에조 부저 블럭', + dalgona_dotmatrix_title:'달고나 8X8 도트매트릭스 블럭', + dalgona_rfid_title:'달고나 RFID 블럭', + dalgona_motor_title:'달고나 모터 블럭', + dalgona_stepmotor_title:'달고나 스텝모터 블럭', + dalgona_joystick_title:'달고나 조이스틱 블럭', + dalgona_LCD_title:'달고나 LCD 블럭', + dalgona_mp3_title:'달고나 mp3 블럭', + dalgona_HX711_title:'달고나 HX711 로드셀 블럭', + dalgona_sensor_title:'달고나 센서 블럭', + dalgona_toggle_on: 'LED 켜기', + dalgona_toggle_off: 'LED 끄기', + dalgona_lcd_first_line: '달고나 :: 첫 번째', + dalgona_lcd_seconds_line: '달고나 :: 두 번째', + dalgona_get_analog_value: '달고나 :: 아날로그 %1 핀 읽기', + dalgona_get_light_value: '달고나 :: 조도센서(AO %1)값', + dalgona_get_moisture_value: '달고나 :: 토양수분센서(AO %1)값', + dalgona_get_sound_value: '달고나 :: 사운드센서(AO %1)값', + dalgona_get_infrared_value: '달고나 :: 적외선센서(AO %1)값', + dalgona_get_pullup: '달고나 :: 풀업 저항 사용 버튼 %1 핀 눌림 상태', + dalgona_get_button: '달고나 :: 버튼 %1 핀 눌림 상태', + dalgona_get_analog_mapping: '달고나 :: 아날로그 %1 번 핀 센서 값의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼 값', + dalgona_mapping1: '달고나 :: %1 값을 %2 ~ %3 사이로 제한한 값', + dalgona_mapping2: '달고나 :: %1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환', + dalgona_get_digital_ultrasonic: '달고나 :: 초음파 Trig %1 핀 Echo %2 핀 센서 값', + dalgona_get_digital: '달고나 :: 디지털 %1 핀 읽기', + dalgona_get_digital_toggle: '달고나 :: 디지털 %1 핀 센서 값', + dalgona_get_digital_pir: '달고나 :: PIR %1 핀 센서 값', + dalgona_set_digital_toggle: '달고나 :: 디지털 %1 핀 %2 %3', + dalgona_set_led_toggle: '달고나 :: LED %1 핀 %2 %3', + dalgona_set_digital_pwm: '달고나 :: LED (PWM %1 핀)밝기 %2 출력 (0 ~ 255)%3', + dalgona_set_digital_rgbled: '달고나 :: RGB LED (R %1 핀, G %2 핀, B %3 핀) 색 (R: %4, G: %5, B: %6) 출력 %7', + dalgona_set_digital_servo: '달고나 :: 서보 모터 %1 핀 %2 각도로 회전 %3', + dalgona_set_digital_servo2: "달고나 :: 서보 모터 %1 핀 %2 ~ %3 각도로 %4 초 동안 회전 %5", + dalgona_set_digital_buzzer_toggle: '달고나 :: 피에조부저 %1 핀 %2 %3', + dalgona_set_digital_buzzer_volume: '달고나 :: 피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3', + dalgona_set_digital_buzzer: '달고나 :: 피에조부저 %1 핀 %2 %3 음 %4 박자 연주 %5', + dalgona_set_digital_dcmotor: '달고나 :: DC모터 %1핀 %2 %3', + dalgona_set_analog_dcmotor: '달고나 :: DC모터(PWM %1 핀) 세기 %2 출력 (0 ~ 255) %3', + dalgona_set_neopixel_init: '달고나 :: 네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3', + dalgona_set_neopixel_bright: '달고나 :: 네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3', + dalgona_set_neopixel: '달고나 :: 네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4', + dalgona_set_neopixel_all: '달고나 :: 네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3', + dalgona_set_neopixel_clear: '달고나 :: 네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2', + dalgona_set_dotmatrix_init: '달고나 :: 8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4', + dalgona_set_dotmatrix_bright: '달고나 :: 도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2', + dalgona_set_dotmatrix: '달고나 :: 도트매트릭스 LED %1 그리기 %2', + dalgona_set_dotmatrix_emoji: '달고나 :: 도트매트릭스 LED %1 그리기 %2', + dalgona_set_dotmatrix_clear: '달고나 :: 도트매트릭스 LED 지우기 %1', + dalgona_lcd_init: '달고나 :: I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4', + dalgona_get_lcd_row: '달고나 :: %1', + dalgona_get_lcd_col: '달고나 :: %1', + dalgona_module_digital_lcd: '달고나 :: LCD화면 %1 열 %2 행 부터 %3 출력 %4', + dalgona_lcd_clear: '달고나 :: LCD 화면 지우기 %1', + dalgona_get_dht: '달고나 :: DHT11 온습도센서(out %1)의 %2값', + //dalgona_get_dht_temp_value: 'DHT11 온습도센서(out %1)의 온도(°C)값', + //dalgona_get_dht_humi_value: 'DHT11 온습도센서(out %1)의 습도(%)값', + + dalgona_set_mp3_init: '달고나 :: mp3 초기화 ( tx: %1, rx: %2 ) %3', + dalgona_set_mp3_play: '달고나 :: mp3 %1 번 파일 재생 %2', + dalgona_set_mp3_play2: '달고나 :: mp3 %1 번 파일 %2 초 동안 재생 %3', + dalgona_set_mp3_vol: '달고나 :: mp3 볼륨 %1 으로 설정 (0 ~ 30) %2', + dalgona_get_analog_temp_value: '달고나 :: DHT11 포트 %1의 %2 센서 값', + + dalgona_load_init: '달고나 :: HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3', + dalgona_load_scale: '달고나 :: HX711 로드셀 보정하기 %1 %2', + dalgona_load_value: '달고나 :: HX711 로드셀 값', + + dalgona_get_dust: '달고나 :: 미세먼지센서 (LED %1, AO %2) 값', + + dalgona_rfid_init: '달고나 :: RFID 시작하기 설정 (SS %1, RST %2) %3', + dalgona_is_rfid_tapped: '달고나 :: RFID 카드가 인식되었는가?', + dalgona_get_rfid_value: '달고나 :: RFID 카드 값', + dalgona_joy_init: '달고나 :: %1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5', + dalgona_get_joy_x: '달고나 :: %1 조이스틱 X값', + dalgona_get_joy_y: '달고나 :: %1 조이스틱 y값', + dalgona_get_joy_z: '달고나 :: %1 조이스틱 버튼 눌림 상태', + dalgona_get_joy_move: '달고나 :: %1 조이스틱이 %2 방향으로 움직였을 때', + + dalgona_get_mlx: '달고나 :: mlx90614 비접촉 온도센서 %1값', + + dalgona_step_init: '달고나 :: %1 스텝모터 시작하기 설정 (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6', + dalgona_step_speed: '달고나 :: %1 스텝모터 속도를 %2 로 설정하기 (0 ~ 20) %3', + dalgona_step_rotate: '달고나 :: %1 스텝모터 %2 으로 %3 바퀴 회전하기 %4', + dalgona_step_rotate2: '달고나 :: %1 스텝모터 %2 으로 %3 도 회전하기 %4', + dalgona_step_rotate3: '달고나 :: %1 스텝모터 %2 으로 %3 초 동안 회전하기 %4', + + // dalgona_get_digital_bluetooth: '블루투스 RX 2 핀 데이터 값', + // dalgona_module_digital_bluetooth: '블루투스 TX 3 핀에 %1 데이터 보내기 %2', + + }, + }, + en: { + template: { + dalgona_digital_title:'달고나 디지털 블럭', + dalgona_analog_title:'달고나 아날로그 블럭', + dalgona_pwm_title:'달고나 PWM 블럭', + dalgona_library_title:'달고나 라이브러리 블럭', + dalgona_neopixel_title:'달고나 네오픽셀 블럭', + dalgona_ultrasonic_title: '달고나 초음파센서 블럭', + dalgona_buzzer_title: '달고나 피에조 부저 블럭', + dalgona_dotmatrix_title:'달고나 8X8 도트매트릭스 블럭', + dalgona_rfid_title:'달고나 RFID 블럭', + dalgona_motor_title:'달고나 모터 블럭', + dalgona_stepmotor_title:'달고나 스텝모터 블럭', + dalgona_joystick_title:'달고나 조이스틱 블럭', + dalgona_LCD_title:'달고나 LCD 블럭', + dalgona_mp3_title:'달고나 mp3 블럭', + dalgona_HX711_title:'달고나 HX711 로드셀 블럭', + dalgona_sensor_title:'달고나 센서 블럭', + + dalgona_toggle_on: 'on', + dalgona_toggle_off: 'off', + dalgona_lcd_first_line: 'first', + dalgona_lcd_seconds_line: 'seconds', + dalgona_get_analog_value: 'Read analog %1 pin sensor value', + dalgona_get_analog_mapping: 'Map analog %1 pin sensor value from %2 ~ %3 to %4 ~ %5', + dalgona_mapping1: '%1 값을 %2 ~ %3 사이로 제한한 값', + dalgona_mapping2: '%1 값을 %2 ~ %3 범위에서 %4 ~ %5 범위로 변환', + dalgona_get_digital_bluetooth: 'Bluetooth RX 2 value', + dalgona_get_digital_ultrasonic: 'Read ultrasonic Trig %1 Echo %2 sensor value', + dalgona_get_digital: 'Digital %1 pin sensor value', + dalgona_get_digital_toggle: 'Digital %1 pin sensor value', + dalgona_set_digital_toggle: 'Digital %1 pin %2 %3', + dalgona_set_digital_pwm: 'Digital pwm %1 Pin %2 %3', + dalgona_set_digital_rgbled: 'Digital %1 pin RGB LED Red %2 Green %3 Blue %4 %5', + dalgona_set_digital_servo: '서보 모터 %1 핀 %2 각도로 회전 %3', + dalgona_set_digital_buzzer_toggle: '피에조부저 %1 핀 %2 %3', + dalgona_set_digital_buzzer_volume: '피에조부저 (PWM %1 핀) 음량 %2 출력 (0 ~ 255) %3', + dalgona_set_digital_buzzer:'피에조부저 %1 번 핀의 버저를 %2 %3 음으로 %4 박자 연주 %5', + dalgona_set_digital_dcmotor: 'DC Motor %1 pin direction %2 %3 pin speed %4 %5', + dalgona_set_neopixel_init:'네오픽셀 LED 시작하기 설정 ( %1 핀에 %2 개의 LED 연결) %3', + dalgona_set_neopixel_bright: '네오픽셀 LED ( %1 핀) 밝기 %2 으로 설정 (0 ~ 255) %3', + dalgona_set_neopixel: '네오픽셀 LED ( %1 핀) %2 번째 LED 색 %3 출력 %4', + dalgona_set_neopixel_all: '네오픽셀 LED ( %1 핀) 모든 LED 색 %2 출력 %3', + dalgona_set_neopixel_clear: '네오픽셀 LED ( %1 핀) 모든 LED 끄기 %2', + dalgona_set_dotmatrix_init: '8x8 도트매트릭스 시작하기 설정 (DIN %1, CLK %2, CS %3) %4', + dalgona_set_dotmatrix_bright: '도트매트릭스 밝기 %1 으로 설정 (0 ~ 8) %2', + dalgona_set_dotmatrix: '도트매트릭스 LED 그리기 %1 %2', + dalgona_set_dotmatrix_emoji: '도트매트릭스 LED %1 그리기 %2', + dalgona_module_digital_lcd: 'LCD %1 열 %2 행 부터 %3 출력', + dalgona_lcd_init: 'I2C LCD 시작하기 설정 (주소 %1 ,열 %2, 행 %3) %4', + + dalgona_module_digital_bluetooth: 'Bluetooth TX 3 Pin %1 data send %2', + dalgona_module_digital_oled: 'OLED X codinate %1 Y coodinate %2 appear %3 %4', + dalgona_get_dht_temp_value: '온습도센서의 온도값', + dalgona_get_dht_humi_value: '온습도센서의 습도값', + + dalgona_set_mp3_init: 'mp3 초기화 ( tx: %1, rx: %2 ) %3', + dalgona_set_mp3_play: 'mp3 %1 번 파일 재생 %2', + dalgona_set_mp3_play2: 'mp3 %1 번 파일 %2 초 동안 재생 %3', + dalgona_set_mp3_vol: 'mp3 볼륨 %1 으로 설정 (0 ~ 30) %2', + + dalgona_load_init: 'HX711 로드셀 시작하기 설정 (DOUT %1, SCK %2) %3', + dalgona_load_scale: 'HX711 로드셀 보정하기 %1 %2', + dalgona_load_value: 'HX711 로드셀 값', + + dalgona_get_dust: '미세먼지센서(LED %1, AO %2) 값(μg/m³)', + + dalgona_rfid_init: 'RFID 시작하기 설정 (RST %1, SS %2) %3', + dalgona_is_rfid_tapped: 'RFID 카드가 인식되었는가?', + dalgona_get_rfid_value: 'RFID 카드 값', + + dalgona_joy_init: '%1 조이스틱 시작하기 설정 (X AO %2, Y AO %3, Z %4) %5', + dalgona_get_joy_x: '%1 조이스틱 X값', + dalgona_get_joy_y: '%1 조이스틱 y값', + dalgona_get_joy_z: '%1 조이스틱 버튼 눌림 상태', + dalgona_get_joy_move: '%1 조이스틱이 %2 방향으로 움직였을 때', + + dalgona_step_init: '%1 스텝모터 시작하기 설정 (IN1 %2, IN2 %3, IN3 %4, IN4 %5) %6', + dalgona_step_speed: '%1 스텝모터 속도를 %2 로 설정하기 (0 ~ 20) %3', + dalgona_step_rotate: '%1 스텝모터 %2 으로 %3 바퀴 회전하기 %4', + dalgona_step_rotate2: '%1 스텝모터 %2 으로 %3 도 회전하기 %4', + dalgona_step_rotate3: '%1 스텝모터 %2 으로 %3 초 동안 회전하기 %4', + + dalgona_mlx: 'mlx90614 값', + }, + }, + }; +}; +Entry.Dalgona.blockMenuBlocks = [ + 'dalgona_digital_title', + 'dalgona_set_digital_toggle', + 'dalgona_get_digital', + 'dalgona_set_led_toggle', + + 'dalgona_analog_title', + 'dalgona_get_analog_value', + 'dalgona_get_analog_mapping', + 'dalgona_mapping1', + 'dalgona_mapping2', + + 'dalgona_pwm_title', + 'dalgona_set_digital_pwm', + 'dalgona_set_digital_rgbled', + + 'dalgona_library_title', + + 'dalgona_neopixel_title', + 'dalgona_set_neopixel_init', + 'dalgona_set_neopixel_bright', + 'dalgona_set_neopixel', + 'dalgona_set_neopixel_all', + 'dalgona_set_neopixel_clear', + + 'dalgona_ultrasonic_title', + 'dalgona_get_digital_ultrasonic', + + 'dalgona_buzzer_title', + 'dalgona_set_digital_buzzer_toggle', + 'dalgona_set_digital_buzzer_volume', + 'dalgona_set_digital_buzzer', + + 'dalgona_dotmatrix_title', + 'dalgona_set_dotmatrix_init', + 'dalgona_set_dotmatrix_bright', + 'dalgona_set_dotmatrix', + 'dalgona_set_dotmatrix_emoji', + 'dalgona_set_dotmatrix_clear', + + 'dalgona_rfid_title', + 'dalgona_rfid_init', + 'dalgona_is_rfid_tapped', + 'dalgona_get_rfid_value', + + 'dalgona_motor_title', + 'dalgona_set_digital_dcmotor', + 'dalgona_set_analog_dcmotor', + 'dalgona_set_digital_servo', + 'dalgona_set_digital_servo2', + + 'dalgona_stepmotor_title', + 'dalgona_step_init', + 'dalgona_step_speed', + 'dalgona_step_rotate', + 'dalgona_step_rotate2', + 'dalgona_step_rotate3', + + 'dalgona_joystick_title', + 'dalgona_joy_init', + 'dalgona_get_joy_x', + 'dalgona_get_joy_y', + 'dalgona_get_joy_z', + 'dalgona_get_joy_move', + + 'dalgona_LCD_title', + 'dalgona_lcd_init', + 'dalgona_module_digital_lcd', + 'dalgona_get_lcd_row', + 'dalgona_get_lcd_col', + 'dalgona_lcd_clear', + + 'dalgona_mp3_title', + 'dalgona_set_mp3_init', + 'dalgona_set_mp3_vol', + 'dalgona_set_mp3_play', + 'dalgona_set_mp3_play2', + + 'dalgona_HX711_title', + 'dalgona_load_init', + 'dalgona_load_scale', + 'dalgona_load_value', + + 'dalgona_sensor_title', + + 'dalgona_get_dust', + 'dalgona_get_digital_toggle', + 'dalgona_get_digital_pir', + 'dalgona_get_light_value', + 'dalgona_get_moisture_value', + 'dalgona_get_sound_value', + 'dalgona_get_infrared_value', + 'dalgona_get_dht', + //'dalgona_get_dht_temp_value', + //'dalgona_get_dht_humi_value', + 'dalgona_get_pullup', + 'dalgona_get_button', + 'dalgona_get_mlx', + // 'dalgona_get_digital_bluetooth', + // 'dalgona_module_digital_bluetooth', +]; +Entry.Dalgona.getBlocks = function() { + var tx; + var din; + // var clk; + // var cs; + var dout; + var sck; + var joyx, joyy, joyz; + var joyx2, joyy2, joyz2; + var portpin1, portpin2, portpin3; + var ss; + var RGBport; + var mlxport; + var speed1 = 14; + var speed2 = 14; + var speed3 = 14; + var num = 0; + + return { + dalgona_digital_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_digital_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_digital_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_digital_title', + }, + class: 'digital', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_analog_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_analog_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_analog_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_analog_title', + }, + class: 'analog', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_pwm_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_pwm_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_pwm_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_pwm_title', + }, + class: 'pwm', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_library_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_library_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_library_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_library_title', + }, + class: 'library', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_neopixel_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_neopixel_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_neopixel_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_neopixel_title', + }, + class: 'neopixel', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_ultrasonic_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_ultrasonic_title), + offsetY: 7, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_ultrasonic_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_ultrasonic_title', + }, + class: 'ultrasonic', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_buzzer_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_buzzer_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_buzzer_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_buzzer_title', + }, + class: 'buzzer', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_dotmatrix_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_dotmatrix_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_dotmatrix_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_dotmatrix_title', + }, + class: 'dotmatrix', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_rfid_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_rfid_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_rfid_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_rfid_title', + }, + class: 'RFID', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_motor_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_motor_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_motor_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_motor_title', + }, + class: 'motor', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_stepmotor_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_stepmotor_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_stepmotor_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_stepmotor_title', + }, + class: 'step', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_joystick_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_joystick_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_joystick_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_joystick_title', + }, + class: 'joystick', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_LCD_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_LCD_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_LCD_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_LCD_title', + }, + class: 'LCD', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_mp3_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_mp3_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_mp3_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_mp3_title', + }, + class: 'mp3', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_HX711_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_HX711_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_HX711_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_HX711_title', + }, + class: 'HX711', + isNotFor: ['Dalgona'], + events: {}, + }, + dalgona_sensor_title: { + skeleton: 'basic_text', + skeletonOptions: { + box: { + offsetX: this.getOffsetX(Lang.template.dalgona_sensor_title), + offsetY: 3, + }, + }, + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#d1702a', + params: [ + { + type: 'Text', + text: Lang.template.dalgona_sensor_title, + color: '#d1702a', + align: 'left', + }, + ], + def: { + type: 'dalgona_sensor_title', + }, + class: 'sensor', + isNotFor: ['Dalgona'], + events: {}, + }, + + + + + dalgona_list_analog_basic: { + 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, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + PORT: 0, + }, + func: function(sprite, script) { + return script.getField('PORT'); + }, + }, + dalgona_list_digital_basic: { + 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'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ['9', '9'], + ['10', '10'], + ['11', '11'], + ['12', '12'], + ['13', '13'], + ], + value: '10', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + PORT: 0, + }, + func: function(sprite, script) { + return script.getStringField('PORT'); + }, + }, + dalgona_list_digital_octave: { + 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'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ], + value: '3', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + OCTAVE: 0, + }, + func: function(sprite, script) { + return script.getField('OCTAVE'); + }, + }, + dalgona_list_digital_pwm: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['3', '3'], + ['5', '5'], + ['6', '6'], + ['9', '9'], + ['10', '10'], + ['11', '11'], + ], + value: '11', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + PORT: 0, + }, + func: function(sprite, script) { + return script.getStringField('PORT'); + }, + }, + dalgona_list_digital_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.dalgona_toggle_on, 'on'], + [Lang.template.dalgona_toggle_off, 'off'], + ], + value: 'on', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + OPERATOR: 0, + }, + func: function(sprite, script) { + return script.getStringField('OPERATOR'); + }, + }, + dalgona_list_digital_toggle_en: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['HIGH', 'on'], + ['LOW', 'off'], + ], + value: 'on', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + OPERATOR: 0, + }, + func: function(sprite, script) { + return script.getStringField('OPERATOR'); + }, + }, + dalgona_list_digital_tone: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.silent, '0'], + [Lang.Blocks.do_name, 'C'], + [Lang.Blocks.do_sharp_name, 'CS'], + [Lang.Blocks.re_name, 'D'], + [Lang.Blocks.re_sharp_name, 'DS'], + [Lang.Blocks.mi_name, 'E'], + [Lang.Blocks.fa_name, 'F'], + [Lang.Blocks.fa_sharp_name, 'FS'], + [Lang.Blocks.sol_name, 'G'], + [Lang.Blocks.sol_sharp_name, 'GS'], + [Lang.Blocks.la_name, 'A'], + [Lang.Blocks.la_sharp_name, 'AS'], + [Lang.Blocks.si_name, 'B'], + ], + value: 'C', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + NOTE: 0, + }, + func: function(sprite, script) { + return script.getField('NOTE'); + }, + }, + dalgona_set_neopixel_init: { + 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: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'arduino_get_port_number', + params: ['7'], + }, + { + type: 'number', + params: ['4'], + }, + null, + ], + type: 'dalgona_set_neopixel_init', + }, + paramsKeyMap: { + PORT: 0, + NUM: 1, + }, + class: 'neopixel', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getNumberValue('NUM'); + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.NEOPIXELINIT, + data: value, + time: new Date().getTime(), + }; + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_set_neopixel_bright: { + 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: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'arduino_get_port_number', + params: ['7'], + }, + { + type: 'number', + params: ['255'], + }, + null, + ], + type: 'dalgona_set_neopixel_bright', + }, + paramsKeyMap: { + PORT: 0, + NUM: 1, + }, + class: 'neopixel', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getNumberValue('NUM'); + + value = Math.round(value); + value = Math.min(value, 255); + value = Math.max(value, 0); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.NEOPIXELBRIGHT, + data: value, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_set_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: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'arduino_get_port_number', + params: ['7'], + }, + { + type: 'number', + params: ['0'], + }, + null, + null, + ], + type: 'dalgona_set_neopixel', + }, + paramsKeyMap: { + PORT: 0, + NUM: 1, + COLOR: 2, + }, + class: 'neopixel', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + //var sq = Entry.hw.sendQueue; + var port = script.getNumberValue('PORT', script); + var num = script.getNumberValue('NUM', script); + var value = script.getStringField('COLOR', script); + + let r = parseInt(value.substr(1, 2), 16); + let g = parseInt(value.substr(3, 2), 16); + let b = parseInt(value.substr(5, 2), 16); + + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + r = Math.round(r); + r = Math.min(r, 255); + r = Math.max(r, 0); + + g = Math.round(g); + g = Math.min(g, 255); + g = Math.max(g, 0); + + b = Math.round(b); + b = Math.min(b, 255); + b = Math.max(b, 0); + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.NEOPIXEL, + data: { + num: num, + r: r, + g: g, + b: b, + }, + time: new Date().getTime(), + }; + setTimeout(function() { + script.timeFlag = 0; + }, 10); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_set_neopixel_all: { + 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: 'arduino_get_port_number', + params: ['7'], + }, + null, + null, + ], + type: 'dalgona_set_neopixel_all', + }, + paramsKeyMap: { + PORT: 0, + COLOR: 1, + }, + class: 'neopixel', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT', script); + var value = script.getStringField('COLOR', script); + + let r = parseInt(value.substr(1, 2), 16); + let g = parseInt(value.substr(3, 2), 16); + let b = parseInt(value.substr(5, 2), 16); + + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + r = Math.round(r); + r = Math.min(r, 255); + r = Math.max(r, 0); + + g = Math.round(g); + g = Math.min(g, 255); + g = Math.max(g, 0); + + b = Math.round(b); + b = Math.min(b, 255); + b = Math.max(b, 0); + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.NEOPIXELALL, + data: { + r: r, + g: g, + b: b, + }, + time: new Date().getTime(), + }; + setTimeout(function() { + script.timeFlag = 0; + }, 10); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_set_neopixel_clear: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'arduino_get_port_number', + params: ['7'], + }, + null, + ], + type: 'dalgona_set_neopixel_clear', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'neopixel', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.NEOPIXELCLEAR, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_lcd_list_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0x27', '0'], + ['0x3F', '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + LINE: 0, + }, + func: function(sprite, script) { + return script.getField('LINE'); + }, + }, + dalgona_set_dotmatrix_init: { + 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: 'arduino_get_port_number', + params: ['12'], + }, + { + type: 'arduino_get_port_number', + params: ['11'], + }, + { + type: 'arduino_get_port_number', + params: ['10'], + }, + null, + ], + type: 'dalgona_set_dotmatrix_init', + }, + paramsKeyMap: { + PORT1: 0, + PORT2: 1, + PORT3: 2, + }, + class: 'dotmatrix', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port1 = script.getNumberValue('PORT1', script); + var port2 = script.getNumberValue('PORT2', script); + var port3 = script.getNumberValue('PORT3', script); + + din = port1; + // clk = port2; + // cs = port3; + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][port1] = { + type: Entry.Dalgona.sensorTypes.DOTMATRIXINIT, + data: { + port1: port1, + port2: port2, + port3: port3, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_set_dotmatrix_bright: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['8'], + }, + null, + ], + type: 'dalgona_set_dotmatrix_bright', + }, + paramsKeyMap: { + NUM: 0, + }, + class: 'dotmatrix', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM', script); + + num = Math.round(num); + num = Math.min(num, 8); + num = Math.max(num, 0); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][din] = { + type: Entry.Dalgona.sensorTypes.DOTMATRIXBRIGHT, + data: num, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_set_dotmatrix_clear: { + 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: 'dalgona_set_dotmatrix_clear', + }, + class: 'dotmatrix', + isNotFor: ['Dalgona'], + func(sprite, script) { + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (1 + 0.5) * 0.1; //0.15 + timeValue = (60 / fps) * timeValue * 100; + + Entry.hw.sendQueue['SET'][din] = { + type: Entry.Dalgona.sensorTypes.DOTMATRIXCLEAR, + data: 0, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_set_dotmatrix: { + 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: [ + { + type: 'text', + params: ['003c420024242400'], + }, + ], + type: 'dalgona_set_dotmatrix', + }, + paramsKeyMap: { + STRING: 0, + }, + class: 'dotmatrix', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var text = script.getValue('STRING'); + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][din] = { + type: Entry.Dalgona.sensorTypes.DOTMATRIX, + data: { + text: text, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_dotmatrix_emoji_list: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['🖤', '1'], + ['🤍', '2'], + ['👆', '3'], + ['👇', '4'], + ['👈', '5'], + ['👉', '6'], + ['😊', '7'], + ['😥', '8'], + ['😡', '9'], + ['😆', '10'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + LINE: 0, + }, + func: function(sprite, script) { + return script.getField('LINE'); + }, + }, + dalgona_set_dotmatrix_emoji: { + 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: [ + { + type: 'dalgona_dotmatrix_emoji_list', + params: ['1'], + }, + null, + ], + type: 'dalgona_set_dotmatrix_emoji', + }, + paramsKeyMap: { + LIST: 0, + }, + class: 'dotmatrix', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var value = script.getNumberValue('LIST'); + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][din] = { + type: Entry.Dalgona.sensorTypes.DOTMATRIXEMOJI, + data: value, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_list_digital_lcd: { + 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.dalgona_lcd_first_line, '0'], + [Lang.template.dalgona_lcd_seconds_line, '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + LINE: 0, + }, + func: function(sprite, script) { + return script.getField('LINE'); + }, + }, + dalgona_get_lcd_row: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['0', '0'], + ['1', '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + ROW: 0, + }, + func(sprite, script) { + return script.getStringField('ROW'); + }, + syntax: { + js: [], + py: [ + { + syntax: '%1', + textParams: [ + { + type: 'Dropdown', + options: [ + ['0', '0'], + ['1', '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + keyOption: 'dalgona_get_lcd_row', + }, + ], + }, + }, + + dalgona_get_lcd_col: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['0', '0'], + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ['9', '9'], + ['10', '10'], + ['11', '11'], + ['12', '12'], + ['13', '13'], + ['14', '14'], + ['15', '15'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + ROW: 0, + }, + func(sprite, script) { + return script.getStringField('ROW'); + }, + syntax: { + js: [], + py: [ + { + syntax: '%1', + textParams: [ + { + type: 'Dropdown', + options: [ + ['0', '0'], + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ['9', '9'], + ['10', '10'], + ['11', '11'], + ['12', '12'], + ['13', '13'], + ['14', '14'], + ['15', '15'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + keyOption: 'dalgona_get_lcd_col', + }, + ], + }, + }, + dalgona_get_analog_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + template: Lang.template.dalgona_get_analog_value, + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_analog_basic', + }, + ], + type: 'dalgona_get_analog_value', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'analog', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getValue('PORT', script); + var ANALOG = Entry.hw.portData.ANALOG; + + if (port[0] === 'A') port = port.substring(1); + + return ANALOG ? ANALOG[port] || 0 : 0; + }, + syntax: { js: [], py: ['Dalgona.get_analog_value(%1)'] }, + }, + dalgona_get_light_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_analog_basic', + }, + ], + type: 'dalgona_get_light_value', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getValue('PORT', script); + var ANALOG = Entry.hw.portData.ANALOG; + + if (port[0] === 'A') port = port.substring(1); + + return ANALOG ? ANALOG[port] || 0 : 0; + }, + syntax: { js: [], py: ['dalgona.get_analog_value(%1)'] }, + }, + dalgona_get_moisture_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + //template: Lang.template.dalgona_get_analog_value, + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_analog_basic', + params: ['1'], + }, + ], + type: 'dalgona_get_moisture_value', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getValue('PORT', script); + var ANALOG = Entry.hw.portData.ANALOG; + + if (port[0] === 'A') port = port.substring(1); + + return ANALOG ? ANALOG[port] || 0 : 0; + }, + syntax: { js: [], py: ['dalgona.get_analog_value(%1)'] }, + }, + + dalgona_set_digital_dcmotor: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_set_digital_dcmotor, + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + }, + { + type: 'dalgona_list_digital_toggle', + }, + null, + ], + type: 'dalgona_set_digital_dcmotor', + }, + paramsKeyMap: { + PORT: 0, + VALUE: 1, + }, + class: 'motor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getValue('VALUE'); + + if (typeof value === 'string') { + value = value.toLowerCase(); + } + if (Entry.Dalgona.highList.indexOf(value) > -1) { + value = 255; + } else if (Entry.Dalgona.lowList.indexOf(value) > -1) { + value = 0; + } else { + throw new Error(); + } + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.DIGITAL, + data: value, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { js: [], py: ['dalgona.set_digital_dcmotor(%1, %2, %3, %4)'] }, + }, + dalgona_set_analog_dcmotor: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_set_analog_dcmotor, + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_pwm', + }, + { + type: 'text', + params: ['255'], + }, + null, + ], + type: 'dalgona_set_analog_dcmotor', + }, + paramsKeyMap: { + PORT: 0, + VALUE: 1, + }, + class: 'motor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getNumberValue('VALUE'); + + value = Math.round(value); + value = Math.min(value, 255); + value = Math.max(value, 0); + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.PWM, + data: value, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { js: [], py: ['dalgona.set_digital_dcmotor(%1, %2, %3, %4)'] }, + }, + dalgona_get_sound_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_analog_basic', + }, + ], + type: 'dalgona_get_sound_value', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getValue('PORT', script); + var ANALOG = Entry.hw.portData.ANALOG; + + if (port[0] === 'A') port = port.substring(1); + + return ANALOG ? ANALOG[port] || 0 : 0; + }, + syntax: { js: [], py: ['dalgona.get_analog_value(%1)'] }, + }, + dalgona_get_infrared_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_analog_basic', + }, + ], + type: 'dalgona_get_infrared_value', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getValue('PORT', script); + var ANALOG = Entry.hw.portData.ANALOG; + + if (port[0] === 'A') port = port.substring(1); + + return ANALOG ? ANALOG[port] || 0 : 0; + }, + syntax: { js: [], py: ['dalgona.get_analog_value(%1)'] }, + }, + dalgona_get_pullup: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + }, + ], + type: 'dalgona_get_pullup', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var pu = Entry.hw.portData.PULLUP; + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.PULLUP] = { + port: port, + data: 2, + time: new Date().getTime(), + }; + var pullupvalue = pu ? pu[port] || 0 : 0; + return !pullupvalue; + + }, + + syntax: { js: [], py: [] }, + }, + dalgona_get_button: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + }, + ], + type: 'dalgona_get_button', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT', script); + var DIGITAL = Entry.hw.portData.DIGITAL; + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = { + port: port, + data: 2, + time: new Date().getTime(), + }; + + var value = DIGITAL ? DIGITAL[port] || 0 : 0; + return !value; + }, + syntax: { js: [], py: [] }, + }, + dalgona_get_analog_mapping: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + template: Lang.template.dalgona_get_analog_mapping, + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_analog_basic', + }, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['1023'], + }, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['100'], + }, + ], + type: 'dalgona_get_analog_mapping', + }, + paramsKeyMap: { + PORT: 0, + VALUE2: 1, + VALUE3: 2, + VALUE4: 3, + VALUE5: 4, + }, + class: 'analog', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getValue('PORT', script); + var result = 0; + var ANALOG = Entry.hw.portData.ANALOG; + var value2 = script.getNumberValue('VALUE2', script); + var value3 = script.getNumberValue('VALUE3', script); + var value4 = script.getNumberValue('VALUE4', script); + var value5 = script.getNumberValue('VALUE5', script); + + if (port[0] === 'A') { + port = port.substring(1); + } + result = ANALOG ? ANALOG[port] || 0 : 0; + if (value2 > value3) { + var swap = value2; + value2 = value3; + value3 = swap; + } + if (value4 > value5) { + var swap = value4; + value4 = value5; + value5 = swap; + } + result -= value2; + result = result * ((value5 - value4) / (value3 - value2)); + result += value4; + result = Math.min(value5, result); + result = Math.max(value4, result); + + return result; + }, + syntax: { + js: [], + py: ['dalgona.get_analog_mapping(%1, %2, %3, %4, %5)'], + }, + }, + dalgona_mapping1: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['255'], + }, + ], + type: 'dalgona_mapping1', + }, + paramsKeyMap: { + NUM: 0, + VALUE2: 1, + VALUE3: 2, + }, + class: 'analog', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM', script); + + var value2 = script.getNumberValue('VALUE2', script); + var value3 = script.getNumberValue('VALUE3', script); + + if (value2 > value3) { + var swap = value2; + value2 = value3; + value3 = swap; + } + + num = Math.min(value3, num); + num = Math.max(value2, num); + + return parseInt(num); + }, + syntax: { + js: [], + py: [], + }, + }, + dalgona_mapping2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['1024'], + }, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['100'], + }, + ], + type: 'dalgona_mapping2', + }, + paramsKeyMap: { + NUM: 0, + VALUE2: 1, + VALUE3: 2, + VALUE4: 3, + VALUE5: 4, + }, + class: 'analog', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM', script); + var flag = 0; + + var value2 = script.getNumberValue('VALUE2', script); + var value3 = script.getNumberValue('VALUE3', script); + var value4 = script.getNumberValue('VALUE4', script); + var value5 = script.getNumberValue('VALUE5', script); + + var value4_1 = value4; + var value5_1 = value5; + + if (value2 > value3) { + var swap = value2; + value2 = value3; + value3 = swap; + } + + if (value4 > value5) { + flag = 1; + var swap = value4; + value4_1 = value5; + value5_1 = swap; + } + + num -= value2; + num = num * ((value5_1 - value4_1) / (value3 - value2)); + + if (flag == 1) { + num = value4 - num; + num = Math.min(value4, num); + num = Math.max(value5, num); + } else { + num = num + value4; + num = Math.min(value5, num); + num = Math.max(value4, num); + } + + return parseInt(num); + }, + syntax: { + js: [], + py: [], + }, + }, + dalgona_get_digital_ultrasonic: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + template: Lang.template.dalgona_get_digital_ultrasonic, + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + params: ['13'], + }, + { + type: 'dalgona_list_digital_basic', + params: ['12'], + }, + ], + type: 'dalgona_get_digital_ultrasonic', + }, + paramsKeyMap: { + PORT1: 0, + PORT2: 1, + }, + class: 'ultrasonic', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port1 = script.getNumberValue('PORT1'); + var port2 = script.getNumberValue('PORT2'); + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + delete Entry.hw.sendQueue['SET'][port1]; + delete Entry.hw.sendQueue['SET'][port2]; + + Entry.Utils.sleep(700); + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.ULTRASONIC] = { + port: [port1, port2], + time: new Date().getTime(), + }; + + return Entry.hw.portData.ULTRASONIC[port2] || 0; + }, + syntax: { + js: [], + py: ['dalgona.get_digital_ultrasonic(%1, %2)'], + }, + }, + dalgona_get_dust: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + params: ['7'], + }, + { + type: 'dalgona_list_analog_basic', + params: ['0'], + }, + ], + type: 'dalgona_get_dust', + }, + paramsKeyMap: { + PORT1: 0, + PORT2: 1, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port1 = script.getNumberValue('PORT1'); + var port2 = script.getNumberValue('PORT2'); + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + delete Entry.hw.sendQueue['SET'][port1]; + delete Entry.hw.sendQueue['SET'][port2]; + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DUST] = { + port: [port1, port2], + time: new Date().getTime(), + }; + + return Entry.hw.portData.DUST || 0; + }, + syntax: { + js: [], + py: ['dalgona.get_digital_ultrasonic(%1, %2)'], + }, + }, + dalgona_get_digital: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.dalgona_get_digital, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + }, + ], + type: 'dalgona_get_digital', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'digital', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var DIGITAL = Entry.hw.portData.DIGITAL; + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + if (Entry.hw.sendQueue.SET[port]) { + return Entry.hw.sendQueue.SET[port].data; + } else { + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = { + port: port, + time: new Date().getTime(), + }; + } + + return DIGITAL ? DIGITAL[port] || 0 : 0; + }, + syntax: { js: [], py: ['dalgona.get_digital(%1)'] }, + }, + dalgona_get_digital_toggle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.dalgona_get_digital_toggle, + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + }, + ], + type: 'dalgona_get_digital_toggle', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var DIGITAL = Entry.hw.portData.DIGITAL; + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = { + port: port, + time: new Date().getTime(), + }; + + return DIGITAL ? DIGITAL[port] || 0 : 0; + }, + syntax: { js: [], py: ['dalgona.get_digital_toggle(%1)'] }, + }, + dalgona_get_digital_pir: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.dalgona_get_digital_pir, + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + }, + ], + type: 'dalgona_get_digital_pir', + }, + paramsKeyMap: { + PORT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var DIGITAL = Entry.hw.portData.DIGITAL; + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.PIR] = { + port: port, + time: new Date().getTime(), + }; + + return DIGITAL ? DIGITAL[port] || 0 : 0; + }, + syntax: { js: [], py: ['dalgona.get_digital_pir(%1)'] }, + }, + + dalgona_set_digital_toggle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_set_digital_toggle, + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + }, + { + type: 'dalgona_list_digital_toggle_en', + }, + null, + ], + type: 'dalgona_set_digital_toggle', + }, + paramsKeyMap: { + PORT: 0, + VALUE: 1, + }, + class: 'digital', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getValue('VALUE'); + + if (typeof value === 'string') { + value = value.toLowerCase(); + } + if (Entry.Dalgona.highList.indexOf(value) > -1) { + value = 255; + } else if (Entry.Dalgona.lowList.indexOf(value) > -1) { + value = 0; + } else { + throw new Error(); + } + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.DIGITAL, + data: value, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { js: [], py: ['dalgona.set_digital_toggle(%1, %2)'] }, + }, + dalgona_set_led_toggle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + params: ['13'], + }, + { + type: 'dalgona_list_digital_toggle', + }, + null, + ], + type: 'dalgona_set_led_toggle', + }, + paramsKeyMap: { + PORT: 0, + VALUE: 1, + }, + class: 'digital', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getValue('VALUE'); + + if (typeof value === 'string') { + value = value.toLowerCase(); + } + if (Entry.Dalgona.highList.indexOf(value) > -1) { + value = 255; + } else if (Entry.Dalgona.lowList.indexOf(value) > -1) { + value = 0; + } else { + throw new Error(); + } + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.DIGITAL, + data: value, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { js: [], py: ['dalgona.set_digital_toggle(%1, %2)'] }, + }, + dalgona_set_digital_pwm: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_set_digital_pwm, + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_pwm', + params: ['5'], + }, + { + type: 'text', + params: ['255'], + }, + null, + ], + type: 'dalgona_set_digital_pwm', + }, + paramsKeyMap: { + PORT: 0, + VALUE: 1, + }, + class: 'pwm', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getNumberValue('VALUE'); + + value = Math.round(value); + value = Math.min(value, 255); + value = Math.max(value, 0); + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.PWM, + data: value, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { js: [], py: ['dalgona.set_digital_pwm(%1, %2)'] }, + }, + dalgona_set_digital_rgbled: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_set_digital_rgbled, + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + 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: 'dalgona_list_digital_pwm', + params: ['9'], + }, + { + type: 'dalgona_list_digital_pwm', + params: ['10'], + }, + { + type: 'dalgona_list_digital_pwm', + params: ['11'], + }, + { + type: 'text', + params: ['0'], + }, + { + type: 'text', + params: ['0'], + }, + { + type: 'text', + params: ['0'], + }, + null, + ], + type: 'dalgona_set_digital_rgbled', + }, + paramsKeyMap: { + PORT1: 0, + PORT2: 1, + PORT3: 2, + VALUE1: 3, + VALUE2: 4, + VALUE3: 5, + }, + class: 'pwm', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port1 = script.getNumberValue('PORT1', script); + var port2 = script.getNumberValue('PORT2', script); + var port3 = script.getNumberValue('PORT3', script); + var value1 = script.getNumberValue('VALUE1', script); + var value2 = script.getNumberValue('VALUE2', script); + var value3 = script.getNumberValue('VALUE3', script); + + RGBport = port1; + + // if (!Entry.hw.sendQueue['SET']) { + // Entry.hw.sendQueue['SET'] = {}; + // } + // Entry.hw.sendQueue['SET'][RGBport] = { + // type: Entry.Dalgona.sensorTypes.RGBLED, + // data: { + // port1: port1, + // port2: port2, + // port3: port3, + // value1: value1, + // value2: value2, + // value3: value3, + // }, + // time: new Date().getTime(), + // }; + // return script.callReturn(); + + + // if (!script.isStart) { + // script.isStart = true; + // script.timeFlag = 1; + // var fps = Entry.FPS || 60; + // var timeValue = (60 / fps) * 50; + + // value1 = Math.round(value1); + // value1 = Math.min(value1, 255); + // value1 = Math.max(value1, 0); + // value2 = Math.round(value2); + // value2 = Math.min(value2, 255); + // value2 = Math.max(value2, 0); + // value3 = Math.round(value3); + // value3 = Math.min(value3, 255); + // value3 = Math.max(value3, 0); + + // if (!Entry.hw.sendQueue['SET']) { + // Entry.hw.sendQueue['SET'] = {}; + // } + // Entry.hw.sendQueue['SET'][RGBport] = { + // type: Entry.Dalgona.sensorTypes.RGBLED, + // data: { + // port1: port1, + // port2: port2, + // port3: port3, + // value1: value1, + // value2: value2, + // value3: value3, + // }, + // time: new Date().getTime(), + // }; + // setTimeout(function() { + // script.timeFlag = 0; + // }, 10); + // return script; + // } else if (script.timeFlag == 1) { + // return script; + // } else { + // delete script.timeFlag; + // delete script.isStart; + // Entry.engine.isContinue = false; + // return script.callReturn(); + // } + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port1] = { + type: Entry.Dalgona.sensorTypes.PWM, + data: value1, + time: new Date().getTime(), + }; + Entry.hw.sendQueue['SET'][port2] = { + type: Entry.Dalgona.sensorTypes.PWM, + data: value2, + time: new Date().getTime(), + }; + Entry.hw.sendQueue['SET'][port3] = { + type: Entry.Dalgona.sensorTypes.PWM, + data: value3, + time: new Date().getTime(), + }; + return script.callReturn(); + }, + syntax: { js: [], py: [{}] }, + }, + dalgona_set_digital_servo: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_set_digital_servo, + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + params: ['8'], + }, + { + type: 'text', + params: ['90'], + }, + null, + ], + type: 'dalgona_set_digital_servo', + }, + paramsKeyMap: { + PORT: 0, + VALUE: 1, + }, + class: 'motor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getNumberValue('VALUE'); + value = Math.min(value, 180); + value = Math.max(value, 0); + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.SERVO, + data: value, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { js: [], py: ['dalgona.set_digital_servo(%1, %2)'] }, + }, + dalgona_set_digital_servo2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_set_digital_servo2, + params: [ + { + type: 'Block', + accept: 'string', + }, + { + 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: 'dalgona_list_digital_basic', + params: ['8'], + }, + { + type: 'text', + params: ['0'], + }, + { + type: 'text', + params: ['180'], + }, + { + type: 'text', + params: ['1'], + }, + null, + ], + type: 'dalgona_set_digital_servo2', + }, + paramsKeyMap: { + PORT: 0, + VALUE1: 1, + VALUE2: 2, + STIME: 3, + }, + class: 'motor', + isNotFor: ['Dalgona'], + // func: function(sprite, script) { + // var port = script.getNumberValue('PORT'); + // var value1 = script.getNumber Value('VALUE1', script); + // var value2 = script.getNumberValue('VALUE2', script); + // var stime = script.getNumberValue('STIME', script); + + // value1 = Math.min(value1, 180); + // value1 = Math.max(value1, 0); + // value2 = Math.min(value2, 180); + // value2 = Math.max(value2, 0); + + // if (!Entry.hw.sendQueue['SET']) { + // Entry.hw.sendQueue['SET'] = {}; + // } + + // Entry.hw.sendQueue['SET'][port] = { + // type: Entry.Dalgona.sensorTypes.SERVO2, + // data: { + // value1: value1, + // value2: value2, + // stime: stime, + // }, + // time: new Date().getTime(), + // }; + // return script.callReturn(); + // }, + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value1 = script.getNumberValue('VALUE1', script); + var value2 = script.getNumberValue('VALUE2', script); + var stime = script.getNumberValue('STIME', script); + + value1 = Math.min(value1, 180); + value1 = Math.max(value1, 0); + value2 = Math.min(value2, 180); + value2 = Math.max(value2, 0); + + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.SERVO2, + data: { + value1: value1, + value2: value2, + stime: stime, + }, + time: new Date().getTime(), + }; + setTimeout(function() { + script.timeFlag = 0; + }, 10); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { js: [], py: [{}] }, + }, + dalgona_set_digital_buzzer_toggle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_basic', + params: ['6'], + }, + { + type: 'dalgona_list_digital_toggle', + }, + + null, + ], + type: 'dalgona_set_digital_buzzer_toggle', + }, + paramsKeyMap: { + PORT: 0, + VALUE: 1, + }, + class: 'buzzer', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getValue('VALUE'); + + if (typeof value === 'string') { + value = value.toLowerCase(); + } + if (Entry.Dalgona.highList.indexOf(value) > -1) { + value = 255; + } else if (Entry.Dalgona.lowList.indexOf(value) > -1) { + value = 0; + } else { + throw new Error(); + } + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.DIGITAL, + data: value, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { + js: [], + py: ['dalgona.set_digital_toggle(%1, %2, %3, %4)'], + }, + }, + dalgona_set_digital_buzzer_volume: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_digital_pwm', + params: ['6'], + }, + { + type: 'text', + params: ['255'], + }, + null, + ], + type: 'dalgona_set_digital_buzzer_volume', + }, + paramsKeyMap: { + PORT: 0, + VALUE: 1, + }, + class: 'buzzer', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var value = script.getNumberValue('VALUE'); + + value = Math.round(value); + value = Math.min(value, 255); + value = Math.max(value, 0); + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.PWM, + data: value, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { + js: [], + py: ['dalgona.set_digital_toggle(%1, %2, %3, %4)'], + }, + }, + dalgona_set_digital_buzzer: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_set_digital_buzzer, + params: [ + { + type: 'Block', + accept: 'string', + }, + { + 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: 'dalgona_list_digital_basic', + params: ['6'], + }, + { + type: 'dalgona_list_digital_tone', + }, + { + type: 'dalgona_list_digital_octave', + }, + { + type: 'text', + params: ['1'], + }, + null, + ], + type: 'dalgona_set_digital_buzzer', + }, + paramsKeyMap: { + PORT: 0, + NOTE: 1, + OCTAVE: 2, + DURATION: 3, + }, + class: 'buzzer', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var duration = script.getNumberValue('DURATION'); + var octave = script.getNumberValue('OCTAVE') - 1; + var value = 0; + + if (!script.isStart) { + var note = script.getValue('NOTE'); + if (!Entry.Utils.isNumber(note)) { + note = Entry.Dalgona.toneTable[note]; + } + if (note < 0) { + note = 0; + } else if (note > 12) { + note = 12; + } + if (duration < 0) { + duration = 0; + } + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + if (duration === 0) { + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.TONE, + data: 0, + time: new Date().getTime(), + }; + return script.callReturn(); + } + if (octave < 0) { + octave = 0; + } else if (octave > 8) { + octave = 8; + } + if (note != 0) { + value = Entry.Dalgona.toneMap[note][octave]; + } + + duration = duration * 1000; + script.isStart = true; + script.timeFlag = 1; + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.TONE, + data: { + value: value, + duration: duration, + }, + time: new Date().getTime(), + }; + + setTimeout(function() { + script.timeFlag = 0; + }, duration + 32); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.TONE, + data: 0, + time: new Date().getTime(), + }; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: ['dalgona.set_digital_toggle(%1, %2, %3, %4)'], + }, + }, + dalgona_lcd_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + 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: 'dalgona_lcd_list_init', + params: ['0'], + }, + { + type: 'text', + params: ['16'], + }, + { + type: 'text', + params: ['2'], + }, + null, + ], + type: 'dalgona_lcd_init', + }, + paramsKeyMap: { + LIST: 0, + COL: 1, + LINE: 2, + }, + class: 'LCD', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var list = script.getNumberValue('LIST'); + var col = script.getNumberValue('COL'); + var line = script.getValue('LINE'); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 0.1 * 1000; + + Entry.hw.sendQueue['SET'][1] = { + type: Entry.Dalgona.sensorTypes.LCDINIT, + data: { + list: list, + col: col, + line: line, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { js: [], py: ['dalgona.module_digital_lcd(%1, %2)'] }, + }, + dalgona_module_digital_lcd: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_get_lcd_col', + params: ['0'], + }, + { + type: 'dalgona_get_lcd_row', + params: ['0'], + }, + { + type: 'text', + params: ['Hello, dalgona'], + }, + null, + ], + type: 'dalgona_module_digital_lcd', + }, + paramsKeyMap: { + COL: 0, + ROW: 1, + STRING: 2, + }, + class: 'LCD', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var row = script.getNumberValue('ROW'); + var col = script.getNumberValue('COL'); + var text = script.getValue('STRING'); + text += ' '; + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 100; + + Entry.hw.sendQueue['SET'][1] = { + type: Entry.Dalgona.sensorTypes.LCD, + data: { + line: row, + column: col, + text: text, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { js: [], py: ['dalgona.module_digital_lcd(%1, %2)'] }, + }, + dalgona_lcd_clear: { + 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: 'dalgona_lcd_clear', + }, + class: 'LCD', + isNotFor: ['Dalgona'], + func(sprite, script) { + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][1] = { + type: Entry.Dalgona.sensorTypes.LCDCLEAR, + data: 0, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_get_dht: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + ['온도(°C)', '0'], + ['습도(%)', '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [ + { + type: 'arduino_get_port_number', + params: ['4'], + }, + + ], + type: 'dalgona_get_dht', + }, + paramsKeyMap: { + PORT: 0, + DHT_SELECT: 1, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = script.getNumberValue('PORT'); + var type = script.getNumberValue('DHT_SELECT'); + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + delete Entry.hw.sendQueue['SET'][port]; + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + + if (type == 0) { + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DHTTEMP] = { + port: port, + time: new Date().getTime(), + }; + return Entry.hw.portData.DHTTEMP || 0; + } else if (type == 1) { + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DHTHUMI] = { + port: port, + time: new Date().getTime(), + }; + return Entry.hw.portData.DHTHUMI || 0; + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_set_mp3_init: { + 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: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'arduino_get_port_number', + params: ['10'], + }, + { + type: 'arduino_get_port_number', + params: ['11'], + }, + null, + ], + type: 'dalgona_set_mp3_init', + }, + paramsKeyMap: { + PORT1: 0, + PORT2: 1, + }, + class: 'mp3', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + tx = script.getNumberValue('PORT1'); + var rx = script.getNumberValue('PORT2'); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][tx] = { + type: Entry.Dalgona.sensorTypes.MP3INIT, + data: { + tx: tx, + rx: rx, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_set_mp3_play: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['1'], + }, + null, + ], + type: 'dalgona_set_mp3_play', + }, + paramsKeyMap: { + NUM: 0, + }, + class: 'mp3', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM'); + + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][tx] = { + type: Entry.Dalgona.sensorTypes.MP3PLAY1, + data: { + tx: tx, + num: num, + }, + time: new Date().getTime(), + }; + + return script.callReturn(); + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_set_mp3_play2: { + 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: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['1'], + }, + { + type: 'number', + params: ['3'], + }, + null, + ], + type: 'dalgona_set_mp3_play2', + }, + paramsKeyMap: { + NUM: 0, + TIME: 1, + }, + class: 'mp3', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM'); + var time_value = script.getNumberValue('TIME'); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + time_value = (60 / fps) * time_value * 1000; + + Entry.hw.sendQueue['SET'][tx] = { + type: Entry.Dalgona.sensorTypes.MP3PLAY1, + data: { + tx: tx, + num: num, + //time_value: time_value, + }, + time: new Date().getTime(), + }; + + setTimeout(function() { + script.timeFlag = 0; + }, time_value); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + + Entry.hw.sendQueue['SET'][tx] = { + type: Entry.Dalgona.sensorTypes.MP3PLAY1, + data: 0, + time: new Date().getTime(), + }; + Entry.engine.isContinue = false; + + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_set_mp3_vol: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['15'], + }, + null, + ], + type: 'dalgona_set_mp3_vol', + }, + paramsKeyMap: { + VOL: 0, + }, + class: 'mp3', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var vol = script.getNumberValue('VOL'); + + vol = Math.round(vol); + vol = Math.min(vol, 30); + vol = Math.max(vol, 0); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][tx] = { + type: Entry.Dalgona.sensorTypes.MP3VOL, + data: { + tx: tx, + vol: vol, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_load_init: { + 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: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'arduino_get_port_number', + params: ['6'], + }, + { + type: 'arduino_get_port_number', + params: ['7'], + }, + null, + ], + type: 'dalgona_load_init', + }, + paramsKeyMap: { + PORT1: 0, + PORT2: 1, + }, + class: 'HX711', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port1 = script.getNumberValue('PORT1', script); + var port2 = script.getNumberValue('PORT2', script); + + dout = port1; + sck = port2; + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][sck] = { + type: Entry.Dalgona.sensorTypes.LOADINIT, + data: { + port1: port1, + port2: port2, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_load_scale: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['-20000'], + }, + null, + ], + type: 'dalgona_load_scale', + }, + paramsKeyMap: { + NUM: 0, + }, + class: 'HX711', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM', script); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][sck] = { + type: Entry.Dalgona.sensorTypes.LOADSCALE, + data: { + num: num, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_load_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [], + events: {}, + def: { + type: 'dalgona_load_value', + }, + paramsKeyMap: {}, + class: 'HX711', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + delete Entry.hw.sendQueue['SET'][sck]; + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.LOADVALUE] = { + port: sck, + time: new Date().getTime(), + }; + + return Entry.hw.portData.LOADVALUE || 0; + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_list_joy: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['첫번째', '1'], + ['두번째', '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + NUM: 0, + }, + func: function(sprite, script) { + return script.getField('NUM'); + }, + }, + dalgona_joy_init: { + 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: 'dalgona_list_joy', + params: ['1'], + }, + { + type: 'dalgona_list_analog_basic', + params: ['0'], + }, + { + type: 'dalgona_list_analog_basic', + params: ['1'], + }, + { + type: 'arduino_get_port_number', + params: ['8'], + }, + null, + ], + type: 'dalgona_joy_init', + }, + paramsKeyMap: { + NUM: 0, + PORT1: 1, + PORT2: 2, + PORT3: 3, + }, + class: 'joystick', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM', script); + var port1 = script.getNumberValue('PORT1', script); + var port2 = script.getNumberValue('PORT2', script); + var port3 = script.getNumberValue('PORT3', script); + + if (num == 1) { + joyx = port1; + joyy = port2; + joyz = port3; + } else if (num == 2) { + joyx2 = port1; + joyy2 = port2; + joyz2 = port3; + } + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + if (num == 1) { + Entry.hw.sendQueue['SET'][joyx] = { + type: Entry.Dalgona.sensorTypes.JOYINIT, + data: { + num: num, + port1: port1, + port2: port2, + port3: port3, + }, + time: new Date().getTime(), + }; + } else if (num == 2) { + Entry.hw.sendQueue['SET'][joyx2] = { + type: Entry.Dalgona.sensorTypes.JOYINIT, + data: { + num: num, + port1: port1, + port2: port2, + port3: port3, + }, + time: new Date().getTime(), + }; + } + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_get_joy_x: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_joy', + params: ['1'], + }, + ], + type: 'dalgona_get_joy_x', + }, + paramsKeyMap: { + NUM: 0, + }, + class: 'joystick', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var ANALOG = Entry.hw.portData.ANALOG; + var num = script.getNumberValue('NUM', script); + if (num == 1) { + return ANALOG ? ANALOG[joyx] || 0 : 0; + } else if (num == 2) { + return ANALOG ? ANALOG[joyx2] || 0 : 0; + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_get_joy_y: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_joy', + params: ['1'], + }, + ], + type: 'dalgona_get_joy_y', + }, + paramsKeyMap: { + NUM: 0, + }, + class: 'joystick', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var ANALOG = Entry.hw.portData.ANALOG; + var num = script.getNumberValue('NUM', script); + if (num == 1) { + return ANALOG ? ANALOG[joyy] || 0 : 0; + } else if (num == 2) { + return ANALOG ? ANALOG[joyy2] || 0 : 0; + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + + dalgona_get_joy_z: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_joy', + params: ['1'], + }, + ], + type: 'dalgona_get_joy_z', + }, + paramsKeyMap: { + NUM: 0, + }, + class: 'joystick', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var DIGITAL = Entry.hw.portData.DIGITAL; + var num = script.getNumberValue('NUM', script); + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + + if (num == 1) { + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = { + port: joyz, + data: 2, + time: new Date().getTime(), + }; + + var value = DIGITAL ? DIGITAL[joyz] || 0 : 0; + return !value; + } else if (num == 2) { + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.DIGITAL] = { + port: joyz2, + data: 2, + time: new Date().getTime(), + }; + + var value = DIGITAL ? DIGITAL[joyz2] || 0 : 0; + return !value; + } + }, + syntax: { js: [], py: [] }, + }, + dalgona_list_joy_direction: { + 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'], + ['아래', '4'], + ['왼쪽', '2'], + ['오른쪽', '3'], + ['왼쪽위', '5'], + ['왼쪽아래', '6'], + ['오른쪽위', '7'], + ['오른쪽아래', '8'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + DIR: 0, + }, + func: function(sprite, script) { + return script.getField('DIR'); + }, + }, + dalgona_get_joy_move: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_joy', + params: ['1'], + }, + { + type: 'dalgona_list_joy_direction', + params: ['0'], + }, + ], + type: 'dalgona_get_joy_move', + }, + paramsKeyMap: { + NUM: 0, + DIR: 1, + }, + class: 'joystick', + isNotFor: ['Dalgona'], + func(sprite, script) { + var direction = script.getNumberValue('DIR'); + const ANALOG = Entry.hw.portData.ANALOG; + num = script.getNumberValue('NUM', script); + + const getValue = function(w) { + return ANALOG[w] <= 100 ? 0 : ANALOG[w] >= 930 ? 2 : 1; + }; + + var xpin; + var ypin; + if (num == 1) { + xpin = joyx; + ypin = joyy; + } else if (num == 2) { + xpin = joyx2; + ypin = joyy2; + } + if ( + direction == Entry.Dalgona.direction.CENTER && + getValue(xpin) == 1 && + getValue(ypin) == 1 + ) { + return 1; + } else if ( + direction == Entry.Dalgona.direction.DOWN && + getValue(xpin) == 1 && + getValue(ypin) == 2 + ) { + return 1; + } else if ( + direction == Entry.Dalgona.direction.LEFT && + getValue(xpin) == 0 && + getValue(ypin) == 1 + ) { + return 1; + } else if ( + direction == Entry.Dalgona.direction.LEFT_DOWN && + getValue(xpin) == 0 && + getValue(ypin) == 2 + ) { + return 1; + } else if ( + direction == Entry.Dalgona.direction.LEFT_UP && + getValue(xpin) == 0 && + getValue(ypin) == 0 + ) { + return 1; + } else if ( + direction == Entry.Dalgona.direction.RIGHT && + getValue(xpin) == 2 && + getValue(ypin) == 1 + ) { + return 1; + } else if ( + direction == Entry.Dalgona.direction.RIGHT_DOWN && + getValue(xpin) == 2 && + getValue(ypin) == 2 + ) { + return 1; + } else if ( + direction == Entry.Dalgona.direction.RIGHT_UP && + getValue(xpin) == 2 && + getValue(ypin) == 0 + ) { + return 1; + } else if ( + direction == Entry.Dalgona.direction.UP && + getValue(xpin) == 1 && + getValue(ypin) == 0 + ) { + return 1; + } + + return 0; + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_list_step: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['첫번째', '1'], + ['두번째', '2'], + ['세번째', '3'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + NUM: 0, + }, + func: function(sprite, script) { + return script.getField('NUM'); + }, + }, + dalgona_step_init: { + 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: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_step', + params: ['1'], + }, + { + type: 'arduino_get_port_number', + params: ['8'], + }, + { + type: 'arduino_get_port_number', + params: ['9'], + }, + { + type: 'arduino_get_port_number', + params: ['10'], + }, + { + type: 'arduino_get_port_number', + params: ['11'], + }, + null, + ], + type: 'dalgona_step_init', + }, + paramsKeyMap: { + NUM: 0, + PORT1: 1, + PORT2: 2, + PORT3: 3, + PORT4: 4, + }, + class: 'step', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM', script); + var port1 = script.getNumberValue('PORT1', script); + var port2 = script.getNumberValue('PORT2', script); + var port3 = script.getNumberValue('PORT3', script); + var port4 = script.getNumberValue('PORT4', script); + + if (num == 1) { + portpin1 = port1; + } else if (num == 2) { + portpin2 = port1; + } else if (num == 3) { + portpin3 = port1; + } + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + if (num == 1) { + console.log('STEP INIT 1st'); + console.log(num); + console.log(port1); + console.log(port2); + console.log(port3); + console.log(port4); + + Entry.hw.sendQueue['SET'][portpin1] = { + type: Entry.Dalgona.sensorTypes.STEPINIT, + data: { + num: num, + port1: port1, + port2: port2, + port3: port3, + port4: port4, + }, + time: new Date().getTime(), + }; + } else if (num == 2) { + console.log('STEP INIT 2nd'); + console.log(num); + console.log(port1); + console.log(port2); + console.log(port3); + console.log(port4); + Entry.hw.sendQueue['SET'][portpin2] = { + type: Entry.Dalgona.sensorTypes.STEPINIT, + data: { + num: num, + port1: port1, + port2: port2, + port3: port3, + port4: port4, + }, + time: new Date().getTime(), + }; + } else if (num == 3) { + console.log('STEP INIT 3rd'); + console.log(num); + console.log(port1); + console.log(port2); + console.log(port3); + console.log(port4); + Entry.hw.sendQueue['SET'][portpin3] = { + type: Entry.Dalgona.sensorTypes.STEPINIT, + data: { + num: num, + port1: port1, + port2: port2, + port3: port3, + port4: port4, + }, + time: new Date().getTime(), + }; + } + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_step_speed: { + 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: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'dalgona_list_step', + params: ['1'], + }, + { + type: 'number', + params: ['14'], + }, + null, + ], + type: 'dalgona_step_speed', + }, + paramsKeyMap: { + NUM: 0, + SPEED: 1, + }, + class: 'step', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var num = script.getNumberValue('NUM', script); + var sp = script.getNumberValue('SPEED', script); + + sp = Math.round(sp); + sp = Math.min(sp, 20); + sp = Math.max(sp, 0); + + if (num == 1) { + speed1 = sp; + } else if (num == 2) { + speed2 = sp; + } else if (num == 3) { + speed3 = sp; + } + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + if (num == 1) { + Entry.hw.sendQueue['SET'][portpin1] = { + type: Entry.Dalgona.sensorTypes.STEPSPEED, + data: { + num: num, + speed: speed1, + }, + time: new Date().getTime(), + }; + } else if (num == 2) { + Entry.hw.sendQueue['SET'][portpin2] = { + type: Entry.Dalgona.sensorTypes.STEPSPEED, + data: { + num: num, + speed: speed2, + }, + time: new Date().getTime(), + }; + } else if (num == 3) { + Entry.hw.sendQueue['SET'][portpin3] = { + type: Entry.Dalgona.sensorTypes.STEPSPEED, + data: { + num: num, + speed: speed3, + }, + time: new Date().getTime(), + }; + } + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_list_step_direction: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['정방향', '1'], + ['역방향', '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + DIR: 0, + }, + func: function(sprite, script) { + return script.getField('DIR'); + }, + }, + dalgona_step_rotate: { + 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: 'dalgona_list_step', + params: ['1'], + }, + { + type: 'dalgona_list_step_direction', + params: ['1'], + }, + { + type: 'number', + params: ['1'], + }, + null, + ], + type: 'dalgona_step_rotate', + }, + paramsKeyMap: { + NUM: 0, + DIR: 1, + VALUE: 2, + }, + class: 'step', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var dir = script.getNumberValue('DIR', script); + num = script.getNumberValue('NUM', script); + var val = script.getNumberValue('VALUE', script); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var timeValue; + + if (num == 1) { + timeValue = (60 / speed1) * val * 1000 + 32; + console.log(timeValue); + Entry.hw.sendQueue['SET'][portpin1] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE, + data: { + num: num, + dir: dir, + val: val * 2048, + }, + time: new Date().getTime(), + }; + } else if (num == 2) { + timeValue = (60 / speed2) * val * 1000 + 32; + Entry.hw.sendQueue['SET'][portpin2] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE, + data: { + num: num, + dir: dir, + val: val * 2048, + }, + time: new Date().getTime(), + }; + } else if (num == 3) { + timeValue = (60 / speed3) * val * 1000 + 32; + Entry.hw.sendQueue['SET'][portpin3] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE, + data: { + num: num, + dir: dir, + val: val * 2048, + }, + time: new Date().getTime(), + }; + } + + setTimeout(function() { + script.timeFlag = 0; + }, timeValue); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + if (num == 1) { + Entry.hw.sendQueue['SET'][portpin1] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE, + data: 0, + time: new Date().getTime(), + }; + } else if (num == 2) { + Entry.hw.sendQueue['SET'][portpin2] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE, + data: 0, + time: new Date().getTime(), + }; + } else if (num == 3) { + Entry.hw.sendQueue['SET'][portpin3] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE, + data: 0, + time: new Date().getTime(), + }; + } + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_step_rotate2: { + 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: 'dalgona_list_step', + params: ['1'], + }, + { + type: 'dalgona_list_step_direction', + params: ['1'], + }, + { + type: 'number', + params: ['90'], + }, + null, + ], + type: 'dalgona_step_rotate2', + }, + paramsKeyMap: { + NUM: 0, + DIR: 1, + VALUE: 2, + }, + class: 'step', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var dir = script.getNumberValue('DIR', script); + num = script.getNumberValue('NUM', script); + var val = script.getNumberValue('VALUE', script); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + + var timeValue; + + if (num == 1) { + timeValue = (60 / (speed1 * 360)) * val * 1000 + 32; + console.log(timeValue); + Entry.hw.sendQueue['SET'][portpin1] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE2, + data: { + num: num, + dir: dir, + val: (val / 360) * 2048, + }, + time: new Date().getTime(), + }; + } else if (num == 2) { + timeValue = (60 / (speed2 * 360)) * val * 1000 + 32; + Entry.hw.sendQueue['SET'][portpin2] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE2, + data: { + num: num, + dir: dir, + val: (val / 360) * 2048, + }, + time: new Date().getTime(), + }; + } else if (num == 3) { + timeValue = (60 / (speed3 * 360)) * val * 1000 + 32; + Entry.hw.sendQueue['SET'][portpin3] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE2, + data: { + num: num, + dir: dir, + val: (val / 360) * 2048, + }, + time: new Date().getTime(), + }; + } + + setTimeout(function() { + script.timeFlag = 0; + }, timeValue); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + if (num == 1) { + Entry.hw.sendQueue['SET'][portpin1] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE2, + data: 0, + time: new Date().getTime(), + }; + } else if (num == 2) { + Entry.hw.sendQueue['SET'][portpin2] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE2, + data: 0, + time: new Date().getTime(), + }; + } else if (num == 3) { + Entry.hw.sendQueue['SET'][portpin3] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE2, + data: 0, + time: new Date().getTime(), + }; + } + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_step_rotate3: { + 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: 'dalgona_list_step', + params: ['1'], + }, + { + type: 'dalgona_list_step_direction', + params: ['1'], + }, + { + type: 'number', + params: ['5'], + }, + null, + ], + type: 'dalgona_step_rotate3', + }, + paramsKeyMap: { + NUM: 0, + DIR: 1, + SEC: 2, + }, + class: 'step', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + num = script.getNumberValue('NUM'); + var dir = script.getNumberValue('DIR'); + var sec = script.getNumberValue('SEC'); + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + + if (num == 1) { + Entry.hw.sendQueue['SET'][portpin1] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE3, + data: { + num: num, + dir: dir, + sec: sec, + }, + time: new Date().getTime(), + }; + } else if (num == 2) { + Entry.hw.sendQueue['SET'][portpin2] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE3, + data: { + num: num, + dir: dir, + sec: sec, + }, + time: new Date().getTime(), + }; + } else if (num == 3) { + Entry.hw.sendQueue['SET'][portpin3] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE3, + data: { + num: num, + dir: dir, + sec: sec, + }, + time: new Date().getTime(), + }; + } + + setTimeout(function() { + script.timeFlag = 0; + }, sec * 1000 + 32); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + if (num == 1) { + Entry.hw.sendQueue['SET'][portpin1] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE3, + data: 0, + time: new Date().getTime(), + }; + } else if (num == 2) { + Entry.hw.sendQueue['SET'][portpin2] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE3, + data: 0, + time: new Date().getTime(), + }; + } else if (num == 3) { + Entry.hw.sendQueue['SET'][portpin3] = { + type: Entry.Dalgona.sensorTypes.STEPROTATE3, + data: 0, + time: new Date().getTime(), + }; + } + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_module_digital_oled: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.dalgona_module_digital_oled, + 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: 'text', + params: ['20'], + }, + { + type: 'text', + params: ['20'], + }, + { + type: 'text', + params: ['My Entry!!'], + }, + null, + ], + type: 'dalgona_module_digital_oled', + }, + paramsKeyMap: { + VALUE0: 0, + VALUE1: 1, + STRING: 2, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port = 0; + var coodinate_x = script.getNumberValue('VALUE0'); + var coodinate_y = script.getNumberValue('VALUE1'); + var string = script.getValue('STRING'); + var text = []; + + if (!script.isStart) { + if (typeof string === 'string') { + for (var i = 0; i < string.length; i++) { + text[i] = string.charCodeAt(i); + } + } else if (typeof string === 'number') { + text[0] = 1; + text[1] = string / 1; + } else { + text[0] = string; + } + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + coodinate_x = Math.min(coodinate_x, 127); + coodinate_x = Math.max(coodinate_x, 0); + coodinate_y = Math.min(coodinate_y, 63); + coodinate_y = Math.max(coodinate_y, 0); + + Entry.hw.sendQueue['SET'][port] = { + type: Entry.Dalgona.sensorTypes.OLED, + data: { + value0: coodinate_x, + value1: coodinate_y, + text0: text[0], + text1: text[1], + text2: text[2], + text3: text[3], + text4: text[4], + text5: text[5], + text6: text[6], + text7: text[7], + text8: text[8], + text9: text[9], + text10: text[10], + text11: text[11], + text12: text[12], + text13: text[13], + text14: text[14], + text15: text[15], + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { js: [], py: ['dalgona.Module_digital_oled(%1, %2, %3)'] }, + }, + + dalgona_rfid_init: { + 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: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'arduino_get_port_number', + params: ['10'], + }, + { + type: 'arduino_get_port_number', + params: ['9'], + }, + null, + ], + type: 'dalgona_rfid_init', + }, + paramsKeyMap: { + PORT1: 0, + PORT2: 1, + }, + class: 'RFID', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + var port1 = script.getNumberValue('PORT1', script); + var port2 = script.getNumberValue('PORT2', script); + + ss = port1; + + if (!script.isStart) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + script.isStart = true; + script.timeFlag = 1; + var fps = Entry.FPS || 60; + var timeValue = (60 / fps) * 50; + + Entry.hw.sendQueue['SET'][ss] = { + type: Entry.Dalgona.sensorTypes.RFIDINIT, + data: { + port1: port1, + port2: port2, + }, + time: new Date().getTime(), + }; + + setTimeout(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(); + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_is_rfid_tapped: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [], + events: {}, + def: { + params: [], + type: 'dalgona_is_rfid_tapped', + }, + paramsKeyMap: {}, + class: 'RFID', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.RFIDTAP] = { + port: ss, + time: new Date().getTime(), + }; + + var value = Entry.hw.portData.RFIDTAP || 0; + return value; + }, + syntax: { js: [], py: [] }, + }, + dalgona_get_rfid_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [], + events: {}, + def: { + type: 'dalgona_get_rfid_value', + }, + paramsKeyMap: {}, + class: 'RFID', + isNotFor: ['Dalgona'], + func: function(sprite, script) { + if (!Entry.hw.sendQueue['SET']) { + Entry.hw.sendQueue['SET'] = {}; + } + delete Entry.hw.sendQueue['SET'][ss]; + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.RFIDVALUE] = { + port: ss, + time: new Date().getTime(), + }; + + return Entry.hw.portData.RFIDVALUE || 0; + }, + syntax: { + js: [], + py: [{}], + }, + }, + dalgona_get_mlx: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['목표물', '0'], + ['주변', '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [], + type: 'dalgona_get_mlx', + }, + paramsKeyMap: { + MLX_SELECT: 0, + }, + class: 'sensor', + isNotFor: ['Dalgona'], + + func: function(sprite, script) { + var type = script.getNumberValue('MLX_SELECT') + + + if (!Entry.hw.sendQueue['GET']) { + Entry.hw.sendQueue['GET'] = {}; + } + + if (type == 0) { + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.MLXOBJ] = { + port: 0, + time: new Date().getTime(), + }; + return Entry.hw.portData.MLXOBJ || 0; + } else if (type == 1) { + Entry.hw.sendQueue['GET'][Entry.Dalgona.sensorTypes.MLXAMB] = { + port: 0, + time: new Date().getTime(), + }; + return Entry.hw.portData.MLXAMB || 0; + } + }, + syntax: { + js: [], + py: [{}], + }, + }, + }; +}; + +module.exports = Entry.Dalgona; diff --git a/src/playground/blocks/hardware/block_neo.js b/src/playground/blocks/hardware/block_neo.js index 0585051572..166112d515 100644 --- a/src/playground/blocks/hardware/block_neo.js +++ b/src/playground/blocks/hardware/block_neo.js @@ -337,7 +337,7 @@ Entry.Neo = new (class Neo { // led neo_led_title: 'LED', - neo_led_on: 'LED 켜기 %1 %2 %3', + neo_led_on: 'LED 켜기 %1 %2 %3 %4', neo_led_blink: 'LED 깜빡이기 %1 %2 %3 %4', neo_led_off: 'LED 끄기 %1 %2', @@ -731,21 +731,19 @@ Entry.Neo = new (class Neo { neo_buzzer_quarter_note: '4분 음표', neo_buzzer_8th_note: '8분 음표', - neo_lcd_image_1: '1', - neo_lcd_image_2: '2', - neo_lcd_image_3: '3', - neo_lcd_image_4: '4', - neo_lcd_image_5: '5', - neo_lcd_image_6: '6', - neo_lcd_image_7: '7', - neo_lcd_image_8: '8', - neo_lcd_image_9: '9', - neo_lcd_image_10: '10', - neo_lcd_image_11: '11', - neo_lcd_image_12: '12', - neo_lcd_image_13: '13', - neo_lcd_image_14: '14', - neo_lcd_image_15: '15', + neo_lcd_image_1: '화남', + neo_lcd_image_2: '어지러움', + neo_lcd_image_3: '똑똑함', + neo_lcd_image_4: '활기참', + neo_lcd_image_5: '뽀뽀', + neo_lcd_image_6: '사랑해', + neo_lcd_image_7: '윙크', + neo_lcd_image_8: '폭풍눈물', + neo_lcd_image_9: '졸림', + neo_lcd_image_10: '미소', + neo_lcd_image_11: '깜찍함', + neo_lcd_image_12: '의심', + neo_lcd_image_13: '못마땅', }, }, en: { @@ -797,7 +795,7 @@ Entry.Neo = new (class Neo { // led neo_led_title: 'LED', - neo_led_on: 'Turn on the LED %1 %2 %3', + neo_led_on: 'Turn on the LED %1 %2 %3 %4', neo_led_blink: 'Blink the LED %1 %2 %3 %4', neo_led_off: 'Turn off the LED %1 %2', @@ -805,7 +803,8 @@ Entry.Neo = new (class Neo { neo_color_led_title: 'Color LED', neo_color_led_on: 'Turn on the color LED %1 %2 %3 %4', neo_color_led_off: 'Turn off the color LED %1 %2', - neo_color_led_on_with_sensor: 'Turn on the color LED %2 with color sensor %1 %3', + neo_color_led_on_with_sensor: + 'Turn on the color LED %2 with color sensor %1 %3', // set output neo_set_output_title: 'Set output', @@ -886,14 +885,14 @@ Entry.Neo = new (class Neo { neo_duration_c: 'constantly', neo_duration_0: '0 second', neo_duration_1: '1 second', - neo_duration_2: '2 second', - neo_duration_3: '3 second', - neo_duration_4: '4 second', - neo_duration_5: '5 second', - neo_duration_6: '6 second', - neo_duration_7: '7 second', - neo_duration_8: '8 second', - neo_duration_9: '9 second', + neo_duration_2: '2 seconds', + neo_duration_3: '3 seconds', + neo_duration_4: '4 seconds', + neo_duration_5: '5 seconds', + neo_duration_6: '6 seconds', + neo_duration_7: '7 seconds', + neo_duration_8: '8 seconds', + neo_duration_9: '9 seconds', neo_compare_gt: '≥', neo_compare_g: '>', @@ -1088,10 +1087,10 @@ Entry.Neo = new (class Neo { neo_led_brightness_100: '100%', neo_led_blink_speed_1: '1 step', - neo_led_blink_speed_2: '2 step', - neo_led_blink_speed_3: '3 step', - neo_led_blink_speed_4: '4 step', - neo_led_blink_speed_5: '5 step', + neo_led_blink_speed_2: '2 steps', + neo_led_blink_speed_3: '3 steps', + neo_led_blink_speed_4: '4 steps', + neo_led_blink_speed_5: '5 steps', neo_set_output_value_0: '0', neo_set_output_value_5: '5', @@ -1191,21 +1190,19 @@ Entry.Neo = new (class Neo { neo_buzzer_quarter_note: 'a quarter note', neo_buzzer_8th_note: 'a eighth note', - neo_lcd_image_1: '1', - neo_lcd_image_2: '2', - neo_lcd_image_3: '3', - neo_lcd_image_4: '4', - neo_lcd_image_5: '5', - neo_lcd_image_6: '6', - neo_lcd_image_7: '7', - neo_lcd_image_8: '8', - neo_lcd_image_9: '9', - neo_lcd_image_10: '10', - neo_lcd_image_11: '11', - neo_lcd_image_12: '12', - neo_lcd_image_13: '13', - neo_lcd_image_14: '14', - neo_lcd_image_15: '15', + neo_lcd_image_1: 'angry', + neo_lcd_image_2: 'dizzy', + neo_lcd_image_3: 'smart', + neo_lcd_image_4: 'lively', + neo_lcd_image_5: 'kiss', + neo_lcd_image_6: 'lovely', + neo_lcd_image_7: 'wink', + neo_lcd_image_8: 'cry', + neo_lcd_image_9: 'sleepy', + neo_lcd_image_10: 'smiley', + neo_lcd_image_11: 'cute', + neo_lcd_image_12: 'doubt', + neo_lcd_image_13: 'bad', }, }, // }; @@ -1347,7 +1344,7 @@ Entry.Neo = new (class Neo { const speed = script.getStringField('SPEED', script); const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); - if (speed === 'IN1' || speed === 'IN2' || speed === 'IN3') { + if (speed.indexOf('IN') >= 0) { this.requestExtCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, speed]); } else { this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, speed]); @@ -1426,13 +1423,16 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const speedL = script.getNumberValue('SPEED_L', script); const speedR = script.getNumberValue('SPEED_R', script); const blockId = this.generateBlockId(); script.block_id = blockId; - this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE_BOTH, [speedL, speedR]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE_BOTH, [ + speedL, + speedR, + ]); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -1532,10 +1532,16 @@ Entry.Neo = new (class Neo { const speed = script.getStringField('SPEED', script); const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); - if (speed === 'IN1' || speed === 'IN2' || speed === 'IN3') { - this.requestExtCommand(blockId, NeoBlockType.ROBOT_MOVE, [direction, speed]); + if (speed.indexOf('IN') >= 0) { + this.requestExtCommand(blockId, NeoBlockType.ROBOT_MOVE, [ + direction, + speed, + ]); } else { - this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [direction, speed]); + this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [ + direction, + speed, + ]); } if (duration === 'c' || !Entry.parseNumber(duration)) { script.block_id = blockId; @@ -1603,10 +1609,20 @@ Entry.Neo = new (class Neo { class: 'neo_motor', isNotFor: ['neo'], func: (sprite, script) => { - const dc = script.getStringValue('DC', script); - const blockId = this.generateBlockId(); - this.requestCommand(blockId, NeoBlockType.MOTOR_STOP, [dc]); - return script.callReturn(); + if (!script.exec_phase) { + const dc = script.getStringValue('DC', script); + const blockId = this.generateBlockId(); + script.block_id = blockId; + script.exec_phase = ExecPhase.PENDING_RESPONSE; + this.requestCommand(blockId, NeoBlockType.MOTOR_STOP, [dc]); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { + if (!this.pendingResponseList[script.block_id]) { + delete script.block_id; + delete script.exec_phase; + return script.callReturn(); + } + } + return script; }, }, neo_robot_stop: { @@ -1632,9 +1648,19 @@ Entry.Neo = new (class Neo { class: 'neo_motor', isNotFor: ['neo'], func: (sprite, script) => { - const blockId = this.generateBlockId(); - this.requestCommand(blockId, NeoBlockType.ROBOT_STOP, []); - return script.callReturn(); + if (!script.exec_phase) { + const blockId = this.generateBlockId(); + script.block_id = blockId; + script.exec_phase = ExecPhase.PENDING_RESPONSE; + this.requestCommand(blockId, NeoBlockType.ROBOT_STOP, []); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { + if (!this.pendingResponseList[script.block_id]) { + delete script.block_id; + delete script.exec_phase; + return script.callReturn(); + } + } + return script; }, }, /** @@ -1865,22 +1891,36 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringField('OUTPUT', script); const angle = script.getStringField('ANGLE', script); const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; - if (angle === 'IN1' || angle === 'IN2' || angle === 'IN3') { - if (speed === 'IN1' || angle === 'IN2' || angle === 'IN3') { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE, [output, angle, speed]); + const isExt2 = angle.indexOf('IN') >= 0 && speed.indexOf('IN') >= 0; + if (isExt2) { + this.requestExt2Command(blockId, NeoBlockType.SERVO_ANGLE, [ + output, + angle, + speed, + ]); + } else { + const isExt1 = angle.indexOf('IN') >= 0 || speed.indexOf('IN') >= 0; + if (isExt1) { + this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE, [ + output, + angle, + speed, + ]); } else { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE, [output, angle, speed]); + this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [ + output, + angle, + speed, + ]); } - } else { - this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [output, angle, speed]); } - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -1971,8 +2011,12 @@ Entry.Neo = new (class Neo { const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; - this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [output, angle, speed]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [ + output, + angle, + speed, + ]); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -2133,14 +2177,28 @@ Entry.Neo = new (class Neo { const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; - if (angle === 'IN1' || angle === 'IN2' || angle === 'IN3') { - if (speed === 'IN1' || angle === 'IN2' || angle === 'IN3') { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [output, angle, speed]); + const isExt2 = angle.indexOf('IN') >= 0 && speed.indexOf('IN') >= 0; + if (isExt2) { + this.requestExt2Command(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [ + output, + angle, + speed, + ]); + } else { + const isExt1 = angle.indexOf('IN') >= 0 || speed.indexOf('IN') >= 0; + if (isExt1) { + this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [ + output, + angle, + speed, + ]); } else { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [output, angle, speed]); + this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [ + output, + angle, + speed, + ]); } - } else { - this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [output, angle, speed]); } } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { @@ -2226,18 +2284,26 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringField('OUTPUT', script); const direction = script.getStringField('DIRECTION', script); const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; if (speed.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ROTATE, [output, direction, speed]); + this.requestExtCommand(blockId, NeoBlockType.SERVO_ROTATE, [ + output, + direction, + speed, + ]); } else { - this.requestCommand(blockId, NeoBlockType.SERVO_ROTATE, [output, direction, speed]); + this.requestCommand(blockId, NeoBlockType.SERVO_ROTATE, [ + output, + direction, + speed, + ]); } - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -2285,12 +2351,12 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringValue('OUTPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; this.requestCommand(blockId, NeoBlockType.SERVO_STOP, [output]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -2387,8 +2453,10 @@ Entry.Neo = new (class Neo { const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); const duration = script.getStringValue('DURATION', script); - if (speed === 'IN1' || speed === 'IN2' || speed === 'IN3') { - this.requestExtCommand(blockId, NeoBlockType.LINE_TRACER_START, [speed]); + if (speed.indexOf('IN') >= 0) { + this.requestExtCommand(blockId, NeoBlockType.LINE_TRACER_START, [ + speed, + ]); } else { this.requestCommand(blockId, NeoBlockType.LINE_TRACER_START, [speed]); } @@ -2621,7 +2689,9 @@ Entry.Neo = new (class Neo { const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); if (speed.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [speed]); + this.requestExtCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [ + speed, + ]); } else { this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [speed]); } @@ -2717,17 +2787,24 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const sensor = script.getNumberField('SENSOR', script); const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; if (speed.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.AUTO_DRIVING_SENSOR_START, [sensor, speed]); + this.requestExtCommand( + blockId, + NeoBlockType.AUTO_DRIVING_SENSOR_START, + [sensor, speed] + ); } else { - this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_SENSOR_START, [sensor, speed]); + this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_SENSOR_START, [ + sensor, + speed, + ]); } - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -2761,11 +2838,11 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const blockId = this.generateBlockId(); script.block_id = blockId; this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_STOP, []); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -3191,7 +3268,10 @@ Entry.Neo = new (class Neo { const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); if (brightness.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.LED_ON, [output, brightness]); + this.requestExtCommand(blockId, NeoBlockType.LED_ON, [ + output, + brightness, + ]); } else { this.requestCommand(blockId, NeoBlockType.LED_ON, [output, brightness]); } @@ -3366,12 +3446,12 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringValue('OUTPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; this.requestCommand(blockId, NeoBlockType.LED_OFF, [output]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -3537,12 +3617,12 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringValue('OUTPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; this.requestCommand(blockId, NeoBlockType.COLOR_LED_OFF, [output]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -3603,13 +3683,16 @@ Entry.Neo = new (class Neo { isNotFor: ['neo'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringValue('OUTPUT', script); const input = script.getStringValue('INPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; - this.requestExtCommand(blockId, NeoBlockType.COLOR_LED_ON_SENSOR, [output, input]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + this.requestExtCommand(blockId, NeoBlockType.COLOR_LED_ON_SENSOR, [ + output, + input, + ]); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -3767,7 +3850,10 @@ Entry.Neo = new (class Neo { const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); if (value.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.SET_OUTPUT, [output, value]); + this.requestExtCommand(blockId, NeoBlockType.SET_OUTPUT, [ + output, + value, + ]); } else { this.requestCommand(blockId, NeoBlockType.SET_OUTPUT, [output, value]); } @@ -4270,7 +4356,8 @@ Entry.Neo = new (class Neo { const sensor3 = sensorData['in3Values'][0]; let lResult = false; if (lSymbol === '=') { - lResult = lValue === sensor1 && lValue === sensor2 && lValue === sensor3; + lResult = + lValue === sensor1 && lValue === sensor2 && lValue === sensor3; } else if (lSymbol === '>') { lResult = lValue > sensor1 && lValue > sensor2 && lValue > sensor3; } else if (lSymbol === '<') { @@ -4282,7 +4369,8 @@ Entry.Neo = new (class Neo { } let rResult = false; if (rSymbol === '=') { - rResult = sensor1 === rValue && sensor2 === rValue && sensor3 === rValue; + rResult = + sensor1 === rValue && sensor2 === rValue && sensor3 === rValue; } else if (rSymbol === '>') { rResult = sensor1 > rValue && sensor2 > rValue && sensor3 > rValue; } else if (rSymbol === '<') { @@ -4386,32 +4474,68 @@ Entry.Neo = new (class Neo { const input = script.getStringField('INPUT'); const sensorData = Entry.hw.portData['sensor']; const color = script.getNumberField('COLOR'); - let sensorValue = 0; - switch (input) { - case 'in1': - sensorValue = sensorData['in1Values'][0]; - break; - case 'in2': - sensorValue = sensorData['in2Values'][0]; - break; - case 'in3': - sensorValue = sensorData['in3Values'][0]; - break; - } + if (input === 'IN12') { + const sensor1 = sensorData['in1Values'][0]; + const sensor2 = sensorData['in2Values'][0]; + if (color === 1) { + return sensor1 === 0 && sensor2 === 0; + } else if (color === 2) { + return sensor1 === 40 && sensor2 === 40; + } else if (color === 3) { + return sensor1 === 80 && sensor2 === 80; + } else if (color === 4) { + return sensor1 === 120 && sensor2 === 120; + } else if (color === 5) { + return sensor1 === 160 && sensor2 === 160; + } else if (color === 6) { + return sensor1 === 200 && sensor2 === 200; + } + } else if (input === 'IN123') { + const sensor1 = sensorData['in1Values'][0]; + const sensor2 = sensorData['in2Values'][0]; + const sensor3 = sensorData['in3Values'][0]; + if (color === 1) { + return sensor1 === 0 && sensor2 === 0 && sensor3 === 0; + } else if (color === 2) { + return sensor1 === 40 && sensor2 === 40 && sensor3 === 40; + } else if (color === 3) { + return sensor1 === 80 && sensor2 === 80 && sensor3 === 80; + } else if (color === 4) { + return sensor1 === 120 && sensor2 === 120 && sensor3 === 120; + } else if (color === 5) { + return sensor1 === 160 && sensor2 === 160 && sensor3 === 160; + } else if (color === 6) { + return sensor1 === 200 && sensor2 === 200 && sensor3 === 200; + } + } else { + let sensorValue = 0; + switch (input) { + case 'IN1': + sensorValue = sensorData['in1Values'][0]; + break; + case 'IN2': + sensorValue = sensorData['in2Values'][0]; + break; + case 'IN3': + sensorValue = sensorData['in3Values'][0]; + break; + } - if (color === 1) { - return sensorValue === 0; - } else if (color === 2) { - return sensorValue === 0; - } else if (color === 3) { - return sensorValue === 0; - } else if (color === 4) { - return sensorValue === 0; - } else if (color === 5) { - return sensorValue === 0; - } else if (color === 6) { - return sensorValue === 0; + if (color === 1) { + return sensorValue === 0; + } else if (color === 2) { + return sensorValue === 40; + } else if (color === 3) { + return sensorValue === 80; + } else if (color === 4) { + return sensorValue === 120; + } else if (color === 5) { + return sensorValue === 160; + } else if (color === 6) { + return sensorValue === 200; + } } + return false; }, }, @@ -4758,8 +4882,6 @@ Entry.Neo = new (class Neo { [Lang.Blocks.neo_lcd_image_11, '11'], [Lang.Blocks.neo_lcd_image_12, '12'], [Lang.Blocks.neo_lcd_image_13, '13'], - [Lang.Blocks.neo_lcd_image_14, '14'], - [Lang.Blocks.neo_lcd_image_15, '15'], ], value: '1', fontSize: 11, @@ -4862,7 +4984,7 @@ Entry.Neo = new (class Neo { /** * ARG Blocks */ - neo_arg_motor_speed: { + neo_arg_duration: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, skeleton: 'basic_string_field', @@ -4871,29 +4993,19 @@ Entry.Neo = new (class Neo { { type: 'Dropdown', options: [ - [Lang.Blocks.neo_motor_speed_100, '100'], - [Lang.Blocks.neo_motor_speed_90, '90'], - [Lang.Blocks.neo_motor_speed_80, '80'], - [Lang.Blocks.neo_motor_speed_70, '70'], - [Lang.Blocks.neo_motor_speed_60, '60'], - [Lang.Blocks.neo_motor_speed_50, '50'], - [Lang.Blocks.neo_motor_speed_40, '40'], - [Lang.Blocks.neo_motor_speed_30, '30'], - [Lang.Blocks.neo_motor_speed_20, '20'], - [Lang.Blocks.neo_motor_speed_10, '10'], - [Lang.Blocks.neo_motor_speed_0, '0'], - [Lang.Blocks.neo_motor_speed_n10, '-10'], - [Lang.Blocks.neo_motor_speed_n20, '-20'], - [Lang.Blocks.neo_motor_speed_n30, '-30'], - [Lang.Blocks.neo_motor_speed_n40, '-40'], - [Lang.Blocks.neo_motor_speed_n50, '-50'], - [Lang.Blocks.neo_motor_speed_n60, '-60'], - [Lang.Blocks.neo_motor_speed_n70, '-70'], - [Lang.Blocks.neo_motor_speed_n80, '-80'], - [Lang.Blocks.neo_motor_speed_n90, '-90'], - [Lang.Blocks.neo_motor_speed_n100, '-100'], + [Lang.Blocks.neo_duration_c, 'c'], + [Lang.Blocks.neo_duration_0, '0'], + [Lang.Blocks.neo_duration_1, '1'], + [Lang.Blocks.neo_duration_2, '2'], + [Lang.Blocks.neo_duration_3, '3'], + [Lang.Blocks.neo_duration_4, '4'], + [Lang.Blocks.neo_duration_5, '5'], + [Lang.Blocks.neo_duration_6, '6'], + [Lang.Blocks.neo_duration_7, '7'], + [Lang.Blocks.neo_duration_8, '8'], + [Lang.Blocks.neo_duration_9, '9'], ], - value: '100', + value: 'c', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -4912,7 +5024,7 @@ Entry.Neo = new (class Neo { return script.getStringField('VALUE'); }, }, - neo_arg_duration: { + neo_arg_motor_speed: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, skeleton: 'basic_string_field', @@ -4921,19 +5033,29 @@ Entry.Neo = new (class Neo { { type: 'Dropdown', options: [ - [Lang.Blocks.neo_duration_c, 'c'], - [Lang.Blocks.neo_duration_0, '0'], - [Lang.Blocks.neo_duration_1, '1'], - [Lang.Blocks.neo_duration_2, '2'], - [Lang.Blocks.neo_duration_3, '3'], - [Lang.Blocks.neo_duration_4, '4'], - [Lang.Blocks.neo_duration_5, '5'], - [Lang.Blocks.neo_duration_6, '6'], - [Lang.Blocks.neo_duration_7, '7'], - [Lang.Blocks.neo_duration_8, '8'], - [Lang.Blocks.neo_duration_9, '9'], + [Lang.Blocks.neo_motor_speed_100, '100'], + [Lang.Blocks.neo_motor_speed_90, '90'], + [Lang.Blocks.neo_motor_speed_80, '80'], + [Lang.Blocks.neo_motor_speed_70, '70'], + [Lang.Blocks.neo_motor_speed_60, '60'], + [Lang.Blocks.neo_motor_speed_50, '50'], + [Lang.Blocks.neo_motor_speed_40, '40'], + [Lang.Blocks.neo_motor_speed_30, '30'], + [Lang.Blocks.neo_motor_speed_20, '20'], + [Lang.Blocks.neo_motor_speed_10, '10'], + [Lang.Blocks.neo_motor_speed_0, '0'], + [Lang.Blocks.neo_motor_speed_n10, '-10'], + [Lang.Blocks.neo_motor_speed_n20, '-20'], + [Lang.Blocks.neo_motor_speed_n30, '-30'], + [Lang.Blocks.neo_motor_speed_n40, '-40'], + [Lang.Blocks.neo_motor_speed_n50, '-50'], + [Lang.Blocks.neo_motor_speed_n60, '-60'], + [Lang.Blocks.neo_motor_speed_n70, '-70'], + [Lang.Blocks.neo_motor_speed_n80, '-80'], + [Lang.Blocks.neo_motor_speed_n90, '-90'], + [Lang.Blocks.neo_motor_speed_n100, '-100'], ], - value: 'c', + value: '100', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5389,6 +5511,23 @@ Entry.Neo = new (class Neo { Entry.hw.update(); } + requestExt2Command(blockId, type, params) { + console.log(blockId + ' requested'); + if (this.pendingResponseList[blockId]) { + delete this.pendingResponseList[blockId]; + } + this.pendingResponseList[blockId] = 'executed'; + const command = this.makeCommandExt2(blockId, type, params); + if (!command) return; + const pdu = this.makePdu(command); + this.executeList[blockId] = { + blockId, + pdu, + }; + Entry.hw.sendQueue.executeList = { ...this.executeList }; + Entry.hw.update(); + } + requestExtCommand(blockId, type, params) { console.log(blockId + ' requested'); if (this.pendingResponseList[blockId]) { @@ -5465,6 +5604,7 @@ Entry.Neo = new (class Neo { const output = params[0]; const angle = params[1]; const speed = params[2]; + body.push(this.getUnitId(output), ActorKind.SERVO, ServoCommand.ANGLE_WAIT); const data = Buffer.from([0, 0, 0, 0, 1, 0]); data.writeInt16LE(angle, 0); @@ -5622,22 +5762,35 @@ Entry.Neo = new (class Neo { if (type === NeoBlockType.MOTOR_MOVE) { const which = params[0]; const unitId = this.getUnitId(params[1]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.MOTOR + ); const data = Buffer.from([unitId, 0, which, 0, 0, 0]); body.push(...data); } else if (type === NeoBlockType.ROBOT_MOVE) { const robotCommand = params[0]; const unitId = this.getUnitId(params[1]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.ROBOT + ); const data = Buffer.from([unitId, 0, 0, 0]); data.writeInt16LE(robotCommand, 2); body.push(...data); } else if (type === NeoBlockType.SERVO_ANGLE || type === NeoBlockType.SERVO_ANGLE_WAIT) { const unitId = this.getUnitId(params[0]); - const inUnitId = this.getUnitId(params[1]); - const speed = params[2]; + let angle = params[1]; + let speed = params[2]; + if (angle.indexOf('IN') >= 0) angle = this.getUnitId(angle); body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.SERVO, ServoCommand.ANGLE); - const data = Buffer.from([inUnitId, 0, 0, 0, 1, 0]); + const data = Buffer.from([angle, 0, 0, 0, 1, 0]); data.writeInt16LE(speed, 2); body.push(...data); } else if (type === NeoBlockType.SERVO_ROTATE) { @@ -5654,13 +5807,25 @@ Entry.Neo = new (class Neo { type === NeoBlockType.AUTO_DETECT_WALL_START ) { const unitId = this.getUnitId(params[0]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.ROBOT + ); const data = Buffer.from([unitId, 0, 0x10, 0]); body.push(...data); } else if (type === NeoBlockType.AUTO_DRIVING_SENSOR_START) { const sensor = params[0]; const unitId = this.getUnitId(params[1]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.ROBOT + ); const data = Buffer.from([0, 0, 0, 0]); data.writeInt16LE(unitId, 0); data.writeInt16LE(sensor, 2); @@ -5679,7 +5844,13 @@ Entry.Neo = new (class Neo { body.push(...data); } else if (type === NeoBlockType.BUZZER_WITH_SENSOR) { const sensorUnitId = this.getUnitId(params[0]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.BUZZER); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.BUZZER + ); const data = Buffer.from([0, 0]); data.writeInt16LE(sensorUnitId, 0); body.push(...data); @@ -5693,6 +5864,18 @@ Entry.Neo = new (class Neo { return body; } + makeCommandExt2(blockId, type, params) { + const body = [FrameCode.BASIC]; + if (type === NeoBlockType.SERVO_ANGLE || type === NeoBlockType.SERVO_ANGLE_WAIT) { + const unitId = this.getUnitId(params[0]); + const angleInUnitId = this.getUnitId(params[1]); + const speedInUnitId = this.getUnitId(params[2]); + body.push(PduCode.EXTEND_2, blockId, unitId, ActorKind.SERVO, ServoCommand.ANGLE); + const data = Buffer.from([angleInUnitId, 0, speedInUnitId, 0, 1, 0]); + body.push(...data); + } + return body; + } /* 후면주차 실행 (pending response 하지 않고 바로 다음 단계로 넘어감 : phase 가 너무 많아서 간소화) 주석은 왼쪽 기준으로 오른쪽에서는 좌우만 바꿔준다. diff --git a/src/playground/blocks/hardware/block_neo_cannon.js b/src/playground/blocks/hardware/block_neo_cannon.js new file mode 100644 index 0000000000..d242d9f6b7 --- /dev/null +++ b/src/playground/blocks/hardware/block_neo_cannon.js @@ -0,0 +1,1485 @@ +'use strict'; + +Entry.NeoCannon = { + id: '41.2', + name: 'NeoCannon', + url: 'https://blog.naver.com/PostView.naver?blogId=neo3ds&logNo=223071491275', + imageName: 'neo_cannon.png', + title: { + ko: '네오캐논', + en: 'NeoCannon', + }, + PORT_MAP: { + mode: 1, + life: 0, + tone: 0, + motorState: 0, + led: 0, + shootState: 0, + d9: 0, + d10: 0, + angleState: 0, + }, + setZero() { + let portMap = Entry.NeoCannon.PORT_MAP; + let sq = Entry.hw.sendQueue; + for (let port in portMap) { + sq[port] = portMap[port]; + } + Entry.hw.update(); + }, + toneTable: { + '0': 0, + C: 1, + CS: 2, + D: 3, + DS: 4, + E: 5, + F: 6, + FS: 7, + G: 8, + GS: 9, + A: 10, + AS: 11, + 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], + }, + monitorTemplate: { + imgPath: 'hw/neo_cannon.png', + width: 400, + height: 400, + listPorts: { + vibe: { + name: '진동센서', + type: 'input', + pos: { x: 0, y: 0 }, + }, + }, + mode: 'both', + }, + BlockState: {}, +}; + +Entry.NeoCannon.setLanguage = function() { + return { + ko: { + template: { + neo_cannon_get_vibe_value: '진동 센서 감지됨', + neo_cannon_set_tone: '부저를 %1 %2 음으로 %3 초 연주하기 %4', + neo_cannon_motor_state: '%1 이동하기 %2', + neo_cannon_motor_state_secs: '%1 %2 초 이동하기 %3', + neo_cannon_motor_stop: '정지하기 %1', + neo_cannon_shoot_reload: '%1 초 장전하기 %2', + neo_cannon_shoot_catch: '장전 풀림 방지 %1', + neo_cannon_shoot_shooting: '발사하기 %1', + neo_cannon_angle_state: '각도 %1 %2 초 이동하기 %3', + neo_cannon_rgb_led_select_state: '%1 %2 %3', + neo_cannon_rgb_led_select_pwm: '%1 %2 세기로 켜기 %3', + 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', + }, + + Helper: { + neo_cannon_get_vibe_value: + '진동 감지 여부를 가져옵니다.
센서값 0: `감지 못함`, 1: `감지됨`', + neo_cannon_set_tone: + '부저를 통해 선택한 옥타브 음계를 통해 해당 시간만큼 소리를 냅니다.
(참고, 다음 블럭이 있을경우에 부저 연주시간이 끝난 후에 다음 블럭을 실행합니다.)', + neo_cannon_motor_state: '네오캐논을 앞, 왼쪽, 오른쪽, 뒤로 이동시킬 수 있습니다.', + neo_cannon_motor_state_secs: + '네오캐논을 앞, 왼쪽, 오른쪽, 뒤로 정해진 시간(초)만큼 이동시킬 수 있습니다.', + neo_cannon_motor_stop: '네오캐논 이동을 정지합니다.', + neo_cannon_shoot_reload: '장전 모터를 정해진 시간(초)만큼 장전합니다.', + neo_cannon_shoot_catch: + '장전 모터가 풀리는 것을 방지해주기 위해 일정 세기로 잡아줍니다.', + neo_cannon_shoot_shooting: '장전 모터를 풀어서 발사합니다.', + neo_cannon_angle_state: + '각도 모터를 제어하여 위, 아래로 정해진 시간(초)만큼 이동합니다.', + neo_cannon_rgb_led_select_state: + 'RGB LED 중 빨강, 초록, 파랑을 선택하여 ON/OFF를 제어합니다.
(주의, LED모드로 진행해주세요.)', + neo_cannon_rgb_led_select_pwm: + 'RGB LED 중 빨강, 초록, 파랑을 선택하여 세기값(0~255)을 주어 원하는 색상을 나타낼 수 있습니다.
(주의, LED모드로 진행해주세요.)', + neo_cannon_rgb_led_color_picker: + 'RGB LED를 색을 선택하여 원하는 색상을 나타낼 수 있습니다.
(주의, LED모드로 진행해주세요.)', + neo_cannon_rgb_led_pwm: + 'RGB LED에 세기값(0~255)을 주어 원하는 색상을 나타낼 수 있습니다.
(주의, LED모드로 진행해주세요.)', + neo_cannon_rgb_led_off: 'RGB LED를 끌 수 있습니다.', + }, + }, + en: { + template: { + neo_cannon_get_vibe_value: 'Detected Vibe Sensor', + neo_cannon_set_tone: 'Play tone note %1 octave %2 beat %3 %4', + neo_cannon_motor_state: 'Move %1 %2', + neo_cannon_motor_state_secs: 'Move %1 %2 secs %3', + neo_cannon_motor_stop: 'Move Stop %1', + neo_cannon_shoot_reload: 'Reload %1 secs %2', + neo_cannon_shoot_catch: 'Anti-shoot %1', + neo_cannon_shoot_shooting: 'Shoot %1', + neo_cannon_angle_state: 'Move Angle %1 %2 secs %3', + neo_cannon_rgb_led_select_state: '%1 color %2 %3', + neo_cannon_rgb_led_select_pwm: '%1 color %2 turn on pwm %3', + 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', + }, + }, + }; +}; + +Entry.NeoCannon.blockMenuBlocks = [ + 'neo_cannon_get_vibe_value', + 'neo_cannon_set_tone', + 'neo_cannon_motor_state', + 'neo_cannon_motor_state_secs', + 'neo_cannon_motor_stop', + 'neo_cannon_shoot_reload', + 'neo_cannon_shoot_catch', + 'neo_cannon_shoot_shooting', + 'neo_cannon_angle_state', + 'neo_cannon_rgb_led_select_state', + 'neo_cannon_rgb_led_select_pwm', + 'neo_cannon_rgb_led_color_picker', + 'neo_cannon_rgb_led_pwm', + 'neo_cannon_rgb_led_off', +]; + +Entry.NeoCannon.getBlocks = function() { + return { + neo_cannon_get_vibe_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [], + events: {}, + def: { + params: [], + type: 'neo_cannon_get_vibe_value', + }, + paramsKeyMap: {}, + class: 'NeoCannonGet', + isNotFor: ['NeoCannon'], + func(sprite, script) { + let port = 'vibe' + + return Entry.hw.portData[port] || 0; + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.getVibe()', + blockType: 'param', + textParams: [], + }, + ], + }, + }, + neo_cannon_tone_list: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.silent, '0'], + [Lang.Blocks.do_name, 'C'], + [Lang.Blocks.do_sharp_name, 'CS'], + [Lang.Blocks.re_name, 'D'], + [Lang.Blocks.re_sharp_name, 'DS'], + [Lang.Blocks.mi_name, 'E'], + [Lang.Blocks.fa_name, 'F'], + [Lang.Blocks.fa_sharp_name, 'FS'], + [Lang.Blocks.sol_name, 'G'], + [Lang.Blocks.sol_sharp_name, 'GS'], + [Lang.Blocks.la_name, 'A'], + [Lang.Blocks.la_sharp_name, 'AS'], + [Lang.Blocks.si_name, 'B'], + ], + value: 'C', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + NOTE: 0, + }, + func(sprite, script) { + return script.getField('NOTE'); + }, + syntax: { + js: [], + py: [ + { + syntax: '%1', + textParams: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.silent, '0'], + [Lang.Blocks.do_name, 'C'], + [Lang.Blocks.do_sharp_name, 'CS'], + [Lang.Blocks.re_name, 'D'], + [Lang.Blocks.re_sharp_name, 'DS'], + [Lang.Blocks.mi_name, 'E'], + [Lang.Blocks.fa_name, 'F'], + [Lang.Blocks.fa_sharp_name, 'FS'], + [Lang.Blocks.sol_name, 'G'], + [Lang.Blocks.sol_sharp_name, 'GS'], + [Lang.Blocks.la_name, 'A'], + [Lang.Blocks.la_sharp_name, 'AS'], + [Lang.Blocks.si_name, 'B'], + ], + value: 'C', + fontSize: 11, + converter: Entry.block.converters.returnStringValueUpperCase, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + keyOption: 'neo_cannon_tone_list', + }, + ], + }, + }, + neo_cannon_tone_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + { + type: 'neo_cannon_tone_list', + }, + ], + type: 'neo_cannon_tone_value', + }, + paramsKeyMap: { + NOTE: 0, + }, + func(sprite, script) { + return script.getNumberValue('NOTE'); + }, + syntax: { + js: [], + py: [ + { + syntax: '%1', + keyOption: 'neo_cannon_tone_value', + }, + ], + }, + }, + neo_cannon_octave_list: { + 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'], + ['6', '6'], + ], + value: '4', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + }, + paramsKeyMap: { + OCTAVE: 0, + }, + func(sprite, script) { + return script.getField('OCTAVE'); + }, + syntax: { + js: [], + py: [ + { + syntax: '%1', + keyOption: 'neo_cannon_octave_list', + }, + ], + }, + }, + neo_cannon_set_tone: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + 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: 'neo_cannon_tone_list', + }, + { + type: 'neo_cannon_octave_list', + }, + { + type: 'text', + params: ['1'], + }, + null, + ], + type: 'neo_cannon_set_tone', + }, + paramsKeyMap: { + NOTE: 0, + OCTAVE: 1, + DURATION: 2, + }, + class: 'NeoCannon', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + + if (!script.isStart) { + let note = script.getValue('NOTE', script); + if (!Entry.Utils.isNumber(note)) { + note = Entry.NeoCannon.toneTable[note]; + } + + if (note < 0) { + note = 0; + } else if (note > 12) { + note = 12; + } + + let duration = script.getNumberValue('DURATION', script); + + if (duration < 0) { + duration = 0; + } + + if (!sq.tone) { + sq.tone = {}; + } + + if (duration === 0) { + sq.tone = { + type: Entry.NeoCannon.PORT_MAP.tone, + data: 0, + time: new Date().getTime(), + }; + return script.callReturn(); + } + + let octave = script.getNumberValue('OCTAVE', script) - 1; + if (octave < 0) { + octave = 0; + } else if (octave > 5) { + octave = 5; + } + + let value = 0; + + if (note != 0) { + value = Entry.NeoCannon.toneMap[note][octave]; + } + + duration = duration * 1000; + script.isStart = true; + script.timeFlag = 1; + + sq.tone = { + type: Entry.NeoCannon.PORT_MAP.tone, + data: { + value, + duration, + }, + time: new Date().getTime(), + }; + + setTimeout(() => { + script.timeFlag = 0; + }, duration + 32); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + sq.tone = { + type: Entry.NeoCannon.PORT_MAP.tone, + data: 0, + time: new Date().getTime(), + }; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.tone(%1, %2, %3)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_motor_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['앞으로', 1], + ['왼쪽으로', 2], + ['오른쪽으로', 3], + ['뒤로', 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: [null], + type: 'neo_cannon_motor_state', + }, + paramsKeyMap: { + STATE: 0, + }, + class: 'NeoCannon', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + let state = script.getNumberValue('STATE', script); + + if (!sq.motorState) { + sq.motorState = {}; + } + + sq.motorState = state; + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.motorState(%1)', + textParams: [ + { + type: 'Dropdown', + options: [ + ['앞으로', '1'], + ['왼쪽으로', '2'], + ['오른쪽으로', '3'], + ['뒤로', '4'], + ], + value: '1', + fontSize: 11, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + converter: Entry.block.converters.returnStringValueUpperCase, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + }, + ], + }, + ], + }, + }, + neo_cannon_motor_state_secs: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['앞으로', 1], + ['왼쪽으로', 2], + ['오른쪽으로', 3], + ['뒤로', 4], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'text', + params: ['1'], + }, + ], + type: 'neo_cannon_motor_state_secs', + }, + paramsKeyMap: { + STATE: 0, + DURATION: 1, + }, + class: 'NeoCannon', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + + if (!script.isStart) { + let state = script.getNumberValue('STATE', script); + let duration = script.getNumberValue('DURATION', script); + + if (duration <= 0) { + duration = 0; + state = 0; + } + + duration = duration * 1000; + script.isStart = true; + script.timeFlag = 1; + + if (!sq.motorState) { + sq.motorState = {}; + } + + sq.motorState = state; + + setTimeout(() => { + script.timeFlag = 0; + }, duration + 32); + + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + sq.motorState = 0; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.motorStateSecs(%1, %2)', + textParams: [ + { + type: 'Dropdown', + options: [ + ['앞으로', '1'], + ['왼쪽으로', '2'], + ['오른쪽으로', '3'], + ['뒤로', '4'], + ], + value: '1', + fontSize: 11, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + converter: Entry.block.converters.returnStringValueUpperCase, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_motor_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: 'neo_cannon_motor_stop', + }, + paramsKeyMap: {}, + class: 'NeoCannon', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + if (!sq.motorState) { + sq.motorState = {}; + } + sq.motorState = 0; + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.motorStop()', + textParams: [], + }, + ], + }, + }, + neo_cannon_shoot_reload: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'text', + params: ['1'], + }, + ], + type: 'neo_cannon_shoot_reload', + }, + paramsKeyMap: { + DURATION: 0, + }, + class: 'NeoCannon', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + + if (!script.isStart) { + let duration = script.getNumberValue('DURATION', script); + + if (duration <= 0) { + duration = 0; + state = 0; + } + + duration = duration * 1000; + script.isStart = true; + script.timeFlag = 1; + + if (!sq.shootState) { + sq.shootState = {}; + } + if (!sq.d9) { + sq.d9 = {}; + } + if (!sq.d10) { + sq.d10 = {}; + } + + sq.shootState = 1; + sq.d9 = 200; + sq.d10 = 0; + + setTimeout(() => { + script.timeFlag = 0; + }, duration + 32); + + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + sq.shootState = 0; + sq.d9 = 0; + sq.d10 = 0; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.reload(%1)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_shoot_catch: { + 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_shoot_catch', + }, + paramsKeyMap: {}, + class: 'NeoCannon', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + if (!sq.shootState) { + sq.shootState = {}; + } + if (!sq.d9) { + sq.d9 = {}; + } + if (!sq.d10) { + sq.d10 = {}; + } + sq.shootState = 3; + sq.d9 = 80; + sq.d10 = 0; + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.shootCatch()', + textParams: [], + }, + ], + }, + }, + neo_cannon_shoot_shooting: { + 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_shoot_shooting', + }, + paramsKeyMap: {}, + class: 'NeoCannon', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + + if (!script.isStart) { + let duration = 40; + script.isStart = true; + script.timeFlag = 1; + + if (!sq.shootState) { + sq.shootState = {}; + } + if (!sq.d9) { + sq.d9 = {}; + } + if (!sq.d10) { + sq.d10 = {}; + } + + sq.shootState = 2; + sq.d9 = 0; + sq.d10 = 200; + + setTimeout(() => { + script.timeFlag = 0; + }, duration + 32); + + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + sq.shootState = 0; + sq.d9 = 0; + sq.d10 = 0; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.shooting()', + textParams: [], + }, + ], + }, + }, + neo_cannon_angle_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['UP', '1'], + ['DOWN', '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'text', + params: ['0.1'], + }, + ], + type: 'neo_cannon_angle_state', + }, + paramsKeyMap: { + STATE: 0, + DURATION: 1, + }, + class: 'NeoCannon', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + if (!script.isStart) { + let state = script.getNumberValue('STATE', script); + let duration = script.getNumberValue('DURATION', script); + + if (duration <= 0) { + duration = 0; + state = 0; + } + + duration = duration * 1000; + script.isStart = true; + script.timeFlag = 1; + + if (!sq.angleState) { + sq.angleState = {}; + } + + sq.angleState = state; + + setTimeout(() => { + script.timeFlag = 0; + }, duration + 32); + + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + sq.angleState = 0; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.angleState(%1, %2)', + textParams: [ + { + type: 'Dropdown', + options: [ + ['UP', '1'], + ['DOWN', '2'], + ], + value: '1', + fontSize: 11, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + converter: Entry.block.converters.returnStringValueLowerCase, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_rgb_led_select_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['BLUE', '0'], + ['RED', '1'], + ['GREEN', '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + ['OFF', '0'], + ['ON', '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: [null, null], + type: 'neo_cannon_rgb_led_select_state', + }, + paramsKeyMap: { + COLOR: 0, + STATE: 1, + }, + class: 'NeoCannonRGB', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + let color = script.getNumberValue('COLOR', script); + let state = script.getNumberValue('STATE', script); + + let power = state == 1 ? 255 : 0; + + if (color == 0) { + if (!sq.led) { + sq.led = {}; + } + sq.led = power; + } else if (color == 1) { + if (!sq.shootState) { + sq.shootState = {}; + } + if (!sq.d9) { + sq.d9 = {}; + } + sq.shootState = 4; + sq.d9 = power; + } else if (color == 2) { + if (!sq.shootState) { + sq.shootState = {}; + } + if (!sq.d10) { + sq.d10 = {}; + } + sq.shootState = 4; + sq.d10 = power; + } + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.rgbLedSelectState(%1, %2)', + textParams: [ + { + type: 'Dropdown', + options: [ + ['BLUE', '0'], + ['RED', '1'], + ['GREEN', '2'], + ], + value: '0', + fontSize: 11, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + converter: Entry.block.converters.returnStringValueUpperCase, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + ['ON', '1'], + ['OFF', '0'], + ], + value: '1', + fontSize: 11, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + converter: Entry.block.converters.returnStringValueUpperCase, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + }, + ], + }, + ], + }, + }, + neo_cannon_rgb_led_select_pwm: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['BLUE', '0'], + ['RED', '1'], + ['GREEN', '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'neo_cannon_rgb_led_select_pwm', + }, + paramsKeyMap: { + COLOR: 0, + POWER: 1, + }, + class: 'NeoCannonRGB', + isNotFor: ['NeoCannon'], + func(sprite, script) { + const sq = Entry.hw.sendQueue; + let color = script.getNumberValue('COLOR', script); + let power = script.getNumberValue('POWER', script); + + if (color == 0) { + if (!sq.led) { + sq.led = {}; + } + sq.led = power; + } else if (color == 1) { + if (!sq.shootState) { + sq.shootState = {}; + } + if (!sq.d9) { + sq.d9 = {}; + } + sq.shootState = 4; + sq.d9 = power; + } else if (color == 2) { + if (!sq.shootState) { + sq.shootState = {}; + } + if (!sq.d10) { + sq.d10 = {}; + } + sq.shootState = 4; + sq.d10 = power; + } + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.rgbLedSelectPwm(%1, %2)', + textParams: [ + { + type: 'Dropdown', + options: [ + ['BLUE', '0'], + ['RED', '1'], + ['GREEN', '2'], + ], + value: '0', + fontSize: 11, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + converter: Entry.block.converters.returnStringValueUpperCase, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_rgb_led_color_picker: { + 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: ["#0000FF", null], + type: 'neo_cannon_rgb_led_color_picker', + }, + paramsKeyMap: { + COLOR: 0, + }, + class: 'NeoCannonRGB', + isNotFor: ['NeoCannon'], + func: function(sprite, script) { + const sq = Entry.hw.sendQueue; + + let value = script.getStringField('COLOR'); + + if (!sq.shootState) { + sq.shootState = {}; + } + + if (!sq.led) { + sq.led = {}; + } + if (!sq.d9) { + sq.d9 = {}; + } + if (!sq.d10) { + sq.d10 = {}; + } + + 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.shootState = 4; + sq.led = blue; + sq.d9 = red; + sq.d10 = green; + + Entry.hw.update(); + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.rgbLedColorPicker(%1)', + textParams: [ + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neo_cannon_rgb_led_pwm: { + 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: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + null, + ], + type: 'neo_cannon_rgb_led_pwm', + }, + paramsKeyMap: { + RED: 0, + GREEN: 1, + BLUE: 2, + }, + class: 'NeoCannonRGB', + 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.shootState) { + sq.shootState = {}; + } + + if (!sq.led) { + sq.led = {}; + } + if (!sq.d9) { + sq.d9 = {}; + } + if (!sq.d10) { + sq.d10 = {}; + } + + sq.shootState = 4; + sq.led = blue & 255; + sq.d9 = red & 255; + sq.d10 = green & 255; + + Entry.hw.update(); + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.rgbLedPwm(%1, %2, %3)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_rgb_led_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_rgb_led_off', + }, + paramsKeyMap: {}, + class: 'NeoCannonRGB', + isNotFor: ['NeoCannon'], + func: function(sprite, script) { + const sq = Entry.hw.sendQueue; + + if (!sq.shootState) { + sq.shootState = {}; + } + + if (!sq.led) { + sq.led = {}; + } + if (!sq.d9) { + sq.d9 = {}; + } + if (!sq.d10) { + sq.d10 = {}; + } + + sq.shootState = 4; + sq.led = 0; + sq.d9 = 0; + sq.d10 = 0; + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.rgbLedOff()', + textParams: [], + }, + ], + }, + }, + }; +}; + +module.exports = Entry.NeoCannon; diff --git a/src/playground/blocks/hardware/block_neobot_purple.js b/src/playground/blocks/hardware/block_neobot_purple.js index 6d7a21cd5a..e9b7b16bd0 100644 --- a/src/playground/blocks/hardware/block_neobot_purple.js +++ b/src/playground/blocks/hardware/block_neobot_purple.js @@ -47,18 +47,16 @@ Entry.NeobotPurple.setLanguage = function() { ko: { template: { // sensor + neobot_purple_sensor_title: '센서', neobot_purple_sensor_value: '%1', neobot_purple_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환', - - // decision neobot_purple_decision_sensor_is_over: '%1 %2 %3', neobot_purple_decision_equal_with_sensor: '%1 컬러가 %2', neobot_purple_decision_sensor_angle: '%1 각도 %2 %3', - - // remote neobot_purple_remote_button: '리모컨 버튼 %1 을 누름', // LED + neobot_purple_led_title: 'LED', neobot_purple_arg_led_duration: '%1', neobot_purple_led_on: 'LED 켜기 %1 %2 %3 %4', neobot_purple_output_led_off: '%1 LED 끄기 %2', @@ -66,9 +64,11 @@ Entry.NeobotPurple.setLanguage = function() { neobot_purple_color_led_on: '%1 컬러LED 켜기 R %2 G %3 B %4 %5', // output + neobot_purple_output_title: '출력', neobot_purple_set_output: '%1 에 %2 값 출력하기 %3', // motor + neobot_purple_motor_title: '회전모터', neobot_purple_robot: '로봇 %1 %2', neobot_purple_motor_start: '모터 회전하기 %1 %2 %3 %4 %5', neobot_purple_motor_stop: '%1 모터 멈추기 %2', @@ -76,11 +76,13 @@ Entry.NeobotPurple.setLanguage = function() { neobot_purple_arg_motor_duration: '%1', // melody + neobot_purple_buzzer_title: '버저', neobot_purple_play_note_for: '버저 울리기 옥타브: %2 음: %1 길이: %3 %4', neobot_purple_melody_play_with_sensor: '%1 센서로 버저 울리기 %2', neobot_purple_melody_stop: '버저 멈추기 %1', // servo + neobot_purple_servo_title: '서보모터', get_servo_degree: '%1', neobot_purple_servo_init: '%1 서보모터 리셋 %2', neobot_purple_servo_rotate: '서보모터 회전하기 %1 %2 %3 %4', @@ -220,28 +222,30 @@ Entry.NeobotPurple.setLanguage = function() { // en.js에 작성하던 내용 template: { // sensor + neobot_purple_sensor_title: 'Sensor', neobot_purple_sensor_value: '%1', - neobot_purple_sensor_convert_scale: '%1 \'s changed value range: %2 ~ %3 conversion: %4 ~ %5', - - // decision + neobot_purple_sensor_convert_scale: + "%1 's changed value range: %2 ~ %3 conversion: %4 ~ %5", neobot_purple_decision_sensor_is_over: '%1 %2 %3', - neobot_purple_decision_equal_with_sensor: '%1 \'s color is %2', + neobot_purple_decision_equal_with_sensor: "%1 's color is %2", neobot_purple_decision_sensor_angle: '%1 angle %2 %3', - - // remote neobot_purple_remote_button: 'pressing button %1 of remote controller', // LED + neobot_purple_led_title: 'LED', neobot_purple_arg_led_duration: '%1', neobot_purple_led_on: 'Turn on the LED %1 %2 %3 %4', neobot_purple_output_led_off: 'Turn off the %1 LED %2', - neobot_purple_led_brightness_with_sensor: 'Control %2 LED\'s brightness with %1 sensor %3', + neobot_purple_led_brightness_with_sensor: + "Control %2 LED's brightness with %1 sensor %3", neobot_purple_color_led_on: 'Turn on the %1 color LED R %2 G %3 B %4 %5', // output + neobot_purple_output_title: 'Set output', neobot_purple_set_output: 'Output %2 value to %1 port %3', // motor + neobot_purple_motor_title: 'Motor', neobot_purple_robot: 'Robot %1 %2', neobot_purple_motor_start: 'Motor operation %1 %2 %3 %4 %5', neobot_purple_motor_stop: 'Stop the %1 motor(s) %2', @@ -249,11 +253,13 @@ Entry.NeobotPurple.setLanguage = function() { neobot_purple_arg_motor_duration: '%1', // melody + neobot_purple_buzzer_title: 'Buzzer', neobot_purple_play_note_for: 'Buzzer octave: %1 scale: %2 note: %3 %4', neobot_purple_melody_play_with_sensor: 'Buzzer rings by %1 sensor value %2', neobot_purple_melody_stop: 'Stop the buzzer %1', // servo + neobot_purple_servo_title: 'Servo motor', neobot_purple_servo_init: 'Reset the %1 servo motor %2', neobot_purple_servo_rotate: 'Rotate the servo motor %1 %2 %3 %4', neobot_purple_servo_stop: 'Stop the %1 servo motor %2', @@ -393,41 +399,43 @@ Entry.NeobotPurple.setLanguage = function() { Entry.NeobotPurple.blockMenuBlocks = [ // sensor + 'neobot_purple_sensor_title', 'neobot_purple_sensor_value', 'neobot_purple_sensor_convert_scale', - - // decision 'neobot_purple_decision_sensor_is_over', 'neobot_purple_decision_equal_with_sensor', 'neobot_purple_decision_sensor_angle', - - // remote 'neobot_purple_remote_button', // led + 'neobot_purple_led_title', 'neobot_purple_led_on', 'neobot_purple_led_brightness_with_sensor', 'neobot_purple_color_led_on', 'neobot_purple_output_led_off', // output + 'neobot_purple_output_title', 'neobot_purple_set_output', // motor + 'neobot_purple_motor_title', 'neobot_purple_robot', 'neobot_purple_motor_start', 'neobot_purple_motor_stop', - // melody - 'neobot_purple_play_note_for', - 'neobot_purple_melody_play_with_sensor', - 'neobot_purple_melody_stop', - // servo + 'neobot_purple_servo_title', 'neobot_purple_servo_init', 'neobot_purple_servo_rotate', 'neobot_purple_servo_stop', 'neobot_purple_servo_change_degree', + + // melody + 'neobot_purple_buzzer_title', + 'neobot_purple_play_note_for', + 'neobot_purple_melody_play_with_sensor', + 'neobot_purple_melody_stop', ]; Entry.NeobotPurple.getBlocks = function() { @@ -435,6 +443,30 @@ Entry.NeobotPurple.getBlocks = function() { /************************* * class neobot_purple_sensor *************************/ + neobot_purple_sensor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_sensor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_sensor_title', + }, + class: 'neobot_purple_sensor', + isNotFor: ['neobot_purple'], + events: {}, + }, neobot_purple_sensor_value: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -571,9 +603,6 @@ Entry.NeobotPurple.getBlocks = function() { }, }, - /************************* - * class neobot_purple_decision - *************************/ neobot_purple_decision_sensor_is_over: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -623,7 +652,7 @@ Entry.NeobotPurple.getBlocks = function() { SYMBOL: 1, VALUE: 2, }, - class: 'neobot_purple_decision', + class: 'neobot_purple_sensor', isNotFor: ['neobot_purple'], func: function(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -710,7 +739,7 @@ Entry.NeobotPurple.getBlocks = function() { SENSOR: 0, COLOR: 1, }, - class: 'neobot_purple_decision', + class: 'neobot_purple_sensor', isNotFor: ['neobot_purple'], func: function(sprite, script) { var sensorTemp = script.getStringField('SENSOR'); @@ -809,7 +838,7 @@ Entry.NeobotPurple.getBlocks = function() { SYMBOL: 1, VALUE: 2, }, - class: 'neobot_purple_decision', + class: 'neobot_purple_sensor', isNotFor: ['neobot_purple'], func: function(sprite, script) { var sensorTemp = script.getStringField('SENSOR'); @@ -837,9 +866,6 @@ Entry.NeobotPurple.getBlocks = function() { }, }, - /************************* - * class neobot_purple_remote - *************************/ neobot_purple_remote_button: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -873,7 +899,7 @@ Entry.NeobotPurple.getBlocks = function() { paramsKeyMap: { KEY: 0, }, - class: 'neobot_purple_remote', + class: 'neobot_purple_sensor', isNotFor: ['neobot_purple'], func: function(sprite, script) { var key = script.getNumberField('KEY'); @@ -889,6 +915,30 @@ Entry.NeobotPurple.getBlocks = function() { /************************* * class neobot_purple_led *************************/ + neobot_purple_led_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_led_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_led_title', + }, + class: 'neobot_purple_led', + isNotFor: ['neobot_purple'], + events: {}, + }, neobot_purple_led_on: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -972,7 +1022,11 @@ Entry.NeobotPurple.getBlocks = function() { Entry.console.print('==========================', 'speak'); } - if ((duration != '계속' && duration != 'constantly') && Entry.parseNumber(duration) <= 0) { + if ( + duration != '계속' && + duration != 'constantly' && + Entry.parseNumber(duration) <= 0 + ) { return script.callReturn(); } @@ -999,7 +1053,8 @@ Entry.NeobotPurple.getBlocks = function() { } else { Entry.hw.sendQueue[port] = 0; } - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_led_on : 0', 'speak'); + if (Entry.NeobotPurple.log_to_console) + Entry.console.print('neobot_purple_led_on : 0', 'speak'); script.timeFlag = 0; }, durationValue * 1000); return script; @@ -1125,10 +1180,13 @@ Entry.NeobotPurple.getBlocks = function() { // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함. value = Math.max(value, 0); value = Math.min(value, 100); - value = Math.ceil(value / 100 * 255); + value = Math.ceil((value / 100) * 255); if (Entry.NeobotPurple.log_to_console) { - Entry.console.print('=== neobot_purple_led_brightness_with_sensor ===', 'speak'); + Entry.console.print( + '=== neobot_purple_led_brightness_with_sensor ===', + 'speak' + ); Entry.console.print('out port : ' + outPort, 'speak'); Entry.console.print('in port : ' + inPort, 'speak'); Entry.console.print('sensor value : ' + Entry.hw.portData[inPort], 'speak'); @@ -1259,38 +1317,67 @@ Entry.NeobotPurple.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = valRed; if (out2) Entry.hw.sendQueue['OUT2'] = valRed; if (out3) Entry.hw.sendQueue['OUT3'] = valRed; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_color_led_on : ' + valRed, 'speak'); - setTimeout(function() { // set red + if (Entry.NeobotPurple.log_to_console) + Entry.console.print('neobot_purple_color_led_on : ' + valRed, 'speak'); + setTimeout(function() { + // set red if (out1) Entry.hw.sendQueue['OUT1'] = red; if (out2) Entry.hw.sendQueue['OUT2'] = red; if (out3) Entry.hw.sendQueue['OUT3'] = red; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_color_led_on : ' + red, 'speak'); - setTimeout(function() { // choose green + if (Entry.NeobotPurple.log_to_console) + Entry.console.print('neobot_purple_color_led_on : ' + red, 'speak'); + setTimeout(function() { + // choose green if (out1) Entry.hw.sendQueue['OUT1'] = valGreen; if (out2) Entry.hw.sendQueue['OUT2'] = valGreen; if (out3) Entry.hw.sendQueue['OUT3'] = valGreen; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_color_led_on : ' + valGreen, 'speak'); - setTimeout(function() { // set green + if (Entry.NeobotPurple.log_to_console) + Entry.console.print( + 'neobot_purple_color_led_on : ' + valGreen, + 'speak' + ); + setTimeout(function() { + // set green if (out1) Entry.hw.sendQueue['OUT1'] = green; if (out2) Entry.hw.sendQueue['OUT2'] = green; if (out3) Entry.hw.sendQueue['OUT3'] = green; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_color_led_on : ' + green, 'speak'); - setTimeout(function() { // choose blue + if (Entry.NeobotPurple.log_to_console) + Entry.console.print( + 'neobot_purple_color_led_on : ' + green, + 'speak' + ); + setTimeout(function() { + // choose blue if (out1) Entry.hw.sendQueue['OUT1'] = valBlue; if (out2) Entry.hw.sendQueue['OUT2'] = valBlue; if (out3) Entry.hw.sendQueue['OUT3'] = valBlue; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_color_led_on : ' + valBlue, 'speak'); - setTimeout(function() { // set blue + if (Entry.NeobotPurple.log_to_console) + Entry.console.print( + 'neobot_purple_color_led_on : ' + valBlue, + 'speak' + ); + setTimeout(function() { + // set blue if (out1) Entry.hw.sendQueue['OUT1'] = blue; if (out2) Entry.hw.sendQueue['OUT2'] = blue; if (out3) Entry.hw.sendQueue['OUT3'] = blue; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_color_led_on : ' + blue, 'speak'); - setTimeout(function() { // accept + if (Entry.NeobotPurple.log_to_console) + Entry.console.print( + 'neobot_purple_color_led_on : ' + blue, + 'speak' + ); + setTimeout(function() { + // accept if (out1) Entry.hw.sendQueue['OUT1'] = valAccept; if (out2) Entry.hw.sendQueue['OUT2'] = valAccept; if (out3) Entry.hw.sendQueue['OUT3'] = valAccept; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_color_led_on : ' + valAccept, 'speak'); - setTimeout(function() { // final delay + if (Entry.NeobotPurple.log_to_console) + Entry.console.print( + 'neobot_purple_color_led_on : ' + valAccept, + 'speak' + ); + setTimeout(function() { + // final delay script.timeFlag = 0; }, 200); }, 200); @@ -1314,6 +1401,30 @@ Entry.NeobotPurple.getBlocks = function() { /************************* * class neobot_purple_output *************************/ + neobot_purple_output_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_output_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_output_title', + }, + class: 'neobot_purple_output', + isNotFor: ['neobot_purple'], + events: {}, + }, neobot_purple_set_output: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1391,6 +1502,30 @@ Entry.NeobotPurple.getBlocks = function() { /************************* * class neobot_purple_motor *************************/ + neobot_purple_motor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_motor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_motor_title', + }, + class: 'neobot_purple_motor', + isNotFor: ['neobot_purple'], + events: {}, + }, neobot_purple_robot: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1419,10 +1554,7 @@ Entry.NeobotPurple.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_purple_robot', }, paramsKeyMap: { @@ -1550,7 +1682,11 @@ Entry.NeobotPurple.getBlocks = function() { const speed = script.getStringValue('SPEED', script); const duration = script.getStringValue('DURATION', script); - if (duration != '계속' && duration != 'constantly' && Entry.parseNumber(duration) <= 0) { + if ( + duration != '계속' && + duration != 'constantly' && + Entry.parseNumber(duration) <= 0 + ) { return script.callReturn(); } @@ -1590,7 +1726,7 @@ Entry.NeobotPurple.getBlocks = function() { } speedValue = Math.max(speedValue, 0); speedValue = Math.min(speedValue, 100); - speedValue = Math.ceil(speedValue / 100 * 15); + speedValue = Math.ceil((speedValue / 100) * 15); const leftOutValue = leftDirectionValue + speedValue; const rightOutValue = rightDirectionValue + speedValue; @@ -1601,8 +1737,14 @@ Entry.NeobotPurple.getBlocks = function() { Entry.console.print('direction : ' + direction, 'speak'); Entry.console.print('speed : ' + speed, 'speak'); Entry.console.print('duration : ' + duration, 'speak'); - Entry.console.print('left direction value : ' + leftDirectionValue, 'speak'); - Entry.console.print('right direction value : ' + rightDirectionValue, 'speak'); + Entry.console.print( + 'left direction value : ' + leftDirectionValue, + 'speak' + ); + Entry.console.print( + 'right direction value : ' + rightDirectionValue, + 'speak' + ); Entry.console.print('speed value : ' + speedValue, 'speak'); Entry.console.print('left output value : ' + leftOutValue, 'speak'); Entry.console.print('right output value : ' + rightOutValue, 'speak'); @@ -1626,7 +1768,8 @@ Entry.NeobotPurple.getBlocks = function() { setTimeout(function() { Entry.hw.sendQueue['DCL'] = 0; Entry.hw.sendQueue['DCR'] = 0; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_motor_start : 0', 'speak'); + if (Entry.NeobotPurple.log_to_console) + Entry.console.print('neobot_purple_motor_start : 0', 'speak'); script.timeFlag = 0; }, durationValue * 1000); return script; @@ -1667,9 +1810,7 @@ Entry.NeobotPurple.getBlocks = function() { ], events: {}, def: { - params: [ - null, null, - ], + params: [null, null], type: 'neobot_purple_motor_stop', }, paramsKeyMap: { @@ -1701,6 +1842,30 @@ Entry.NeobotPurple.getBlocks = function() { /************************* * class neobot_purple_melody *************************/ + neobot_purple_buzzer_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_buzzer_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_buzzer_title', + }, + class: 'neobot_purple_melody', + isNotFor: ['neobot_purple'], + events: {}, + }, neobot_purple_play_note_for: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1799,9 +1964,10 @@ Entry.NeobotPurple.getBlocks = function() { Entry.hw.sendQueue['SND'] = value; setTimeout(function() { Entry.hw.sendQueue['SND'] = 0; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_play_note_for : 0', 'speak'); + if (Entry.NeobotPurple.log_to_console) + Entry.console.print('neobot_purple_play_note_for : 0', 'speak'); script.timeFlag = 0; - }, 1 / duration * 2000); + }, (1 / duration) * 2000); return script; } else if (script.timeFlag == 1) { return script; @@ -1840,9 +2006,7 @@ Entry.NeobotPurple.getBlocks = function() { ], events: {}, def: { - params: [ - null, null, - ], + params: [null, null], type: 'neobot_purple_melody_play_with_sensor', }, paramsKeyMap: { @@ -1857,7 +2021,7 @@ Entry.NeobotPurple.getBlocks = function() { // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함. value = Math.max(value, 0); value = Math.min(value, 100); - value = Math.ceil(value / 100 * 65); + value = Math.ceil((value / 100) * 65); if (Entry.NeobotPurple.log_to_console) { Entry.console.print('=== neobot_purple_melody_play_with_sensor ===', 'speak'); @@ -1885,9 +2049,7 @@ Entry.NeobotPurple.getBlocks = function() { ], events: {}, def: { - params: [ - null, - ], + params: [null], type: 'neobot_purple_melody_stop', }, paramsKeyMap: {}, @@ -1908,6 +2070,30 @@ Entry.NeobotPurple.getBlocks = function() { /************************* * class neobot_purple_servo *************************/ + neobot_purple_servo_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_servo_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_servo_title', + }, + class: 'neobot_purple_servo', + isNotFor: ['neobot_purple'], + events: {}, + }, neobot_purple_servo_init: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1935,10 +2121,7 @@ Entry.NeobotPurple.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_purple_servo_init', }, paramsKeyMap: { @@ -1973,12 +2156,14 @@ Entry.NeobotPurple.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = resetValue; if (out2) Entry.hw.sendQueue['OUT2'] = resetValue; if (out3) Entry.hw.sendQueue['OUT3'] = resetValue; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_servo_init : ' + resetValue, 'speak'); + if (Entry.NeobotPurple.log_to_console) + Entry.console.print('neobot_purple_servo_init : ' + resetValue, 'speak'); setTimeout(function() { if (out1) Entry.hw.sendQueue['OUT1'] = initValue; if (out2) Entry.hw.sendQueue['OUT2'] = initValue; if (out3) Entry.hw.sendQueue['OUT3'] = initValue; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_servo_init : ' + initValue, 'speak'); + if (Entry.NeobotPurple.log_to_console) + Entry.console.print('neobot_purple_servo_init : ' + initValue, 'speak'); setTimeout(function() { script.timeFlag = 0; }, 100); @@ -2057,12 +2242,7 @@ Entry.NeobotPurple.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - null, - null, - ], + params: [null, null, null, null], type: 'neobot_purple_servo_rotate', }, paramsKeyMap: { @@ -2148,10 +2328,7 @@ Entry.NeobotPurple.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_purple_servo_stop', }, paramsKeyMap: { @@ -2333,18 +2510,33 @@ Entry.NeobotPurple.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = directionValue; if (out2) Entry.hw.sendQueue['OUT2'] = directionValue; if (out3) Entry.hw.sendQueue['OUT3'] = directionValue; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_servo_change_degree : ' + directionValue, 'speak'); - setTimeout(function() { // speed + if (Entry.NeobotPurple.log_to_console) + Entry.console.print( + 'neobot_purple_servo_change_degree : ' + directionValue, + 'speak' + ); + setTimeout(function() { + // speed if (out1) Entry.hw.sendQueue['OUT1'] = speedValue; if (out2) Entry.hw.sendQueue['OUT2'] = speedValue; if (out3) Entry.hw.sendQueue['OUT3'] = speedValue; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_servo_change_degree : ' + speedValue, 'speak'); - setTimeout(function() { // degree + if (Entry.NeobotPurple.log_to_console) + Entry.console.print( + 'neobot_purple_servo_change_degree : ' + speedValue, + 'speak' + ); + setTimeout(function() { + // degree if (out1) Entry.hw.sendQueue['OUT1'] = degreeValue; if (out2) Entry.hw.sendQueue['OUT2'] = degreeValue; if (out3) Entry.hw.sendQueue['OUT3'] = degreeValue; - if (Entry.NeobotPurple.log_to_console) Entry.console.print('neobot_purple_servo_change_degree : ' + degreeValue, 'speak'); - setTimeout(function() { // final delay + if (Entry.NeobotPurple.log_to_console) + Entry.console.print( + 'neobot_purple_servo_change_degree : ' + degreeValue, + 'speak' + ); + setTimeout(function() { + // final delay script.timeFlag = 0; }, 200); }, 200); diff --git a/src/playground/blocks/hardware/block_neobot_soco.js b/src/playground/blocks/hardware/block_neobot_soco.js index 91851353f5..092cda8d1d 100644 --- a/src/playground/blocks/hardware/block_neobot_soco.js +++ b/src/playground/blocks/hardware/block_neobot_soco.js @@ -47,18 +47,16 @@ Entry.NeobotSoco.setLanguage = function() { ko: { template: { // sensor + neobot_soco_sensor_title: '센서', neobot_soco_sensor_value: '%1', neobot_soco_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환', - - // decision neobot_soco_decision_sensor_is_over: '%1 %2 %3', neobot_soco_decision_equal_with_sensor: '%1 컬러가 %2', neobot_soco_decision_sensor_angle: '%1 각도 %2 %3', - - // remote neobot_soco_remote_button: '리모컨 버튼 %1 을 누름', // LED + neobot_soco_led_title: 'LED', neobot_soco_arg_led_duration: '%1', neobot_soco_led_on: 'LED 켜기 %1 %2 %3 %4', neobot_soco_output_led_off: '%1 LED 끄기 %2', @@ -66,9 +64,11 @@ Entry.NeobotSoco.setLanguage = function() { neobot_soco_color_led_on: '%1 컬러LED 켜기 R %2 G %3 B %4 %5', // output + neobot_soco_output_title: '출력', neobot_soco_set_output: '%1 에 %2 값 출력하기 %3', // motor + neobot_soco_motor_title: '회전모터', neobot_soco_robot: '로봇 %1 %2', neobot_soco_motor_start: '모터 회전하기 %1 %2 %3 %4 %5', neobot_soco_motor_stop: '%1 모터 멈추기 %2', @@ -76,11 +76,13 @@ Entry.NeobotSoco.setLanguage = function() { neobot_soco_arg_motor_duration: '%1', // melody + neobot_soco_buzzer_title: '버저', neobot_soco_play_note_for: '버저 울리기 옥타브: %2 음: %1 길이: %3 %4', neobot_soco_melody_play_with_sensor: '%1 센서로 버저 울리기 %2', neobot_soco_melody_stop: '버저 멈추기 %1', // servo + neobot_soco_servo_title: '서보모터', get_servo_degree: '%1', neobot_soco_servo_init: '%1 서보모터 리셋 %2', neobot_soco_servo_rotate: '서보모터 회전하기 %1 %2 %3 %4', @@ -220,28 +222,30 @@ Entry.NeobotSoco.setLanguage = function() { // en.js에 작성하던 내용 template: { // sensor + neobot_soco_sensor_title: 'Sensor', neobot_soco_sensor_value: '%1', - neobot_soco_sensor_convert_scale: '%1 \'s changed value range: %2 ~ %3 conversion: %4 ~ %5', - - // decision + neobot_soco_sensor_convert_scale: + "%1 's changed value range: %2 ~ %3 conversion: %4 ~ %5", neobot_soco_decision_sensor_is_over: '%1 %2 %3', - neobot_soco_decision_equal_with_sensor: '%1 \'s color is %2', + neobot_soco_decision_equal_with_sensor: "%1 's color is %2", neobot_soco_decision_sensor_angle: '%1 angle %2 %3', - - // remote neobot_soco_remote_button: 'pressing button %1 of remote controller', // LED + neobot_soco_led_title: 'LED', neobot_soco_arg_led_duration: '%1', neobot_soco_led_on: 'Turn on the LED %1 %2 %3 %4', neobot_soco_output_led_off: 'Turn off the %1 LED %2', - neobot_soco_led_brightness_with_sensor: 'Control %2 LED\'s brightness with %1 sensor %3', + neobot_soco_led_brightness_with_sensor: + "Control %2 LED's brightness with %1 sensor %3", neobot_soco_color_led_on: 'Turn on the %1 color LED R %2 G %3 B %4 %5', // output + neobot_soco_output_title: 'Set output', neobot_soco_set_output: 'Output %2 value to %1 port %3', // motor + neobot_soco_motor_title: 'Motor', neobot_soco_robot: 'Robot %1 %2', neobot_soco_motor_start: 'Motor operation %1 %2 %3 %4 %5', neobot_soco_motor_stop: 'Stop the %1 motor(s) %2', @@ -249,11 +253,13 @@ Entry.NeobotSoco.setLanguage = function() { neobot_soco_arg_motor_duration: '%1', // melody + neobot_soco_buzzer_title: 'Buzzer', neobot_soco_play_note_for: 'Buzzer octave: %1 scale: %2 note: %3 %4', neobot_soco_melody_play_with_sensor: 'Buzzer rings by %1 sensor value %2', neobot_soco_melody_stop: 'Stop the buzzer %1', // servo + neobot_soco_servo_title: 'Servo motor', neobot_soco_servo_init: 'Reset the %1 servo motor %2', neobot_soco_servo_rotate: 'Rotate the servo motor %1 %2 %3 %4', neobot_soco_servo_stop: 'Stop the %1 servo motor %2', @@ -393,41 +399,43 @@ Entry.NeobotSoco.setLanguage = function() { Entry.NeobotSoco.blockMenuBlocks = [ // sensor + 'neobot_soco_sensor_title', 'neobot_soco_sensor_value', 'neobot_soco_sensor_convert_scale', - - // decision 'neobot_soco_decision_sensor_is_over', 'neobot_soco_decision_equal_with_sensor', 'neobot_soco_decision_sensor_angle', - - // remote 'neobot_soco_remote_button', // led + 'neobot_soco_led_title', 'neobot_soco_led_on', 'neobot_soco_led_brightness_with_sensor', 'neobot_soco_color_led_on', 'neobot_soco_output_led_off', // output + 'neobot_soco_output_title', 'neobot_soco_set_output', // motor + 'neobot_soco_motor_title', 'neobot_soco_robot', 'neobot_soco_motor_start', 'neobot_soco_motor_stop', - // melody - 'neobot_soco_play_note_for', - 'neobot_soco_melody_play_with_sensor', - 'neobot_soco_melody_stop', - // servo + 'neobot_soco_servo_title', 'neobot_soco_servo_init', 'neobot_soco_servo_rotate', 'neobot_soco_servo_stop', 'neobot_soco_servo_change_degree', + + // melody + 'neobot_soco_buzzer_title', + 'neobot_soco_play_note_for', + 'neobot_soco_melody_play_with_sensor', + 'neobot_soco_melody_stop', ]; Entry.NeobotSoco.getBlocks = function() { @@ -435,6 +443,30 @@ Entry.NeobotSoco.getBlocks = function() { /************************* * class neobot_soco_sensor *************************/ + neobot_soco_sensor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_sensor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_sensor_title', + }, + class: 'neobot_soco_sensor', + isNotFor: ['neobot_soco'], + events: {}, + }, neobot_soco_sensor_value: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -571,9 +603,6 @@ Entry.NeobotSoco.getBlocks = function() { }, }, - /************************* - * class neobot_soco_decision - *************************/ neobot_soco_decision_sensor_is_over: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -623,7 +652,7 @@ Entry.NeobotSoco.getBlocks = function() { SYMBOL: 1, VALUE: 2, }, - class: 'neobot_soco_decision', + class: 'neobot_soco_sensor', isNotFor: ['neobot_soco'], func: function(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -710,7 +739,7 @@ Entry.NeobotSoco.getBlocks = function() { SENSOR: 0, COLOR: 1, }, - class: 'neobot_soco_decision', + class: 'neobot_soco_sensor', isNotFor: ['neobot_soco'], func: function(sprite, script) { var sensorTemp = script.getStringField('SENSOR'); @@ -809,7 +838,7 @@ Entry.NeobotSoco.getBlocks = function() { SYMBOL: 1, VALUE: 2, }, - class: 'neobot_soco_decision', + class: 'neobot_soco_sensor', isNotFor: ['neobot_soco'], func: function(sprite, script) { var sensorTemp = script.getStringField('SENSOR'); @@ -837,9 +866,6 @@ Entry.NeobotSoco.getBlocks = function() { }, }, - /************************* - * class neobot_soco_remote - *************************/ neobot_soco_remote_button: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -873,7 +899,7 @@ Entry.NeobotSoco.getBlocks = function() { paramsKeyMap: { KEY: 0, }, - class: 'neobot_soco_remote', + class: 'neobot_soco_sensor', isNotFor: ['neobot_soco'], func: function(sprite, script) { var key = script.getNumberField('KEY'); @@ -889,6 +915,30 @@ Entry.NeobotSoco.getBlocks = function() { /************************* * class neobot_soco_led *************************/ + neobot_soco_led_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_led_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_led_title', + }, + class: 'neobot_soco_led', + isNotFor: ['neobot_soco'], + events: {}, + }, neobot_soco_led_on: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -972,7 +1022,11 @@ Entry.NeobotSoco.getBlocks = function() { Entry.console.print('==========================', 'speak'); } - if ((duration != '계속' && duration != 'constantly') && Entry.parseNumber(duration) <= 0) { + if ( + duration != '계속' && + duration != 'constantly' && + Entry.parseNumber(duration) <= 0 + ) { return script.callReturn(); } @@ -999,7 +1053,8 @@ Entry.NeobotSoco.getBlocks = function() { } else { Entry.hw.sendQueue[port] = 0; } - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_led_on : 0', 'speak'); + if (Entry.NeobotSoco.log_to_console) + Entry.console.print('neobot_soco_led_on : 0', 'speak'); script.timeFlag = 0; }, durationValue * 1000); return script; @@ -1125,7 +1180,7 @@ Entry.NeobotSoco.getBlocks = function() { // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함. value = Math.max(value, 0); value = Math.min(value, 100); - value = Math.ceil(value / 100 * 255); + value = Math.ceil((value / 100) * 255); if (Entry.NeobotSoco.log_to_console) { Entry.console.print('=== neobot_soco_led_brightness_with_sensor ===', 'speak'); @@ -1259,38 +1314,67 @@ Entry.NeobotSoco.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = valRed; if (out2) Entry.hw.sendQueue['OUT2'] = valRed; if (out3) Entry.hw.sendQueue['OUT3'] = valRed; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_color_led_on : ' + valRed, 'speak'); - setTimeout(function() { // set red + if (Entry.NeobotSoco.log_to_console) + Entry.console.print('neobot_soco_color_led_on : ' + valRed, 'speak'); + setTimeout(function() { + // set red if (out1) Entry.hw.sendQueue['OUT1'] = red; if (out2) Entry.hw.sendQueue['OUT2'] = red; if (out3) Entry.hw.sendQueue['OUT3'] = red; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_color_led_on : ' + red, 'speak'); - setTimeout(function() { // choose green + if (Entry.NeobotSoco.log_to_console) + Entry.console.print('neobot_soco_color_led_on : ' + red, 'speak'); + setTimeout(function() { + // choose green if (out1) Entry.hw.sendQueue['OUT1'] = valGreen; if (out2) Entry.hw.sendQueue['OUT2'] = valGreen; if (out3) Entry.hw.sendQueue['OUT3'] = valGreen; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_color_led_on : ' + valGreen, 'speak'); - setTimeout(function() { // set green + if (Entry.NeobotSoco.log_to_console) + Entry.console.print( + 'neobot_soco_color_led_on : ' + valGreen, + 'speak' + ); + setTimeout(function() { + // set green if (out1) Entry.hw.sendQueue['OUT1'] = green; if (out2) Entry.hw.sendQueue['OUT2'] = green; if (out3) Entry.hw.sendQueue['OUT3'] = green; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_color_led_on : ' + green, 'speak'); - setTimeout(function() { // choose blue + if (Entry.NeobotSoco.log_to_console) + Entry.console.print( + 'neobot_soco_color_led_on : ' + green, + 'speak' + ); + setTimeout(function() { + // choose blue if (out1) Entry.hw.sendQueue['OUT1'] = valBlue; if (out2) Entry.hw.sendQueue['OUT2'] = valBlue; if (out3) Entry.hw.sendQueue['OUT3'] = valBlue; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_color_led_on : ' + valBlue, 'speak'); - setTimeout(function() { // set blue + if (Entry.NeobotSoco.log_to_console) + Entry.console.print( + 'neobot_soco_color_led_on : ' + valBlue, + 'speak' + ); + setTimeout(function() { + // set blue if (out1) Entry.hw.sendQueue['OUT1'] = blue; if (out2) Entry.hw.sendQueue['OUT2'] = blue; if (out3) Entry.hw.sendQueue['OUT3'] = blue; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_color_led_on : ' + blue, 'speak'); - setTimeout(function() { // accept + if (Entry.NeobotSoco.log_to_console) + Entry.console.print( + 'neobot_soco_color_led_on : ' + blue, + 'speak' + ); + setTimeout(function() { + // accept if (out1) Entry.hw.sendQueue['OUT1'] = valAccept; if (out2) Entry.hw.sendQueue['OUT2'] = valAccept; if (out3) Entry.hw.sendQueue['OUT3'] = valAccept; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_color_led_on : ' + valAccept, 'speak'); - setTimeout(function() { // final delay + if (Entry.NeobotSoco.log_to_console) + Entry.console.print( + 'neobot_soco_color_led_on : ' + valAccept, + 'speak' + ); + setTimeout(function() { + // final delay script.timeFlag = 0; }, 200); }, 200); @@ -1314,6 +1398,30 @@ Entry.NeobotSoco.getBlocks = function() { /************************* * class neobot_soco_output *************************/ + neobot_soco_output_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_output_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_output_title', + }, + class: 'neobot_soco_output', + isNotFor: ['neobot_soco'], + events: {}, + }, neobot_soco_set_output: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1391,6 +1499,30 @@ Entry.NeobotSoco.getBlocks = function() { /************************* * class neobot_soco_motor *************************/ + neobot_soco_motor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_motor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_motor_title', + }, + class: 'neobot_soco_motor', + isNotFor: ['neobot_soco'], + events: {}, + }, neobot_soco_robot: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1419,10 +1551,7 @@ Entry.NeobotSoco.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_soco_robot', }, paramsKeyMap: { @@ -1550,7 +1679,11 @@ Entry.NeobotSoco.getBlocks = function() { const speed = script.getStringValue('SPEED', script); const duration = script.getStringValue('DURATION', script); - if (duration != '계속' && duration != 'constantly' && Entry.parseNumber(duration) <= 0) { + if ( + duration != '계속' && + duration != 'constantly' && + Entry.parseNumber(duration) <= 0 + ) { return script.callReturn(); } @@ -1590,7 +1723,7 @@ Entry.NeobotSoco.getBlocks = function() { } speedValue = Math.max(speedValue, 0); speedValue = Math.min(speedValue, 100); - speedValue = Math.ceil(speedValue / 100 * 15); + speedValue = Math.ceil((speedValue / 100) * 15); const leftOutValue = leftDirectionValue + speedValue; const rightOutValue = rightDirectionValue + speedValue; @@ -1601,8 +1734,14 @@ Entry.NeobotSoco.getBlocks = function() { Entry.console.print('direction : ' + direction, 'speak'); Entry.console.print('speed : ' + speed, 'speak'); Entry.console.print('duration : ' + duration, 'speak'); - Entry.console.print('left direction value : ' + leftDirectionValue, 'speak'); - Entry.console.print('right direction value : ' + rightDirectionValue, 'speak'); + Entry.console.print( + 'left direction value : ' + leftDirectionValue, + 'speak' + ); + Entry.console.print( + 'right direction value : ' + rightDirectionValue, + 'speak' + ); Entry.console.print('speed value : ' + speedValue, 'speak'); Entry.console.print('left output value : ' + leftOutValue, 'speak'); Entry.console.print('right output value : ' + rightOutValue, 'speak'); @@ -1626,7 +1765,8 @@ Entry.NeobotSoco.getBlocks = function() { setTimeout(function() { Entry.hw.sendQueue['DCL'] = 0; Entry.hw.sendQueue['DCR'] = 0; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_motor_start : 0', 'speak'); + if (Entry.NeobotSoco.log_to_console) + Entry.console.print('neobot_soco_motor_start : 0', 'speak'); script.timeFlag = 0; }, durationValue * 1000); return script; @@ -1667,9 +1807,7 @@ Entry.NeobotSoco.getBlocks = function() { ], events: {}, def: { - params: [ - null, null, - ], + params: [null, null], type: 'neobot_soco_motor_stop', }, paramsKeyMap: { @@ -1701,6 +1839,30 @@ Entry.NeobotSoco.getBlocks = function() { /************************* * class neobot_soco_melody *************************/ + neobot_soco_buzzer_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_buzzer_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_buzzer_title', + }, + class: 'neobot_soco_melody', + isNotFor: ['neobot_soco'], + events: {}, + }, neobot_soco_play_note_for: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1799,9 +1961,10 @@ Entry.NeobotSoco.getBlocks = function() { Entry.hw.sendQueue['SND'] = value; setTimeout(function() { Entry.hw.sendQueue['SND'] = 0; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_play_note_for : 0', 'speak'); + if (Entry.NeobotSoco.log_to_console) + Entry.console.print('neobot_soco_play_note_for : 0', 'speak'); script.timeFlag = 0; - }, 1 / duration * 2000); + }, (1 / duration) * 2000); return script; } else if (script.timeFlag == 1) { return script; @@ -1840,9 +2003,7 @@ Entry.NeobotSoco.getBlocks = function() { ], events: {}, def: { - params: [ - null, null, - ], + params: [null, null], type: 'neobot_soco_melody_play_with_sensor', }, paramsKeyMap: { @@ -1857,7 +2018,7 @@ Entry.NeobotSoco.getBlocks = function() { // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함. value = Math.max(value, 0); value = Math.min(value, 100); - value = Math.ceil(value / 100 * 65); + value = Math.ceil((value / 100) * 65); if (Entry.NeobotSoco.log_to_console) { Entry.console.print('=== neobot_soco_melody_play_with_sensor ===', 'speak'); @@ -1885,9 +2046,7 @@ Entry.NeobotSoco.getBlocks = function() { ], events: {}, def: { - params: [ - null, - ], + params: [null], type: 'neobot_soco_melody_stop', }, paramsKeyMap: {}, @@ -1908,6 +2067,30 @@ Entry.NeobotSoco.getBlocks = function() { /************************* * class neobot_soco_servo *************************/ + neobot_soco_servo_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_servo_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_servo_title', + }, + class: 'neobot_soco_servo', + isNotFor: ['neobot_soco'], + events: {}, + }, neobot_soco_servo_init: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1935,10 +2118,7 @@ Entry.NeobotSoco.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_soco_servo_init', }, paramsKeyMap: { @@ -1973,12 +2153,14 @@ Entry.NeobotSoco.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = resetValue; if (out2) Entry.hw.sendQueue['OUT2'] = resetValue; if (out3) Entry.hw.sendQueue['OUT3'] = resetValue; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_servo_init : ' + resetValue, 'speak'); + if (Entry.NeobotSoco.log_to_console) + Entry.console.print('neobot_soco_servo_init : ' + resetValue, 'speak'); setTimeout(function() { if (out1) Entry.hw.sendQueue['OUT1'] = initValue; if (out2) Entry.hw.sendQueue['OUT2'] = initValue; if (out3) Entry.hw.sendQueue['OUT3'] = initValue; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_servo_init : ' + initValue, 'speak'); + if (Entry.NeobotSoco.log_to_console) + Entry.console.print('neobot_soco_servo_init : ' + initValue, 'speak'); setTimeout(function() { script.timeFlag = 0; }, 100); @@ -2057,12 +2239,7 @@ Entry.NeobotSoco.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - null, - null, - ], + params: [null, null, null, null], type: 'neobot_soco_servo_rotate', }, paramsKeyMap: { @@ -2148,10 +2325,7 @@ Entry.NeobotSoco.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_soco_servo_stop', }, paramsKeyMap: { @@ -2333,18 +2507,33 @@ Entry.NeobotSoco.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = directionValue; if (out2) Entry.hw.sendQueue['OUT2'] = directionValue; if (out3) Entry.hw.sendQueue['OUT3'] = directionValue; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_servo_change_degree : ' + directionValue, 'speak'); - setTimeout(function() { // speed + if (Entry.NeobotSoco.log_to_console) + Entry.console.print( + 'neobot_soco_servo_change_degree : ' + directionValue, + 'speak' + ); + setTimeout(function() { + // speed if (out1) Entry.hw.sendQueue['OUT1'] = speedValue; if (out2) Entry.hw.sendQueue['OUT2'] = speedValue; if (out3) Entry.hw.sendQueue['OUT3'] = speedValue; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_servo_change_degree : ' + speedValue, 'speak'); - setTimeout(function() { // degree + if (Entry.NeobotSoco.log_to_console) + Entry.console.print( + 'neobot_soco_servo_change_degree : ' + speedValue, + 'speak' + ); + setTimeout(function() { + // degree if (out1) Entry.hw.sendQueue['OUT1'] = degreeValue; if (out2) Entry.hw.sendQueue['OUT2'] = degreeValue; if (out3) Entry.hw.sendQueue['OUT3'] = degreeValue; - if (Entry.NeobotSoco.log_to_console) Entry.console.print('neobot_soco_servo_change_degree : ' + degreeValue, 'speak'); - setTimeout(function() { // final delay + if (Entry.NeobotSoco.log_to_console) + Entry.console.print( + 'neobot_soco_servo_change_degree : ' + degreeValue, + 'speak' + ); + setTimeout(function() { + // final delay script.timeFlag = 0; }, 200); }, 200); diff --git a/src/playground/blocks/hardware/block_neobot_thinkcar.js b/src/playground/blocks/hardware/block_neobot_thinkcar.js index 54aac3a664..639d5c341e 100644 --- a/src/playground/blocks/hardware/block_neobot_thinkcar.js +++ b/src/playground/blocks/hardware/block_neobot_thinkcar.js @@ -47,6 +47,7 @@ Entry.NeobotThinkCar.setLanguage = function() { ko: { template: { // think car + neobot_think_car_auto_driving_title: '자율주행', neobot_think_car_line_tracer_start: '차로를 유지하며 속도 %1 으로 자율주행 %2', // neobot_think_car_line_tracer_change_speed: '자율주행 속도 변경 %1 %2', neobot_think_car_reverse_parking_start: '%1 표지판에서 후면 주차 %2', @@ -54,18 +55,16 @@ Entry.NeobotThinkCar.setLanguage = function() { neobot_think_car_driving_stop: '자율주행 중지 %1', // sensor + neobot_think_car_sensor_title: '센서', neobot_think_car_sensor_value: '%1', neobot_think_car_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환', - - // decision neobot_think_car_decision_sensor_is_over: '%1 %2 %3', neobot_think_car_decision_equal_with_sensor: '%1 컬러가 %2', neobot_think_car_decision_sensor_angle: '%1 각도 %2 %3', - - // remote neobot_think_car_remote_button: '리모컨 버튼 %1 을 누름', // LED + neobot_think_car_led_title: 'LED', neobot_think_car_arg_led_duration: '%1', neobot_think_car_led_on: 'LED 켜기 %1 %2 %3 %4', neobot_think_car_output_led_off: '%1 LED 끄기 %2', @@ -73,9 +72,11 @@ Entry.NeobotThinkCar.setLanguage = function() { neobot_think_car_color_led_on: '%1 컬러LED 켜기 R %2 G %3 B %4 %5', // output + neobot_think_car_output_title: '출력', neobot_think_car_set_output: '%1 에 %2 값 출력하기 %3', // motor + neobot_think_car_motor_title: '회전모터', neobot_think_car_robot: '로봇 %1 %2', neobot_think_car_motor_start: '모터 회전하기 %1 %2 %3 %4 %5', neobot_think_car_motor_stop: '%1 모터 멈추기 %2', @@ -83,11 +84,13 @@ Entry.NeobotThinkCar.setLanguage = function() { neobot_think_car_arg_motor_duration: '%1', // melody + neobot_think_car_buzzer_title: '버저', neobot_think_car_play_note_for: '버저 울리기 옥타브: %2 음: %1 길이: %3 %4', neobot_think_car_melody_play_with_sensor: '%1 센서로 버저 울리기 %2', neobot_think_car_melody_stop: '버저 멈추기 %1', // servo + neobot_think_car_servo_title: '서보모터', get_servo_degree: '%1', neobot_think_car_servo_init: '%1 서보모터 리셋 %2', neobot_think_car_servo_rotate: '서보모터 회전하기 %1 %2 %3 %4', @@ -232,35 +235,40 @@ Entry.NeobotThinkCar.setLanguage = function() { // en.js에 작성하던 내용 template: { // think car - neobot_think_car_line_tracer_start: 'Start self-driving at %1 speed while keeping lanes %2', + neobot_think_car_auto_driving_title: 'Self-driving', + neobot_think_car_line_tracer_start: + 'Start self-driving at %1 speed while keeping lanes %2', // neobot_think_car_line_tracer_change_speed: 'Change the speed of self-driving %1 %2', neobot_think_car_reverse_parking_start: 'Start reverse parking at %1 sign %2', - neobot_think_car_line_change: 'Change the lane from primary %1 sign to secondary %2 sign %3', + neobot_think_car_line_change: + 'Change the lane from primary %1 sign to secondary %2 sign %3', neobot_think_car_driving_stop: 'Stop self-driving %1', // sensor + neobot_think_car_sensor_title: 'Sensor', neobot_think_car_sensor_value: '%1', - neobot_think_car_sensor_convert_scale: '%1 \'s changed value range: %2 ~ %3 conversion: %4 ~ %5', - - // decision + neobot_think_car_sensor_convert_scale: + "%1 's changed value range: %2 ~ %3 conversion: %4 ~ %5", neobot_think_car_decision_sensor_is_over: '%1 %2 %3', - neobot_think_car_decision_equal_with_sensor: '%1 \'s color is %2', + neobot_think_car_decision_equal_with_sensor: "%1 's color is %2", neobot_think_car_decision_sensor_angle: '%1 angle %2 %3', - - // remote neobot_think_car_remote_button: 'pressing button %1 of remote controller', // LED + neobot_think_car_led_title: 'LED', neobot_think_car_arg_led_duration: '%1', neobot_think_car_led_on: 'Turn on the LED %1 %2 %3 %4', neobot_think_car_output_led_off: 'Turn off the %1 LED %2', - neobot_think_car_led_brightness_with_sensor: 'Control %2 LED\'s brightness with %1 sensor %3', + neobot_think_car_led_brightness_with_sensor: + "Control %2 LED's brightness with %1 sensor %3", neobot_think_car_color_led_on: 'Turn on the %1 color LED R %2 G %3 B %4 %5', // output + neobot_think_car_output_title: 'Set output', neobot_think_car_set_output: 'Output %2 value to %1 port %3', // motor + neobot_think_car_motor_title: 'Motor', neobot_think_car_robot: 'Robot %1 %2', neobot_think_car_motor_start: 'Motor operation %1 %2 %3 %4 %5', neobot_think_car_motor_stop: 'Stop the %1 motor(s) %2', @@ -268,11 +276,13 @@ Entry.NeobotThinkCar.setLanguage = function() { neobot_think_car_arg_motor_duration: '%1', // melody + neobot_think_car_buzzer_title: 'Buzzer', neobot_think_car_play_note_for: 'Buzzer octave: %1 scale: %2 note: %3 %4', neobot_think_car_melody_play_with_sensor: 'Buzzer rings by %1 sensor value %2', neobot_think_car_melody_stop: 'Stop the buzzer %1', // servo + neobot_think_car_servo_title: 'Servo motor', get_servo_degree: '%1', neobot_think_car_servo_init: 'Reset the %1 servo motor %2', neobot_think_car_servo_rotate: 'Rotate the servo motor %1 %2 %3 %4', @@ -418,6 +428,7 @@ Entry.NeobotThinkCar.setLanguage = function() { Entry.NeobotThinkCar.blockMenuBlocks = [ // think car + 'neobot_think_car_auto_driving_title', 'neobot_think_car_line_tracer_start', // 'neobot_think_car_line_tracer_change_speed', 'neobot_think_car_reverse_parking_start', @@ -425,45 +436,71 @@ Entry.NeobotThinkCar.blockMenuBlocks = [ 'neobot_think_car_driving_stop', // sensor + 'neobot_think_car_sensor_title', 'neobot_think_car_sensor_value', 'neobot_think_car_sensor_convert_scale', - - // decision 'neobot_think_car_decision_sensor_is_over', 'neobot_think_car_decision_equal_with_sensor', 'neobot_think_car_decision_sensor_angle', - - // remote 'neobot_think_car_remote_button', // led + 'neobot_think_car_led_title', 'neobot_think_car_led_on', 'neobot_think_car_led_brightness_with_sensor', 'neobot_think_car_color_led_on', 'neobot_think_car_output_led_off', // output + 'neobot_think_car_output_title', 'neobot_think_car_set_output', // motor + 'neobot_think_car_motor_title', 'neobot_think_car_robot', 'neobot_think_car_motor_start', 'neobot_think_car_motor_stop', - // melody - 'neobot_think_car_play_note_for', - 'neobot_think_car_melody_play_with_sensor', - 'neobot_think_car_melody_stop', - // servo + 'neobot_think_car_servo_title', 'neobot_think_car_servo_init', 'neobot_think_car_servo_rotate', 'neobot_think_car_servo_stop', 'neobot_think_car_servo_change_degree', + + // melody + 'neobot_think_car_buzzer_title', + 'neobot_think_car_play_note_for', + 'neobot_think_car_melody_play_with_sensor', + 'neobot_think_car_melody_stop', ]; Entry.NeobotThinkCar.getBlocks = function() { return { + neobot_think_car_auto_driving_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_auto_driving_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_auto_driving_title', + }, + class: 'neobot_think_car_operation', + isNotFor: ['neobot_think_car'], + events: {}, + }, neobot_think_car_line_tracer_start: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -497,10 +534,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_think_car_line_tracer_start', }, paramsKeyMap: { @@ -519,9 +553,7 @@ Entry.NeobotThinkCar.getBlocks = function() { Entry.hw.sendQueue['OUT3'] = out3Value; Entry.hw.sendQueue['SND'] = buzzerValue; if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_line_tracer_start ===', - 'speak'); + Entry.console.print('=== neobot_think_car_line_tracer_start ===', 'speak'); Entry.console.print('out3 : ' + out3Value, 'speak'); Entry.console.print('buzzer : ' + buzzerValue, 'speak'); } @@ -531,12 +563,8 @@ Entry.NeobotThinkCar.getBlocks = function() { Entry.hw.sendQueue['SND'] = 0; if (Entry.NeobotThinkCar.log_to_console) { Entry.console.print('out1 : ' + speed, 'speak'); - Entry.console.print( - 'buzzer : 0', - 'speak'); - Entry.console.print( - '==========================', - 'speak'); + Entry.console.print('buzzer : 0', 'speak'); + Entry.console.print('==========================', 'speak'); } script.timeFlag = 0; }, 300); @@ -578,10 +606,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_think_car_reverse_parking_start', }, paramsKeyMap: { @@ -603,7 +628,8 @@ Entry.NeobotThinkCar.getBlocks = function() { if (Entry.NeobotThinkCar.log_to_console) { Entry.console.print( '=== neobot_think_car_reverse_parking_start ===', - 'speak'); + 'speak' + ); Entry.console.print('out3 : ' + out3Value, 'speak'); Entry.console.print('buzzer : ' + buzzerValue, 'speak'); } @@ -612,13 +638,9 @@ Entry.NeobotThinkCar.getBlocks = function() { Entry.hw.sendQueue['OUT1'] = colorValue; Entry.hw.sendQueue['SND'] = 0; if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print('out1 : ' + colorValue, - 'speak'); - Entry.console.print( - 'buzzer : 0', 'speak'); - Entry.console.print( - '==========================', - 'speak'); + Entry.console.print('out1 : ' + colorValue, 'speak'); + Entry.console.print('buzzer : 0', 'speak'); + Entry.console.print('==========================', 'speak'); } script.timeFlag = 0; @@ -675,11 +697,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - null, - ], + params: [null, null, null], type: 'neobot_think_car_line_change', }, paramsKeyMap: { @@ -701,9 +719,7 @@ Entry.NeobotThinkCar.getBlocks = function() { Entry.hw.sendQueue['SND'] = buzzerValue; if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_line_change ===', - 'speak'); + Entry.console.print('=== neobot_think_car_line_change ===', 'speak'); Entry.console.print('out3 : ' + out3Value, 'speak'); Entry.console.print('buzzer : ' + buzzerValue, 'speak'); } @@ -713,15 +729,10 @@ Entry.NeobotThinkCar.getBlocks = function() { Entry.hw.sendQueue['OUT2'] = toColorValue; Entry.hw.sendQueue['SND'] = 0; if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print('out1 : ' + fromColorValue, - 'speak'); - Entry.console.print('out2 : ' + toColorValue, - 'speak'); - Entry.console.print( - 'buzzer : 0', 'speak'); - Entry.console.print( - '==========================', - 'speak'); + Entry.console.print('out1 : ' + fromColorValue, 'speak'); + Entry.console.print('out2 : ' + toColorValue, 'speak'); + Entry.console.print('buzzer : 0', 'speak'); + Entry.console.print('==========================', 'speak'); } script.timeFlag = 0; @@ -752,9 +763,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - ], + params: [null], type: 'neobot_think_car_driving_stop', }, paramsKeyMap: {}, @@ -771,9 +780,7 @@ Entry.NeobotThinkCar.getBlocks = function() { Entry.hw.sendQueue['SND'] = buzzerValue; if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_driving_stop ===', - 'speak'); + Entry.console.print('=== neobot_think_car_driving_stop ===', 'speak'); Entry.console.print('out3 : ' + out3Value, 'speak'); Entry.console.print('buzzer : ' + buzzerValue, 'speak'); } @@ -786,12 +793,8 @@ Entry.NeobotThinkCar.getBlocks = function() { Entry.console.print('out1 : 0', 'speak'); Entry.console.print('out2 : 0', 'speak'); Entry.console.print('out3 : 0', 'speak'); - Entry.console.print( - 'buzzer : 0', - 'speak'); - Entry.console.print( - '==========================', - 'speak'); + Entry.console.print('buzzer : 0', 'speak'); + Entry.console.print('==========================', 'speak'); } script.timeFlag = 0; }, 300); @@ -868,6 +871,30 @@ Entry.NeobotThinkCar.getBlocks = function() { /************************* * class neobot_think_car_sensor *************************/ + neobot_think_car_sensor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_sensor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_sensor_title', + }, + class: 'neobot_think_car_sensor', + isNotFor: ['neobot_think_car'], + events: {}, + }, neobot_think_car_sensor_value: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1004,9 +1031,6 @@ Entry.NeobotThinkCar.getBlocks = function() { }, }, - /************************* - * class neobot_think_car_decision - *************************/ neobot_think_car_decision_sensor_is_over: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1056,7 +1080,7 @@ Entry.NeobotThinkCar.getBlocks = function() { SYMBOL: 1, VALUE: 2, }, - class: 'neobot_think_car_decision', + class: 'neobot_think_car_sensor', isNotFor: ['neobot_think_car'], func: function(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -1143,7 +1167,7 @@ Entry.NeobotThinkCar.getBlocks = function() { SENSOR: 0, COLOR: 1, }, - class: 'neobot_think_car_decision', + class: 'neobot_think_car_sensor', isNotFor: ['neobot_think_car'], func: function(sprite, script) { var sensorTemp = script.getStringField('SENSOR'); @@ -1242,7 +1266,7 @@ Entry.NeobotThinkCar.getBlocks = function() { SYMBOL: 1, VALUE: 2, }, - class: 'neobot_think_car_decision', + class: 'neobot_think_car_sensor', isNotFor: ['neobot_think_car'], func: function(sprite, script) { var sensorTemp = script.getStringField('SENSOR'); @@ -1270,9 +1294,6 @@ Entry.NeobotThinkCar.getBlocks = function() { }, }, - /************************* - * class neobot_think_car_remote - *************************/ neobot_think_car_remote_button: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1306,7 +1327,7 @@ Entry.NeobotThinkCar.getBlocks = function() { paramsKeyMap: { KEY: 0, }, - class: 'neobot_think_car_remote', + class: 'neobot_think_car_sensor', isNotFor: ['neobot_think_car'], func: function(sprite, script) { var key = script.getNumberField('KEY'); @@ -1322,6 +1343,30 @@ Entry.NeobotThinkCar.getBlocks = function() { /************************* * class neobot_think_car_led *************************/ + neobot_think_car_led_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_led_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_led_title', + }, + class: 'neobot_think_car_led', + isNotFor: ['neobot_think_car'], + events: {}, + }, neobot_think_car_led_on: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1398,17 +1443,18 @@ Entry.NeobotThinkCar.getBlocks = function() { const duration = script.getStringValue('DURATION', script); if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print('=== neobot_think_car_led_on ===', - 'speak'); + Entry.console.print('=== neobot_think_car_led_on ===', 'speak'); Entry.console.print('port : ' + port, 'speak'); Entry.console.print('brightness : ' + value, 'speak'); Entry.console.print('duration : ' + duration, 'speak'); - Entry.console.print('==========================', - 'speak'); + Entry.console.print('==========================', 'speak'); } - if ((duration != '계속' && duration != 'constantly') && - Entry.parseNumber(duration) <= 0) { + if ( + duration != '계속' && + duration != 'constantly' && + Entry.parseNumber(duration) <= 0 + ) { return script.callReturn(); } @@ -1435,8 +1481,8 @@ Entry.NeobotThinkCar.getBlocks = function() { } else { Entry.hw.sendQueue[port] = 0; } - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_led_on : 0', 'speak'); + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print('neobot_think_car_led_on : 0', 'speak'); script.timeFlag = 0; }, durationValue * 1000); return script; @@ -1490,8 +1536,7 @@ Entry.NeobotThinkCar.getBlocks = function() { const port = script.getStringField('PORT', script); if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_output_led_off ===', 'speak'); + Entry.console.print('=== neobot_think_car_output_led_off ===', 'speak'); Entry.console.print('port : ' + port, 'speak'); Entry.console.print('==========================', 'speak'); } @@ -1563,16 +1608,16 @@ Entry.NeobotThinkCar.getBlocks = function() { // edited 210421, IN 값 0~100 을 0~255로 변경, 센서 100 이상은 최대값으로 처리함. value = Math.max(value, 0); value = Math.min(value, 100); - value = Math.ceil(value / 100 * 255); + value = Math.ceil((value / 100) * 255); if (Entry.NeobotThinkCar.log_to_console) { Entry.console.print( '=== neobot_think_car_led_brightness_with_sensor ===', - 'speak'); + 'speak' + ); Entry.console.print('out port : ' + outPort, 'speak'); Entry.console.print('in port : ' + inPort, 'speak'); - Entry.console.print( - 'sensor value : ' + Entry.hw.portData[inPort], 'speak'); + Entry.console.print('sensor value : ' + Entry.hw.portData[inPort], 'speak'); Entry.console.print('output value : ' + value, 'speak'); Entry.console.print('==========================', 'speak'); } @@ -1681,14 +1726,12 @@ Entry.NeobotThinkCar.getBlocks = function() { blue = Math.min(blue, 251); if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_color_led_on ===', 'speak'); + Entry.console.print('=== neobot_think_car_color_led_on ===', 'speak'); Entry.console.print('port : ' + port, 'speak'); Entry.console.print('red : ' + red, 'speak'); Entry.console.print('green : ' + green, 'speak'); Entry.console.print('blue : ' + blue, 'speak'); - Entry.console.print('==========================', - 'speak'); + Entry.console.print('==========================', 'speak'); } const valRed = 252; @@ -1702,50 +1745,67 @@ Entry.NeobotThinkCar.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = valRed; if (out2) Entry.hw.sendQueue['OUT2'] = valRed; if (out3) Entry.hw.sendQueue['OUT3'] = valRed; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_color_led_on : ' + valRed, 'speak'); - setTimeout(function() { // set red + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print('neobot_think_car_color_led_on : ' + valRed, 'speak'); + setTimeout(function() { + // set red if (out1) Entry.hw.sendQueue['OUT1'] = red; if (out2) Entry.hw.sendQueue['OUT2'] = red; if (out3) Entry.hw.sendQueue['OUT3'] = red; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_color_led_on : ' + red, 'speak'); - setTimeout(function() { // choose green + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print('neobot_think_car_color_led_on : ' + red, 'speak'); + setTimeout(function() { + // choose green if (out1) Entry.hw.sendQueue['OUT1'] = valGreen; if (out2) Entry.hw.sendQueue['OUT2'] = valGreen; if (out3) Entry.hw.sendQueue['OUT3'] = valGreen; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_color_led_on : ' + valGreen, - 'speak'); - setTimeout(function() { // set green + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_color_led_on : ' + valGreen, + 'speak' + ); + setTimeout(function() { + // set green if (out1) Entry.hw.sendQueue['OUT1'] = green; if (out2) Entry.hw.sendQueue['OUT2'] = green; if (out3) Entry.hw.sendQueue['OUT3'] = green; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_color_led_on : ' + green, - 'speak'); - setTimeout(function() { // choose blue + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_color_led_on : ' + green, + 'speak' + ); + setTimeout(function() { + // choose blue if (out1) Entry.hw.sendQueue['OUT1'] = valBlue; if (out2) Entry.hw.sendQueue['OUT2'] = valBlue; if (out3) Entry.hw.sendQueue['OUT3'] = valBlue; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_color_led_on : ' + - valBlue, 'speak'); - setTimeout(function() { // set blue + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_color_led_on : ' + valBlue, + 'speak' + ); + setTimeout(function() { + // set blue if (out1) Entry.hw.sendQueue['OUT1'] = blue; if (out2) Entry.hw.sendQueue['OUT2'] = blue; if (out3) Entry.hw.sendQueue['OUT3'] = blue; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_color_led_on : ' + - blue, 'speak'); - setTimeout(function() { // accept + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_color_led_on : ' + blue, + 'speak' + ); + setTimeout(function() { + // accept if (out1) Entry.hw.sendQueue['OUT1'] = valAccept; if (out2) Entry.hw.sendQueue['OUT2'] = valAccept; if (out3) Entry.hw.sendQueue['OUT3'] = valAccept; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_color_led_on : ' + - valAccept, 'speak'); - setTimeout(function() { // final delay + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_color_led_on : ' + valAccept, + 'speak' + ); + setTimeout(function() { + // final delay script.timeFlag = 0; }, 200); }, 200); @@ -1769,6 +1829,30 @@ Entry.NeobotThinkCar.getBlocks = function() { /************************* * class neobot_think_car_output *************************/ + neobot_think_car_output_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_output_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_output_title', + }, + class: 'neobot_think_car_output', + isNotFor: ['neobot_think_car'], + events: {}, + }, neobot_think_car_set_output: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1826,8 +1910,7 @@ Entry.NeobotThinkCar.getBlocks = function() { } if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print('=== neobot_think_car_set_output ===', - 'speak'); + Entry.console.print('=== neobot_think_car_set_output ===', 'speak'); Entry.console.print('port : ' + port, 'speak'); Entry.console.print('value : ' + value, 'speak'); Entry.console.print('==========================', 'speak'); @@ -1847,6 +1930,30 @@ Entry.NeobotThinkCar.getBlocks = function() { /************************* * class neobot_think_car_motor *************************/ + neobot_think_car_motor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_motor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_motor_title', + }, + class: 'neobot_think_car_motor', + isNotFor: ['neobot_think_car'], + events: {}, + }, neobot_think_car_robot: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1875,10 +1982,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_think_car_robot', }, paramsKeyMap: { @@ -1914,8 +2018,7 @@ Entry.NeobotThinkCar.getBlocks = function() { } if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print('=== neobot_think_car_robot ===', - 'speak'); + Entry.console.print('=== neobot_think_car_robot ===', 'speak'); Entry.console.print('move : ' + move, 'speak'); Entry.console.print('left value : ' + leftValue, 'speak'); Entry.console.print('right value : ' + rightValue, 'speak'); @@ -2003,13 +2106,15 @@ Entry.NeobotThinkCar.getBlocks = function() { func: function(sprite, script) { if (!script.isStart) { const motor = script.getStringField('MOTOR', script); - const direction = script.getStringField('DIRECTION', - script); + const direction = script.getStringField('DIRECTION', script); const speed = script.getStringValue('SPEED', script); const duration = script.getStringValue('DURATION', script); - if (duration != '계속' && duration != 'constantly' && - Entry.parseNumber(duration) <= 0) { + if ( + duration != '계속' && + duration != 'constantly' && + Entry.parseNumber(duration) <= 0 + ) { return script.callReturn(); } @@ -2049,33 +2154,29 @@ Entry.NeobotThinkCar.getBlocks = function() { } speedValue = Math.max(speedValue, 0); speedValue = Math.min(speedValue, 100); - speedValue = Math.ceil(speedValue / 100 * 15); + speedValue = Math.ceil((speedValue / 100) * 15); const leftOutValue = leftDirectionValue + speedValue; const rightOutValue = rightDirectionValue + speedValue; if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_motor_start ===', 'speak'); + Entry.console.print('=== neobot_think_car_motor_start ===', 'speak'); Entry.console.print('motor : ' + motor, 'speak'); - Entry.console.print('direction : ' + direction, - 'speak'); + Entry.console.print('direction : ' + direction, 'speak'); Entry.console.print('speed : ' + speed, 'speak'); Entry.console.print('duration : ' + duration, 'speak'); Entry.console.print( 'left direction value : ' + leftDirectionValue, - 'speak'); + 'speak' + ); Entry.console.print( 'right direction value : ' + rightDirectionValue, - 'speak'); - Entry.console.print('speed value : ' + speedValue, - 'speak'); - Entry.console.print( - 'left output value : ' + leftOutValue, 'speak'); - Entry.console.print( - 'right output value : ' + rightOutValue, 'speak'); - Entry.console.print('==========================', - 'speak'); + 'speak' + ); + Entry.console.print('speed value : ' + speedValue, 'speak'); + Entry.console.print('left output value : ' + leftOutValue, 'speak'); + Entry.console.print('right output value : ' + rightOutValue, 'speak'); + Entry.console.print('==========================', 'speak'); } if (moveLeft) { @@ -2095,8 +2196,8 @@ Entry.NeobotThinkCar.getBlocks = function() { setTimeout(function() { Entry.hw.sendQueue['DCL'] = 0; Entry.hw.sendQueue['DCR'] = 0; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_motor_start : 0', 'speak'); + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print('neobot_think_car_motor_start : 0', 'speak'); script.timeFlag = 0; }, durationValue * 1000); return script; @@ -2137,9 +2238,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, null, - ], + params: [null, null], type: 'neobot_think_car_motor_stop', }, paramsKeyMap: { @@ -2151,8 +2250,7 @@ Entry.NeobotThinkCar.getBlocks = function() { const motor = script.getNumberField('MOTOR'); if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print('=== neobot_think_car_motor_stop ===', - 'speak'); + Entry.console.print('=== neobot_think_car_motor_stop ===', 'speak'); Entry.console.print('motor : ' + motor, 'speak'); Entry.console.print('==========================', 'speak'); } @@ -2172,6 +2270,30 @@ Entry.NeobotThinkCar.getBlocks = function() { /************************* * class neobot_think_car_melody *************************/ + neobot_think_car_buzzer_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_buzzer_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_buzzer_title', + }, + class: 'neobot_think_car_melody', + isNotFor: ['neobot_think_car'], + events: {}, + }, neobot_think_car_play_note_for: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2221,9 +2343,7 @@ Entry.NeobotThinkCar.getBlocks = function() { [Lang.Blocks.neobot_think_car_sound_half_note, '2'], [Lang.Blocks.neobot_think_car_sound_quarter_note, '4'], [Lang.Blocks.neobot_think_car_sound_eighth_note, '8'], - [ - Lang.Blocks.neobot_think_car_sound_sixteenth_note, - '16'], + [Lang.Blocks.neobot_think_car_sound_sixteenth_note, '16'], ], value: '2', fontSize: 11, @@ -2258,14 +2378,12 @@ Entry.NeobotThinkCar.getBlocks = function() { value = Math.min(value, 72); if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_play_note_for ===', 'speak'); + Entry.console.print('=== neobot_think_car_play_note_for ===', 'speak'); Entry.console.print('note : ' + note, 'speak'); Entry.console.print('octave : ' + octave, 'speak'); Entry.console.print('duration : ' + duration, 'speak'); Entry.console.print('value : ' + value, 'speak'); - Entry.console.print('==========================', - 'speak'); + Entry.console.print('==========================', 'speak'); } script.isStart = true; @@ -2274,10 +2392,10 @@ Entry.NeobotThinkCar.getBlocks = function() { Entry.hw.sendQueue['SND'] = value; setTimeout(function() { Entry.hw.sendQueue['SND'] = 0; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_play_note_for : 0', 'speak'); + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print('neobot_think_car_play_note_for : 0', 'speak'); script.timeFlag = 0; - }, 1 / duration * 2000); + }, (1 / duration) * 2000); return script; } else if (script.timeFlag == 1) { return script; @@ -2316,9 +2434,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, null, - ], + params: [null, null], type: 'neobot_think_car_melody_play_with_sensor', }, paramsKeyMap: { @@ -2333,12 +2449,13 @@ Entry.NeobotThinkCar.getBlocks = function() { // edited 210421, 0~100 을 0~65로 변환, 100 이상은 최대값으로 처리함. value = Math.max(value, 0); value = Math.min(value, 100); - value = Math.ceil(value / 100 * 65); + value = Math.ceil((value / 100) * 65); if (Entry.NeobotThinkCar.log_to_console) { Entry.console.print( '=== neobot_think_car_melody_play_with_sensor ===', - 'speak'); + 'speak' + ); Entry.console.print('input : ' + input, 'speak'); Entry.console.print('value : ' + value, 'speak'); Entry.console.print('==========================', 'speak'); @@ -2363,9 +2480,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - ], + params: [null], type: 'neobot_think_car_melody_stop', }, paramsKeyMap: {}, @@ -2373,8 +2488,7 @@ Entry.NeobotThinkCar.getBlocks = function() { isNotFor: ['neobot_think_car'], func: function(sprite, script) { if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print('=== neobot_think_car_melody_stop ===', - 'speak'); + Entry.console.print('=== neobot_think_car_melody_stop ===', 'speak'); Entry.console.print('value : 0', 'speak'); Entry.console.print('==========================', 'speak'); } @@ -2387,6 +2501,30 @@ Entry.NeobotThinkCar.getBlocks = function() { /************************* * class neobot_think_car_servo *************************/ + neobot_think_car_servo_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_servo_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_servo_title', + }, + class: 'neobot_think_car_servo', + isNotFor: ['neobot_think_car'], + events: {}, + }, neobot_think_car_servo_init: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2414,10 +2552,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_think_car_servo_init', }, paramsKeyMap: { @@ -2432,11 +2567,9 @@ Entry.NeobotThinkCar.getBlocks = function() { const initValue = 1; if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_servo_init ===', 'speak'); + Entry.console.print('=== neobot_think_car_servo_init ===', 'speak'); Entry.console.print('port : ' + port, 'speak'); - Entry.console.print('==========================', - 'speak'); + Entry.console.print('==========================', 'speak'); } let out1 = port == 'OUT1'; @@ -2454,15 +2587,17 @@ Entry.NeobotThinkCar.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = resetValue; if (out2) Entry.hw.sendQueue['OUT2'] = resetValue; if (out3) Entry.hw.sendQueue['OUT3'] = resetValue; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_servo_init : ' + resetValue, 'speak'); + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print('neobot_think_car_servo_init : ' + resetValue, 'speak'); setTimeout(function() { if (out1) Entry.hw.sendQueue['OUT1'] = initValue; if (out2) Entry.hw.sendQueue['OUT2'] = initValue; if (out3) Entry.hw.sendQueue['OUT3'] = initValue; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_servo_init : ' + initValue, - 'speak'); + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_servo_init : ' + initValue, + 'speak' + ); setTimeout(function() { script.timeFlag = 0; }, 100); @@ -2541,12 +2676,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - null, - null, - ], + params: [null, null, null, null], type: 'neobot_think_car_servo_rotate', }, paramsKeyMap: { @@ -2585,13 +2715,11 @@ Entry.NeobotThinkCar.getBlocks = function() { } if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print( - '=== neobot_think_car_servo_rotate ==='); + Entry.console.print('=== neobot_think_car_servo_rotate ==='); Entry.console.print('port : ' + port, 'speak'); Entry.console.print('direction : ' + direction, 'speak'); Entry.console.print('speed : ' + speed, 'speak'); - Entry.console.print('direction value : ' + directionValue, - 'speak'); + Entry.console.print('direction value : ' + directionValue, 'speak'); Entry.console.print('speed value : ' + speedValue, 'speak'); Entry.console.print('output value : ' + outValue, 'speak'); Entry.console.print('==========================', 'speak'); @@ -2634,10 +2762,7 @@ Entry.NeobotThinkCar.getBlocks = function() { ], events: {}, def: { - params: [ - null, - null, - ], + params: [null, null], type: 'neobot_think_car_servo_stop', }, paramsKeyMap: { @@ -2650,8 +2775,7 @@ Entry.NeobotThinkCar.getBlocks = function() { let outValue = 254; if (Entry.NeobotThinkCar.log_to_console) { - Entry.console.print('=== neobot_think_car_servo_stop ===', - 'speak'); + Entry.console.print('=== neobot_think_car_servo_stop ===', 'speak'); Entry.console.print('port : ' + port, 'speak'); Entry.console.print('output value: ' + outValue, 'speak'); Entry.console.print('==========================', 'speak'); @@ -2790,8 +2914,7 @@ Entry.NeobotThinkCar.getBlocks = function() { if (Entry.Utils.isNumber(degree)) { degreeValue = Entry.parseNumber(degree); } else { - if (degree == 'IN1' || degree == 'IN2' || degree == - 'IN3') { + if (degree == 'IN1' || degree == 'IN2' || degree == 'IN3') { degreeValue = Entry.hw.portData[degree]; } else { degreeValue = 0; @@ -2805,20 +2928,16 @@ Entry.NeobotThinkCar.getBlocks = function() { if (Entry.NeobotThinkCar.log_to_console) { Entry.console.print( '=== neobot_think_car_servo_change_degree ===', - 'speak'); + 'speak' + ); Entry.console.print('port : ' + port, 'speak'); - Entry.console.print('direction : ' + direction, - 'speak'); + Entry.console.print('direction : ' + direction, 'speak'); Entry.console.print('speed : ' + speed, 'speak'); Entry.console.print('degree : ' + degree, 'speak'); - Entry.console.print( - 'directionValue : ' + directionValue, 'speak'); - Entry.console.print('speedValue : ' + speedValue, - 'speak'); - Entry.console.print('degreeValue : ' + degreeValue, - 'speak'); - Entry.console.print('==========================', - 'speak'); + Entry.console.print('directionValue : ' + directionValue, 'speak'); + Entry.console.print('speedValue : ' + speedValue, 'speak'); + Entry.console.print('degreeValue : ' + degreeValue, 'speak'); + Entry.console.print('==========================', 'speak'); } script.isStart = true; @@ -2828,24 +2947,33 @@ Entry.NeobotThinkCar.getBlocks = function() { if (out1) Entry.hw.sendQueue['OUT1'] = directionValue; if (out2) Entry.hw.sendQueue['OUT2'] = directionValue; if (out3) Entry.hw.sendQueue['OUT3'] = directionValue; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_servo_change_degree : ' + - directionValue, 'speak'); - setTimeout(function() { // speed + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_servo_change_degree : ' + directionValue, + 'speak' + ); + setTimeout(function() { + // speed if (out1) Entry.hw.sendQueue['OUT1'] = speedValue; if (out2) Entry.hw.sendQueue['OUT2'] = speedValue; if (out3) Entry.hw.sendQueue['OUT3'] = speedValue; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_servo_change_degree : ' + - speedValue, 'speak'); - setTimeout(function() { // degree + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_servo_change_degree : ' + speedValue, + 'speak' + ); + setTimeout(function() { + // degree if (out1) Entry.hw.sendQueue['OUT1'] = degreeValue; if (out2) Entry.hw.sendQueue['OUT2'] = degreeValue; if (out3) Entry.hw.sendQueue['OUT3'] = degreeValue; - if (Entry.NeobotThinkCar.log_to_console) Entry.console.print( - 'neobot_think_car_servo_change_degree : ' + - degreeValue, 'speak'); - setTimeout(function() { // final delay + if (Entry.NeobotThinkCar.log_to_console) + Entry.console.print( + 'neobot_think_car_servo_change_degree : ' + degreeValue, + 'speak' + ); + setTimeout(function() { + // final delay script.timeFlag = 0; }, 200); }, 200); diff --git a/src/playground/blocks/hardwareLite/block_microbit2_lite.js b/src/playground/blocks/hardwareLite/block_microbit2_lite.js index c747731d5f..0b86d4da22 100644 --- a/src/playground/blocks/hardwareLite/block_microbit2_lite.js +++ b/src/playground/blocks/hardwareLite/block_microbit2_lite.js @@ -9,7 +9,7 @@ const EVENT_INTERVAL = 150; constructor() { this.commandStatus = {}; this.btnEventIntervalId = -1; - this.retryLimitCnt = 4; + this.retryLimitCnt = 8; this.portData = { baudRate: 115200, dataBits: 8, diff --git a/src/playground/blocks/hardwareLite/block_neo_lite.js b/src/playground/blocks/hardwareLite/block_neo_lite.js index 9d3f733c4b..2aabaf68fe 100644 --- a/src/playground/blocks/hardwareLite/block_neo_lite.js +++ b/src/playground/blocks/hardwareLite/block_neo_lite.js @@ -310,13 +310,14 @@ } setZero() { - /*if (Entry.Lite) { - Entry.hwLite.update(); - }*/ if (Entry.hwLite) { const blockId = this.generateBlockId(); - const pdu = this.makePdu([FrameCode.BASIC, PduCode.CONTROLLER_COMMAND, blockId, 0x04]); - // Entry.hwLite.writer.write(Buffer.from(pdu)); + const pdu = this.makePdu([ + FrameCode.BASIC, + PduCode.CONTROLLER_COMMAND, + blockId, + 0x04, + ]); this.executeList = [ { blockId, @@ -467,7 +468,6 @@ this.pendingResponseList[responseData.blockId] = 'pending'; } if (responseData.result === 0x01) { - // this.pendingResponseList[responseData.blockId] = 'completed'; delete this.pendingResponseList[responseData.blockId]; } } @@ -659,6 +659,20 @@ }); } + requestExt2Command(blockId, type, params) { + if (this.pendingResponseList[blockId]) { + delete this.pendingResponseList[blockId]; + } + this.pendingResponseList[blockId] = 'executed'; + const command = this.makeCommandExt2(blockId, type, params); + if (!command) return; + const pdu = this.makePdu(command); + this.executeList.push({ + blockId, + pdu, + }); + } + generateBlockId() { this.seqBlockId += 1; if (this.seqBlockId > 255) { @@ -716,7 +730,7 @@ // led neo_lite_led_title: 'LED', - neo_lite_led_on: 'LED 켜기 %1 %2 %3', + neo_lite_led_on: 'LED 켜기 %1 %2 %3 %4', neo_lite_led_blink: 'LED 깜빡이기 %1 %2 %3 %4', neo_lite_led_off: 'LED 끄기 %1 %2', @@ -1110,21 +1124,19 @@ neo_lite_buzzer_quarter_note: '4분 음표', neo_lite_buzzer_8th_note: '8분 음표', - neo_lite_lcd_image_1: '1', - neo_lite_lcd_image_2: '2', - neo_lite_lcd_image_3: '3', - neo_lite_lcd_image_4: '4', - neo_lite_lcd_image_5: '5', - neo_lite_lcd_image_6: '6', - neo_lite_lcd_image_7: '7', - neo_lite_lcd_image_8: '8', - neo_lite_lcd_image_9: '9', - neo_lite_lcd_image_10: '10', - neo_lite_lcd_image_11: '11', - neo_lite_lcd_image_12: '12', - neo_lite_lcd_image_13: '13', - neo_lite_lcd_image_14: '14', - neo_lite_lcd_image_15: '15', + neo_lite_lcd_image_1: '화남', + neo_lite_lcd_image_2: '어지러움', + neo_lite_lcd_image_3: '똑똑함', + neo_lite_lcd_image_4: '활기참', + neo_lite_lcd_image_5: '뽀뽀', + neo_lite_lcd_image_6: '사랑해', + neo_lite_lcd_image_7: '윙크', + neo_lite_lcd_image_8: '폭풍눈물', + neo_lite_lcd_image_9: '졸림', + neo_lite_lcd_image_10: '미소', + neo_lite_lcd_image_11: '깜찍함', + neo_lite_lcd_image_12: '의심', + neo_lite_lcd_image_13: '못마땅', }, }, en: { @@ -1141,7 +1153,8 @@ // servo neo_lite_servo_title: 'Servo motor', - neo_lite_servo_reset: 'Reset the current position of %1 servo motor to 0 degree %2', + neo_lite_servo_reset: + 'Reset the current position of %1 servo motor to 0 degree %2', neo_lite_servo_angle: 'Change servo angle %1 %2 %3 %4', neo_lite_servo_angle_var: 'Change servo angle %1 %2 %3 %4', neo_lite_servo_angle_wait: 'Wait to change servo angle %1 %2 %3 %4', @@ -1176,7 +1189,7 @@ // led neo_lite_led_title: 'LED', - neo_lite_led_on: 'Turn on the LED %1 %2 %3', + neo_lite_led_on: 'Turn on the LED %1 %2 %3 %4', neo_lite_led_blink: 'Blink the LED %1 %2 %3 %4', neo_lite_led_off: 'Turn off the LED %1 %2', @@ -1184,7 +1197,8 @@ neo_lite_color_led_title: 'Color LED', neo_lite_color_led_on: 'Turn on the color LED %1 %2 %3 %4', neo_lite_color_led_off: 'Turn off the color LED %1 %2', - neo_lite_color_led_on_with_sensor: 'Turn on the color LED %2 with color sensor %1 %3', + neo_lite_color_led_on_with_sensor: + 'Turn on the color LED %2 with color sensor %1 %3', // set output neo_lite_set_output_title: 'Set output', @@ -1265,14 +1279,14 @@ neo_lite_duration_c: 'constantly', neo_lite_duration_0: '0 second', neo_lite_duration_1: '1 second', - neo_lite_duration_2: '2 second', - neo_lite_duration_3: '3 second', - neo_lite_duration_4: '4 second', - neo_lite_duration_5: '5 second', - neo_lite_duration_6: '6 second', - neo_lite_duration_7: '7 second', - neo_lite_duration_8: '8 second', - neo_lite_duration_9: '9 second', + neo_lite_duration_2: '2 seconds', + neo_lite_duration_3: '3 seconds', + neo_lite_duration_4: '4 seconds', + neo_lite_duration_5: '5 seconds', + neo_lite_duration_6: '6 seconds', + neo_lite_duration_7: '7 seconds', + neo_lite_duration_8: '8 seconds', + neo_lite_duration_9: '9 seconds', neo_lite_compare_gt: '≥', neo_lite_compare_g: '>', @@ -1467,10 +1481,10 @@ neo_lite_led_brightness_100: '100%', neo_lite_led_blink_speed_1: '1 step', - neo_lite_led_blink_speed_2: '2 step', - neo_lite_led_blink_speed_3: '3 step', - neo_lite_led_blink_speed_4: '4 step', - neo_lite_led_blink_speed_5: '5 step', + neo_lite_led_blink_speed_2: '2 steps', + neo_lite_led_blink_speed_3: '3 steps', + neo_lite_led_blink_speed_4: '4 steps', + neo_lite_led_blink_speed_5: '5 steps', neo_lite_set_output_value_0: '0', neo_lite_set_output_value_5: '5', @@ -1570,21 +1584,19 @@ neo_lite_buzzer_quarter_note: 'a quarter note', neo_lite_buzzer_8th_note: 'a eighth note', - neo_lite_lcd_image_1: '1', - neo_lite_lcd_image_2: '2', - neo_lite_lcd_image_3: '3', - neo_lite_lcd_image_4: '4', - neo_lite_lcd_image_5: '5', - neo_lite_lcd_image_6: '6', - neo_lite_lcd_image_7: '7', - neo_lite_lcd_image_8: '8', - neo_lite_lcd_image_9: '9', - neo_lite_lcd_image_10: '10', - neo_lite_lcd_image_11: '11', - neo_lite_lcd_image_12: '12', - neo_lite_lcd_image_13: '13', - neo_lite_lcd_image_14: '14', - neo_lite_lcd_image_15: '15', + neo_lite_lcd_image_1: 'angry', + neo_lite_lcd_image_2: 'dizzy', + neo_lite_lcd_image_3: 'smart', + neo_lite_lcd_image_4: 'lively', + neo_lite_lcd_image_5: 'kiss', + neo_lite_lcd_image_6: 'lovely', + neo_lite_lcd_image_7: 'wink', + neo_lite_lcd_image_8: 'cry', + neo_lite_lcd_image_9: 'sleepy', + neo_lite_lcd_image_10: 'smiley', + neo_lite_lcd_image_11: 'cute', + neo_lite_lcd_image_12: 'doubt', + neo_lite_lcd_image_13: 'bad', }, }, // }; @@ -1726,8 +1738,11 @@ const speed = script.getStringField('SPEED', script); const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); - if (speed === 'IN1' || speed === 'IN2' || speed === 'IN3') { - this.requestExtCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, speed]); + if (speed.indexOf('IN') >= 0) { + this.requestExtCommand(blockId, NeoBlockType.MOTOR_MOVE, [ + dc, + speed, + ]); } else { this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE, [dc, speed]); } @@ -1805,13 +1820,16 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const speedL = script.getNumberValue('SPEED_L', script); const speedR = script.getNumberValue('SPEED_R', script); const blockId = this.generateBlockId(); script.block_id = blockId; - this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE_BOTH, [speedL, speedR]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + this.requestCommand(blockId, NeoBlockType.MOTOR_MOVE_BOTH, [ + speedL, + speedR, + ]); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -1911,10 +1929,16 @@ const speed = script.getStringField('SPEED', script); const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); - if (speed === 'IN1' || speed === 'IN2' || speed === 'IN3') { - this.requestExtCommand(blockId, NeoBlockType.ROBOT_MOVE, [direction, speed]); + if (speed.indexOf('IN') >= 0) { + this.requestExtCommand(blockId, NeoBlockType.ROBOT_MOVE, [ + direction, + speed, + ]); } else { - this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [direction, speed]); + this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [ + direction, + speed, + ]); } if (duration === 'c' || !Entry.parseNumber(duration)) { script.block_id = blockId; @@ -1982,10 +2006,20 @@ class: 'neo_lite_motor', isNotFor: ['NeoLite'], func: (sprite, script) => { - const dc = script.getStringValue('DC', script); - const blockId = this.generateBlockId(); - this.requestCommand(blockId, NeoBlockType.MOTOR_STOP, [dc]); - return script.callReturn(); + if (!script.exec_phase) { + const dc = script.getStringValue('DC', script); + const blockId = this.generateBlockId(); + script.block_id = blockId; + script.exec_phase = ExecPhase.PENDING_RESPONSE; + this.requestCommand(blockId, NeoBlockType.MOTOR_STOP, [dc]); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { + if (!this.pendingResponseList[script.block_id]) { + delete script.block_id; + delete script.exec_phase; + return script.callReturn(); + } + } + return script; }, }, neo_lite_robot_stop: { @@ -2011,9 +2045,19 @@ class: 'neo_lite_motor', isNotFor: ['NeoLite'], func: (sprite, script) => { - const blockId = this.generateBlockId(); - this.requestCommand(blockId, NeoBlockType.ROBOT_STOP, []); - return script.callReturn(); + if (!script.exec_phase) { + const blockId = this.generateBlockId(); + script.block_id = blockId; + script.exec_phase = ExecPhase.PENDING_RESPONSE; + this.requestCommand(blockId, NeoBlockType.ROBOT_STOP, []); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { + if (!this.pendingResponseList[script.block_id]) { + delete script.block_id; + delete script.exec_phase; + return script.callReturn(); + } + } + return script; }, }, /** @@ -2244,22 +2288,36 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringField('OUTPUT', script); const angle = script.getStringField('ANGLE', script); const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; - if (angle === 'IN1' || angle === 'IN2' || angle === 'IN3') { - if (speed === 'IN1' || angle === 'IN2' || angle === 'IN3') { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE, [output, angle, speed]); + const isExt2 = angle.indexOf('IN') >= 0 && speed.indexOf('IN') >= 0; + if (isExt2) { + this.requestExt2Command(blockId, NeoBlockType.SERVO_ANGLE, [ + output, + angle, + speed, + ]); + } else { + const isExt1 = angle.indexOf('IN') >= 0 || speed.indexOf('IN') >= 0; + if (isExt1) { + this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE, [ + output, + angle, + speed, + ]); } else { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE, [output, angle, speed]); + this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [ + output, + angle, + speed, + ]); } - } else { - this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [output, angle, speed]); } - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -2350,8 +2408,12 @@ const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; - this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [output, angle, speed]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE, [ + output, + angle, + speed, + ]); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -2512,22 +2574,28 @@ const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; - if (angle === 'IN1' || angle === 'IN2' || angle === 'IN3') { - if (speed === 'IN1' || angle === 'IN2' || angle === 'IN3') { + const isExt2 = angle.indexOf('IN') >= 0 && speed.indexOf('IN') >= 0; + if (isExt2) { + this.requestExt2Command(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [ + output, + angle, + speed, + ]); + } else { + const isExt1 = angle.indexOf('IN') >= 0 || speed.indexOf('IN') >= 0; + if (isExt1) { this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [ output, angle, speed, ]); } else { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [ + this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [ output, angle, speed, ]); } - } else { - this.requestCommand(blockId, NeoBlockType.SERVO_ANGLE_WAIT, [output, angle, speed]); } } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { @@ -2613,18 +2681,26 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringField('OUTPUT', script); const direction = script.getStringField('DIRECTION', script); const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; if (speed.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.SERVO_ROTATE, [output, direction, speed]); + this.requestExtCommand(blockId, NeoBlockType.SERVO_ROTATE, [ + output, + direction, + speed, + ]); } else { - this.requestCommand(blockId, NeoBlockType.SERVO_ROTATE, [output, direction, speed]); + this.requestCommand(blockId, NeoBlockType.SERVO_ROTATE, [ + output, + direction, + speed, + ]); } - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -2672,12 +2748,12 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringValue('OUTPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; this.requestCommand(blockId, NeoBlockType.SERVO_STOP, [output]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -2774,10 +2850,14 @@ const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); const duration = script.getStringValue('DURATION', script); - if (speed === 'IN1' || speed === 'IN2' || speed === 'IN3') { - this.requestExtCommand(blockId, NeoBlockType.LINE_TRACER_START, [speed]); + if (speed.indexOf('IN') >= 0) { + this.requestExtCommand(blockId, NeoBlockType.LINE_TRACER_START, [ + speed, + ]); } else { - this.requestCommand(blockId, NeoBlockType.LINE_TRACER_START, [speed]); + this.requestCommand(blockId, NeoBlockType.LINE_TRACER_START, [ + speed, + ]); } if (duration === 'c' || !Entry.parseNumber(duration)) { script.block_id = blockId; @@ -3008,9 +3088,13 @@ const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); if (speed.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [speed]); + this.requestExtCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [ + speed, + ]); } else { - this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [speed]); + this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_START, [ + speed, + ]); } if (duration === 'c' || !Entry.parseNumber(duration)) { script.block_id = blockId; @@ -3104,20 +3188,25 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const sensor = script.getNumberField('SENSOR', script); const speed = script.getStringField('SPEED', script); const blockId = this.generateBlockId(); script.block_id = blockId; if (speed.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.AUTO_DRIVING_SENSOR_START, [ - sensor, - speed, - ]); + this.requestExtCommand( + blockId, + NeoBlockType.AUTO_DRIVING_SENSOR_START, + [sensor, speed] + ); } else { - this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_SENSOR_START, [sensor, speed]); + this.requestCommand( + blockId, + NeoBlockType.AUTO_DRIVING_SENSOR_START, + [sensor, speed] + ); } - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -3151,11 +3240,11 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const blockId = this.generateBlockId(); script.block_id = blockId; this.requestCommand(blockId, NeoBlockType.AUTO_DRIVING_STOP, []); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -3581,9 +3670,15 @@ const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); if (brightness.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.LED_ON, [output, brightness]); + this.requestExtCommand(blockId, NeoBlockType.LED_ON, [ + output, + brightness, + ]); } else { - this.requestCommand(blockId, NeoBlockType.LED_ON, [output, brightness]); + this.requestCommand(blockId, NeoBlockType.LED_ON, [ + output, + brightness, + ]); } if (duration === 'c' || !Entry.parseNumber(duration)) { script.block_id = blockId; @@ -3686,7 +3781,11 @@ const speed = script.getStringValue('SPEED', script); const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); - this.requestCommand(blockId, NeoBlockType.LED_BLINK, [output, speed, 100]); + this.requestCommand(blockId, NeoBlockType.LED_BLINK, [ + output, + speed, + 100, + ]); if (duration === 'c' || !Entry.parseNumber(duration)) { script.exec_phase = ExecPhase.PENDING_STOP; script.block_id = blockId; @@ -3756,12 +3855,12 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringValue('OUTPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; this.requestCommand(blockId, NeoBlockType.LED_OFF, [output]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -3857,7 +3956,10 @@ const color = script.getStringValue('COLOR', script); const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); - this.requestCommand(blockId, NeoBlockType.COLOR_LED_ON, [output, color]); + this.requestCommand(blockId, NeoBlockType.COLOR_LED_ON, [ + output, + color, + ]); if (duration === 'c' || !Entry.parseNumber(duration)) { script.exec_phase = ExecPhase.PENDING_STOP; script.block_id = blockId; @@ -3927,12 +4029,12 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringValue('OUTPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; this.requestCommand(blockId, NeoBlockType.COLOR_LED_OFF, [output]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -3993,13 +4095,16 @@ isNotFor: ['NeoLite'], func: (sprite, script) => { if (!script.exec_phase) { - script.exec_phase = ExecPhase.PENDING_STOP; + script.exec_phase = ExecPhase.PENDING_RESPONSE; const output = script.getStringValue('OUTPUT', script); const input = script.getStringValue('INPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; - this.requestExtCommand(blockId, NeoBlockType.COLOR_LED_ON_SENSOR, [output, input]); - } else if (script.exec_phase === ExecPhase.PENDING_STOP) { + this.requestExtCommand(blockId, NeoBlockType.COLOR_LED_ON_SENSOR, [ + output, + input, + ]); + } else if (script.exec_phase === ExecPhase.PENDING_RESPONSE) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; delete script.exec_phase; @@ -4157,9 +4262,15 @@ const duration = script.getStringValue('DURATION', script); const blockId = this.generateBlockId(); if (value.indexOf('IN') >= 0) { - this.requestExtCommand(blockId, NeoBlockType.SET_OUTPUT, [output, value]); + this.requestExtCommand(blockId, NeoBlockType.SET_OUTPUT, [ + output, + value, + ]); } else { - this.requestCommand(blockId, NeoBlockType.SET_OUTPUT, [output, value]); + this.requestCommand(blockId, NeoBlockType.SET_OUTPUT, [ + output, + value, + ]); } if (duration === 'c' || !Entry.parseNumber(duration)) { script.exec_phase = ExecPhase.PENDING_STOP; @@ -4660,27 +4771,33 @@ const sensor3 = sensorData['in3Values'][0]; let lResult = false; if (lSymbol === '=') { - lResult = lValue === sensor1 && lValue === sensor2 && lValue === sensor3; + lResult = + lValue === sensor1 && lValue === sensor2 && lValue === sensor3; } else if (lSymbol === '>') { lResult = lValue > sensor1 && lValue > sensor2 && lValue > sensor3; } else if (lSymbol === '<') { lResult = lValue < sensor1 && lValue < sensor2 && lValue < sensor3; } else if (lSymbol === '>=') { - lResult = lValue >= sensor1 && lValue >= sensor2 && lValue >= sensor3; + lResult = + lValue >= sensor1 && lValue >= sensor2 && lValue >= sensor3; } else if (lSymbol === '<=') { - lResult = lValue <= sensor1 && lValue <= sensor2 && lValue <= sensor3; + lResult = + lValue <= sensor1 && lValue <= sensor2 && lValue <= sensor3; } let rResult = false; if (rSymbol === '=') { - rResult = sensor1 === rValue && sensor2 === rValue && sensor3 === rValue; + rResult = + sensor1 === rValue && sensor2 === rValue && sensor3 === rValue; } else if (rSymbol === '>') { rResult = sensor1 > rValue && sensor2 > rValue && sensor3 > rValue; } else if (rSymbol === '<') { rResult = sensor1 < rValue && sensor2 < rValue && sensor3 < rValue; } else if (rSymbol === '>=') { - rResult = sensor1 >= rValue && sensor2 >= rValue && sensor3 >= rValue; + rResult = + sensor1 >= rValue && sensor2 >= rValue && sensor3 >= rValue; } else if (rSymbol === '<=') { - rResult = sensor1 <= rValue && sensor2 <= rValue && sensor3 <= rValue; + rResult = + sensor1 <= rValue && sensor2 <= rValue && sensor3 <= rValue; } return lResult && rResult; } else { @@ -4776,32 +4893,68 @@ const input = script.getStringField('INPUT'); const sensorData = this.sensorValues; const color = script.getNumberField('COLOR'); - let sensorValue = 0; - switch (input) { - case 'in1': - sensorValue = sensorData['in1Values'][0]; - break; - case 'in2': - sensorValue = sensorData['in2Values'][0]; - break; - case 'in3': - sensorValue = sensorData['in3Values'][0]; - break; - } + if (input === 'IN12') { + const sensor1 = sensorData['in1Values'][0]; + const sensor2 = sensorData['in2Values'][0]; + if (color === 1) { + return sensor1 === 0 && sensor2 === 0; + } else if (color === 2) { + return sensor1 === 40 && sensor2 === 40; + } else if (color === 3) { + return sensor1 === 80 && sensor2 === 80; + } else if (color === 4) { + return sensor1 === 120 && sensor2 === 120; + } else if (color === 5) { + return sensor1 === 160 && sensor2 === 160; + } else if (color === 6) { + return sensor1 === 200 && sensor2 === 200; + } + } else if (input === 'IN123') { + const sensor1 = sensorData['in1Values'][0]; + const sensor2 = sensorData['in2Values'][0]; + const sensor3 = sensorData['in3Values'][0]; + if (color === 1) { + return sensor1 === 0 && sensor2 === 0 && sensor3 === 0; + } else if (color === 2) { + return sensor1 === 40 && sensor2 === 40 && sensor3 === 40; + } else if (color === 3) { + return sensor1 === 80 && sensor2 === 80 && sensor3 === 80; + } else if (color === 4) { + return sensor1 === 120 && sensor2 === 120 && sensor3 === 120; + } else if (color === 5) { + return sensor1 === 160 && sensor2 === 160 && sensor3 === 160; + } else if (color === 6) { + return sensor1 === 200 && sensor2 === 200 && sensor3 === 200; + } + } else { + let sensorValue = 0; + switch (input) { + case 'IN1': + sensorValue = sensorData['in1Values'][0]; + break; + case 'IN2': + sensorValue = sensorData['in2Values'][0]; + break; + case 'IN3': + sensorValue = sensorData['in3Values'][0]; + break; + } - if (color === 1) { - return sensorValue === 0; - } else if (color === 2) { - return sensorValue === 0; - } else if (color === 3) { - return sensorValue === 0; - } else if (color === 4) { - return sensorValue === 0; - } else if (color === 5) { - return sensorValue === 0; - } else if (color === 6) { - return sensorValue === 0; + if (color === 1) { + return sensorValue === 0; + } else if (color === 2) { + return sensorValue === 40; + } else if (color === 3) { + return sensorValue === 80; + } else if (color === 4) { + return sensorValue === 120; + } else if (color === 5) { + return sensorValue === 160; + } else if (color === 6) { + return sensorValue === 200; + } } + return false; }, }, @@ -5039,7 +5192,9 @@ const input = script.getStringValue('INPUT', script); const blockId = this.generateBlockId(); script.block_id = blockId; - this.requestExtCommand(blockId, NeoBlockType.BUZZER_WITH_SENSOR, [input]); + this.requestExtCommand(blockId, NeoBlockType.BUZZER_WITH_SENSOR, [ + input, + ]); } else if (script.exec_phase === ExecPhase.PENDING_STOP) { if (!this.pendingResponseList[script.block_id]) { delete script.block_id; @@ -5148,8 +5303,6 @@ [Lang.Blocks.neo_lite_lcd_image_11, '11'], [Lang.Blocks.neo_lite_lcd_image_12, '12'], [Lang.Blocks.neo_lite_lcd_image_13, '13'], - [Lang.Blocks.neo_lite_lcd_image_14, '14'], - [Lang.Blocks.neo_lite_lcd_image_15, '15'], ], value: '1', fontSize: 11, @@ -5252,7 +5405,7 @@ /** * ARG Blocks */ - neo_lite_arg_motor_speed: { + neo_lite_arg_duration: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, skeleton: 'basic_string_field', @@ -5261,29 +5414,19 @@ { type: 'Dropdown', options: [ - [Lang.Blocks.neo_lite_motor_speed_100, '100'], - [Lang.Blocks.neo_lite_motor_speed_90, '90'], - [Lang.Blocks.neo_lite_motor_speed_80, '80'], - [Lang.Blocks.neo_lite_motor_speed_70, '70'], - [Lang.Blocks.neo_lite_motor_speed_60, '60'], - [Lang.Blocks.neo_lite_motor_speed_50, '50'], - [Lang.Blocks.neo_lite_motor_speed_40, '40'], - [Lang.Blocks.neo_lite_motor_speed_30, '30'], - [Lang.Blocks.neo_lite_motor_speed_20, '20'], - [Lang.Blocks.neo_lite_motor_speed_10, '10'], - [Lang.Blocks.neo_lite_motor_speed_0, '0'], - [Lang.Blocks.neo_lite_motor_speed_n10, '-10'], - [Lang.Blocks.neo_lite_motor_speed_n20, '-20'], - [Lang.Blocks.neo_lite_motor_speed_n30, '-30'], - [Lang.Blocks.neo_lite_motor_speed_n40, '-40'], - [Lang.Blocks.neo_lite_motor_speed_n50, '-50'], - [Lang.Blocks.neo_lite_motor_speed_n60, '-60'], - [Lang.Blocks.neo_lite_motor_speed_n70, '-70'], - [Lang.Blocks.neo_lite_motor_speed_n80, '-80'], - [Lang.Blocks.neo_lite_motor_speed_n90, '-90'], - [Lang.Blocks.neo_lite_motor_speed_n100, '-100'], + [Lang.Blocks.neo_lite_duration_c, 'c'], + [Lang.Blocks.neo_lite_duration_0, '0'], + [Lang.Blocks.neo_lite_duration_1, '1'], + [Lang.Blocks.neo_lite_duration_2, '2'], + [Lang.Blocks.neo_lite_duration_3, '3'], + [Lang.Blocks.neo_lite_duration_4, '4'], + [Lang.Blocks.neo_lite_duration_5, '5'], + [Lang.Blocks.neo_lite_duration_6, '6'], + [Lang.Blocks.neo_lite_duration_7, '7'], + [Lang.Blocks.neo_lite_duration_8, '8'], + [Lang.Blocks.neo_lite_duration_9, '9'], ], - value: '100', + value: 'c', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5302,7 +5445,7 @@ return script.getStringField('VALUE'); }, }, - neo_lite_arg_duration: { + neo_lite_arg_motor_speed: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, skeleton: 'basic_string_field', @@ -5311,19 +5454,29 @@ { type: 'Dropdown', options: [ - [Lang.Blocks.neo_lite_duration_c, 'c'], - [Lang.Blocks.neo_lite_duration_0, '0'], - [Lang.Blocks.neo_lite_duration_1, '1'], - [Lang.Blocks.neo_lite_duration_2, '2'], - [Lang.Blocks.neo_lite_duration_3, '3'], - [Lang.Blocks.neo_lite_duration_4, '4'], - [Lang.Blocks.neo_lite_duration_5, '5'], - [Lang.Blocks.neo_lite_duration_6, '6'], - [Lang.Blocks.neo_lite_duration_7, '7'], - [Lang.Blocks.neo_lite_duration_8, '8'], - [Lang.Blocks.neo_lite_duration_9, '9'], + [Lang.Blocks.neo_lite_motor_speed_100, '100'], + [Lang.Blocks.neo_lite_motor_speed_90, '90'], + [Lang.Blocks.neo_lite_motor_speed_80, '80'], + [Lang.Blocks.neo_lite_motor_speed_70, '70'], + [Lang.Blocks.neo_lite_motor_speed_60, '60'], + [Lang.Blocks.neo_lite_motor_speed_50, '50'], + [Lang.Blocks.neo_lite_motor_speed_40, '40'], + [Lang.Blocks.neo_lite_motor_speed_30, '30'], + [Lang.Blocks.neo_lite_motor_speed_20, '20'], + [Lang.Blocks.neo_lite_motor_speed_10, '10'], + [Lang.Blocks.neo_lite_motor_speed_0, '0'], + [Lang.Blocks.neo_lite_motor_speed_n10, '-10'], + [Lang.Blocks.neo_lite_motor_speed_n20, '-20'], + [Lang.Blocks.neo_lite_motor_speed_n30, '-30'], + [Lang.Blocks.neo_lite_motor_speed_n40, '-40'], + [Lang.Blocks.neo_lite_motor_speed_n50, '-50'], + [Lang.Blocks.neo_lite_motor_speed_n60, '-60'], + [Lang.Blocks.neo_lite_motor_speed_n70, '-70'], + [Lang.Blocks.neo_lite_motor_speed_n80, '-80'], + [Lang.Blocks.neo_lite_motor_speed_n90, '-90'], + [Lang.Blocks.neo_lite_motor_speed_n100, '-100'], ], - value: 'c', + value: '100', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5791,7 +5944,10 @@ data.writeInt16LE(speed, 0); data.writeInt16LE(robotCommand, 2); body.push(...data); - } else if (type === NeoBlockType.MOTOR_STOP || type === NeoBlockType.AUTO_DRIVING_STOP) { + } else if ( + type === NeoBlockType.MOTOR_STOP || + type === NeoBlockType.AUTO_DRIVING_STOP + ) { const which = params[0]; const direction = 1; body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR); @@ -5892,7 +6048,11 @@ body.push(...data); } else if (type === NeoBlockType.AUTO_DETECT_WALL_TURN) { const direction = params[0]; - body.push(UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.AUTO_DETECT_WALL); + body.push( + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.AUTO_DETECT_WALL + ); const data = Buffer.from([0, 0, 0, 0]); data.writeInt16LE(60, 0); data.writeInt16LE(direction, 2); @@ -5978,22 +6138,38 @@ if (type === NeoBlockType.MOTOR_MOVE) { const which = params[0]; const unitId = this.getUnitId(params[1]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.MOTOR); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.MOTOR + ); const data = Buffer.from([unitId, 0, which, 0, 0, 0]); body.push(...data); } else if (type === NeoBlockType.ROBOT_MOVE) { const robotCommand = params[0]; const unitId = this.getUnitId(params[1]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.ROBOT + ); const data = Buffer.from([unitId, 0, 0, 0]); data.writeInt16LE(robotCommand, 2); body.push(...data); - } else if (type === NeoBlockType.SERVO_ANGLE || type === NeoBlockType.SERVO_ANGLE_WAIT) { + } else if ( + type === NeoBlockType.SERVO_ANGLE || + type === NeoBlockType.SERVO_ANGLE_WAIT + ) { const unitId = this.getUnitId(params[0]); - const inUnitId = this.getUnitId(params[1]); - const speed = params[2]; + let angle = params[1]; + let speed = params[2]; + if (angle.indexOf('IN') >= 0) angle = this.getUnitId(angle); body.push(PduCode.EXTEND_1, blockId, unitId, ActorKind.SERVO, ServoCommand.ANGLE); - const data = Buffer.from([inUnitId, 0, 0, 0, 1, 0]); + const data = Buffer.from([angle, 0, 0, 0, 1, 0]); data.writeInt16LE(speed, 2); body.push(...data); } else if (type === NeoBlockType.SERVO_ROTATE) { @@ -6010,13 +6186,25 @@ type === NeoBlockType.AUTO_DETECT_WALL_START ) { const unitId = this.getUnitId(params[0]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.ROBOT + ); const data = Buffer.from([unitId, 0, 0x10, 0]); body.push(...data); } else if (type === NeoBlockType.AUTO_DRIVING_SENSOR_START) { const sensor = params[0]; const unitId = this.getUnitId(params[1]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.ROBOT); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.ROBOT + ); const data = Buffer.from([0, 0, 0, 0]); data.writeInt16LE(unitId, 0); data.writeInt16LE(sensor, 2); @@ -6035,7 +6223,13 @@ body.push(...data); } else if (type === NeoBlockType.BUZZER_WITH_SENSOR) { const sensorUnitId = this.getUnitId(params[0]); - body.push(PduCode.EXTEND_1, blockId, UnitId.CONTROLLER, ActorKind.CONTROLLER, ControllerCommand.BUZZER); + body.push( + PduCode.EXTEND_1, + blockId, + UnitId.CONTROLLER, + ActorKind.CONTROLLER, + ControllerCommand.BUZZER + ); const data = Buffer.from([0, 0]); data.writeInt16LE(sensorUnitId, 0); body.push(...data); @@ -6049,6 +6243,18 @@ return body; } + makeCommandExt2(blockId, type, params) { + const body = [FrameCode.BASIC]; + if (type === NeoBlockType.SERVO_ANGLE || type === NeoBlockType.SERVO_ANGLE_WAIT) { + const unitId = this.getUnitId(params[0]); + const angleInUnitId = this.getUnitId(params[1]); + const speedInUnitId = this.getUnitId(params[2]); + body.push(PduCode.EXTEND_2, blockId, unitId, ActorKind.SERVO, ServoCommand.ANGLE); + const data = Buffer.from([angleInUnitId, 0, speedInUnitId, 0, 1, 0]); + body.push(...data); + } + return body; + } /* 후면주차 실행 (pending response 하지 않고 바로 다음 단계로 넘어감 : phase 가 너무 많아서 간소화) 주석은 왼쪽 기준으로 오른쪽에서는 좌우만 바꿔준다. @@ -6078,7 +6284,8 @@ this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [which === 1 ? 5 : 6, 20]); } else if (script.exec_phase === '5_wait_sensor') { // 5. IN2 40 초과 기다리기 - const compareValue = which === 1 ? sensorData.in2Values[0] : sensorData.in1Values[0]; + const compareValue = + which === 1 ? sensorData.in2Values[0] : sensorData.in1Values[0]; if (compareValue > 40) { script.exec_phase = '6_stop_robot'; } @@ -6099,7 +6306,8 @@ this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [2, 20]); } else if (script.exec_phase === '9_wait_sensor') { // 9. IN1 20초과 기다리기 - const compareValue = which === 1 ? sensorData.in1Values[0] : sensorData.in2Values[0]; + const compareValue = + which === 1 ? sensorData.in1Values[0] : sensorData.in2Values[0]; if (compareValue > 20) { script.exec_phase = '10_stop_robot'; } @@ -6191,13 +6399,15 @@ this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [2, 30]); } else if (script.exec_phase === '5_wait_sensor') { // 5. IN1 40 초과 기다리기 - const compareValue = which === 1 ? sensorData.in1Values[0] : sensorData.in2Values[0]; + const compareValue = + which === 1 ? sensorData.in1Values[0] : sensorData.in2Values[0]; if (compareValue > 40) { script.exec_phase = '6_wait_sensor'; } } else if (script.exec_phase === '6_wait_sensor') { // 6. IN2 40 초과 기다리기 - const compareValue = which === 1 ? sensorData.in2Values[0] : sensorData.in1Values[0]; + const compareValue = + which === 1 ? sensorData.in2Values[0] : sensorData.in1Values[0]; if (compareValue > 40) { script.exec_phase = '7_robot_stop'; } @@ -6218,7 +6428,8 @@ this.requestCommand(blockId, NeoBlockType.ROBOT_MOVE, [which === 1 ? 5 : 6, 20]); } else if (script.exec_phase === '10_wait_sensor') { // 10. IN1 40초과 기다리기 - const compareValue = which === 1 ? sensorData.in1Values[0] : sensorData.in2Values[0]; + const compareValue = + which === 1 ? sensorData.in1Values[0] : sensorData.in2Values[0]; if (compareValue > 40) { script.exec_phase = '11_stop_robot'; } diff --git a/src/playground/blocks/hardwareLite/block_neobot_purple_lite.js b/src/playground/blocks/hardwareLite/block_neobot_purple_lite.js index 61250f880a..add61313a3 100644 --- a/src/playground/blocks/hardwareLite/block_neobot_purple_lite.js +++ b/src/playground/blocks/hardwareLite/block_neobot_purple_lite.js @@ -1,5 +1,6 @@ 'use strict'; (function() { + const HEADER = [0xab, 0xcd]; Entry.NeobotPurpleLite = new (class NeobotPurpleLite { constructor() { this.id = '5.5'; @@ -27,8 +28,8 @@ OUT1: 0, OUT2: 0, OUT3: 0, - DCR: 0, DCL: 0, + DCR: 0, SND: 0, FND: 0, OPT: 0, @@ -37,41 +38,43 @@ this.blockMenuBlocks = [ // sensor + 'neobot_purple_lite_sensor_title', 'neobot_purple_lite_sensor_value', 'neobot_purple_lite_sensor_convert_scale', - - // decision 'neobot_purple_lite_decision_sensor_is_over', 'neobot_purple_lite_decision_equal_with_sensor', 'neobot_purple_lite_decision_sensor_angle', - - // remote 'neobot_purple_lite_remote_button', // led + 'neobot_purple_lite_led_title', 'neobot_purple_lite_led_on', 'neobot_purple_lite_led_brightness_with_sensor', 'neobot_purple_lite_color_led_on', 'neobot_purple_lite_output_led_off', // output + 'neobot_purple_lite_output_title', 'neobot_purple_lite_set_output', // motor + 'neobot_purple_lite_motor_title', 'neobot_purple_lite_robot', 'neobot_purple_lite_motor_start', 'neobot_purple_lite_motor_stop', - // melody - 'neobot_purple_lite_play_note_for', - 'neobot_purple_lite_melody_play_with_sensor', - 'neobot_purple_lite_melody_stop', - // servo + 'neobot_purple_lite_servo_title', 'neobot_purple_lite_servo_init', 'neobot_purple_lite_servo_rotate', 'neobot_purple_lite_servo_stop', 'neobot_purple_lite_servo_change_degree', + + // melody + 'neobot_purple_lite_buzzer_title', + 'neobot_purple_lite_play_note_for', + 'neobot_purple_lite_melody_play_with_sensor', + 'neobot_purple_lite_melody_stop', ]; this.setZero(); @@ -79,7 +82,7 @@ get monitorTemplate() { return { - imgPath: 'hw_lite/neobot_purple_lite.png', + imgPath: 'hw/neobot_purple.png', width: 700, height: 700, listPorts: { @@ -147,8 +150,8 @@ OUT1: 0, OUT2: 0, OUT3: 0, - DCR: 0, DCL: 0, + DCR: 0, SND: 0, FND: 0, OPT: 0, @@ -159,17 +162,95 @@ } handleLocalData(data) { - for (let i = 0; i < data.length - 1; i++) { - if (data[i] === 171 && data[i + 1] === 205) { - const dataSet = data.slice(i + 2, i + 7); - dataSet.forEach((value, idx) => { - this.localBuffer[this.LOCAL_MAP[idx]] = value; - }); + let validPdu = this.getValidPdu(data); + while (validPdu) { + this.onReceivePdu(validPdu); + if (!this.remainingPdu || this.remainingPdu.length <= 0) { break; } + validPdu = this.getValidPdu([]); } } + onReceivePdu(pdu) { + if (pdu[0] === HEADER[0] && pdu[1] === HEADER[1]) { + this.localBuffer['IN1'] = pdu[2]; + this.localBuffer['IN2'] = pdu[3]; + this.localBuffer['IN3'] = pdu[4]; + this.localBuffer['IR'] = pdu[5]; + this.localBuffer['BAT'] = pdu[6]; + } + } + + getValidPdu(pdu) { + const mergedPdu = []; + if (this.remainingPdu) { + mergedPdu.push(...this.remainingPdu); + this.remainingPdu = null; + } + mergedPdu.push(...pdu); + if (mergedPdu.length < 2) { + this.remainingPdu = [...mergedPdu]; + return null; + } + + // 헤더 불일치는 버림 + if (!this.checkHeader(mergedPdu)) { + return null; + } + + // 유효 데이터 길이는 header 2 + body 5 + checksum 1 = 8 + const validDataLength = 8; + /* + 전체 길이가 유효 데이터 길이보다 작을 경우 + 아직 도착하지 않은 부분이 있으므로 병합을 위해 remainingPdu 에 저장 + */ + if (mergedPdu.length < validDataLength) { + this.remainingPdu = [...mergedPdu]; + return null; + } + + /* + 전체 길이가 유효 데이터 길이보다 클 경우 + 유효한 부분만 잘라내고 나머지는 remainingPdu 에 저장 + */ + if (mergedPdu.length > validDataLength) { + this.remainingPdu = mergedPdu.slice(validDataLength, mergedPdu.length); + } + + const validPdu = mergedPdu.slice(0, validDataLength); + + /* + 유효 Pdu 의 checksum 확인 + */ + const dataLength = 5; + let checkSum = 0; + for (let i = 0; i < dataLength; i++) { + checkSum += validPdu[i + 2]; + } + checkSum = checkSum & 255; + const pduCheckSum = validPdu[7]; + if (pduCheckSum !== checkSum) { + return null; + } + + return validPdu; + } + + checkHeader(pdu) { + if (pdu.length < HEADER.length) { + return false; + } + + for (let i = 0; i < HEADER.length; i++) { + if (HEADER[i] !== pdu[i]) { + return false; + } + } + + return true; + } + requestLocalData() { const requestData = []; @@ -201,18 +282,16 @@ ko: { template: { // sensor + neobot_purple_lite_sensor_title: '센서', neobot_purple_lite_sensor_value: '%1', neobot_purple_lite_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환', - - // decision neobot_purple_lite_decision_sensor_is_over: '%1 %2 %3', neobot_purple_lite_decision_equal_with_sensor: '%1 컬러가 %2', neobot_purple_lite_decision_sensor_angle: '%1 각도 %2 %3', - - // remote neobot_purple_lite_remote_button: '리모컨 버튼 %1 을 누름', // LED + neobot_purple_lite_led_title: 'LED', neobot_purple_lite_arg_led_duration: '%1', neobot_purple_lite_led_on: 'LED 켜기 %1 %2 %3 %4', neobot_purple_lite_output_led_off: '%1 LED 끄기 %2', @@ -220,9 +299,11 @@ neobot_purple_lite_color_led_on: '%1 컬러LED 켜기 R %2 G %3 B %4 %5', // output + neobot_purple_lite_output_title: '출력', neobot_purple_lite_set_output: '%1 에 %2 값 출력하기 %3', // motor + neobot_purple_lite_motor_title: '회전모터', neobot_purple_lite_robot: '로봇 %1 %2', neobot_purple_lite_motor_start: '모터 회전하기 %1 %2 %3 %4 %5', neobot_purple_lite_motor_stop: '%1 모터 멈추기 %2', @@ -230,12 +311,14 @@ neobot_purple_lite_arg_motor_duration: '%1', // melody + neobot_purple_lite_buzzer_title: '버저', neobot_purple_lite_play_note_for: '버저 울리기 옥타브: %2 음: %1 길이: %3 %4', neobot_purple_lite_melody_play_with_sensor: '%1 센서로 버저 울리기 %2', neobot_purple_lite_melody_stop: '버저 멈추기 %1', // servo + neobot_purple_lite_servo_title: '서보모터', get_servo_degree: '%1', neobot_purple_lite_servo_init: '%1 서보모터 리셋 %2', neobot_purple_lite_servo_rotate: '서보모터 회전하기 %1 %2 %3 %4', @@ -376,19 +459,17 @@ // en.js에 작성하던 내용 template: { // sensor + neobot_purple_lite_sensor_title: 'Sensor', neobot_purple_lite_sensor_value: '%1', neobot_purple_lite_sensor_convert_scale: "%1 's changed value range: %2 ~ %3 conversion: %4 ~ %5", - - // decision neobot_purple_lite_decision_sensor_is_over: '%1 %2 %3', neobot_purple_lite_decision_equal_with_sensor: "%1 's color is %2", neobot_purple_lite_decision_sensor_angle: '%1 angle %2 %3', - - // remote neobot_purple_lite_remote_button: 'pressing button %1 of remote controller', // LED + neobot_purple_lite_led_title: 'LED', neobot_purple_lite_arg_led_duration: '%1', neobot_purple_lite_led_on: 'Turn on the LED %1 %2 %3 %4', neobot_purple_lite_output_led_off: 'Turn off the %1 LED %2', @@ -398,9 +479,11 @@ 'Turn on the %1 color LED R %2 G %3 B %4 %5', // output + neobot_purple_lite_output_title: 'Set output', neobot_purple_lite_set_output: 'Output %2 value to %1 port %3', // motor + neobot_purple_lite_motor_title: 'Motor', neobot_purple_lite_robot: 'Robot %1 %2', neobot_purple_lite_motor_start: 'Motor operation %1 %2 %3 %4 %5', neobot_purple_lite_motor_stop: 'Stop the %1 motor(s) %2', @@ -408,6 +491,7 @@ neobot_purple_lite_arg_motor_duration: '%1', // melody + neobot_purple_lite_buzzer_title: 'Buzzer', neobot_purple_lite_play_note_for: 'Buzzer octave: %1 scale: %2 note: %3 %4', neobot_purple_lite_melody_play_with_sensor: @@ -415,6 +499,7 @@ neobot_purple_lite_melody_stop: 'Stop the buzzer %1', // servo + neobot_purple_lite_servo_title: 'Servo motor', neobot_purple_lite_servo_init: 'Reset the %1 servo motor %2', neobot_purple_lite_servo_rotate: 'Rotate the servo motor %1 %2 %3 %4', neobot_purple_lite_servo_stop: 'Stop the %1 servo motor %2', @@ -558,6 +643,30 @@ /************************* * class neobot_purple_lite_sensor *************************/ + neobot_purple_lite_sensor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_lite_sensor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_lite_sensor_title', + }, + class: 'neobot_purple_lite_sensor', + isNotFor: ['NeobotPurpleLite'], + events: {}, + }, neobot_purple_lite_sensor_value: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -693,10 +802,6 @@ return Math.round(value); }, }, - - /************************* - * class neobot_purple_lite_decision - *************************/ neobot_purple_lite_decision_sensor_is_over: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -746,7 +851,7 @@ SYMBOL: 1, VALUE: 2, }, - class: 'neobot_purple_lite_decision', + class: 'neobot_purple_lite_sensor', isNotFor: ['NeobotPurpleLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -848,7 +953,7 @@ SENSOR: 0, COLOR: 1, }, - class: 'neobot_purple_lite_decision', + class: 'neobot_purple_lite_sensor', isNotFor: ['NeobotPurpleLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -962,7 +1067,7 @@ SYMBOL: 1, VALUE: 2, }, - class: 'neobot_purple_lite_decision', + class: 'neobot_purple_lite_sensor', isNotFor: ['NeobotPurpleLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -1004,10 +1109,6 @@ return false; }, }, - - /************************* - * class neobot_purple_lite_remote - *************************/ neobot_purple_lite_remote_button: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1041,7 +1142,7 @@ paramsKeyMap: { KEY: 0, }, - class: 'neobot_purple_lite_remote', + class: 'neobot_purple_lite_sensor', isNotFor: ['NeobotPurpleLite'], func(sprite, script) { const key = script.getNumberField('KEY'); @@ -1057,6 +1158,30 @@ /************************* * class neobot_purple_lite_led *************************/ + neobot_purple_lite_led_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_lite_led_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_lite_led_title', + }, + class: 'neobot_purple_lite_led', + isNotFor: ['NeobotPurpleLite'], + events: {}, + }, neobot_purple_lite_led_on: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1584,6 +1709,30 @@ /************************* * class neobot_purple_lite_output *************************/ + neobot_purple_lite_output_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_lite_output_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_lite_output_title', + }, + class: 'neobot_purple_lite_output', + isNotFor: ['NeobotPurpleLite'], + events: {}, + }, neobot_purple_lite_set_output: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1661,6 +1810,30 @@ /************************* * class neobot_purple_lite_motor *************************/ + neobot_purple_lite_motor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_lite_motor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_lite_motor_title', + }, + class: 'neobot_purple_lite_motor', + isNotFor: ['NeobotPurpleLite'], + events: {}, + }, neobot_purple_lite_robot: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1987,6 +2160,30 @@ /************************* * class neobot_purple_lite_melody *************************/ + neobot_purple_lite_buzzer_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_lite_buzzer_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_lite_buzzer_title', + }, + class: 'neobot_purple_lite_buzzer', + isNotFor: ['NeobotPurpleLite'], + events: {}, + }, neobot_purple_lite_play_note_for: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2059,7 +2256,7 @@ OCTAVE: 1, DURATION: 2, }, - class: 'neobot_purple_lite_melody', + class: 'neobot_purple_lite_buzzer', isNotFor: ['NeobotPurpleLite'], func(sprite, script) { if (!script.isStart) { @@ -2140,7 +2337,7 @@ paramsKeyMap: { INPUT: 0, }, - class: 'neobot_purple_lite_melody', + class: 'neobot_purple_lite_buzzer', isNotFor: ['NeobotPurpleLite'], func(sprite, script) { const input = script.getStringField('INPUT'); @@ -2184,7 +2381,7 @@ type: 'neobot_purple_lite_melody_stop', }, paramsKeyMap: {}, - class: 'neobot_purple_lite_melody', + class: 'neobot_purple_lite_buzzer', isNotFor: ['NeobotPurpleLite'], func(sprite, script) { if (Entry.NeobotPurpleLite.log_to_console) { @@ -2201,6 +2398,30 @@ /************************* * class neobot_purple_lite_servo *************************/ + neobot_purple_lite_servo_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_purple_lite_servo_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_purple_lite_servo_title', + }, + class: 'neobot_purple_lite_servo', + isNotFor: ['NeobotPurpleLite'], + events: {}, + }, neobot_purple_lite_servo_init: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, diff --git a/src/playground/blocks/hardwareLite/block_neobot_soco_lite.js b/src/playground/blocks/hardwareLite/block_neobot_soco_lite.js index f06d91f5ea..de221e2bd7 100644 --- a/src/playground/blocks/hardwareLite/block_neobot_soco_lite.js +++ b/src/playground/blocks/hardwareLite/block_neobot_soco_lite.js @@ -1,5 +1,6 @@ 'use strict'; (function() { + const HEADER = [0xab, 0xcd]; Entry.NeobotSocoLite = new (class NeobotSocoLite { constructor() { this.id = '5.6'; @@ -27,8 +28,8 @@ OUT1: 0, OUT2: 0, OUT3: 0, - DCR: 0, DCL: 0, + DCR: 0, SND: 0, FND: 0, OPT: 0, @@ -37,41 +38,43 @@ this.blockMenuBlocks = [ // sensor + 'neobot_soco_lite_sensor_title', 'neobot_soco_lite_sensor_value', 'neobot_soco_lite_sensor_convert_scale', - - // decision 'neobot_soco_lite_decision_sensor_is_over', 'neobot_soco_lite_decision_equal_with_sensor', 'neobot_soco_lite_decision_sensor_angle', - - // remote 'neobot_soco_lite_remote_button', // led + 'neobot_soco_lite_led_title', 'neobot_soco_lite_led_on', 'neobot_soco_lite_led_brightness_with_sensor', 'neobot_soco_lite_color_led_on', 'neobot_soco_lite_output_led_off', // output + 'neobot_soco_lite_output_title', 'neobot_soco_lite_set_output', // motor + 'neobot_soco_lite_motor_title', 'neobot_soco_lite_robot', 'neobot_soco_lite_motor_start', 'neobot_soco_lite_motor_stop', - // melody - 'neobot_soco_lite_play_note_for', - 'neobot_soco_lite_melody_play_with_sensor', - 'neobot_soco_lite_melody_stop', - // servo + 'neobot_soco_lite_servo_title', 'neobot_soco_lite_servo_init', 'neobot_soco_lite_servo_rotate', 'neobot_soco_lite_servo_stop', 'neobot_soco_lite_servo_change_degree', + + // buzzer + 'neobot_soco_lite_buzzer_title', + 'neobot_soco_lite_play_note_for', + 'neobot_soco_lite_melody_play_with_sensor', + 'neobot_soco_lite_melody_stop', ]; this.setZero(); @@ -79,7 +82,7 @@ get monitorTemplate() { return { - imgPath: 'hw_lite/neobot_soco_lite.png', + imgPath: 'hw/neobot_soco.png', width: 700, height: 700, listPorts: { @@ -111,8 +114,8 @@ OUT1: 0, OUT2: 0, OUT3: 0, - DCR: 0, DCL: 0, + DCR: 0, SND: 0, FND: 0, OPT: 0, @@ -123,15 +126,93 @@ } handleLocalData(data) { - for (let i = 0; i < data.length - 1; i++) { - if (data[i] === 171 && data[i + 1] === 205) { - const dataSet = data.slice(i + 2, i + 7); - dataSet.forEach((value, idx) => { - this.localBuffer[this.LOCAL_MAP[idx]] = value; - }); + let validPdu = this.getValidPdu(data); + while (validPdu) { + this.onReceivePdu(validPdu); + if (!this.remainingPdu || this.remainingPdu.length <= 0) { break; } + validPdu = this.getValidPdu([]); + } + } + + onReceivePdu(pdu) { + if (pdu[0] === HEADER[0] && pdu[1] === HEADER[1]) { + this.localBuffer['IN1'] = pdu[2]; + this.localBuffer['IN2'] = pdu[3]; + this.localBuffer['IN3'] = pdu[4]; + this.localBuffer['IR'] = pdu[5]; + this.localBuffer['BAT'] = pdu[6]; + } + } + + getValidPdu(pdu) { + const mergedPdu = []; + if (this.remainingPdu) { + mergedPdu.push(...this.remainingPdu); + this.remainingPdu = null; + } + mergedPdu.push(...pdu); + if (mergedPdu.length < 2) { + this.remainingPdu = [...mergedPdu]; + return null; + } + + // 헤더 불일치는 버림 + if (!this.checkHeader(mergedPdu)) { + return null; + } + + // 유효 데이터 길이는 header 2 + body 5 + checksum 1 = 8 + const validDataLength = 8; + /* + 전체 길이가 유효 데이터 길이보다 작을 경우 + 아직 도착하지 않은 부분이 있으므로 병합을 위해 remainingPdu 에 저장 + */ + if (mergedPdu.length < validDataLength) { + this.remainingPdu = [...mergedPdu]; + return null; + } + + /* + 전체 길이가 유효 데이터 길이보다 클 경우 + 유효한 부분만 잘라내고 나머지는 remainingPdu 에 저장 + */ + if (mergedPdu.length > validDataLength) { + this.remainingPdu = mergedPdu.slice(validDataLength, mergedPdu.length); + } + + const validPdu = mergedPdu.slice(0, validDataLength); + + /* + 유효 Pdu 의 checksum 확인 + */ + const dataLength = 5; + let checkSum = 0; + for (let i = 0; i < dataLength; i++) { + checkSum += validPdu[i + 2]; + } + checkSum = checkSum & 255; + const pduCheckSum = validPdu[7]; + if (pduCheckSum !== checkSum) { + return null; + } + + return validPdu; + } + + checkHeader(pdu) { + if (pdu.length < HEADER.length) { + return false; + } + + for (let i = 0; i < HEADER.length; i++) { + if (HEADER[i] !== pdu[i]) { + return false; + } } + + return true; } requestLocalData() { @@ -165,18 +246,16 @@ ko: { template: { // sensor + neobot_soco_lite_sensor_title: '센서', neobot_soco_lite_sensor_value: '%1', neobot_soco_lite_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환', - - // decision neobot_soco_lite_decision_sensor_is_over: '%1 %2 %3', neobot_soco_lite_decision_equal_with_sensor: '%1 컬러가 %2', neobot_soco_lite_decision_sensor_angle: '%1 각도 %2 %3', - - // remote neobot_soco_lite_remote_button: '리모컨 버튼 %1 을 누름', // LED + neobot_soco_lite_led_title: 'LED', neobot_soco_lite_arg_led_duration: '%1', neobot_soco_lite_led_on: 'LED 켜기 %1 %2 %3 %4', neobot_soco_lite_output_led_off: '%1 LED 끄기 %2', @@ -184,9 +263,11 @@ neobot_soco_lite_color_led_on: '%1 컬러LED 켜기 R %2 G %3 B %4 %5', // output + neobot_soco_lite_output_title: '출력', neobot_soco_lite_set_output: '%1 에 %2 값 출력하기 %3', // motor + neobot_soco_lite_motor_title: '회전모터', neobot_soco_lite_robot: '로봇 %1 %2', neobot_soco_lite_motor_start: '모터 회전하기 %1 %2 %3 %4 %5', neobot_soco_lite_motor_stop: '%1 모터 멈추기 %2', @@ -194,12 +275,14 @@ neobot_soco_lite_arg_motor_duration: '%1', // melody + neobot_soco_lite_buzzer_title: '버저', neobot_soco_lite_play_note_for: '버저 울리기 옥타브: %2 음: %1 길이: %3 %4', neobot_soco_lite_melody_play_with_sensor: '%1 센서로 버저 울리기 %2', neobot_soco_lite_melody_stop: '버저 멈추기 %1', // servo + neobot_soco_lite_servo_title: '서보모터', get_servo_degree: '%1', neobot_soco_lite_servo_init: '%1 서보모터 리셋 %2', neobot_soco_lite_servo_rotate: '서보모터 회전하기 %1 %2 %3 %4', @@ -340,19 +423,17 @@ // en.js에 작성하던 내용 template: { // sensor + neobot_soco_lite_sensor_title: 'Sensor', neobot_soco_lite_sensor_value: '%1', neobot_soco_lite_sensor_convert_scale: "%1 's changed value range: %2 ~ %3 conversion: %4 ~ %5", - - // decision neobot_soco_lite_decision_sensor_is_over: '%1 %2 %3', neobot_soco_lite_decision_equal_with_sensor: "%1 's color is %2", neobot_soco_lite_decision_sensor_angle: '%1 angle %2 %3', - - // remote neobot_soco_lite_remote_button: 'pressing button %1 of remote controller', // LED + neobot_soco_lite_led_title: 'LED', neobot_soco_lite_arg_led_duration: '%1', neobot_soco_lite_led_on: 'Turn on the LED %1 %2 %3 %4', neobot_soco_lite_output_led_off: 'Turn off the %1 LED %2', @@ -362,9 +443,11 @@ 'Turn on the %1 color LED R %2 G %3 B %4 %5', // output + neobot_soco_lite_output_title: 'Set output', neobot_soco_lite_set_output: 'Output %2 value to %1 port %3', // motor + neobot_soco_lite_motor_title: 'Motor', neobot_soco_lite_robot: 'Robot %1 %2', neobot_soco_lite_motor_start: 'Motor operation %1 %2 %3 %4 %5', neobot_soco_lite_motor_stop: 'Stop the %1 motor(s) %2', @@ -372,12 +455,14 @@ neobot_soco_lite_arg_motor_duration: '%1', // melody + neobot_soco_lite_buzzer_title: 'Buzzer', neobot_soco_lite_play_note_for: 'Buzzer octave: %1 scale: %2 note: %3 %4', neobot_soco_lite_melody_play_with_sensor: 'Buzzer rings by %1 sensor value %2', neobot_soco_lite_melody_stop: 'Stop the buzzer %1', // servo + neobot_soco_lite_servo_title: 'Servo motor', neobot_soco_lite_servo_init: 'Reset the %1 servo motor %2', neobot_soco_lite_servo_rotate: 'Rotate the servo motor %1 %2 %3 %4', neobot_soco_lite_servo_stop: 'Stop the %1 servo motor %2', @@ -520,6 +605,30 @@ /************************* * class neobot_soco_lite_sensor *************************/ + neobot_soco_lite_sensor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_lite_sensor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_lite_sensor_title', + }, + class: 'neobot_soco_lite_sensor', + isNotFor: ['NeobotSocoLite'], + events: {}, + }, neobot_soco_lite_sensor_value: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -655,10 +764,6 @@ return Math.round(value); }, }, - - /************************* - * class neobot_soco_lite_decision - *************************/ neobot_soco_lite_decision_sensor_is_over: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -708,7 +813,7 @@ SYMBOL: 1, VALUE: 2, }, - class: 'neobot_soco_lite_decision', + class: 'neobot_soco_lite_sensor', isNotFor: ['NeobotSocoLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -810,7 +915,7 @@ SENSOR: 0, COLOR: 1, }, - class: 'neobot_soco_lite_decision', + class: 'neobot_soco_lite_sensor', isNotFor: ['NeobotSocoLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -924,7 +1029,7 @@ SYMBOL: 1, VALUE: 2, }, - class: 'neobot_soco_lite_decision', + class: 'neobot_soco_lite_sensor', isNotFor: ['NeobotSocoLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -967,9 +1072,6 @@ }, }, - /************************* - * class neobot_soco_lite_remote - *************************/ neobot_soco_lite_remote_button: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1003,7 +1105,7 @@ paramsKeyMap: { KEY: 0, }, - class: 'neobot_soco_lite_remote', + class: 'neobot_soco_lite_sensor', isNotFor: ['NeobotSocoLite'], func(sprite, script) { const key = script.getNumberField('KEY'); @@ -1019,6 +1121,30 @@ /************************* * class neobot_soco_lite_led *************************/ + neobot_soco_lite_led_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_lite_led_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_lite_led_title', + }, + class: 'neobot_soco_lite_led', + isNotFor: ['NeobotSocoLite'], + events: {}, + }, neobot_soco_lite_led_on: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1543,6 +1669,30 @@ /************************* * class neobot_soco_lite_output *************************/ + neobot_soco_lite_output_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_lite_output_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_lite_output_title', + }, + class: 'neobot_soco_lite_output', + isNotFor: ['NeobotSocoLite'], + events: {}, + }, neobot_soco_lite_set_output: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1620,6 +1770,30 @@ /************************* * class neobot_soco_lite_motor *************************/ + neobot_soco_lite_motor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_lite_motor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_lite_motor_title', + }, + class: 'neobot_soco_lite_motor', + isNotFor: ['NeobotSocoLite'], + events: {}, + }, neobot_soco_lite_robot: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1946,6 +2120,30 @@ /************************* * class neobot_soco_lite_melody *************************/ + neobot_soco_lite_buzzer_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_lite_buzzer_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_lite_buzzer_title', + }, + class: 'neobot_soco_lite_melody', + isNotFor: ['NeobotSocoLite'], + events: {}, + }, neobot_soco_lite_play_note_for: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2160,6 +2358,30 @@ /************************* * class neobot_soco_lite_servo *************************/ + neobot_soco_lite_servo_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_soco_lite_servo_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_soco_lite_servo_title', + }, + class: 'neobot_soco_lite_servo', + isNotFor: ['NeobotSocoLite'], + events: {}, + }, neobot_soco_lite_servo_init: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, diff --git a/src/playground/blocks/hardwareLite/block_neobot_thinkcar_lite.js b/src/playground/blocks/hardwareLite/block_neobot_thinkcar_lite.js index 978b395351..aba040d809 100644 --- a/src/playground/blocks/hardwareLite/block_neobot_thinkcar_lite.js +++ b/src/playground/blocks/hardwareLite/block_neobot_thinkcar_lite.js @@ -1,5 +1,7 @@ 'use strict'; (function() { + const HEADER = [0xab, 0xcd]; + Entry.NeobotThinkCarLite = new (class NeobotThinkCarLite { constructor() { this.id = '5.7'; @@ -27,8 +29,8 @@ OUT1: 0, OUT2: 0, OUT3: 0, - DCR: 0, DCL: 0, + DCR: 0, SND: 0, FND: 0, OPT: 0, @@ -37,6 +39,7 @@ this.blockMenuBlocks = [ // think car + 'neobot_think_car_lite_auto_driving_title', 'neobot_think_car_lite_line_tracer_start', // 'neobot_think_car_lite_line_tracer_change_speed', 'neobot_think_car_lite_reverse_parking_start', @@ -44,41 +47,43 @@ 'neobot_think_car_lite_driving_stop', // sensor + 'neobot_think_car_lite_sensor_title', 'neobot_think_car_lite_sensor_value', 'neobot_think_car_lite_sensor_convert_scale', - - // decision 'neobot_think_car_lite_decision_sensor_is_over', 'neobot_think_car_lite_decision_equal_with_sensor', 'neobot_think_car_lite_decision_sensor_angle', - - // remote 'neobot_think_car_lite_remote_button', // led + 'neobot_think_car_lite_led_title', 'neobot_think_car_lite_led_on', 'neobot_think_car_lite_led_brightness_with_sensor', 'neobot_think_car_lite_color_led_on', 'neobot_think_car_lite_output_led_off', // output + 'neobot_think_car_lite_output_title', 'neobot_think_car_lite_set_output', // motor + 'neobot_think_car_lite_motor_title', 'neobot_think_car_lite_robot', 'neobot_think_car_lite_motor_start', 'neobot_think_car_lite_motor_stop', - // melody - 'neobot_think_car_lite_play_note_for', - 'neobot_think_car_lite_melody_play_with_sensor', - 'neobot_think_car_lite_melody_stop', - // servo + 'neobot_think_car_lite_servo_title', 'neobot_think_car_lite_servo_init', 'neobot_think_car_lite_servo_rotate', 'neobot_think_car_lite_servo_stop', 'neobot_think_car_lite_servo_change_degree', + + // melody + 'neobot_think_car_lite_buzzer_title', + 'neobot_think_car_lite_play_note_for', + 'neobot_think_car_lite_melody_play_with_sensor', + 'neobot_think_car_lite_melody_stop', ]; this.setZero(); @@ -86,7 +91,7 @@ get monitorTemplate() { return { - imgPath: 'hw_lite/neobot_thinkcar_lite.png', + imgPath: 'hw/neobot_thinkcar.png', width: 700, height: 700, listPorts: { @@ -118,8 +123,8 @@ OUT1: 0, OUT2: 0, OUT3: 0, - DCR: 0, DCL: 0, + DCR: 0, SND: 0, FND: 0, OPT: 0, @@ -130,17 +135,95 @@ } handleLocalData(data) { - for (let i = 0; i < data.length - 1; i++) { - if (data[i] === 171 && data[i + 1] === 205) { - const dataSet = data.slice(i + 2, i + 7); - dataSet.forEach((value, idx) => { - this.localBuffer[this.LOCAL_MAP[idx]] = value; - }); + let validPdu = this.getValidPdu(data); + while (validPdu) { + this.onReceivePdu(validPdu); + if (!this.remainingPdu || this.remainingPdu.length <= 0) { break; } + validPdu = this.getValidPdu([]); + } + } + + onReceivePdu(pdu) { + if (pdu[0] === HEADER[0] && pdu[1] === HEADER[1]) { + this.localBuffer['IN1'] = pdu[2]; + this.localBuffer['IN2'] = pdu[3]; + this.localBuffer['IN3'] = pdu[4]; + this.localBuffer['IR'] = pdu[5]; + this.localBuffer['BAT'] = pdu[6]; } } + getValidPdu(pdu) { + const mergedPdu = []; + if (this.remainingPdu) { + mergedPdu.push(...this.remainingPdu); + this.remainingPdu = null; + } + mergedPdu.push(...pdu); + if (mergedPdu.length < 2) { + this.remainingPdu = [...mergedPdu]; + return null; + } + + // 헤더 불일치는 버림 + if (!this.checkHeader(mergedPdu)) { + return null; + } + + // 유효 데이터 길이는 header 2 + body 5 + checksum 1 = 8 + const validDataLength = 8; + /* + 전체 길이가 유효 데이터 길이보다 작을 경우 + 아직 도착하지 않은 부분이 있으므로 병합을 위해 remainingPdu 에 저장 + */ + if (mergedPdu.length < validDataLength) { + this.remainingPdu = [...mergedPdu]; + return null; + } + + /* + 전체 길이가 유효 데이터 길이보다 클 경우 + 유효한 부분만 잘라내고 나머지는 remainingPdu 에 저장 + */ + if (mergedPdu.length > validDataLength) { + this.remainingPdu = mergedPdu.slice(validDataLength, mergedPdu.length); + } + + const validPdu = mergedPdu.slice(0, validDataLength); + + /* + 유효 Pdu 의 checksum 확인 + */ + const dataLength = 5; + let checkSum = 0; + for (let i = 0; i < dataLength; i++) { + checkSum += validPdu[i + 2]; + } + checkSum = checkSum & 255; + const pduCheckSum = validPdu[7]; + if (pduCheckSum !== checkSum) { + return null; + } + + return validPdu; + } + + checkHeader(pdu) { + if (pdu.length < HEADER.length) { + return false; + } + + for (let i = 0; i < HEADER.length; i++) { + if (HEADER[i] !== pdu[i]) { + return false; + } + } + + return true; + } + requestLocalData() { const requestData = []; @@ -172,6 +255,7 @@ ko: { template: { // think car + neobot_think_car_lite_auto_driving_title: '자율주행', neobot_think_car_lite_line_tracer_start: '차로를 유지하며 속도 %1 으로 자율주행 %2', // neobot_think_car_lite_line_tracer_change_speed: '자율주행 속도 변경 %1 %2', @@ -181,19 +265,17 @@ neobot_think_car_lite_driving_stop: '자율주행 중지 %1', // sensor + neobot_think_car_lite_sensor_title: '센서', neobot_think_car_lite_sensor_value: '%1', neobot_think_car_lite_sensor_convert_scale: '%1 %2 ~ %3 를 %4 ~ %5 으로 변환', - - // decision neobot_think_car_lite_decision_sensor_is_over: '%1 %2 %3', neobot_think_car_lite_decision_equal_with_sensor: '%1 컬러가 %2', neobot_think_car_lite_decision_sensor_angle: '%1 각도 %2 %3', - - // remote neobot_think_car_lite_remote_button: '리모컨 버튼 %1 을 누름', // LED + neobot_think_car_lite_led_title: 'LED', neobot_think_car_lite_arg_led_duration: '%1', neobot_think_car_lite_led_on: 'LED 켜기 %1 %2 %3 %4', neobot_think_car_lite_output_led_off: '%1 LED 끄기 %2', @@ -201,9 +283,11 @@ neobot_think_car_lite_color_led_on: '%1 컬러LED 켜기 R %2 G %3 B %4 %5', // output + neobot_think_car_lite_output_title: '출력', neobot_think_car_lite_set_output: '%1 에 %2 값 출력하기 %3', // motor + neobot_think_car_lite_motor_title: '회전모터', neobot_think_car_lite_robot: '로봇 %1 %2', neobot_think_car_lite_motor_start: '모터 회전하기 %1 %2 %3 %4 %5', neobot_think_car_lite_motor_stop: '%1 모터 멈추기 %2', @@ -211,12 +295,14 @@ neobot_think_car_lite_arg_motor_duration: '%1', // melody + neobot_think_car_lite_buzzer_title: '버저', neobot_think_car_lite_play_note_for: '버저 울리기 옥타브: %2 음: %1 길이: %3 %4', neobot_think_car_lite_melody_play_with_sensor: '%1 센서로 버저 울리기 %2', neobot_think_car_lite_melody_stop: '버저 멈추기 %1', // servo + neobot_think_car_lite_servo_title: '서보모터', get_servo_degree: '%1', neobot_think_car_lite_servo_init: '%1 서보모터 리셋 %2', neobot_think_car_lite_servo_rotate: '서보모터 회전하기 %1 %2 %3 %4', @@ -362,6 +448,7 @@ // en.js에 작성하던 내용 template: { // think car + neobot_think_car_lite_auto_driving_title: 'Self-driving', neobot_think_car_lite_line_tracer_start: 'Start self-driving at %1 speed while keeping lanes %2', // neobot_think_car_lite_line_tracer_change_speed: 'Change the speed of self-driving %1 %2', @@ -372,20 +459,18 @@ neobot_think_car_lite_driving_stop: 'Stop self-driving %1', // sensor + neobot_think_car_lite_sensor_title: 'Sensor', neobot_think_car_lite_sensor_value: '%1', neobot_think_car_lite_sensor_convert_scale: "%1 's changed value range: %2 ~ %3 conversion: %4 ~ %5", - - // decision neobot_think_car_lite_decision_sensor_is_over: '%1 %2 %3', neobot_think_car_lite_decision_equal_with_sensor: "%1 's color is %2", neobot_think_car_lite_decision_sensor_angle: '%1 angle %2 %3', - - // remote neobot_think_car_lite_remote_button: 'pressing button %1 of remote controller', // LED + neobot_think_car_lite_led_title: 'LED', neobot_think_car_lite_arg_led_duration: '%1', neobot_think_car_lite_led_on: 'Turn on the LED %1 %2 %3 %4', neobot_think_car_lite_output_led_off: 'Turn off the %1 LED %2', @@ -395,16 +480,19 @@ 'Turn on the %1 color LED R %2 G %3 B %4 %5', // output + neobot_think_car_lite_output_title: 'Set output', neobot_think_car_lite_set_output: 'Output %2 value to %1 port %3', // motor + neobot_think_car_lite_motor_title: 'Motor', neobot_think_car_lite_robot: 'Robot %1 %2', neobot_think_car_lite_motor_start: 'Motor operation %1 %2 %3 %4 %5', neobot_think_car_lite_motor_stop: 'Stop the %1 motor(s) %2', neobot_think_car_lite_arg_motor_speed: '%1', neobot_think_car_lite_arg_motor_duration: '%1', - // melody + // buzzer + neobot_think_car_lite_buzzer_title: 'Buzzer', neobot_think_car_lite_play_note_for: 'Buzzer octave: %1 scale: %2 note: %3 %4', neobot_think_car_lite_melody_play_with_sensor: @@ -412,6 +500,7 @@ neobot_think_car_lite_melody_stop: 'Stop the buzzer %1', // servo + neobot_think_car_lite_servo_title: 'Servo motor', get_servo_degree: '%1', neobot_think_car_lite_servo_init: 'Reset the %1 servo motor %2', neobot_think_car_lite_servo_rotate: 'Rotate the servo motor %1 %2 %3 %4', @@ -558,6 +647,30 @@ getBlocks = function() { return { + neobot_think_car_lite_auto_driving_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_lite_auto_driving_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_lite_auto_driving_title', + }, + class: 'neobot_think_car_lite_operation', + isNotFor: ['NeobotThinkCarLite'], + events: {}, + }, neobot_think_car_lite_line_tracer_start: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -937,6 +1050,30 @@ /************************* * class neobot_think_car_lite_sensor *************************/ + neobot_think_car_lite_sensor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_lite_sensor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_lite_sensor_title', + }, + class: 'neobot_think_car_lite_sensor', + isNotFor: ['NeobotThinkCarLite'], + events: {}, + }, neobot_think_car_lite_sensor_value: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -974,7 +1111,6 @@ return Entry.NeobotThinkCarLite.localBuffer[port]; }, }, - neobot_think_car_lite_sensor_convert_scale: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1072,10 +1208,6 @@ return Math.round(value); }, }, - - /************************* - * class neobot_think_car_lite_decision - *************************/ neobot_think_car_lite_decision_sensor_is_over: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1125,7 +1257,7 @@ SYMBOL: 1, VALUE: 2, }, - class: 'neobot_think_car_lite_decision', + class: 'neobot_think_car_lite_sensor', isNotFor: ['NeobotThinkCarLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -1183,7 +1315,6 @@ return false; }, }, - neobot_think_car_lite_decision_equal_with_sensor: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1227,7 +1358,7 @@ SENSOR: 0, COLOR: 1, }, - class: 'neobot_think_car_lite_decision', + class: 'neobot_think_car_lite_sensor', isNotFor: ['NeobotThinkCarLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -1268,7 +1399,6 @@ return false; }, }, - neobot_think_car_lite_decision_sensor_angle: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1341,7 +1471,7 @@ SYMBOL: 1, VALUE: 2, }, - class: 'neobot_think_car_lite_decision', + class: 'neobot_think_car_lite_sensor', isNotFor: ['NeobotThinkCarLite'], func(sprite, script) { const sensorTemp = script.getStringField('SENSOR'); @@ -1383,10 +1513,6 @@ return false; }, }, - - /************************* - * class neobot_think_car_lite_remote - *************************/ neobot_think_car_lite_remote_button: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1420,7 +1546,7 @@ paramsKeyMap: { KEY: 0, }, - class: 'neobot_think_car_lite_remote', + class: 'neobot_think_car_lite_sensor', isNotFor: ['NeobotThinkCarLite'], func(sprite, script) { const key = script.getNumberField('KEY'); @@ -1436,6 +1562,30 @@ /************************* * class neobot_think_car_lite_led *************************/ + neobot_think_car_lite_led_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_lite_led_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_lite_led_title', + }, + class: 'neobot_think_car_lite_led', + isNotFor: ['NeobotThinkCarLite'], + events: {}, + }, neobot_think_car_lite_led_on: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1572,7 +1722,6 @@ } }, }, - neobot_think_car_lite_output_led_off: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1630,7 +1779,6 @@ return script.callReturn(); }, }, - neobot_think_car_lite_led_brightness_with_sensor: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1714,7 +1862,6 @@ return script.callReturn(); }, }, - neobot_think_car_lite_color_led_on: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -1969,6 +2116,30 @@ /************************* * class neobot_think_car_lite_output *************************/ + neobot_think_car_lite_output_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_lite_output_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_lite_output_title', + }, + class: 'neobot_think_car_lite_output', + isNotFor: ['NeobotThinkCarLite'], + events: {}, + }, neobot_think_car_lite_set_output: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2049,6 +2220,30 @@ /************************* * class neobot_think_car_lite_motor *************************/ + neobot_think_car_lite_motor_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_lite_motor_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_lite_motor_title', + }, + class: 'neobot_think_car_lite_motor', + isNotFor: ['NeobotThinkCarLite'], + events: {}, + }, neobot_think_car_lite_robot: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2125,7 +2320,6 @@ return script.callReturn(); }, }, - neobot_think_car_lite_motor_start: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2316,7 +2510,6 @@ } }, }, - neobot_think_car_lite_motor_stop: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2378,6 +2571,30 @@ /************************* * class neobot_think_car_lite_melody *************************/ + neobot_think_car_lite_buzzer_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_lite_buzzer_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_lite_buzzer_title', + }, + class: 'neobot_think_car_lite_melody', + isNotFor: ['NeobotThinkCarLite'], + events: {}, + }, neobot_think_car_lite_play_note_for: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2498,7 +2715,6 @@ } }, }, - neobot_think_car_lite_melody_play_with_sensor: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2556,7 +2772,6 @@ return script.callReturn(); }, }, - neobot_think_car_lite_melody_stop: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2595,6 +2810,30 @@ /************************* * class neobot_think_car_lite_servo *************************/ + neobot_think_car_lite_servo_title: { + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#191970', + skeleton: 'basic_text', + skeletonOptions: { + contentPos: { + x: 5, + }, + }, + params: [ + { + type: 'Text', + text: Lang.template.neobot_think_car_lite_servo_title, + color: '#191970', + align: 'left', + }, + ], + def: { + type: 'neobot_think_car_lite_servo_title', + }, + class: 'neobot_think_car_lite_servo', + isNotFor: ['NeobotThinkCarLite'], + events: {}, + }, neobot_think_car_lite_servo_init: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2704,7 +2943,6 @@ } }, }, - neobot_think_car_lite_servo_rotate: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE, @@ -2884,7 +3122,6 @@ return script.callReturn(); }, }, - neobot_think_car_lite_servo_change_degree: { color: EntryStatic.colorSet.block.default.HARDWARE, outerLine: EntryStatic.colorSet.block.darken.HARDWARE,