diff --git a/extern/lang/en.js b/extern/lang/en.js index 9e3380c112..93187e0e50 100644 --- a/extern/lang/en.js +++ b/extern/lang/en.js @@ -1124,8 +1124,8 @@ Lang.Blocks = { EXPANSION_WEATHER_finedust: 'concentration of fine dust(㎍)', ardublock_motor_forward: 'Forward', ardublock_motor_backward: 'Backward', - ARDUINO_on: 'On', - ARDUINO_off: 'Off', + ARDUINO_on: 'Turn on', + ARDUINO_off: 'Turn off', EXPANSION_FESTIVAL_title: 'Title', EXPANSION_FESTIVAL_area: 'area', EXPANSION_FESTIVAL_start_date: 'start date', diff --git a/images/hw_lite/arduinolite.png b/images/hw_lite/arduinolite.png old mode 100755 new mode 100644 index dc5ce96f08..f2cd70ffe3 Binary files a/images/hw_lite/arduinolite.png and b/images/hw_lite/arduinolite.png differ diff --git a/images/hw_lite/robotis_robotai_lite.png b/images/hw_lite/robotis_robotai_lite.png new file mode 100644 index 0000000000..ad983b52d7 Binary files /dev/null and b/images/hw_lite/robotis_robotai_lite.png differ diff --git a/images/hw_lite/whalesbotlite.png b/images/hw_lite/whalesbotlite.png new file mode 100644 index 0000000000..bcef940572 Binary files /dev/null and b/images/hw_lite/whalesbotlite.png differ diff --git a/src/playground/blocks/hardware/block_altino_lite.js b/src/playground/blocks/hardware/block_altino_lite.js index 53dec3c600..a39e199ba2 100644 --- a/src/playground/blocks/hardware/block_altino_lite.js +++ b/src/playground/blocks/hardware/block_altino_lite.js @@ -16,6 +16,7 @@ Entry.AltinoLite = { dot6: 0, dot7: 0, dot8: 0, + ir: 0 }, setZero: function() { var portMap = Entry.AltinoLite.PORT_MAP; @@ -68,6 +69,7 @@ Entry.AltinoLite.blockMenuBlocks = [ 'altino_lite_dot_display_hex', 'altino_lite_dot_display_matrix_on', 'altino_lite_dot_display_matrix_off', + 'altino_lite_ir_reset', ]; Entry.AltinoLite.setLanguage = function() { @@ -150,6 +152,7 @@ Entry.AltinoLite.setLanguage = function() { altino_lite_sound: '소리 %1 %2 %3', altino_lite_steering_hex: '조향 %1%2', altino_lite_steering: '조향 %1°%2', + altino_lite_ir_reset: '알티노 라이트 IR 센서 초기화', }, }, en: { @@ -230,6 +233,7 @@ Entry.AltinoLite.setLanguage = function() { altino_lite_sound: 'Sound %1 %2 %3', altino_lite_steering_hex: 'Steering %1%2', altino_lite_steering: 'Steering %1°%2', + altino_lite_ir_reset: 'Reset Altino lite IR Sensor', }, }, }; @@ -562,7 +566,7 @@ Entry.AltinoLite.getBlocks = function() { skeleton: 'basic', statements: [], params: [ - { + { type: 'Dropdown', options: [ ['1-' + Lang.Blocks.altino_lite_sound_oct, '1'], @@ -1385,6 +1389,40 @@ Entry.AltinoLite.getBlocks = function() { }, syntax: { js: [], py: ['AltinoLite.dot_display_hex(%1, %2, %3, %4, %5, %6, %7, %8)'] }, }, + altino_lite_ir_reset: { + 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: 'altino_lite_ir_reset', + }, + paramsKeyMap: { + DEVICE : 0, + }, + class: 'altino_lite_output', + isNotFor: ['altino_lite'], + func: function(sprite, script) { + var sq = Entry.hw.sendQueue; + + // sq.rightWheel = 300;//script.getNumberValue('rightWheel'); + // sq.leftWheel = 300;//script.getNumberValue('leftWheel'); + sq.ir = 6; + return script.callReturn(); + }, + syntax: { js: [], py: ['AltinoLite.ir_reset'] }, + }, //endregion Altino 알티노 }; }; diff --git a/src/playground/blocks/hardware/block_alux_nemo.js b/src/playground/blocks/hardware/block_alux_nemo.js new file mode 100644 index 0000000000..61377e3020 --- /dev/null +++ b/src/playground/blocks/hardware/block_alux_nemo.js @@ -0,0 +1,2488 @@ +'use strict'; + +Entry.nemo = { + id: ['63.1'], + name: 'nemo', + url: 'https://www.aluxonline.com', + imageName: 'alux_nemo.png', + title: { + ko: '네모', + en: 'NEMO', + }, + delayTime: 0.001, + setZero: function() { + Entry.hw.sendQueue['NEMO_INIT'] = { + id: Math.random(), + setZero: 1, + }; + Entry.hw.update(); + this.setCount = 0; + }, + numToMS(num) { + let ms = 0; + if (num < 0) { + ms = 0; + } else if (0 <= num && num <= 5) { + switch(num) { + case 0: + ms = 0; + break; + case 1: + ms = 500; + break; + case 2: + ms = 200; + break; + case 3: + ms = 100; + break; + case 4: + ms = 50; + break; + case 5: + ms = 20; + break; + } + } else { + ms = 500; + } + return ms; + }, + afterReceive(portData) { + const motion = portData['NEMO_EVENT_MOTION']; + const button = portData['NEMO_EVENT_BUTTON']; + const temp = Entry.hw.portData['NEMO_DEVICE'].anSwitch; + if (button === true) { + Entry.engine.fireEvent('aluxNemoButtonEventReceived'); + } + if (motion === true) { + Entry.engine.fireEvent('aluxNemoMotionEventReceived'); + } + }, + setProcessor(script, delayTime, code) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const fps = Entry.FPS || 60; + const timeValue = (60 / fps) * delayTime * 1000; + Entry.TimeWaitManager.add( + Math.random(), + () => { + script.timeFlag = 0; + }, + timeValue + ); + Entry.toybot.scoreFlag = code(); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, +}; + +Entry.nemo.setLanguage = function() { + return { + ko: { + template: { + title_namo_input: '네모 입력', + title_namo_output: '네모 출력', + title_namo_extension: '네모 확장', + line_emtpy: ' ', + + list_s1: 'S1', + list_s2: 'S2', + list_s3: 'S3', + list_s4: 'S4', + list_motion_1: '앞으로 기울임', + list_motion_2: '뒤로 기울임', + list_motion_3: '왼쪽으로 기울임', + list_motion_4: '오른쪽으로 기울임', + list_motion_5: '위로 놓음', + list_motion_6: '아래로 놓음', + list_motion_7: '세워 놓음', + list_motion_8: '충격 받음', + list_smile: '웃음', + list_not_much: '별로', + list_good: '좋음', + list_bad: '나쁨', + list_wink: '윙크', + list_cry: '울음', + list_absurd: '어이없음', + list_peck: '뽀뽀', + list_arrow_1: '화살표 1', + list_arrow_2: '화살표 2', + list_arrow_3: '화살표 3', + list_arrow_4: '화살표 4', + list_arrow_5: '화살표 5', + list_arrow_6: '화살표 6', + list_arrow_7: '화살표 7', + list_arrow_8: '화살표 8', + list_spade: '스페이드', + list_club: '클럽', + list_diamond: '다이아몬드', + list_heart: '하트', + list_circle: '원', + list_x: '엑스', + list_triangle: '세모', + list_square: '네모', + list_note_1: '음표 1', + list_note_2: '음표 2', + list_note_3: '음표 3', + list_dice_1: '주사위 1', + list_dice_2: '주사위 2', + list_dice_3: '주사위 3', + list_dice_4: '주사위 4', + list_dice_5: '주사위 5', + list_dice_6: '주사위 6', + list_is_pressing: '눌려 있을 때', + list_pressed: '눌렀을 때', + list_released: '뗐을 때', + list_has_prssing: '눌려 있는가', + list_has_pressed: '눌렀는가', + list_has_released: '뗐는가', + list_axis_x: 'X축', + list_axis_y: 'Y축', + list_axis_z: 'Z축', + list_linear_acceleration: '선형 가속도', + list_off1: '끄기', + list_on1: '켜기', + list_off2: '□', + list_on2: '■', + list_toggle: '토글', + list_do_re_mi_song: '도레미송', + list_an_island_baby: '섬집아기', + list_twinkle_twinkle_little_star: '작은별', + list_spring_in_my_hometown: '고향의 봄', + list_for_elise: '엘리제를 위하여', + list_celebrated_chop_waltz: '젓가락 행진곡', + list_happy_birthday_to_you: '생일 축하곡', + list_lc: 'C(0)', + list_lcs: 'C#(1)', + list_ld: 'D(2)', + list_lds: 'D#(3)', + list_le: 'E(4)', + list_lf: 'F(5)', + list_lfs: 'F#(6)', + list_lg: 'G(7)', + list_lgs: 'G#(8)', + list_la: 'A(9)', + list_las: 'A#(10)', + list_lb: 'B(11)', + list_mc: 'C(12)', + list_mcs: 'C#(13)', + list_md: 'D(14)', + list_mds: 'D#(15)', + list_me: 'E(16)', + list_mf: 'F(17)', + list_mfs: 'F#(18)', + list_mg: 'G(19)', + list_mgs: 'G#(20)', + list_ma: 'A(21)', + list_mas: 'A#(22)', + list_mb: 'B(23)', + list_hc: 'C(24)', + list_switch: '스위치', + list_infrared_ray: '적외선', + list_magnet: '자석', + list_rotation: '회전', + list_brightness: '밝기', + list_sound: '소리', + list_tilt: '기울기', + list_pressure: '압력', + list_heart_rate: '심박', + list_value: '값', + list_angle: '각도', + list_absolute_angle: '절대 각도', + list_rotation_value: '회전 수', + list_east: '동쪽', + list_west: '서쪽', + list_south: '남쪽', + list_north: '북쪽', + + input_event_button_state: '%1 %2 버튼 %3', + input_event_motion_sensing: '%1 %2 이 감지되었을 때', + input_bool_button_state: '%1 버튼 %2 ?', + input_bool_motion_sensing: '%1 이 감지되었는가?', + input_bool_led_state_value: 'LED X: %1 Y: %2 상태값', + input_field_button_analog_value: '%1 버튼의 아날로그 값', + input_field_acceleration_value: '가속도 센서 %1 의 값', + input_field_brightness_value: '밝기 센서의 값', + input_field_convert_value: '%1 의 값 %2 ~ %3 을 %4 ~ %5 으(로) 변환', + + output_basic_display_led_icon: 'LED 아이콘 %1 을 %2 속도로 출력 %3', + output_basic_diplay_led_custom_icon: 'LED %1 줄의 %2%3%4%5%6%7%8 을 %9 속도로 출력 %10', + output_basic_display_led_string: 'LED %1 문자열을 %2 속도로 출력 %3', + output_basic_delete_all_led: 'LED 출력 지우기 %1', + output_basic_coordinate_value: 'LED X: %1 Y: %2 %3 %4', + output_basic_play_melody: '멜로디 %1 재생하기 %2', + output_basic_play_melody_to_the_end: '멜로디 %1 끝까지 재생하기 %2', + output_basic_play_note: '%1 음을 재생하기 %2', + output_basic_play_note_for_seconds: '%1 음을 %2 초동안 재생하기 %3', + output_basic_stop_all_sound: '모든 소리 정지 %1', + + extension_basic_set_expension: '확장센서를 %1 (으)로 설정 %2', + extension_basic_set_expension_value: '확장센서를 %1 값으로 정하기', + extension_bool_expension_state: '확장센서 %1 ? %2', + extension_field_expension_anlog_value: '확장센서의 아날로그 값 %1', + extension_field_expension_custom_value: '확장센서의 %1', + extension_basic_set_compass_value: '나침반센서를 %1 값으로 정하기', + extension_field_compass_analog_value: '나침반센서의 아날로그 값 %1', + extension_field_compass_custom_value: '나침반센서의 %1', + extension_bool_compass_state: '나침반센서의 방향이 %1 인가 ?', + }, + }, + en: { + template: { + title_namo_input: 'NAMO INPUT', + title_namo_output: 'NAMO OUTPUT', + title_namo_extension: 'NAMO EXTENSION', + line_emtpy: ' ', + + list_s1: 'S1', + list_s2: 'S2', + list_s3: 'S3', + list_s4: 'S4', + list_motion_1: 'Tilting forward', + list_motion_2: 'Tilting back', + list_motion_3: 'Tilting to the left', + list_motion_4: 'Tilting to the right', + list_motion_5: 'Put it up', + list_motion_6: 'Put it down', + list_motion_7: 'Standing up', + list_motion_8: 'Impacted', + list_smile: 'Smile', + list_not_much: 'Not much', + list_good: 'Good', + list_bad: 'Bad', + list_wink: 'Wink', + list_cry: 'Cry', + list_absurd: 'Absurd', + list_peck: 'Peck', + list_arrow_1: 'Arrow 1', + list_arrow_2: 'Arrow 2', + list_arrow_3: 'Arrow 3', + list_arrow_4: 'Arrow 4', + list_arrow_5: 'Arrow 5', + list_arrow_6: 'Arrow 6', + list_arrow_7: 'Arrow 7', + list_arrow_8: 'Arrow 8', + list_spade: 'Spade', + list_club: 'Club', + list_diamond: 'Diamond', + list_heart: 'heart', + list_circle: 'Circle', + list_x: 'X', + list_triangle: 'Triangle', + list_square: 'Square', + list_note_1: 'note 1', + list_note_2: 'note 2', + list_note_3: 'note 3', + list_dice_1: 'dice 1', + list_dice_2: 'dice 2', + list_dice_3: 'dice 3', + list_dice_4: 'dice 4', + list_dice_5: 'dice 5', + list_dice_6: 'dice 6', + list_is_pressing: 'Is pressing', + list_pressed: 'Pressed', + list_released: 'released', + list_has_prssing: 'has be pressing', + list_has_pressed: 'has pressed', + list_has_released: 'has released', + list_axis_x: 'X axis', + list_axis_y: 'Y axis', + list_axis_z: 'Z axis', + list_linear_acceleration: 'Linear acceleration', + list_off1: 'Off', + list_on1: 'On', + list_off2: '□', + list_on2: '■', + list_toggle: 'Toggle', + list_do_re_mi_song: 'Do Re Mi Song', + list_an_island_baby: 'An Island Baby', + list_twinkle_twinkle_little_star: 'Twinkle Twinkle Little Star', + list_spring_in_my_hometown: 'Spring in My Hometwon', + list_for_elise: 'For Elise', + list_celebrated_chop_waltz: 'Celebrate Chop Waltz', + list_happy_birthday_to_you: 'Happy Birthday To You', + list_lc: 'C(0)', + list_lcs: 'C#(1)', + list_ld: 'D(2)', + list_lds: 'D#(3)', + list_le: 'E(4)', + list_lf: 'F(5)', + list_lfs: 'F#(6)', + list_lg: 'G(7)', + list_lgs: 'G#(8)', + list_la: 'A(9)', + list_las: 'A#(10)', + list_lb: 'B(11)', + list_mc: 'C(12)', + list_mcs: 'C#(13)', + list_md: 'D(14)', + list_mds: 'D#(15)', + list_me: 'E(16)', + list_mf: 'F(17)', + list_mfs: 'F#(18)', + list_mg: 'G(19)', + list_mgs: 'G#(20)', + list_ma: 'A(21)', + list_mas: 'A#(22)', + list_mb: 'B(23)', + list_hc: 'C(24)', + list_switch: 'Switch', + list_infrared_ray: 'Infrared ray', + list_magnet: 'Magnet', + list_rotation: 'Rotation', + list_brightness: 'Brightness', + list_sound: 'Sound', + list_tilt: 'Tilt', + list_pressure: 'Pressure', + list_heart_rate: 'Heart rate', + list_value: 'Value', + list_angle: 'Angle', + list_absolute_angle: 'Absolute angle', + list_rotation_value: 'Rotation value', + list_east: 'East', + list_west: 'West', + list_south: 'South', + list_north: 'North', + + input_event_button_state: 'When %1 button %2', + input_event_button_motion_sensing: 'When %1 motion is detected', + input_bool_button_state: 'Is %1 button %2 ?', + input_bool_motion_sensing: 'Is %1 motion detected', + input_bool_led_state_value: ' LED X: %1 Y: %2 status', + input_field_button_analog_value: 'Analog value of %1 button', + input_field_acceleration_value: 'Acceleration sensor %1 value', + input_field_brightness_value: 'Value of illuminance sensor', + input_field_convert_value: 'change the value of %1 from %2 ~ %3 to %4 ~ %5', + + output_basic_display_led_icon: 'LED icon %1 output %2 speed %3', + output_basic_diplay_led_custom_icon: 'LED %1 line %2%3%4%5%6%7%8 at %9 speed %10', + output_basic_display_led_string: 'LED %1 string output %2 speed %3', + output_basic_delete_all_led: 'Clear LED output %1', + output_basic_coordinate_value: 'LED X: %1 Y: %2 %3 %4', + output_basic_play_melody: 'Play melody %1 %2', + output_basic_play_melody_to_the_end: 'melody %1 play to the end %2', + output_basic_play_note: 'Playing note %1 %2', + output_basic_play_note_for_seconds: 'Play note %1 for %2 second(s) %3', + output_basic_stop_all_sound: 'Stop all sound %1', + + extension_basic_set_expension: 'Expansion type set %1 %2', + extension_basic_set_expension_value: 'Expansion sensor set %1 value ? %2', + extension_bool_expension_state: 'Is extended sensor %1', + extension_field_expension_anlog_value: 'Value of extended sensor %1', + extension_field_expension_custom_value: 'Exansion sensor value of %1', + extension_basic_set_compass_value: 'Compass sensor value Set %1', + extension_field_compass_analog_value: 'Value of compass sensor %1', + extension_field_compass_custom_value: 'compass sensor value of %1', + extension_bool_compass_state: 'Does the rotation sensor point %1 ?', + }, + }, + }; +}; + +Entry.nemo.blockMenuBlocks = [ + 'nemo_dropdown_button', + 'nemo_dropdown_button_now_state', + 'nemo_dropdown_button_state_question', + 'nemo_dropdown_motion', + 'nemo_dropdown_coordinate_acceleration', + 'nemo_dropdown_led_icon', + 'nemo_dropdown_switch', + 'nemo_dropdown_melody', + 'nemo_dropdown_keyboard', + 'nemo_dropdown_expension_sensor_mode', + 'nemo_dropdown_compass_sensor_mode', + 'nemo_dropdown_direction', + 'nemo_dropdown_index_0_5', + 'nemo_dropdown_index_1_5', + 'nemo_dropdown_index_1_7', + 'nemo_dropdown_toggle', + 'nemo_dropdown_toggle2', + + 'nemo_title_namo_input', + 'nemo_block_input_event_button_state', + 'nemo_block_input_event_motion_sensing', + 'nemo_block_input_bool_button_state', + 'nemo_block_input_bool_motion_sensing', + 'nemo_block_input_bool_led_state_value', + 'nemo_block_input_field_button_analog_value', + 'nemo_block_input_field_acceleration_value', + 'nemo_block_input_field_brightness_value', + 'nemo_block_input_field_convert_value', + + 'nemo_title_namo_output', + 'nemo_block_output_basic_display_led_icon', + 'nemo_block_output_basic_diplay_led_custom_icon', + 'nemo_block_output_basic_display_led_string', + 'nemo_block_output_basic_delete_all_led', + 'nemo_block_output_basic_coordinate_value', + 'nemo_block_output_basic_play_melody', + 'nemo_block_output_basic_play_melody_to_the_end', + 'nemo_block_output_basic_play_note', + 'nemo_block_output_basic_play_note_for_seconds', + 'nemo_block_output_basic_stop_all_sound', + + 'nemo_title_namo_extension', + 'nemo_block_extension_basic_set_expension', + 'nemo_block_extension_basic_set_expension_value', + 'nemo_block_extension_bool_expension_state', + 'nemo_block_extension_field_expension_anlog_value', + 'nemo_block_extension_field_expension_custom_value', + 'nemo_block_extension_basic_set_compass_value', + 'nemo_block_extension_field_compass_analog_value', + 'nemo_block_extension_field_compass_custom_value', + 'nemo_block_extension_bool_compass_state', +]; + +Entry.nemo.getBlocks = function() { + return { + ///======================================================================================== + /// Dropdown block + ///======================================================================================== + nemo_dropdown_button: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_s1, 0], + [Lang.template.list_s2, 1], + [Lang.template.list_s3, 2], + [Lang.template.list_s4, 3], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_button_now_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_is_pressing, 0], + [Lang.template.list_pressed, 1], + [Lang.template.list_released, 2], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_button_state_question: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_has_prssing, 0], + [Lang.template.list_has_pressed, 1], + [Lang.template.list_has_released, 2], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_motion: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_motion_1, 0], + [Lang.template.list_motion_2, 1], + [Lang.template.list_motion_3, 2], + [Lang.template.list_motion_4, 3], + [Lang.template.list_motion_5, 4], + [Lang.template.list_motion_6, 5], + [Lang.template.list_motion_7, 6], + [Lang.template.list_motion_8, 7], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_coordinate_acceleration: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_axis_x, 0], + [Lang.template.list_axis_y, 1], + [Lang.template.list_axis_z, 2], + [Lang.template.list_linear_acceleration, 3], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_led_icon: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'DropdownExtra', + options: [ + [Lang.template.list_smile, 1], + [Lang.template.list_not_much, 2], + [Lang.template.list_good, 3], + [Lang.template.list_bad, 4], + [Lang.template.list_wink, 5], + [Lang.template.list_cry, 6], + [Lang.template.list_absurd, 7], + [Lang.template.list_peck, 8], + [Lang.template.list_arrow_1, 9], + [Lang.template.list_arrow_2, 10], + [Lang.template.list_arrow_3, 11], + [Lang.template.list_arrow_4, 12], + [Lang.template.list_arrow_5, 13], + [Lang.template.list_arrow_6, 14], + [Lang.template.list_arrow_7, 15], + [Lang.template.list_arrow_8, 16], + [Lang.template.list_spade, 17], + [Lang.template.list_club, 18], + [Lang.template.list_diamond, 19], + [Lang.template.list_heart, 20], + [Lang.template.list_circle, 21], + [Lang.template.list_x, 22], + [Lang.template.list_triangle, 23], + [Lang.template.list_square, 24], + [Lang.template.list_note_1, 25], + [Lang.template.list_note_2, 26], + [Lang.template.list_note_3, 27], + [Lang.template.list_dice_1, 28], + [Lang.template.list_dice_2, 29], + [Lang.template.list_dice_3, 30], + [Lang.template.list_dice_4, 31], + [Lang.template.list_dice_5, 32], + [Lang.template.list_dice_6, 33], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_switch: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_off1, 1], + [Lang.template.list_on1, 2], + [Lang.template.list_toggle, 3], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_melody: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_do_re_mi_song, 1], + [Lang.template.list_an_island_baby, 2], + [Lang.template.list_twinkle_twinkle_little_star, 3], + [Lang.template.list_spring_in_my_hometown, 4], + [Lang.template.list_for_elise, 5], + [Lang.template.list_celebrated_chop_waltz, 6], + [Lang.template.list_happy_birthday_to_you, 7], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_keyboard: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'DropdownExtra', + options: [ + [Lang.template.list_lc, 0], + [Lang.template.list_lcs, 1], + [Lang.template.list_ld, 2], + [Lang.template.list_lds, 3], + [Lang.template.list_le, 4], + [Lang.template.list_lf, 5], + [Lang.template.list_lfs, 6], + [Lang.template.list_lg, 7], + [Lang.template.list_lgs, 8], + [Lang.template.list_la, 9], + [Lang.template.list_las, 10], + [Lang.template.list_lb, 11], + [Lang.template.list_mc, 12], + [Lang.template.list_mcs, 13], + [Lang.template.list_md, 14], + [Lang.template.list_mds, 15], + [Lang.template.list_me, 16], + [Lang.template.list_mf, 17], + [Lang.template.list_mfs, 18], + [Lang.template.list_mg, 19], + [Lang.template.list_mgs, 20], + [Lang.template.list_ma, 21], + [Lang.template.list_mas, 22], + [Lang.template.list_mb, 23], + [Lang.template.list_hc, 24] + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_expension_sensor_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_switch, 0], + [Lang.template.list_infrared_ray, 1], + [Lang.template.list_magnet, 2], + [Lang.template.list_rotation, 3], + [Lang.template.list_brightness, 4], + [Lang.template.list_sound, 5], + [Lang.template.list_tilt, 6], + [Lang.template.list_pressure, 7], + [Lang.template.list_heart_rate, 8] + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_compass_sensor_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_value, 0], + [Lang.template.list_angle, 1], + [Lang.template.list_absolute_angle, 2], + [Lang.template.list_rotation_value, 3], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_direction: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_east, 0], + [Lang.template.list_west, 1], + [Lang.template.list_south, 2], + [Lang.template.list_north, 3], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_index_0_5: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0', 0], + ['1', 1], + ['2', 2], + ['3', 3], + ['4', 4], + ['5', 5], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_index_1_5: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 1], + ['2', 2], + ['3', 3], + ['4', 4], + ['5', 5], + ], + value: 1, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_index_1_7: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 0], + ['2', 1], + ['3', 2], + ['4', 3], + ['5', 4], + ['6', 5], + ['7', 6], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_toggle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_off1, 0], + [Lang.template.list_on1, 1], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + nemo_dropdown_toggle2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.list_off2, 0], + [Lang.template.list_on2, 1], + ], + value: 0, + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + } + ], + def: { + params: [null], + }, + paramsKeyMap: { + INDEX: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('INDEX'); + } + }, + ///======================================================================================== + /// Input block + ///======================================================================================== + nemo_title_namo_input: { + skeleton: 'basic_text', + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#333333', + template: Lang.template.title_namo_input, + skeletonOptions: { + box: { + offsetX: 20, + }, + }, + def: { + type: 'nemo_title_namo_input', + }, + isNotFor: ['nemo'], + class : 'inputBlock', + }, + nemo_block_input_event_button_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_event', + statements: [], + template: Lang.template.input_event_button_state, + params: [ + { + type: 'Indicator', + img: 'block_icon/start_icon_hardware.svg', + size: 14, + position: { + x: 0, + y: -2, + }, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'nemo_dropdown_button', + }, + { + type: 'nemo_dropdown_button_now_state', + }, + ], + type: 'nemo_block_input_event_button_state', + }, + paramsKeyMap: { + DUMMY: 0, + INDEX: 1, + STATE: 2, + }, + event: 'aluxNemoButtonEventReceived', + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const state = script.getNumberValue('STATE'); + const getState = Entry.hw.portData['NEMO_DEVICE_EX'].button[index].state[state]; + return getState === true ? script.callReturn() : this.die(); + } + }, + nemo_block_input_event_motion_sensing: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_event', + statements: [], + template: Lang.template.input_event_motion_sensing, + params: [ + { + type: 'Indicator', + img: 'block_icon/start_icon_hardware.svg', + size: 14, + position: { + x: 0, + y: -2, + }, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + } + ], + events: {}, + def: { + params: [ + null, + { + type: 'nemo_dropdown_motion', + }, + ], + type: 'nemo_block_input_event_motion_sensing', + }, + paramsKeyMap: { + DUMMY: 0, + INDEX: 1, + }, + event: 'aluxNemoMotionEventReceived', + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const motion = Entry.hw.portData['NEMO_DEVICE'].accelD; + if (motion[index] === true) { + return script.callReturn(); + } else { + return this.die(); + } + } + }, + nemo_block_input_bool_button_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.input_bool_button_state, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_button', + }, + { + type: 'nemo_dropdown_button_state_question', + }, + ], + type: 'nemo_block_input_bool_button_state', + }, + paramsKeyMap: { + INDEX: 0, + STATE: 1, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const state = script.getNumberValue('STATE'); + const getState = Entry.hw.portData['NEMO_DEVICE_EX'].button[index].state[state]; + return getState; + } + }, + nemo_block_input_bool_motion_sensing: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.input_bool_motion_sensing, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_motion', + }, + ], + type: 'nemo_block_input_bool_motion_sensing', + }, + paramsKeyMap: { + INDEX: 0, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const motion = Entry.hw.portData['NEMO_DEVICE'].accelD; + return motion[index]; + } + }, + nemo_block_input_bool_led_state_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.input_bool_led_state_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + ], + type: 'nemo_block_input_bool_led_state_value', + }, + paramsKeyMap: { + X: 0, + Y: 1, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const x = script.getNumberValue('X'); + const y = script.getNumberValue('Y'); + const index = x * 7 + y + 1; + + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 10, + readLED: { + index: index + }, + }; + Entry.hw.update(); + + const led = Entry.hw.portData['NEMO_DEVICE'].ledRead; + return led.state; + } + }, + nemo_block_input_field_button_analog_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.input_field_button_analog_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_button', + }, + ], + type: 'nemo_block_input_field_button_analog_value', + }, + paramsKeyMap: { + INDEX: 0, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const button = Entry.hw.portData['NEMO_DEVICE'].anSwitch; + return button[index]; + } + }, + nemo_block_input_field_acceleration_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.input_field_acceleration_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_coordinate_acceleration', + }, + ], + type: 'nemo_block_input_field_acceleration_value', + }, + paramsKeyMap: { + INDEX: 0, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const index = script.getNumberValue('INDEX'); + const accel = Entry.hw.portData['NEMO_DEVICE'].accelA; + return accel[index]; + } + }, + nemo_block_input_field_brightness_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.input_field_brightness_value, + params: [ + ], + events: {}, + def: { + params: [null], + type: 'nemo_block_input_field_brightness_value', + }, + paramsKeyMap: {}, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const illuminance = Entry.hw.portData['NEMO_DEVICE'].illumi; + return illuminance; + } + }, + nemo_block_input_field_convert_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.input_field_convert_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + ], + type: 'nemo_block_input_field_convert_value', + }, + paramsKeyMap: { + VALUE: 0, + IN_MIN: 1, + IN_MAX: 2, + OUT_MIN: 3, + OUT_MAX: 4, + }, + class: 'inputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const value = script.getNumberValue('VALUE'); + const inMin = script.getNumberValue('IN_MIN'); + const inMax = script.getNumberValue('IN_MAX'); + const outMin = script.getNumberValue('OUT_MIN'); + const outMax = script.getNumberValue('OUT_MAX'); + let result = Math.round(((value - inMin) * (outMax - outMin)) / (inMax - inMin) + outMin); + if (result < outMin) { + result = outMin; + } else if (result > outMax) { + result = outMax; + } + return result; + } + }, + ///======================================================================================== + /// Output block + ///======================================================================================== + nemo_title_namo_output: { + skeleton: 'basic_text', + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#333333', + template: Lang.template.title_namo_output, + skeletonOptions: { + box: { + offsetX: 20, + }, + }, + def: { + type: 'nemo_title_namo_output', + }, + isNotFor: ['nemo'], + class : 'outputBlock', + }, + nemo_block_output_basic_display_led_icon: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_display_led_icon, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_led_icon', + }, + { + type: 'nemo_dropdown_index_0_5', + }, + null, + ], + type: 'nemo_block_output_basic_display_led_icon', + }, + paramsKeyMap: { + INDEX: 0, + SPEED: 1, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const index = script.getNumberValue('INDEX'); + const speed = script.getNumberValue('SPEED'); + const time = Entry.nemo.numToMS(speed); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 0, + iconLED: { + index: index, + time: time, + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_diplay_led_custom_icon: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_diplay_led_custom_icon, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_index_1_7', + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'nemo_dropdown_index_0_5', + }, + null, + ], + type: 'nemo_block_output_basic_diplay_led_custom_icon', + }, + paramsKeyMap: { + INDEX: 0, + VALUE1: 1, + VALUE2: 2, + VALUE3: 3, + VALUE4: 4, + VALUE5: 5, + VALUE6: 6, + VALUE7: 7, + SPEED: 8, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const index = script.getNumberValue('INDEX'); + const value1 = script.getNumberValue('VALUE1'); + const value2 = script.getNumberValue('VALUE2'); + const value3 = script.getNumberValue('VALUE3'); + const value4 = script.getNumberValue('VALUE4'); + const value5 = script.getNumberValue('VALUE5'); + const value6 = script.getNumberValue('VALUE6'); + const value7 = script.getNumberValue('VALUE7'); + const speed = script.getNumberValue('SPEED'); + const time = Entry.nemo.numToMS(speed); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 1, + customLED: { + icon: index, + value: [value1, value2, value3, value4, value5, value6, value7], + time: time, + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_display_led_string: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_display_led_string, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'text', + params: [ 'Hello' ], + }, + { + type: 'nemo_dropdown_index_1_5', + }, + null, + ], + type: 'nemo_block_output_basic_display_led_string', + }, + paramsKeyMap: { + TEXT: 0, + SPEED: 1, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const text = script.getValue('TEXT'); + const speed = script.getNumberValue('SPEED'); + const time = Entry.nemo.numToMS(speed); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 2, + textLED: { + text: text, + time: time, + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_delete_all_led: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_delete_all_led, + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'nemo_block_output_basic_delete_all_led', + }, + paramsKeyMap: {}, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 3, + deleteLED: { + value: true, + }, + }; + + return script.callReturn(); + } + }, + nemo_block_output_basic_coordinate_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_coordinate_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'nemo_dropdown_switch', + }, + null, + ], + type: 'nemo_block_output_basic_coordinate_value', + }, + paramsKeyMap: { + X: 0, + Y: 1, + STATE: 2, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const x = script.getNumberValue('X'); + const y = script.getNumberValue('Y'); + const index = x * 7 + y + 1; + const state = script.getNumberValue('STATE'); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 4, + coordinateLED: { + index: index, + state: state, + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_play_melody: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_play_melody, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_melody', + }, + null, + ], + type: 'nemo_block_output_basic_play_melody', + }, + paramsKeyMap: { + TITLE: 0, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const title = script.getNumberValue('TITLE'); + + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 5, + playMelody: { + title: title, + }, + }; + + return script.callReturn(); + } + }, + nemo_block_output_basic_play_melody_to_the_end: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_play_melody_to_the_end, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_melody', + }, + null, + ], + type: 'nemo_block_output_basic_play_melody_to_the_end', + }, + paramsKeyMap: { + TITLE: 0, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const title = script.getNumberValue('TITLE'); + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 6, + playMelody: { + title: title, + }, + }; + return script; + } else if (script.timeFlag == 1) { + const finished = Entry.hw.portData['NEMO_DEVICE_EX'].timeCheck[1]; + if (finished.state) { + script.timeFlag = 2; + } + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + } + }, + nemo_block_output_basic_play_note: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_play_note, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_keyboard', + }, + null, + ], + type: 'nemo_block_output_basic_play_note', + }, + paramsKeyMap: { + PITCH: 0, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const pitch = script.getNumberValue('PITCH'); + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 7, + playNote: { + pitch: pitch + }, + }; + return false; + }); + } + }, + nemo_block_output_basic_play_note_for_seconds: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_play_note_for_seconds, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_keyboard', + }, + { + type: 'number', + params: ['1'], + }, + null, + ], + type: 'nemo_block_output_basic_play_note_for_seconds', + }, + paramsKeyMap: { + PITCH: 0, + TIME: 1, + }, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const pitch = script.getNumberValue('PITCH'); + const time = script.getNumberValue('TIME'); + + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const fps = Entry.FPS || 60; + const timeValue = (60 / fps) * time * 1000; + Entry.TimeWaitManager.add( + Math.random(), + () => { + script.timeFlag = 0; + }, + timeValue + ); + + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 7, + playNote: { + pitch: pitch + }, + }; + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + } + }, + nemo_block_output_basic_stop_all_sound: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.output_basic_stop_all_sound, + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'nemo_block_output_basic_stop_all_sound', + }, + paramsKeyMap: {}, + class: 'outputBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + Entry.hw.sendQueue['NEMO_OUTPUT'] = { + id: Math.random(), + index: 9, + playNote: { + pitch: -1, + }, + playMelody: { + title: 0, + }, + }; + return false; + }); + } + }, + ///======================================================================================== + /// Extension block + ///======================================================================================== + nemo_title_namo_extension: { + skeleton: 'basic_text', + color: EntryStatic.colorSet.common.TRANSPARENT, + fontColor: '#333333', + template: Lang.template.title_namo_extension, + skeletonOptions: { + box: { + offsetX: 20, + }, + }, + def: { + type: 'nemo_title_namo_extension', + }, + isNotFor: ['nemo'], + class : 'extensionBlock', + }, + nemo_block_extension_basic_set_expension: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.extension_basic_set_expension, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_expension_sensor_mode', + }, + null, + ], + type: 'nemo_block_extension_basic_set_expension', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const type = script.getNumberValue('TYPE'); + Entry.hw.sendQueue['NEMO_EXTENSION'] = { + id: Math.random(), + index: 0, + setExpansion: { + type: type, + }, + }; + return false; + }); + } + }, + nemo_block_extension_basic_set_expension_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.extension_basic_set_expension_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + null, + ], + type: 'nemo_block_extension_basic_set_expension_value', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const value = script.getNumberValue('VALUE'); + Entry.hw.sendQueue['NEMO_EXTENSION'] = { + id: Math.random(), + index: 1, + setExpansionValue: { + value: value, + }, + }; + return false; + }); + } + }, + nemo_block_extension_bool_expension_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.extension_bool_expension_state, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_button_state_question', + }, + null + ], + type: 'nemo_block_extension_bool_expension_state', + }, + paramsKeyMap: { + STATE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const state = script.getNumberValue('STATE') + 4; + const expansion = Entry.hw.portData['NEMO_DEVICE_EX'].expansion; + return expansion.state[state]; + } + }, + nemo_block_extension_field_expension_anlog_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.extension_field_expension_anlog_value, + params: [], + events: {}, + def: { + params: [], + type: 'nemo_block_extension_field_expension_anlog_value', + }, + paramsKeyMap: {}, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const value = Entry.hw.portData['NEMO_DEVICE'].exPort; + return value; + } + }, + nemo_block_extension_field_expension_custom_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.extension_field_expension_custom_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_compass_sensor_mode', + }, + ], + type: 'nemo_block_extension_field_expension_custom_value', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const type = script.getNumberValue('TYPE'); + const expansion = Entry.hw.portData['NEMO_DEVICE_EX'].expansion; + return expansion.state[type]; + } + }, + nemo_block_extension_basic_set_compass_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + template: Lang.template.extension_basic_set_compass_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + ], + type: 'nemo_block_extension_basic_set_compass_value', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + return Entry.nemo.setProcessor(script, Entry.nemo.delayTime, function() { + const value = script.getNumberValue('VALUE'); + Entry.hw.sendQueue['NEMO_EXTENSION'] = { + id: Math.random(), + index: 2, + setCompassValue: { + value: value, + }, + }; + return false; + }); + } + }, + + nemo_block_extension_field_compass_analog_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.extension_field_compass_analog_value, + params: [], + events: {}, + def: { + params: [], + type: 'nemo_block_extension_field_compass_analog_value', + }, + paramsKeyMap: {}, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const value = Entry.hw.portData['NEMO_DEVICE'].compass; + return value; + } + }, + nemo_block_extension_field_compass_custom_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + template: Lang.template.extension_field_compass_custom_value, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_compass_sensor_mode', + }, + ], + type: 'nemo_block_extension_field_compass_custom_value', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const type = script.getNumberValue('TYPE'); + const compass = Entry.hw.portData['NEMO_DEVICE_EX'].compass; + return compass.state[type]; + } + }, + nemo_block_extension_bool_compass_state: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + template: Lang.template.extension_bool_compass_state, + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + },], + events: {}, + def: { + params: [ + { + type: 'nemo_dropdown_direction', + }, + ], + type: 'nemo_block_extension_bool_compass_state', + }, + paramsKeyMap: { + DIRECTION: 0, + }, + class: 'extensionBlock', + isNotFor: ['nemo'], + func: function(sprite, script) { + const direction = script.getNumberValue('DIRECTION'); + const compass = Entry.hw.portData['NEMO_DEVICE_EX'].compass; + return compass.state[4] === direction ? true : false; + } + }, + }; +}; + +module.exports = Entry.nemo; \ No newline at end of file diff --git a/src/playground/blocks/hardware/block_arduino.js b/src/playground/blocks/hardware/block_arduino.js index 4d34477882..5b95c8e10b 100644 --- a/src/playground/blocks/hardware/block_arduino.js +++ b/src/playground/blocks/hardware/block_arduino.js @@ -22,62 +22,62 @@ Entry.Arduino = { width: 605, height: 434, listPorts: { - '2': { + 2: { name: `${Lang.Hw.port_en} 2 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '3': { + 3: { name: `${Lang.Hw.port_en} 3 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '4': { + 4: { name: `${Lang.Hw.port_en} 4 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '5': { + 5: { name: `${Lang.Hw.port_en} 5 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '6': { + 6: { name: `${Lang.Hw.port_en} 6 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '7': { + 7: { name: `${Lang.Hw.port_en} 7 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '8': { + 8: { name: `${Lang.Hw.port_en} 8 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '9': { + 9: { name: `${Lang.Hw.port_en} 9 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '10': { + 10: { name: `${Lang.Hw.port_en} 10 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '11': { + 11: { name: `${Lang.Hw.port_en} 11 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '12': { + 12: { name: `${Lang.Hw.port_en} 12 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, }, - '13': { + 13: { name: `${Lang.Hw.port_en} 13 ${Lang.Hw.port_ko}`, type: 'input', pos: { x: 0, y: 0 }, @@ -117,15 +117,15 @@ Entry.Arduino = { }, }; -Entry.Arduino.setLanguage = function() { +Entry.Arduino.setLanguage = function () { return { ko: { template: { - arduino_get_number_sensor_value: '아날로그 %1 번 센서값 ', - arduino_get_digital_value: '디지털 %1 번 센서값 ', + arduino_get_number_sensor_value: '아날로그 %1 번 값 ', + arduino_get_digital_value: '디지털 %1 번 값', arduino_toggle_led: '디지털 %1 번 핀 %2 %3', arduino_toggle_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3', - arduino_convert_scale: '%1 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼값 ', + arduino_convert_scale: '%1 번 값의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼 값', }, Device: { arduino: '아두이노', @@ -133,14 +133,22 @@ Entry.Arduino.setLanguage = function() { Menus: { arduino: '아두이노', }, + Helper: { + arduino_get_number_sensor_value: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)', + arduino_convert_scale: '선택한 핀의 아날로그 값을 입력한 범위로 바꾼 값입니다.', + arduino_get_digital_value: + '선택한 핀의 디지털 값입니다. 핀이 켜진 경우 "참"으로 판단합니다.', + arduino_toggle_led: '선택한 핀을 켜거나 끕니다.', + arduino_toggle_pwm: '선택한 핀을 입력한 값으로 정합니다.', + }, }, en: { template: { - arduino_get_number_sensor_value: 'Analog %1 Sensor value ', - arduino_get_digital_value: 'Digital %1 Sensor value ', - arduino_toggle_led: 'Digital %1 Pin %2 %3', - arduino_toggle_pwm: 'Digital %1 Pin %2 %3', - arduino_convert_scale: 'Map Value %1 %2 ~ %3 to %4 ~ %5 ', + arduino_get_number_sensor_value: 'analog %1 value ', + arduino_get_digital_value: 'digital %1 value ', + arduino_toggle_led: '%2 digital %1 pin %3', + arduino_toggle_pwm: 'Set digital %1 pin to %2 %3', + arduino_convert_scale: 'mapped value of analog %1 that %2 ~ %3 to %4 ~ %5', }, Device: { arduino: 'arduino', @@ -148,6 +156,16 @@ Entry.Arduino.setLanguage = function() { Menus: { arduino: 'Arduino', }, + Helper: { + arduino_get_number_sensor_value: + 'Reports the value that analog signal of the selected pin. (0 ~ 1023)', + arduino_convert_scale: + 'Reports the value that analog signal of the selected pin mapping original range onto input range.', + arduino_get_digital_value: + 'Checks whether the selected pin is turned on. If it turned on, it is judged as "True".', + arduino_toggle_led: 'Turn on or turn off the selected pin.', + arduino_toggle_pwm: 'Set the selected pin to input value.', + }, }, }; }; @@ -160,7 +178,7 @@ Entry.Arduino.blockMenuBlocks = [ 'arduino_convert_scale', ]; -Entry.Arduino.getBlocks = function() { +Entry.Arduino.getBlocks = function () { return { //region arduino 아두이노 arduino_text: { @@ -208,12 +226,12 @@ Entry.Arduino.getBlocks = function() { { type: 'Dropdown', options: [ - ['0', 'A0'], - ['1', 'A1'], - ['2', 'A2'], - ['3', 'A3'], - ['4', 'A4'], - ['5', 'A5'], + ['A0', 'A0'], + ['A1', 'A1'], + ['A2', 'A2'], + ['A3', 'A3'], + ['A4', 'A4'], + ['A5', 'A5'], ], value: 'A0', fontSize: 11, diff --git a/src/playground/blocks/hardware/block_arduino_ext.js b/src/playground/blocks/hardware/block_arduino_ext.js index 856e5c5326..d811577596 100644 --- a/src/playground/blocks/hardware/block_arduino_ext.js +++ b/src/playground/blocks/hardware/block_arduino_ext.js @@ -36,7 +36,7 @@ Entry.ArduinoExt = { TIMER: 8, }, toneTable: { - '0': 0, + 0: 0, C: 1, CS: 2, D: 3, @@ -51,48 +51,82 @@ Entry.ArduinoExt = { 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], + 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], }, highList: ['high', '1', 'on'], lowList: ['low', '0', 'off'], BlockState: {}, }; -Entry.ArduinoExt.setLanguage = function() { +Entry.ArduinoExt.setLanguage = function () { return { ko: { template: { - arduino_ext_get_analog_value: '아날로그 %1 번 센서값', - arduino_ext_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값', - arduino_ext_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값', + arduino_ext_get_analog_value: '아날로그 %1 번 값', + arduino_ext_get_analog_value_map: + '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼 값', + arduino_ext_get_ultrasonic_value: + '디지털 %1 번 핀을 Trig에 디지털 %2 번 핀을 Echo에 연결한 초음파 센서 값', arduino_ext_toggle_led: '디지털 %1 번 핀 %2 %3', arduino_ext_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3', - arduino_ext_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5', - arduino_ext_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3', - arduino_ext_get_digital: '디지털 %1 번 센서값', + arduino_ext_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 울리기 %5', + arduino_ext_set_servo: '디지털 %1 번 핀의 서보모터를 %2 도로 정하기 %3', + arduino_ext_get_digital: '디지털 %1 번 값', + }, + Helper: { + arduino_ext_get_analog_value: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)', + arduino_ext_get_analog_value_map: + '선택한 핀의 아날로그 값을 입력한 범위로 바꾼 값입니다.', + arduino_ext_get_ultrasonic_value: '선택한 핀에 연결한 초음파 센서 값입니다.', + arduino_ext_set_servo: '선택한 핀에 연결한 서보모터의 각도를 정합니다.', + arduino_ext_set_tone: + '선택한 핀에 연결한 버저를 선택한 음으로 입력한 시간 동안 울립니다.', + arduino_ext_get_digital: + '선택한 핀의 디지털 값입니다. 핀이 켜진 경우 "참"으로 판단합니다.', + arduino_ext_toggle_led: '선택한 핀을 켜거나 끕니다.', + arduino_ext_digital_pwm: '선택한 핀을 입력한 값으로 정합니다.', }, }, en: { template: { - arduino_ext_get_analog_value: 'Analog %1 Sensor value', - arduino_ext_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5', - arduino_ext_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2', - arduino_ext_toggle_led: 'Digital %1 Pin %2 %3', - arduino_ext_digital_pwm: 'Digital %1 Pin %2 %3', - arduino_ext_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5', - arduino_ext_set_servo: 'Set servo pin %1 angle as %2 %3', - arduino_ext_get_digital: 'Digital %1 Sensor value', + arduino_ext_get_analog_value: 'analog %1 value', + arduino_ext_get_analog_value_map: + 'mapped value of analog %1 that %2 ~ %3 to %4 ~ %5', + arduino_ext_get_ultrasonic_value: + 'ultrasonic sensor value that connects pin %1 to Trig and pin %2 to Echo', + arduino_ext_toggle_led: '%2 digital %1 pin %3', + arduino_ext_digital_pwm: 'Set digital %1 pin to %2 %3', + arduino_ext_set_tone: + 'Ring buzzer of pin %1 on note %2 octave %3 for %4 second(s) %5', + arduino_ext_set_servo: 'Set servo motor of pin %1 to %2 degree %3', + arduino_ext_get_digital: 'digital %1 value', + }, + Helper: { + arduino_ext_get_analog_value: + 'Reports the value that analog signal of the selected pin. (0 ~ 1023)', + arduino_ext_get_analog_value_map: + 'Reports the value that analog signal of the selected pin mapping original range onto input range.', + arduino_ext_get_ultrasonic_value: + 'Reports the value of ultrasonic sensor that connects pin.', + arduino_ext_set_servo: + 'Set the degree of servo motor that connected with selected pin.', + arduino_ext_set_tone: + 'Rings buzzer connected with selected pin during input seconds.', + arduino_ext_get_digital: + 'Checks whether the selected pin is turned on. If it turned on, it is judged as "True".', + arduino_ext_toggle_led: 'Turn on or turn off the selected pin.', + arduino_ext_digital_pwm: 'Set the selected pin to input value.', }, }, }; @@ -110,7 +144,7 @@ Entry.ArduinoExt.blockMenuBlocks = [ ]; //region arduinoExt 아두이노 확장모드 -Entry.ArduinoExt.getBlocks = function() { +Entry.ArduinoExt.getBlocks = function () { return { arduino_ext_analog_list: { color: EntryStatic.colorSet.block.default.HARDWARE, @@ -518,7 +552,10 @@ Entry.ArduinoExt.getBlocks = function() { params: [ { type: 'Dropdown', - options: [[Lang.Blocks.ARDUINO_on, 'on'], [Lang.Blocks.ARDUINO_off, 'off']], + options: [ + [Lang.Blocks.ARDUINO_on, 'on'], + [Lang.Blocks.ARDUINO_off, 'off'], + ], value: 'on', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, diff --git a/src/playground/blocks/hardware/block_arduino_nano.js b/src/playground/blocks/hardware/block_arduino_nano.js index 959f59f058..879fa129d7 100644 --- a/src/playground/blocks/hardware/block_arduino_nano.js +++ b/src/playground/blocks/hardware/block_arduino_nano.js @@ -36,7 +36,7 @@ Entry.ArduinoNano = { TIMER: 8, }, toneTable: { - '0': 0, + 0: 0, C: 1, CS: 2, D: 3, @@ -51,51 +51,85 @@ Entry.ArduinoNano = { 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], + 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], }, highList: ['high', '1', 'on'], lowList: ['low', '0', 'off'], BlockState: {}, }; -Entry.ArduinoNano.setLanguage = function() { +Entry.ArduinoNano.setLanguage = function () { return { ko: { template: { - arduino_nano_get_analog_value: '아날로그 %1 번 센서값', - arduino_nano_get_analog_value_map: '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 로 바꾼값', - arduino_nano_get_ultrasonic_value: '울트라소닉 Trig %1 Echo %2 센서값', + arduino_nano_get_analog_value: '아날로그 %1 번 값', + arduino_nano_get_analog_value_map: + '%1 의 범위를 %2 ~ %3 에서 %4 ~ %5 (으)로 바꾼 값', + arduino_nano_get_ultrasonic_value: + '디지털 %1 번 핀을 Trig에 디지털 %2 번 핀을 Echo에 연결한 초음파 센서 값', arduino_nano_toggle_led: '디지털 %1 번 핀 %2 %3', arduino_nano_digital_pwm: '디지털 %1 번 핀을 %2 (으)로 정하기 %3', - arduino_nano_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 연주하기 %5', - arduino_nano_set_servo: '디지털 %1 번 핀의 서보모터를 %2 의 각도로 정하기 %3', - arduino_nano_get_digital: '디지털 %1 번 센서값', + arduino_nano_set_tone: '디지털 %1 번 핀의 버저를 %2 %3 음으로 %4 초 울리기 %5', + arduino_nano_set_servo: '디지털 %1 번 핀의 서보모터를 %2 도로 정하기 %3', + arduino_nano_get_digital: '디지털 %1 번 값', }, Device: { arduinonano: '아두이노 Nano', }, + Helper: { + arduino_nano_get_analog_value: '선택한 핀의 아날로그 값입니다. (0 ~ 1023)', + arduino_nano_get_analog_value_map: + '선택한 핀의 아날로그 값을 입력한 범위로 바꾼 값입니다.', + arduino_nano_get_digital: + '선택한 핀의 디지털 값입니다. 핀이 켜진 경우 "참"으로 판단합니다.', + arduino_nano_toggle_led: '선택한 핀을 켜거나 끕니다.', + arduino_nano_digital_pwm: '선택한 핀을 입력한 값으로 정합니다.', + arduino_nano_get_ultrasonic_value: '선택한 핀에 연결한 초음파 센서 값입니다.', + arduino_nano_set_servo: '선택한 핀에 연결한 서보모터의 각도를 정합니다.', + arduino_nano_set_tone: + '선택한 핀에 연결한 버저를 선택한 음으로 입력한 시간 동안 울립니다.', + }, }, en: { template: { - arduino_nano_get_analog_value: 'Analog %1 Sensor value', - arduino_nano_get_analog_value_map: 'Map Value %1 %2 ~ %3 to %4 ~ %5', - arduino_nano_get_ultrasonic_value: 'Read ultrasonic sensor trig pin %1 echo pin %2', - arduino_nano_toggle_led: 'Digital %1 Pin %2 %3', - arduino_nano_digital_pwm: 'Digital %1 Pin %2 %3', - arduino_nano_set_tone: 'Play tone pin %1 on note %2 octave %3 beat %4 %5', - arduino_nano_set_servo: 'Set servo pin %1 angle as %2 %3', - arduino_nano_get_digital: 'Digital %1 Sensor value', + arduino_nano_get_analog_value: 'analog %1 value', + arduino_nano_get_analog_value_map: + 'mapped value of analog %1 that %2 ~ %3 to %4 ~ %5', + arduino_nano_get_ultrasonic_value: + 'ultrasonic sensor value that connects pin %1 to Trig and pin %2 to Echo', + arduino_nano_toggle_led: '%2 digital %1 pin %3', + arduino_nano_digital_pwm: 'Set digital %1 pin to %2 %3', + arduino_nano_set_tone: + 'Ring buzzer of pin %1 on note %2 octave %3 for %4 second(s) %5', + arduino_nano_set_servo: 'Set servo motor of pin %1 to %2 degree %3', + arduino_nano_get_digital: 'digital %1 value', + }, + Helper: { + arduino_nano_get_analog_value: + 'Reports the value that analog signal of the selected pin. (0 ~ 1023)', + arduino_nano_get_analog_value_map: + 'Reports the value that analog signal of the selected pin mapping original range onto input range.', + arduino_nano_get_digital: + 'Checks whether the selected pin is turned on. If it turned on, it is judged as "True".', + arduino_nano_toggle_led: 'Turn on or turn off the selected pin.', + arduino_nano_digital_pwm: 'Set the selected pin to input value.', + arduino_nano_set_servo: + 'Set the degree of servo motor that connected with selected pin.', + arduino_nano_set_tone: + 'Rings buzzer connected with selected pin during input seconds.', + arduino_nano_get_ultrasonic_value: + 'Reports the value of ultrasonic sensor that connects pin.', }, }, }; @@ -112,7 +146,7 @@ Entry.ArduinoNano.blockMenuBlocks = [ 'arduino_nano_set_tone', ]; -Entry.ArduinoNano.getBlocks = function() { +Entry.ArduinoNano.getBlocks = function () { return { //region arduinoNano 아두이노 나노 arduino_nano_analog_list: { @@ -140,7 +174,6 @@ Entry.ArduinoNano.getBlocks = function() { }, arduino_nano_get_analog_value: { parent: 'arduino_ext_get_analog_value', - template: Lang.template.arduino_ext_get_analog_value, def: { params: [ { @@ -154,7 +187,6 @@ Entry.ArduinoNano.getBlocks = function() { }, arduino_nano_get_analog_value_map: { parent: 'arduino_ext_get_analog_value_map', - template: Lang.template.arduino_ext_get_analog_value_map, def: { params: [ { @@ -188,7 +220,6 @@ Entry.ArduinoNano.getBlocks = function() { syntax: undefined, }, arduino_nano_get_ultrasonic_value: { - template: Lang.template.arduino_ext_get_ultrasonic_value, parent: 'arduino_ext_get_ultrasonic_value', def: { params: [ @@ -207,7 +238,6 @@ Entry.ArduinoNano.getBlocks = function() { syntax: undefined, }, arduino_nano_get_digital: { - template: Lang.template.arduino_ext_get_digital, parent: 'arduino_ext_get_digital', def: { params: [ @@ -221,7 +251,6 @@ Entry.ArduinoNano.getBlocks = function() { syntax: undefined, }, arduino_nano_toggle_led: { - template: Lang.template.arduino_ext_toggle_led, parent: 'arduino_ext_toggle_led', def: { params: [ @@ -259,7 +288,6 @@ Entry.ArduinoNano.getBlocks = function() { syntax: undefined, }, arduino_nano_set_tone: { - template: Lang.template.arduino_ext_set_tone, parent: 'arduino_ext_set_tone', def: { params: [ @@ -285,7 +313,6 @@ Entry.ArduinoNano.getBlocks = function() { syntax: undefined, }, arduino_nano_set_servo: { - template: Lang.template.arduino_ext_set_servo, parent: 'arduino_ext_set_servo', def: { params: [ diff --git a/src/playground/blocks/hardware/block_jinirobot_toybot.js b/src/playground/blocks/hardware/block_jinirobot_toybot.js index 972af2662d..b495a7143a 100644 --- a/src/playground/blocks/hardware/block_jinirobot_toybot.js +++ b/src/playground/blocks/hardware/block_jinirobot_toybot.js @@ -599,7 +599,8 @@ Entry.toybot.getBlocks = function() { ['1', 1], ['2', 2], ['3', 3], - ['4', 4] + ['4', 4], + ['5', 5] ], value: 3, fontSize: 11, diff --git a/src/playground/blocks/hardware/block_neo_cannon.js b/src/playground/blocks/hardware/block_neo_cannon.js index d242d9f6b7..a4cce5b7d6 100644 --- a/src/playground/blocks/hardware/block_neo_cannon.js +++ b/src/playground/blocks/hardware/block_neo_cannon.js @@ -19,6 +19,7 @@ Entry.NeoCannon = { d9: 0, d10: 0, angleState: 0, + neopixel: 0, }, setZero() { let portMap = Entry.NeoCannon.PORT_MAP; @@ -29,7 +30,7 @@ Entry.NeoCannon = { Entry.hw.update(); }, toneTable: { - '0': 0, + 0: 0, C: 1, CS: 2, D: 3, @@ -44,18 +45,18 @@ Entry.NeoCannon = { B: 12, }, toneMap: { - '1': [33, 65, 131, 262, 523, 1046, 2093, 4186], - '2': [35, 69, 139, 277, 554, 1109, 2217, 4435], - '3': [37, 73, 147, 294, 587, 1175, 2349, 4699], - '4': [39, 78, 156, 310, 622, 1245, 2637, 4978], - '5': [41, 82, 165, 330, 659, 1319, 2794, 5274], - '6': [44, 87, 175, 349, 698, 1397, 2849, 5588], - '7': [46, 92, 185, 370, 740, 1480, 2960, 5920], - '8': [49, 98, 196, 392, 784, 1568, 3136, 6272], - '9': [52, 104, 208, 415, 831, 1661, 3322, 6645], - '10': [55, 110, 220, 440, 880, 1760, 3520, 7040], - '11': [58, 117, 233, 466, 932, 1865, 3729, 7459], - '12': [62, 123, 247, 494, 988, 1976, 3951, 7902], + 1: [33, 65, 131, 262, 523, 1046, 2093, 4186], + 2: [35, 69, 139, 277, 554, 1109, 2217, 4435], + 3: [37, 73, 147, 294, 587, 1175, 2349, 4699], + 4: [39, 78, 156, 310, 622, 1245, 2637, 4978], + 5: [41, 82, 165, 330, 659, 1319, 2794, 5274], + 6: [44, 87, 175, 349, 698, 1397, 2849, 5588], + 7: [46, 92, 185, 370, 740, 1480, 2960, 5920], + 8: [49, 98, 196, 392, 784, 1568, 3136, 6272], + 9: [52, 104, 208, 415, 831, 1661, 3322, 6645], + 10: [55, 110, 220, 440, 880, 1760, 3520, 7040], + 11: [58, 117, 233, 466, 932, 1865, 3729, 7459], + 12: [62, 123, 247, 494, 988, 1976, 3951, 7902], }, monitorTemplate: { imgPath: 'hw/neo_cannon.png', @@ -73,7 +74,7 @@ Entry.NeoCannon = { BlockState: {}, }; -Entry.NeoCannon.setLanguage = function() { +Entry.NeoCannon.setLanguage = function () { return { ko: { template: { @@ -91,6 +92,11 @@ Entry.NeoCannon.setLanguage = function() { neo_cannon_rgb_led_color_picker: 'RGB LED %1 %2', neo_cannon_rgb_led_pwm: 'RGB LED 빨강 %1 초록 %2 파랑 %3 %4', neo_cannon_rgb_led_off: 'RGB LED 끄기 %1', + neo_cannon_neopixel_color_picker: 'Neopixel %1번 %2 (으)로 켜기 %3', + neo_cannon_neopixel: 'Neopixel %1번 빨 %2 녹 %3 파 %4 (으)로 켜기 %5', + neo_cannon_neopixel_color_picker_all_on: 'Neopixel 전체 %1 (으)로 켜기 %2', + neo_cannon_neopixel_all_on: 'Neopixel 전체 빨 %1 녹 %2 파 %3 (으)로 켜기 %4', + neo_cannon_neopixel_all_off: 'Neopixel 전체 끄기 %1', }, Helper: { @@ -117,6 +123,15 @@ Entry.NeoCannon.setLanguage = function() { neo_cannon_rgb_led_pwm: 'RGB LED에 세기값(0~255)을 주어 원하는 색상을 나타낼 수 있습니다.
(주의, LED모드로 진행해주세요.)', neo_cannon_rgb_led_off: 'RGB LED를 끌 수 있습니다.', + neo_cannon_neopixel_color_picker: + '색을 보고 RGB색상을 정하여 정해진 네오픽셀를 켤 수 있습니다.
(참고, 네오픽셀번호는 0번부터 17번까지 입니다.)', + neo_cannon_neopixel: + '정해준 네오픽셀 번호에 빨강, 파랑, 초록의 색을 넣고 조합하여 네오픽셀를 켤 수 있습니다.
(참고, 네오픽셀번호는 0번부터 17번까지 입니다.)', + neo_cannon_neopixel_color_picker_all_on: + '색을 보고 RGB색상을 정하여 모든 네오픽셀를 켤 수 있습니다.', + neo_cannon_neopixel_all_on: + '빨강, 파랑, 초록의 색을 넣고 조합하여 모든 네오픽셀를 켤 수 있습니다.', + neo_cannon_neopixel_all_off: '모든 네오픽셀를 끌 수 있습니다.', }, }, en: { @@ -135,6 +150,11 @@ Entry.NeoCannon.setLanguage = function() { neo_cannon_rgb_led_color_picker: 'RGB LED %1 %2', neo_cannon_rgb_led_pwm: 'RGB LED R %1 G %2 B %3 %4', neo_cannon_rgb_led_off: 'RGB LED OFF', + neo_cannon_neopixel_color_picker: 'Neopixel number %1 turn on %2 %3', + neo_cannon_neopixel: 'Neopixel number %1 turn on R %2 G %3 B %4 %5', + neo_cannon_neopixel_color_picker_all_on: 'All Neopixel turn on %1 %2', + neo_cannon_neopixel_all_on: 'All Neopixel turn on R %1 G %2 B %3 %4', + neo_cannon_neopixel_all_off: 'All Neopixel turn off %1', }, }, }; @@ -155,9 +175,14 @@ Entry.NeoCannon.blockMenuBlocks = [ 'neo_cannon_rgb_led_color_picker', 'neo_cannon_rgb_led_pwm', 'neo_cannon_rgb_led_off', + 'neo_cannon_neopixel_color_picker', + 'neo_cannon_neopixel', + 'neo_cannon_neopixel_color_picker_all_on', + 'neo_cannon_neopixel_all_on', + 'neo_cannon_neopixel_all_off', ]; -Entry.NeoCannon.getBlocks = function() { +Entry.NeoCannon.getBlocks = function () { return { neo_cannon_get_vibe_value: { color: EntryStatic.colorSet.block.default.HARDWARE, @@ -174,7 +199,7 @@ Entry.NeoCannon.getBlocks = function() { class: 'NeoCannonGet', isNotFor: ['NeoCannon'], func(sprite, script) { - let port = 'vibe' + let port = 'vibe'; return Entry.hw.portData[port] || 0; }, @@ -1265,7 +1290,7 @@ Entry.NeoCannon.getBlocks = function() { ], events: {}, def: { - params: ["#0000FF", null], + params: ['#0000FF', null], type: 'neo_cannon_rgb_led_color_picker', }, paramsKeyMap: { @@ -1273,7 +1298,7 @@ Entry.NeoCannon.getBlocks = function() { }, class: 'NeoCannonRGB', isNotFor: ['NeoCannon'], - func: function(sprite, script) { + func: function (sprite, script) { const sq = Entry.hw.sendQueue; let value = script.getStringField('COLOR'); @@ -1373,7 +1398,7 @@ Entry.NeoCannon.getBlocks = function() { }, class: 'NeoCannonRGB', isNotFor: ['NeoCannon'], - func: function(sprite, script) { + func: function (sprite, script) { const sq = Entry.hw.sendQueue; let red = script.getNumberValue('RED', script); @@ -1445,7 +1470,7 @@ Entry.NeoCannon.getBlocks = function() { paramsKeyMap: {}, class: 'NeoCannonRGB', isNotFor: ['NeoCannon'], - func: function(sprite, script) { + func: function (sprite, script) { const sq = Entry.hw.sendQueue; if (!sq.shootState) { @@ -1479,6 +1504,417 @@ Entry.NeoCannon.getBlocks = function() { ], }, }, + neo_cannon_neopixel: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + null, + ], + type: 'neo_cannon_neopixel', + }, + paramsKeyMap: { + NUM: 0, + RED: 1, + GREEN: 2, + BLUE: 3, + }, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + let num = script.getNumberValue('NUM', script) || 0; + num = num % 18; + + let red = script.getNumberValue('RED', script); + let green = script.getNumberValue('GREEN', script); + let blue = script.getNumberValue('BLUE', script); + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + num, + red, + green, + blue, + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixel(%1, %2, %3, %4)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_neopixel_color_picker: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + null, + null, + ], + type: 'neo_cannon_neopixel_color_picker', + }, + paramsKeyMap: { + NUM: 0, + COLOR: 1, + }, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + let num = script.getNumberValue('NUM', script) || 0; + num = num % 18; + + let value = script.getStringField('COLOR'); + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + let red = parseInt(value.substr(1, 2), 16); + let green = parseInt(value.substr(3, 2), 16); + let blue = parseInt(value.substr(5, 2), 16); + + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + num, + red, + green, + blue, + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixelColorPicker(%1, %2)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neo_cannon_neopixel_color_picker_all_on: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'neo_cannon_neopixel_color_picker_all_on', + }, + paramsKeyMap: { + COLOR: 0, + }, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + let value = script.getStringField('COLOR'); + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + let red = parseInt(value.substr(1, 2), 16); + let green = parseInt(value.substr(3, 2), 16); + let blue = parseInt(value.substr(5, 2), 16); + + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + red, + green, + blue, + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixelColorPickerAllOn(%1)', + textParams: [ + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neo_cannon_neopixel_all_on: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + null, + ], + type: 'neo_cannon_neopixel_all_on', + }, + paramsKeyMap: { + RED: 0, + GREEN: 1, + BLUE: 2, + }, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + + let red = script.getNumberValue('RED', script); + let green = script.getNumberValue('GREEN', script); + let blue = script.getNumberValue('BLUE', script); + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + sq.neopixel = { + type: Entry.NeoCannon.PORT_MAP.neopixel, + data: { + red, + green, + blue, + }, + time: new Date().getTime(), + }; + + Entry.hw.update(); + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixelAllON(%1, %2, %3)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neo_cannon_neopixel_all_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'neo_cannon_neopixel_all_off', + }, + paramsKeyMap: {}, + class: 'NeoCannonNeopixel', + isNotFor: ['NeoCannon'], + func: function (sprite, script) { + const sq = Entry.hw.sendQueue; + + if (!sq.neopixel) { + sq.neopixel = {}; + } + + sq.neopixel = 0; + + return script.callReturn(); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannon.neopixelAllOFF()', + textParams: [], + }, + ], + }, + }, }; }; diff --git a/src/playground/blocks/hardware/block_proboconnect.js b/src/playground/blocks/hardware/block_proboconnect.js index 18fd0f21dd..7ce9ede862 100644 --- a/src/playground/blocks/hardware/block_proboconnect.js +++ b/src/playground/blocks/hardware/block_proboconnect.js @@ -1,2663 +1,3978 @@ -'use strict'; - - -Entry.ProboConnect = { - afterReceive(pd) { - if(Entry.engine.isState('run')){ - Entry.engine.fireEvent('event_remote_input'); - Entry.engine.fireEvent('event_digital_input'); - } - - }, - - id: '27.1', - name: 'ProboConnect', // isNotFor 속성과 대소문자까지 정확하게 매치되어야 합니다. - url: 'http://www.probo.kr/', // 생략 가능합니다. 엔트리 사이트에서 홍보시 사용됩니다. - imageName: 'ProboConnect.png', // images/hardware 폴더 내에 존재하는 이미지입니다. 엔트리 사이트에서 홍보시 사용됩니다. - title: { - ko: '프로보커넥트', - en: 'ProboConnect', - }, - Color: [ - /*레드*/ [13, 37], - /*그린*/ [38, 62], - /*블루*/ [63, 87], - /*옐로우*/ [88, 112], - /*블랙*/ [113, 137], - /*화이트*/ [138, 162], - ], - - Note:{ - n32 : 48,// = 1*3*4*4, - n16 : 96,// = 2*3*4*4, - n16d: 144,// = 3*3*4*4, - n16t: 64,// = 2*2*4*4, - n8 : 192,// = 4*3*4*4, - n8d : 288,// = 6*3*4*4, - n8t : 128,// = 4*2*4*4, - n4 : 384,// = 8*3*4*4, - n4d : 576,// = 12*3*4*4, - n4t : 256,// = 8*2*4*4, - n2 : 768,// = 16*3*4*4, - n2d : 1152,// = 24*3*4*4, - n2t : 512,// = 16*2*4*4, - n1 : 1536,// = 32*3*4*4 - }, - - RGB_LED:{ - red : 1, //RED ON - red1: 2, //RED 0.05 ON -> OFF 반복 - red2: 3, //RED 0.1 ON -> OFF 반복 - red3: 4, //RED 0.2 ON -> OFF 반복 - red4: 5, //RED 0.5 ON -> OFF 반복 - red5: 6, //RED 1 ON -> OFF 반복 - _red1: 7, //RED 0.05 OFF -> ON 반복 - _red2: 8, //RED 0.1 OFF -> ON 반복 - _red3: 9, //RED 0.2 OFF -> ON 반복 - _red4: 10, //RED 0.5 OFF -> ON 반복 - _red5: 11, //RED 1 OFF -> ON 반복 - - yellow: 12, //YELLOW ON - yellow1: 13, //YELLOW 0.05 ON -> OFF 반복 - yellow2: 14, //YELLOW 0.1 ON -> OFF 반복 - yellow3: 15, //YELLOW 0.2 ON -> OFF 반복 - yellow4: 16, //YELLOW 0.5 ON -> OFF 반복 - yellow5: 17, //YELLOW 1 ON -> OFF 반복 - _yellow1: 18, //YELLOW 0.05 OFF -> ON 반복 - _yellow2: 19, //YELLOW 0.1 OFF -> ON 반복 - _yellow3: 20, //YELLOW 0.2 OFF -> ON 반복 - _yellow4: 21, //YELLOW 0.5 OFF -> ON 반복 - _yellow5: 22, //YELLOW 1 OFF -> ON 반복 - - green : 23, //GREEN ON - green1: 24, //GREEN 0.05 ON -> OFF 반복 - green2: 25, //GREEN 0.1 ON -> OFF 반복 - green3: 26, //GREEN 0.2 ON -> OFF 반복 - green4: 27, //GREEN 0.5 ON -> OFF 반복 - green5: 28, //GREEN 1 ON -> OFF 반복 - _green1: 29, //GREEN 0.05 OFF -> ON 반복 - _green2: 30, //GREEN 0.1 OFF -> ON 반복 - _green3: 31, //GREEN 0.2 OFF -> ON 반복 - _green4: 32, //GREEN 0.5 OFF -> ON 반복 - _green5: 33, //GREEN 1 OFF -> ON 반복 - - cyan : 34, //CYAN ON - cyan1: 35, //CYAN 0.05 ON -> OFF 반복 - cyan2: 36, //CYAN 0.1 ON -> OFF 반복 - cyan3: 37, //CYAN 0.2 ON -> OFF 반복 - cyan4: 38, //CYAN 0.5 ON -> OFF 반복 - cyan5: 39, //CYAN 1 ON -> OFF 반복 - _cyan1: 40, //CYAN 0.05 OFF -> ON 반복 - _cyan2: 41, //CYAN 0.1 OFF -> ON 반복 - _cyan3: 42, //CYAN 0.2 OFF -> ON 반복 - _cyan4: 43, //CYAN 0.5 OFF -> ON 반복 - _cyan5: 44, //CYAN 1 OFF -> ON 반복 - - blue: 45, //BLUE ON - blue1: 46, //BLUE 0.05 ON -> OFF 반복 - blue2: 47, //BLUE 0.1 ON -> OFF 반복 - blue3: 48, //BLUE 0.2 ON -> OFF 반복 - blue4: 49, //BLUE 0.5 ON -> OFF 반복 - blue5: 50, //BLUE 1 ON -> OFF 반복 - _blue1: 51, //BLUE 0.05 OFF -> ON 반복 - _blue2: 52, //BLUE 0.1 OFF -> ON 반복 - _blue3: 53, //BLUE 0.2 OFF -> ON 반복 - _blue4: 54, //BLUE 0.5 OFF -> ON 반복 - _blue5: 55, //BLUE 1 OFF -> ON 반복 - - magenta: 56, //MAGENTA ON - magenta1: 57, //MAGENTA 0.05 ON -> OFF 반복 - magenta2: 58, //MAGENTA 0.1 ON -> OFF 반복 - magenta3: 59, //MAGENTA 0.2 ON -> OFF 반복 - magenta4: 60, //MAGENTA 0.5 ON -> OFF 반복 - magenta5: 61, //MAGENTA 1 ON -> OFF 반복 - _magenta1: 62, //MAGENTA 0.05 OFF -> ON 반복 - _magenta2: 63, //MAGENTA 0.1 OFF -> ON 반복 - _magenta3: 64, //MAGENTA 0.2 OFF -> ON 반복 - _magenta4: 65, //MAGENTA 0.5 OFF -> ON 반복 - _magenta5: 66, //MAGENTA 1 OFF -> ON 반복 - - white: 67, //WHITE ON - white1: 68, //WHITE 0.05 ON -> OFF 반복 - white2: 69, //WHITE 0.1 ON -> OFF 반복 - white3: 70, //WHITE 0.2 ON -> OFF 반복 - white4: 71, //WHITE 0.5 ON -> OFF 반복 - white5: 72, //WHITE 1 ON -> OFF 반복 - _white1: 73, //WHITE 0.05 OFF -> ON 반복 - _white2: 74, //WHITE 0.1 OFF -> ON 반복 - _white3: 75, //WHITE 0.2 OFF -> ON 반복 - _white4: 76, //WHITE 0.5 OFF -> ON 반복 - _white5: 77, //WHITE 1 OFF -> ON 반복 - - rgbrnd1: 78, //RANDOM 1 - rgbrnd2: 79, //RANDOM 2 - - red_d: 90, //RED - yellow_d: 91, //YELLOW - green_d: 92, //GREEN - cyan_d: 93, //CYAN - blue_d: 94, //BLUE - magenta_d: 95, //MAGENTA - white_d: 96, //WHITE - - rgboff: 100 //RGB LED OFF - }, - - Melody: [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748], - Melody_S: [0, 35391, 31530, 28090, 26513, 23621, 21044, 18748], - - Track:[ - [0x451F,0x3D95,0x36DD,0x33C8,0x2E22,0x291A,0x249E],// Start : size 7, - [0x228F,0x249E,0x291A,0x2E22,0x33C8,0x36DD,0x3D95,0x451F],// End : size 8, - [0x228F,0x1B6E,0x1711,0x1147],// LevelUp : size 4, - [0x1147,0x1711,0x1B6E,0x228F],// LevelDwon : size 4, - ], - - Infinite_Buff: { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - Infinite_Count: { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - Infinite_Start: { AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - - SenserSet:{AA1: 0, AA2: 0, AA3: 0, AA4: 0 }, - - InputData: { - Analog: { - AA1: 0, - AA2: 0, - AA3: 0, - AA4: 0, - }, - Digital: { - A1: 0, - A2: 0, - A3: 0, - A4: 0, - FEA1: 0, - FEA2: 0, - FEA3: 0, - FEA4: 0, - REA1: 0, - REA2: 0, - REA3: 0, - REA4: 0, - BEA1: 0, - BEA2: 0, - BEA3: 0, - BEA4: 0, - }, - Remote: { - R_1: 0, - R_2: 0, - R_3: 0, - R_4: 0, - R_5: 0, - R_6: 0, - R_7: 0, - R_8: 0, - R_L1: 0, - R_L2: 0, - R_R1: 0, - R_R2: 0, - }, - EEPROM: { - EC: 0, - EEPR2: 0, - EEPR1: 0, - }, - Infinite:{ - ROTATION_1:0, - ROTATION_2:0, - ROTATION_3:0, - ROTATION_4:0 - }, - Acceler:{ - AXIS_X1:0, - AXIS_X2:0, - AXIS_X3:0, - AXIS_X4:0, - AXIS_Y1:0, - AXIS_Y2:0, - AXIS_Y3:0, - AXIS_Y4:0, - AXIS_Z1:0, - AXIS_Z2:0, - AXIS_Z3:0, - AXIS_Z4:0, - } - }, - RemoteData: { - B1: 0, - B2: 0, - B3: 0, - B4: 0, - Servo1: 0, - Servo2: 0, - Servo3: 0, - Servo4: 0, - DC1: 0, - DC2: 0, - DC3: 0, - DC4: 0, - MEL2: 0, - MEL1: 0, - FND: 100, - EEPR4: 0, - EEPR3: 0, - EEPR2: 0, - EEPR1: 0, - ASET2: 0, - ASET1: 0, - }, - EdgeFlag: { - FEA1: 0, - FEA2: 0, - FEA3: 0, - FEA4: 0, - REA1: 0, - REA2: 0, - REA3: 0, - REA4: 0, - BEA1: 0, - BEA2: 0, - BEA3: 0, - BEA4: 0, - }, - EEPROM: { - EEPROM_Buff: 0, - EEPROM_Count: 0, - }, - - setZero: function() { - for (var key in this.EdgeFlag) this.EdgeFlag[key] = 0; - for (var key in this.RemoteData) Entry.hw.sendQueue[key] = this.RemoteData[key]; - // for (var key in this.Infinite_Start) this.Infinite_Start[key] = 0; - // for (var key in this.Infinite_Count) this.Infinite_Count[key] = 0; - // for (var key in this.Infinite_Buff) this.Infinite_Buff[key] = 0; - for (var key in this.SenserSet) this.SenserSet[key] = 0; - Entry.hw.update(); - }, -}; - -// 언어 적용 -Entry.ProboConnect.setLanguage = function() { - return { - ko: { - // ko.js에 작성하던 내용 - template: { - connect_remote_event: '%1 리모컨 %2 키를 눌렀을 때 %3', - connect_digital_event: '%1 디지털 입력 %2 이(가) 들어왔을 때 %3', - - connect_senser_setting: '센서 설정 A1:%1 A2:%2 A3:%3 A4:%4 %5', - - connect_remote_input: '리모컨 입력 %1', - connect_digital_input: '디지털 센서 %1', - connect_analog_input: '아날로그 센서 %1', - connect_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환', - //connect_ultrasonic_cm: '초음파 센서 %1 의 거리(cm)', - connect_color_input_b: '컬러 센서 %1 이(가) %2 색 인가?', - connect_color_input_r: '컬러 센서 %1 의 색상', - connect_infinite_reset: '%1 센서 %2 초기화 %3', - connect_infinite_setting: '%1 센서 %2 의 값을 %3 값으로 정하기 %4', - connect_infinite_transform_input: '%1 센서 %2 의 %3', - connect_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값', - connect_3axis_acceler_x: '3가속도 %1의 X축', - connect_3axis_acceler_y: '3가속도 %1의 Y축', - connect_3axis_acceler_z: '3가속도 %1의 Z축', - connect_multi_sensor: '멀티키 센서 %1의 %2', - - - connect_port_output: '출력포트 %1 을(를) %2 %3', - connect_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3', - connect_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3', - connect_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3', - connect_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3', - connect_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4', - connect_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3', - connect_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2', - connect_mel_sec_output: '멜로디 %1 을(를) %2 초 동안 소리내기 %3', - connect_melody_output: '멜로디 %1 을(를) 소리내기 %2', - connect_mel_number_sec_output: '멜로디 %1 을(를) %2 초 동안 소리내기 %3', - connect_melody_number_output: '멜로디 %1 을(를) 소리내기 %2', - connect_melody_number_note_output: '멜로디 %1 을(를) %2음표로 소리내기 %3', - connect_value_output: '멜로디 %1 값을 소리내기 %2', - connect_melody_track_output: '멜로디 %1 을(를) %2초 간격으로 소리내기 %3', - connect_melody_off: '멜로디 소리끄기 %1', - connect_fnd_output: 'FND를 %1 (으)로 켜기 %2', - connect_fnd_off: 'FND를 끄기 %1', - - connect_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3', - connect_eeprom_buffset: 'EEPROM %1 주소의 값 임시저장소로 호출하기 %2', - connect_buff_read: 'EEPROM 임시저장소의 값', - }, - }, - en: { - // en.js에 작성하던 내용 - template: { - connect_remote_event: '%1 when remote control %2 key pressed %3', - connect_digital_event: '%1 when digital input %2 is on %3', - - connect_senser_setting: 'senser setting A1:%1 A2:%2 A3:%3 A4:%4 %5', - - connect_remote_input: 'remote input %1', - connect_digital_input: 'digital senser %1', - connect_analog_input: 'analog senser %1', - connect_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5', - //connect_ultrasonic_cm: 'Distance(cm) of ultrasonic sensor %1', - connect_color_input_b: 'is color sensor %1 to %2 ?', - connect_color_input_r: 'color of color sensor %1', - connect_infinite_reset: '%1 rotation sensor %2 reset %3', - connect_infinite_setting: '%1 rotation sensor %2 setting the %3 %4', - connect_infinite_transform_input: '%1 rotation sensor %2 to %3', - connect_infinite_mm_diameter: 'mm value of %1 rotation sensor %2 diameter %3', - connect_3axis_acceler_x: 'acceleration %1 of X-axis', - connect_3axis_acceler_y: 'acceleration %1 of Y-axis', - connect_3axis_acceler_z: 'acceleration %1 of Z-axis', - connect_multi_sensor: 'multi sensor %1 key %2', - - connect_port_output: 'output %1 port %2 %3', - connect_servo_output: 'move position of servo motor %1 to %2 %3', - connect_s_dc_output: 'rotate S motor %1 at %2 speed %3', - connect_dc_output: 'rotate dc motor %1 at %2 speed %3', - connect_rgbled_on_output: 'RGB LED %1 at %2 on %3', - connect_rgbled_flashing_output: 'RGB LED %1 %2 with %3 second interval %4', - connect_rgbled_dimming_output: 'RGB LED %1 at %2 Dimming %3', - connect_rgbled_off_output: 'RGB LED %1 off %2', - connect_mel_sec_output: 'melody %1 sounds for %2 seconds %3', - connect_melody_output: 'off melody sound %1', - connect_mel_number_sec_output: 'play melody %1 sounds for %2 seconds %3', - connect_melody_number_output: 'play the melody %1 %2', - connect_melody_number_note_output: 'play melody %1 with %2 notes %2', - connect_value_output: 'play the melody %1 value %2', - connect_melody_track_output: 'play the melody %1 at intervals of %2 second %3', - connect_melody_off: 'off melody sound %1', - connect_fnd_output: 'FND on %1 %2', - connect_fnd_off: 'FND off %1', - connect_eeprom_write: 'setting the EEPROM %1 address to a value of %2 %3', - connect_eeprom_buffset: - 'calling the value of the EEPROM %1 address into the temporary store %2', - connect_buff_read: 'value of EEPROM temporary store', - }, - }, - }; -}; - -Entry.ProboConnect.blockMenuBlocks = [ - //region proboconnect - ////Start - 'connect_remote_event', - 'connect_digital_event', - - ////input - 'connect_senser_setting', - 'connect_remote_input', - 'connect_digital_input', - 'connect_analog_input', - 'connect_value_mapping', - //"connect_ultrasonic_cm", - 'connect_color_input_b', - 'connect_color_input_r', - 'connect_infinite_reset', - 'connect_infinite_setting', - 'connect_infinite_transform_input', - 'connect_infinite_mm_diameter', - 'connect_3axis_acceler_x', - 'connect_3axis_acceler_y', - 'connect_3axis_acceler_z', - 'connect_multi_sensor', - - - ////output - 'connect_port_output', - 'connect_servo_output', - 'connect_s_dc_output', - 'connect_dc_output', - 'connect_rgbled_on_output', - 'connect_rgbled_flashing_output', - 'connect_rgbled_dimming_output', - 'connect_rgbled_off_output', - 'connect_mel_sec_output', - 'connect_melody_output', - 'connect_mel_number_sec_output', - 'connect_melody_number_output', - 'connect_melody_number_note_output', - 'connect_value_output', - 'connect_melody_track_output', - 'connect_melody_off', - 'connect_fnd_output', - 'connect_fnd_off', - - //// EEPROM - 'connect_eeprom_write', - 'connect_eeprom_buffset', - 'connect_buff_read', - //endregion proboconnect -]; - -// 블록 생성 -Entry.ProboConnect.getBlocks = function() { - return { - // 리모컨 입력 이벤트 - connect_remote_event: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_event', - params: [ - { - type: 'Indicator', - img: 'block_icon/start_icon_play.svg', - size: 14, - position: { - x: 0, - y: -2, - }, - }, - { - type: 'Dropdown', - options: [ - ['R_1', 'R_1'], - ['R_2', 'R_2'], - ['R_3', 'R_3'], - ['R_4', 'R_4'], - ['R_5', 'R_5'], - ['R_6', 'R_6'], - ['R_7', 'R_7'], - ['R_8', 'R_8'], - ['R_L1', 'R_L1'], - ['R_L2', 'R_L2'], - ['R_R1', 'R_R1'], - ['R_R2', 'R_R2'], - ], - fontSize: 11, - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - events: {}, - def: { - params: [null,'R_1',null], - type: 'connect_remote_event', - }, - paramsKeyMap: { - BUTTON: 1, - }, - class: 'event', - isNotFor: ['ProboConnect'], - event: 'event_remote_input', - func(sprite, script) { - const btn = script.getStringField('BUTTON', script); - if(Entry.hw.portData.InputData.Remote[btn] == 1 ) - return script.callReturn(); - - return this.die(); - }, - }, - // 디지털 입력 이벤트 - connect_digital_event: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_event', - params: [ - { - type: 'Indicator', - img: 'block_icon/start_icon_play.svg', - size: 14, - position: { - x: 0, - y: -2, - }, - }, - { - type: 'Dropdown', - options: [ - ['A1', 'A1'], - ['A2', 'A2'], - ['A3', 'A3'], - ['A4', 'A4'], - ['FEA1', 'FEA1'], - ['FEA2', 'FEA2'], - ['FEA3', 'FEA3'], - ['FEA4', 'FEA4'], - ['REA1', 'REA1'], - ['REA2', 'REA2'], - ['REA3', 'REA3'], - ['REA4', 'REA4'], - ['BEA1', 'BEA1'], - ['BEA2', 'BEA2'], - ['BEA3', 'BEA3'], - ['BEA4', 'BEA4'], - ], - fontSize: 11, - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - events: {}, - def: { - params: [null,'A1',null], - type: 'connect_digital_event', - }, - paramsKeyMap: { - PORT: 1, - }, - class: 'event', - isNotFor: ['ProboConnect'], - event: 'event_digital_input', - func(sprite, script) { - const port = script.getStringField('PORT', script); - var rt = false; - if ( - port == 'FEA1' || - port == 'FEA2' || - port == 'FEA3' || - port == 'FEA4' || - port == 'REA1' || - port == 'REA2' || - port == 'REA3' || - port == 'REA4' || - port == 'BEA1' || - port == 'BEA2' || - port == 'BEA3' || - port == 'BEA4' - ) { - if (Entry.hw.portData.InputData.Digital[port] == 1) { - if (Entry.ProboConnect.EdgeFlag[port] == 0) { - Entry.ProboConnect.EdgeFlag[port] = 1; - return script.callReturn(); - } - } else { - Entry.ProboConnect.EdgeFlag[port] = 0; - } - } else if(Entry.hw.portData.InputData.Digital[port] == 1 ){ - return script.callReturn(); - } - return this.die(); - }, - }, - // 리모컨 입력 - connect_remote_input: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_boolean_field', - params: [ - { - type: 'Dropdown', - // Dropdown 생성 기준은 - // [["key1", "value1"], - // ["key2", "value2"]] - options: [ - ['R_1', 'R_1'], - ['R_2', 'R_2'], - ['R_3', 'R_3'], - ['R_4', 'R_4'], - ['R_5', 'R_5'], - ['R_6', 'R_6'], - ['R_7', 'R_7'], - ['R_8', 'R_8'], - ['R_L1', 'R_L1'], - ['R_L2', 'R_L2'], - ['R_R1', 'R_R1'], - ['R_R2', 'R_R2'], - ], - fontSize: 11, - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['R_1'], - type: 'connect_remote_input', - }, - paramsKeyMap: { - BUTTON: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const btn = script.getStringField('BUTTON', script); - - return Entry.hw.portData.InputData.Remote[btn] == 1 ? true : false; - }, - }, - // 디지털 입력 - connect_digital_input: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_boolean_field', - params: [ - { - type: 'Dropdown', - - options: [ - ['A1', 'A1'], - ['A2', 'A2'], - ['A3', 'A3'], - ['A4', 'A4'], - ['FEA1', 'FEA1'], - ['FEA2', 'FEA2'], - ['FEA3', 'FEA3'], - ['FEA4', 'FEA4'], - ['REA1', 'REA1'], - ['REA2', 'REA2'], - ['REA3', 'REA3'], - ['REA4', 'REA4'], - ['BEA1', 'BEA1'], - ['BEA2', 'BEA2'], - ['BEA3', 'BEA3'], - ['BEA4', 'BEA4'], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['A1'], - type: 'connect_digital_input', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var rt = false; - - if ( - port == 'FEA1' || - port == 'FEA2' || - port == 'FEA3' || - port == 'FEA4' || - port == 'REA1' || - port == 'REA2' || - port == 'REA3' || - port == 'REA4' || - port == 'BEA1' || - port == 'BEA2' || - port == 'BEA3' || - port == 'BEA4' - ) { - if (Entry.hw.portData.InputData.Digital[port] == 1) { - if (Entry.ProboConnect.EdgeFlag[port] == 0) { - Entry.ProboConnect.EdgeFlag[port] = 1; - rt = true; - } - } else { - Entry.ProboConnect.EdgeFlag[port] = 0; - } - } else rt = Entry.hw.portData.InputData.Digital[port] == 1 ? true : false; - - return rt; - }, - }, - // 아날로그 입력 - connect_analog_input: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - // Dropdown 생성 기준은 - // [["key1", "value1"], - // ["key2", "value2"]] - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ - // Dropdown 값의 경우 Value를 세팅하면 초기값이 처리 됩니다. - 'AA1', - ], - type: 'connect_analog_input', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - - // Port 라는 key값을 가진 정보를 읽는다. - var value = 0; - - if(Entry.ProboConnect.SenserSet[port]==5) - value = 255 - Entry.hw.portData.InputData.Analog[port]; - else - value = Entry.hw.portData.InputData.Analog[port]; - - return value; - }, - }, - // 아날로그 입력 값 맵핑 블럭 - connect_value_mapping: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { type: 'Block', accept: 'string' }, - { type: 'Block', accept: 'string' }, - { type: 'Block', accept: 'string' }, - { type: 'Block', accept: 'string' }, - { type: 'Block', accept: 'string' }, - ], - def: { - params: [ - // Dropdown 값의 경우 Value를 세팅하면 초기값이 처리 됩니다. - '0', - '0', - '0', - '0', - '0', - ], - type: 'connect_value_mapping', - }, - paramsKeyMap: { - DATA: 0, - SOURCE1: 1, - SOURCE2: 2, - TARGET1: 3, - TARGET2: 4, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const data = script.getNumberValue('DATA', script); - const source1 = script.getNumberValue('SOURCE1', script); - const source2 = script.getNumberValue('SOURCE2', script); - const target1 = script.getNumberValue('TARGET1', script); - const target2 = script.getNumberValue('TARGET2', script); - - var value = 0; - var rate = (data - source1) / (source2 - source1); - var num = 0; - - if (target1 < target2) { - value = (target2 - target1) * rate; - - num = value % 1; - - if (num < 0.5) value -= num; - else value += 1 - num; - - value = target1 + value; - - if (value < target1) value = target1; - else if (value > target2) value = target2; - } else { - value = (target1 - target2) * rate; - - num = value % 1; - - if (num < 0.5) value -= num; - else value += 1 - num; - - value = target1 - value; - - if (value > target1) value = target1; - else if (value < target2) value = target2; - } - - return value; - }, - }, - // 컬러센서 bool - connect_color_input_b: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_boolean_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['빨강', '0'], - ['초록', '1'], - ['파랑', '2'], - ['노랑', '3'], - ['검정', '4'], - ['하양', '5'], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['AA1', '0'], - type: 'connect_color_input_b', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const target = script.getNumberField('COLOR', script); - const value = Entry.hw.portData.InputData.Analog[port]; - var color = Entry.ProboConnect.Color; - - return color[target][0] <= value && value <= color[target][1]; - }, - }, - // 컬러센서 value - connect_color_input_r: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['AA1'], - type: 'connect_color_input_r', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const value = Entry.hw.portData.InputData.Analog[port]; - var color = Entry.ProboConnect.Color; - - for (var i = 0; i < 6; i++) { - if (color[i][0] <= value && value <= color[i][1]) { - switch (i) { - case 0: - return '빨강'; - case 1: - return '초록'; - case 2: - return '파랑'; - case 3: - return '노랑'; - case 4: - return '검정'; - case 5: - return '하양'; - } - } - } - return 0; - }, - }, - // 무한회전 센서 값 초기화 - connect_infinite_reset: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['무한회전', '0'], ['나침반', '1']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [0,'AA1', null], - type: 'connect_infinite_reset', - }, - paramsKeyMap: { - PORT: 1, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const value = Entry.hw.portData.InputData.Analog[port]; - Entry.ProboConnect.Infinite_Start[port] = value; - Entry.ProboConnect.Infinite_Buff[port] = value; - Entry.ProboConnect.Infinite_Count[port] = 0; - }, - }, - // 무한회전 센서 값 설정 - connect_infinite_setting: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['무한회전', '0'], ['나침반', '1']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - } - ], - def: { - params: [0, 'AA1', '0', null], - type: 'connect_infinite_setting', - }, - paramsKeyMap: { - NAME: 0, - PORT: 1, - VALUE: 2, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = script.getNumberValue('VALUE', script); - var count = 0; - // console.log("Start",Entry.ProboConnect.Infinite_Start[port]); - // console.log("Buff",Entry.ProboConnect.Infinite_Buff[port]); - // console.log("Count",Entry.ProboConnect.Infinite_Count[port]); - - if (value!=0){ - count = Number(value / 255).toFixed(0); - value = value % 255; - }else{ - value = 0; - count = 0; - } - console.log("count",count); - console.log("value",value); - console.log("Infinite_Buff",Entry.ProboConnect.Infinite_Buff[port]); - - - Entry.ProboConnect.Infinite_Buff[port] = Entry.hw.portData.InputData.Analog[port]; - Entry.ProboConnect.Infinite_Start[port] = Entry.hw.portData.InputData.Analog[port]-value; - Entry.ProboConnect.Infinite_Count[port] = count; - - console.log("Infinite_Start",Entry.ProboConnect.Infinite_Start[port]); - console.log("Infinite_Buff",Entry.ProboConnect.Infinite_Buff[port]); - console.log("Infinite_Count",Entry.ProboConnect.Infinite_Count[port]); - - }, - }, - // 무한회전 센서 - connect_infinite_transform_input: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['무한회전', '0'], ['나침반', '1']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['값', '1'], ['각도', '2'], ['회전 수', '3'], ['절대각도', '4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [0,'AA1', '1'], - type: 'connect_infinite_transform_input', - }, - paramsKeyMap: { - PORT: 1, - SELECT: 2, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = Entry.hw.portData.InputData.Analog[port]; - const select = script.getNumberField('SELECT', script); - - if (value < (Entry.ProboConnect.Infinite_Buff[port] - 150)) - Entry.ProboConnect.Infinite_Count[port]++; - else if (value > (Entry.ProboConnect.Infinite_Buff[port] + 150)) - Entry.ProboConnect.Infinite_Count[port]--; - - Entry.ProboConnect.Infinite_Buff[port] = value; - - console.log("-Infinite_Start",Entry.ProboConnect.Infinite_Start[port]); - console.log("-Infinite_Buff",Entry.ProboConnect.Infinite_Buff[port]); - console.log("-Infinite_Count",Entry.ProboConnect.Infinite_Count[port]); - - value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255); - - switch (select) { - case 2: - if(value > 0) - return Math.floor((value%255) * 1.41732); - else - return Math.ceil((value%255) * 1.41732); - case 3: - if(value > 0) - return Math.floor(value / 255); - else - return Math.ceil(value / 255); - case 4: - return Number((360/255) * Entry.hw.portData.InputData.Analog[port]).toFixed(0); - default: - return value; - } - }, - }, - // 무한회전 센서 지름 설정 - connect_infinite_mm_diameter: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['무한회전', '0'], ['나침반', '1']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - ], - def: { - params: [0,'AA1', 53.5], - type: 'connect_infinite_mm_diameter', - }, - paramsKeyMap: { - PORT: 1, - DIAMETER: 2, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = Entry.hw.portData.InputData.Analog[port]; - const diameter = script.getNumberValue('DIAMETER', script); - - if (value < Entry.ProboConnect.Infinite_Buff[port] - 150) - Entry.ProboConnect.Infinite_Count[port]++; - else if (value > Entry.ProboConnect.Infinite_Buff[port] + 150) - Entry.ProboConnect.Infinite_Count[port]--; - - Entry.ProboConnect.Infinite_Buff[port] = value; - - value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255); - - return Number( - 2 * - 3.141592 * - (diameter / 2) / - 255 * - value - ).toFixed(3); - }, - }, - // 3가속도 X - connect_3axis_acceler_x: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AXIS_X1'], ['AA2', 'AXIS_X2'], ['AA3', 'AXIS_X3'], ['AA4', 'AXIS_X4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ - 'AXIS_X1', - ], - type: 'connect_3axis_acceler_x', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = (Entry.hw.portData.InputData.Acceler[port]) - if(value & 0x80) value = (value - 255); - return Number(value / 10).toFixed(1); - }, - }, - // 3가속도 Y - connect_3axis_acceler_y: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AXIS_Y1'], ['AA2', 'AXIS_Y2'], ['AA3', 'AXIS_Y3'], ['AA4', 'AXIS_Y4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ - 'AXIS_Y1', - ], - type: 'connect_3axis_acceler_y', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = (Entry.hw.portData.InputData.Acceler[port]) - if(value & 0x80) value = (value - 255); - return Number(value / 10).toFixed(1); - }, - }, - // 3가속도 Z - connect_3axis_acceler_z: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AXIS_Z1'], ['AA2', 'AXIS_Z2'], ['AA3', 'AXIS_Z3'], ['AA4', 'AXIS_Z4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: [ - 'AXIS_Z1', - ], - type: 'connect_3axis_acceler_z', - }, - paramsKeyMap: { - PORT: 0, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - var value = (Entry.hw.portData.InputData.Acceler[port]) - if(value & 0x80) value = (value - 255); - return Number(value / 10).toFixed(1); - }, - }, - // 멀티키 센서 - connect_multi_sensor: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_boolean_field', - params: [ - { - type: 'Dropdown', - options: [['AA1', 'AA1'], ['AA2', 'AA2'], ['AA3', 'AA3'], ['AA4', 'AA4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['키1', 0], - ['키2', 1], - ['키3', 2], - ['키4', 3], - ['키5', 4], - ['키6', 5], - ['키7', 6], - ['키8', 7], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - ], - def: { - params: ['AA1', '0'], - type: 'connect_multi_sensor', - }, - paramsKeyMap: { - PORT: 0, - KEY: 1, - }, - class: 'input', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const key = script.getNumberField('KEY', script); - const value = Entry.hw.portData.InputData.Analog[port] & (0x1<100) value = 100; - - Entry.hw.sendQueue[servo] = value; - }, - }, - connect_dc_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['M1', 'DC1'], ['M2', 'DC2'], ['M3', 'DC3'], ['M4', 'DC4'], ['M1,M2', 'DC5'], ['M3,M4', 'DC6'], ['ALL', 'DC7']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['DC1', { type: 'number', params: ['0'] }, null], - type: 'connect_dc_output', - }, - paramsKeyMap: { - MOTOR: 0, - VALUE: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const motor = script.getStringField('MOTOR', script); - const value = script.getNumberValue('VALUE', script); - if(motor=='DC5'){ - Entry.hw.sendQueue['DC1'] = value; - Entry.hw.sendQueue['DC2'] = value; - }else if(motor=='DC6'){ - Entry.hw.sendQueue['DC3'] = value; - Entry.hw.sendQueue['DC4'] = value; - }else if(motor=='DC7'){ - Entry.hw.sendQueue['DC1'] = value; - Entry.hw.sendQueue['DC2'] = value; - Entry.hw.sendQueue['DC3'] = value; - Entry.hw.sendQueue['DC4'] = value; - }else{ - Entry.hw.sendQueue[motor] = value; - } - }, - }, - connect_s_dc_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['S1', 'Servo1'], ['S2', 'Servo2'], ['S3', 'Servo3'], ['S4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', { type: 'number', params: ['0'] }, null], - type: 'connect_s_dc_output', - }, - paramsKeyMap: { - MOTOR: 0, - VALUE: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const motor = script.getStringField('MOTOR', script); - var value = script.getNumberValue('VALUE', script); - - if(value > 20) value = 20; - else if(value < -20) value = -20; - value += 148; - - console.log(value); - - if(motor=='Servo5'){ - Entry.hw.sendQueue['Servo1'] = value; - Entry.hw.sendQueue['Servo2'] = value; - }else if(motor=='Servo6'){ - Entry.hw.sendQueue['Servo3'] = value; - Entry.hw.sendQueue['Servo4'] = value; - }else{ - Entry.hw.sendQueue[motor] = value; - } - }, - }, - connect_rgbled_on_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['B1', 'Servo1'], ['B2', 'Servo2'], ['B3', 'Servo3'], ['B4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['빨강', '1'], - ['노랑', '12'], - ['초록', '23'], - ['청록', '34'], - ['파랑', '45'], - ['자홍', '56'], - ['하양', '67'],], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', '1', null], - type: 'connect_rgbled_on_output', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const color = script.getNumberValue('COLOR', script); - console.log(port); - console.log(color); - Entry.hw.sendQueue[port] = color; - }, - }, - connect_rgbled_flashing_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['B1', 'Servo1'], ['B2', 'Servo2'], ['B3', 'Servo3'], ['B4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['빨강', '1'], - ['노랑', '12'], - ['초록', '23'], - ['청록', '34'], - ['파랑', '45'], - ['자홍', '56'], - ['하양', '67'],], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['0.05', '1'], - ['0.1', '2'], - ['0.2', '3'], - ['0.5', '4'], - ['1', '5'],], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', '1', '3', null], - type: 'connect_rgbled_flashing_output', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - SEC: 2, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const color = script.getNumberValue('COLOR', script); - const sec = script.getNumberField('SEC', script); - const value = color+sec; - console.log("color",color); - console.log("sec",sec); - console.log("color+sec",value); - - Entry.hw.sendQueue[port] = value; - - }, - }, - connect_rgbled_dimming_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['B1', 'Servo1'], ['B2', 'Servo2'], ['B3', 'Servo3'], ['B4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['빨강', '90'], - ['노랑', '91'], - ['초록', '92'], - ['청록', '93'], - ['파랑', '94'], - ['자홍', '95'], - ['하양', '96'],], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', '90', null], - type: 'connect_rgbled_dimming_output', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const color = script.getNumberValue('COLOR', script); - Entry.hw.sendQueue[port] = color; - }, - }, - connect_rgbled_off_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [['B1', 'Servo1'], ['B2', 'Servo2'], ['B3', 'Servo3'], ['B4', 'Servo4']], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['Servo1', null], - type: 'connect_rgbled_off_output', - }, - paramsKeyMap: { - PORT: 0, - COLOR: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const port = script.getStringField('PORT', script); - const color = script.getNumberValue('COLOR', script); - Entry.hw.sendQueue[port] = color; - }, - }, - connect_mel_sec_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [ - ['[1]도', 1], - ['[1]레', 3], - ['[1]미', 5], - ['[1]파', 6], - ['[1]솔', 8], - ['[1]라', 10], - ['[1]시', 12], - ['[2]도', 13], - ['[2]레', 15], - ['[2]미', 17], - ['[2]파', 18], - ['[2]솔', 20], - ['[2]라', 22], - ['[2]시', 24], - ['[3]도', 25], - ['[3]레', 27], - ['[3]미', 29], - ['[3]파', 30], - ['[3]솔', 32], - ['[3]라', 34], - ['[3]시', 36], - ['[4]도', 37], - ['[4]레', 39], - ['[4]미', 41], - ['[4]파', 42], - ['[4]솔', 44], - ['[4]라', 46], - ['[4]시', 48], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [1, { type: 'number', params: ['1'] }, null], - type: 'connect_mel_sec_output', - }, - paramsKeyMap: { - MELODY: 0, - SEC: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - if (!script.isStart) { - script.isStart = true; - script.timeFlag = 1; - const mel = script.getNumberField('MELODY', script); - var timeValue = script.getNumberValue('SEC', script); - var melody = 0; - - if (mel > 0 && mel < 13) melody = Entry.ProboConnect.Melody[mel]; - else if (mel < 25) melody = Entry.ProboConnect.Melody[mel - 12] / 2; - else if (mel < 37) melody = Entry.ProboConnect.Melody[mel - 24] / 4; - else if (mel < 49) melody = Entry.ProboConnect.Melody[mel - 36] / 8; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue * 1000; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - connect_melody_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [ - ['[1]도', 1], - ['[1]레', 3], - ['[1]미', 5], - ['[1]파', 6], - ['[1]솔', 8], - ['[1]라', 10], - ['[1]시', 12], - ['[2]도', 13], - ['[2]레', 15], - ['[2]미', 17], - ['[2]파', 18], - ['[2]솔', 20], - ['[2]라', 22], - ['[2]시', 24], - ['[3]도', 25], - ['[3]레', 27], - ['[3]미', 29], - ['[3]파', 30], - ['[3]솔', 32], - ['[3]라', 34], - ['[3]시', 36], - ['[4]도', 37], - ['[4]레', 39], - ['[4]미', 41], - ['[4]파', 42], - ['[4]솔', 44], - ['[4]라', 46], - ['[4]시', 48], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [1, null], - type: 'connect_melody_output', - }, - paramsKeyMap: { - MELODY: 0, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const mel = script.getNumberField('MELODY', script); - var melody = 0; - - if (mel > 0 && mel < 13) melody = Entry.ProboConnect.Melody[mel]; - else if (mel < 25) melody = Entry.ProboConnect.Melody[mel - 12] / 2; - else if (mel < 37) melody = Entry.ProboConnect.Melody[mel - 24] / 4; - else if (mel < 49) melody = Entry.ProboConnect.Melody[mel - 36] / 8; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - }, - }, - connect_mel_number_sec_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [ - { type: 'number', params: ['1'] }, - { type: 'number', params: ['1'] }, - null], - type: 'connect_mel_number_sec_output', - }, - paramsKeyMap: { - MELODY: 0, - SEC: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - if (!script.isStart) { - script.isStart = true; - script.timeFlag = 1; - const mel = script.getNumberValue('MELODY', script); - var timeValue = script.getNumberValue('SEC', script); - var melody = 0; - - if (mel > 0 && mel < 8) melody = Entry.ProboConnect.Melody_S[mel]; - else if (mel < 15) melody = Entry.ProboConnect.Melody_S[mel - 7] / 2; - else if (mel < 22) melody = Entry.ProboConnect.Melody_S[mel - 14] / 4; - else if (mel < 29) melody = Entry.ProboConnect.Melody_S[mel - 21] / 8; - else melody = 0; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - - console.log(melody); - console.log(timeValue); - - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue * 1000; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - connect_melody_number_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [{ type: 'number', params: ['1'] }, null], - type: 'connect_melody_number_output', - }, - paramsKeyMap: { - MELODY: 0, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const mel = script.getNumberValue('MELODY', script); - - if (mel > 0 && mel < 8) melody = Entry.ProboConnect.Melody_S[mel]; - else if (mel < 15) melody = Entry.ProboConnect.Melody_S[mel - 7] / 2; - else if (mel < 22) melody = Entry.ProboConnect.Melody_S[mel - 14] / 4; - else if (mel < 29) melody = Entry.ProboConnect.Melody_S[mel - 21] / 8; - else melody = 0; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - }, - }, - connect_melody_number_note_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Dropdown', - options: [ - ['온', 'n1'], - ['2분','n2'], - ['4분','n4'], - ['8분','n8'], - ['16분','n16'], - ['32분','n32'], - ], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [{ type: 'number', params: ['1'] }, 'n1', null], - type: 'connect_melody_number_note_output', - }, - paramsKeyMap: { - MELODY: 0, - NOTE: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - if (!script.isStart) { - script.isStart = true; - script.timeFlag = 1; - var mel = script.getNumberValue('MELODY', script); - const note = script.getStringField('NOTE', script); - var timeValue = Entry.ProboConnect.Note[note]; - var melody = 0; - - if (mel > 0 && mel < 8) melody = Entry.ProboConnect.Melody_S[mel]; - else if (mel < 15) melody = Entry.ProboConnect.Melody_S[mel - 7] / 2; - else if (mel < 22) melody = Entry.ProboConnect.Melody_S[mel - 14] / 4; - else if (mel < 29) melody = Entry.ProboConnect.Melody_S[mel - 21] / 8; - else melody = 0; - - Entry.hw.sendQueue['MEL2'] = melody >> 8; - Entry.hw.sendQueue['MEL1'] = melody; - - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - connect_value_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [35391, null], - type: 'connect_value_output', - }, - paramsKeyMap: { - MELODY: 0, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - var melody = script.getNumberValue('MELODY', script); - - Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; - Entry.hw.sendQueue['MEL1'] = melody & 0xff; - }, - }, - connect_melody_track_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Dropdown', - options: [ - ['시작음', 0], - ['종료음', 1], - ['레벨업', 2], - ['레벨다운', 3]], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Dropdown', - options: [ - ['0.1', 100], - ['0.3', 300], - ['0.5', 500], - ['0.7', 700], - ['1', 1000], - ['2', 2000]], - fontSize: 11, - - bgColor: EntryStatic.colorSet.block.darken.HARDWARE, - arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [0, 1000, null], - type: 'connect_melody_track_output', - }, - paramsKeyMap: { - MELODY: 0, - SEC: 1, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - function getTrackStep(track,script){ - if(!script.isStart){ - script.isStart = true; - script.trackStep = 0; - } - else - script.trackStep++; - - var timeValue = script.getNumberValue('SEC', script); - - script.timeFlag = 1; - var melody = Entry.ProboConnect.Track[track][script.trackStep]; - Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; - Entry.hw.sendQueue['MEL1'] = melody & 0xff; - - var fps = Entry.FPS || 60; - var timeValue = 60 / fps * timeValue; - - Entry.TimeWaitManager.add( - script.block.id, - function() { - script.timeFlag = 0; - }, - timeValue - ); - } - - const TR = script.getNumberValue('MELODY', script); - if (!script.isStart) { - switch(TR){ - case 0 : - script.maxStep = 6; - break; - case 1 : - script.maxStep = 7; - break; - case 2 : - script.maxStep = 3; - break; - case 3 : - script.maxStep = 3; - break; - } - getTrackStep(TR,script); - return script; - } else if (script.timeFlag == 1) { - console.log('timeFlag',script.timeFlag); - return script; - } else if (script.trackStep < script.maxStep){ - getTrackStep(TR,script); - return script; - } else { - - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - - delete script.trackStep; - delete script.maxStep; - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - - connect_melody_off: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [null], - type: 'connect_melody_off', - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - Entry.hw.sendQueue['MEL2'] = 0; - Entry.hw.sendQueue['MEL1'] = 0; - }, - }, - connect_fnd_output: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: ['0', null], - type: 'connect_fnd_output', - }, - paramsKeyMap: { - FND: 0, - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const fnd = script.getNumberValue('FND', script); - Entry.hw.sendQueue['FND'] = fnd; - }, - }, - connect_fnd_off: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [null], - type: 'connect_fnd_off', - }, - class: 'output', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - Entry.hw.sendQueue['FND'] = 100; - }, - }, - - //============================================ EEPROM ===================================================== - connect_eeprom_buffset: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [{ type: 'number', params: ['0'] }, null], - type: 'connect_eeprom_buffset', - }, - paramsKeyMap: { - ADDRESS: 0, - }, - class: 'EEPROM', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const address = script.getNumberValue('ADDRESS', script); - if (!script.isStart) { - Entry.ProboConnect.EEPROM.EEPROM_Count = Entry.hw.portData.InputData.EEPROM.EC; - Entry.hw.sendQueue['EEPR4'] = 0x40; - Entry.hw.sendQueue['EEPR3'] = address; - - script.isStart = true; - script.timeFlag = 1; - var timeValue = 0.05; - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue * 1000; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - Entry.ProboConnect.EEPROM.EEPROM_Buff = - (Entry.hw.portData.InputData.EEPROM.EEPR2 << 8) + - Entry.hw.portData.InputData.EEPROM.EEPR1; - Entry.hw.sendQueue['EEPR4'] = 0; - - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - connect_buff_read: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic_string_field', - def: { - type: 'connect_buff_read', - }, - class: 'EEPROM', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - var value = 0; - const count = Entry.ProboConnect.EEPROM.EEPROM_Count; - if (Entry.hw.portData.InputData.EEPROM.EC != count) { - value = Entry.ProboConnect.EEPROM.EEPROM_Buff; - } - return value; - }, - }, - connect_eeprom_write: { - color: EntryStatic.colorSet.block.default.HARDWARE, - outerLine: EntryStatic.colorSet.block.darken.HARDWARE, - fontColor: '#ffffff', - skeleton: 'basic', - params: [ - { - type: 'Block', - accept: 'string', - }, - { - type: 'Block', - accept: 'string', - }, - { - type: 'Indicator', - img: 'block_icon/hardware_icon.svg', - size: 12, - }, - ], - def: { - params: [ - { type: 'number', params: ['0'] }, - { type: 'number', params: ['0'] }, - null, - ], - type: 'connect_eeprom_write', - }, - paramsKeyMap: { - ADDRESS: 0, - VALUE: 1, - }, - class: 'EEPROM', - isNotFor: ['ProboConnect'], - func: function(sprite, script) { - const address = script.getNumberValue('ADDRESS', script); - const value = script.getNumberValue('VALUE', script); - if (!script.isStart) { - Entry.hw.sendQueue['EEPR4'] = 0x80; - Entry.hw.sendQueue['EEPR3'] = address; - Entry.hw.sendQueue['EEPR2'] = value >> 8; - Entry.hw.sendQueue['EEPR1'] = value & 0xff; - - script.isStart = true; - script.timeFlag = 1; - var timeValue = 0.05; - var fps = Entry.FPS || 60; - timeValue = 60 / fps * timeValue * 1000; - - var blockId = script.block.id; - Entry.TimeWaitManager.add( - blockId, - function() { - script.timeFlag = 0; - }, - timeValue - ); - - return script; - } else if (script.timeFlag == 1) { - return script; - } else { - delete script.timeFlag; - delete script.isStart; - Entry.engine.isContinue = false; - return script.callReturn(); - } - }, - }, - }; -}; - -module.exports = Entry.ProboConnect; +'use strict'; + +Entry.ProboConnect = { + afterReceive(pd) { + if(Entry.engine.isState('run')) { + Entry.engine.fireEvent('event_remote_input'); + Entry.engine.fireEvent('event_digital_input'); + } + }, + + id: '27.1', + name: 'ProboConnect', + url: 'https://www.aluxonline.com', + imageName: 'ProboConnect.png', + blockIndex: 0, + title: { + ko: '프로보커넥트', + en: 'ProboConnect', + }, + Color: [ + [13, 37], // 빨강 + [38, 62], // 초록 + [63, 87], // 파랑 + [88, 112], // 노랑 + [113, 137], // 검정 + [138, 162], // 하양 + ], + + Note:{ + n32 : 48, // = 1*3*4*4, + n16 : 96, // = 2*3*4*4, + n16d: 144, // = 3*3*4*4, + n16t: 64, // = 2*2*4*4, + n8 : 192, // = 4*3*4*4, + n8d : 288, // = 6*3*4*4, + n8t : 128, // = 4*2*4*4, + n4 : 384, // = 8*3*4*4, + n4d : 576, // = 12*3*4*4, + n4t : 256, // = 8*2*4*4, + n2 : 768, // = 16*3*4*4, + n2d : 1152, // = 24*3*4*4, + n2t : 512, // = 16*2*4*4, + n1 : 1536, // = 32*3*4*4 + }, + + RGB_LED:{ + red : 1, //RED ON + red1: 2, //RED 0.05 ON -> OFF 반복 + red2: 3, //RED 0.1 ON -> OFF 반복 + red3: 4, //RED 0.2 ON -> OFF 반복 + red4: 5, //RED 0.5 ON -> OFF 반복 + red5: 6, //RED 1 ON -> OFF 반복 + _red1: 7, //RED 0.05 OFF -> ON 반복 + _red2: 8, //RED 0.1 OFF -> ON 반복 + _red3: 9, //RED 0.2 OFF -> ON 반복 + _red4: 10, //RED 0.5 OFF -> ON 반복 + _red5: 11, //RED 1 OFF -> ON 반복 + + yellow: 12, //YELLOW ON + yellow1: 13, //YELLOW 0.05 ON -> OFF 반복 + yellow2: 14, //YELLOW 0.1 ON -> OFF 반복 + yellow3: 15, //YELLOW 0.2 ON -> OFF 반복 + yellow4: 16, //YELLOW 0.5 ON -> OFF 반복 + yellow5: 17, //YELLOW 1 ON -> OFF 반복 + _yellow1: 18, //YELLOW 0.05 OFF -> ON 반복 + _yellow2: 19, //YELLOW 0.1 OFF -> ON 반복 + _yellow3: 20, //YELLOW 0.2 OFF -> ON 반복 + _yellow4: 21, //YELLOW 0.5 OFF -> ON 반복 + _yellow5: 22, //YELLOW 1 OFF -> ON 반복 + + green : 23, //GREEN ON + green1: 24, //GREEN 0.05 ON -> OFF 반복 + green2: 25, //GREEN 0.1 ON -> OFF 반복 + green3: 26, //GREEN 0.2 ON -> OFF 반복 + green4: 27, //GREEN 0.5 ON -> OFF 반복 + green5: 28, //GREEN 1 ON -> OFF 반복 + _green1: 29, //GREEN 0.05 OFF -> ON 반복 + _green2: 30, //GREEN 0.1 OFF -> ON 반복 + _green3: 31, //GREEN 0.2 OFF -> ON 반복 + _green4: 32, //GREEN 0.5 OFF -> ON 반복 + _green5: 33, //GREEN 1 OFF -> ON 반복 + + cyan : 34, //CYAN ON + cyan1: 35, //CYAN 0.05 ON -> OFF 반복 + cyan2: 36, //CYAN 0.1 ON -> OFF 반복 + cyan3: 37, //CYAN 0.2 ON -> OFF 반복 + cyan4: 38, //CYAN 0.5 ON -> OFF 반복 + cyan5: 39, //CYAN 1 ON -> OFF 반복 + _cyan1: 40, //CYAN 0.05 OFF -> ON 반복 + _cyan2: 41, //CYAN 0.1 OFF -> ON 반복 + _cyan3: 42, //CYAN 0.2 OFF -> ON 반복 + _cyan4: 43, //CYAN 0.5 OFF -> ON 반복 + _cyan5: 44, //CYAN 1 OFF -> ON 반복 + + blue: 45, //BLUE ON + blue1: 46, //BLUE 0.05 ON -> OFF 반복 + blue2: 47, //BLUE 0.1 ON -> OFF 반복 + blue3: 48, //BLUE 0.2 ON -> OFF 반복 + blue4: 49, //BLUE 0.5 ON -> OFF 반복 + blue5: 50, //BLUE 1 ON -> OFF 반복 + _blue1: 51, //BLUE 0.05 OFF -> ON 반복 + _blue2: 52, //BLUE 0.1 OFF -> ON 반복 + _blue3: 53, //BLUE 0.2 OFF -> ON 반복 + _blue4: 54, //BLUE 0.5 OFF -> ON 반복 + _blue5: 55, //BLUE 1 OFF -> ON 반복 + + magenta: 56, //MAGENTA ON + magenta1: 57, //MAGENTA 0.05 ON -> OFF 반복 + magenta2: 58, //MAGENTA 0.1 ON -> OFF 반복 + magenta3: 59, //MAGENTA 0.2 ON -> OFF 반복 + magenta4: 60, //MAGENTA 0.5 ON -> OFF 반복 + magenta5: 61, //MAGENTA 1 ON -> OFF 반복 + _magenta1: 62, //MAGENTA 0.05 OFF -> ON 반복 + _magenta2: 63, //MAGENTA 0.1 OFF -> ON 반복 + _magenta3: 64, //MAGENTA 0.2 OFF -> ON 반복 + _magenta4: 65, //MAGENTA 0.5 OFF -> ON 반복 + _magenta5: 66, //MAGENTA 1 OFF -> ON 반복 + + white: 67, //WHITE ON + white1: 68, //WHITE 0.05 ON -> OFF 반복 + white2: 69, //WHITE 0.1 ON -> OFF 반복 + white3: 70, //WHITE 0.2 ON -> OFF 반복 + white4: 71, //WHITE 0.5 ON -> OFF 반복 + white5: 72, //WHITE 1 ON -> OFF 반복 + _white1: 73, //WHITE 0.05 OFF -> ON 반복 + _white2: 74, //WHITE 0.1 OFF -> ON 반복 + _white3: 75, //WHITE 0.2 OFF -> ON 반복 + _white4: 76, //WHITE 0.5 OFF -> ON 반복 + _white5: 77, //WHITE 1 OFF -> ON 반복 + + rgbrnd1: 78, //RANDOM 1 + rgbrnd2: 79, //RANDOM 2 + + red_d: 90, //RED + yellow_d: 91, //YELLOW + green_d: 92, //GREEN + cyan_d: 93, //CYAN + blue_d: 94, //BLUE + magenta_d: 95, //MAGENTA + white_d: 96, //WHITE + + rgboff: 100 //RGB LED OFF + }, + + Melody: [0, 35391, 33405, 31530, 29760, 28090, 26513, 25025, 23621, 22295, 21044, 19863, 18748], + Melody_S: [0, 35391, 31530, 28090, 26513, 23621, 21044, 18748], + + Track:[ + [0x451F, 0x3D95, 0x36DD, 0x33C8, 0x2E22, 0x291A, 0x249E],// Start : size 7, + [0x228F, 0x249E, 0x291A, 0x2E22, 0x33C8, 0x36DD, 0x3D95, 0x451F],// End : size 8, + [0x228F, 0x1B6E, 0x1711, 0x1147 ],// LevelUp : size 4, + [0x1147, 0x1711, 0x1B6E, 0x228F ],// LevelDwon : size 4, + ], + + Infinite_Buff: { + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + Infinite_Count: { + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + Infinite_Start: { + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + + SenserSet:{ + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0 + }, + + InputData: { + Analog: { + AA1: 0, + AA2: 0, + AA3: 0, + AA4: 0, + }, + Digital: { + A1: 0, + A2: 0, + A3: 0, + A4: 0, + FEA1: 0, + FEA2: 0, + FEA3: 0, + FEA4: 0, + REA1: 0, + REA2: 0, + REA3: 0, + REA4: 0, + BEA1: 0, + BEA2: 0, + BEA3: 0, + BEA4: 0, + }, + Remote: { + R_1: 0, + R_2: 0, + R_3: 0, + R_4: 0, + R_5: 0, + R_6: 0, + R_7: 0, + R_8: 0, + R_L1: 0, + R_L2: 0, + R_R1: 0, + R_R2: 0, + }, + EEPROM: { + EC: 0, + EEPR2: 0, + EEPR1: 0, + }, + Infinite:{ + ROTATION_1: 0, + ROTATION_2: 0, + ROTATION_3: 0, + ROTATION_4: 0 + }, + Acceler:{ + AXIS_X1: 0, + AXIS_X2: 0, + AXIS_X3: 0, + AXIS_X4: 0, + AXIS_Y1: 0, + AXIS_Y2: 0, + AXIS_Y3: 0, + AXIS_Y4: 0, + AXIS_Z1: 0, + AXIS_Z2: 0, + AXIS_Z3: 0, + AXIS_Z4: 0, + } + }, + RemoteData: { + B1: 0, + B2: 0, + B3: 0, + B4: 0, + Servo1: 0, + Servo2: 0, + Servo3: 0, + Servo4: 0, + DC1: 0, + DC2: 0, + DC3: 0, + DC4: 0, + MEL2: 0, + MEL1: 0, + FND: 100, + EEPR4: 0, + EEPR3: 0, + EEPR2: 0, + EEPR1: 0, + ASET2: 0, + ASET1: 0, + }, + EdgeFlag: { + FEA1: 0, + FEA2: 0, + FEA3: 0, + FEA4: 0, + REA1: 0, + REA2: 0, + REA3: 0, + REA4: 0, + BEA1: 0, + BEA2: 0, + BEA3: 0, + BEA4: 0, + }, + EEPROM: { + EEPROM_Buff: 0, + EEPROM_Count: 0, + }, + + setZero: function() { + for (let key in this.EdgeFlag) { + this.EdgeFlag[key] = 0; + } + for (let key in this.RemoteData) { + Entry.hw.sendQueue[key] = this.RemoteData[key]; + } + for (let key in this.SenserSet) { + this.SenserSet[key] = 0; + } + Entry.hw.update(); + }, + convertDropdownRemote(value) { + switch (value) { + case '1': + return 'R_1'; + case '2': + return 'R_2'; + case '3': + return 'R_3'; + case '4': + return 'R_4'; + case '5': + return 'R_5'; + case '6': + return 'R_6'; + case '7': + return'R_7'; + case '8': + return'R_8'; + case '9': + return 'R_L1'; + case '10': + return 'R_L2'; + case '11': + return 'R_R1'; + case '12': + return 'R_R2'; + default: + return value; + } + }, + convertDropdownDigital(value) { + switch (value) { + case '1': + return 'A1'; + case '2': + return 'A2'; + case '3': + return 'A3'; + case '4': + return 'A4'; + case '5': + return 'FEA1'; + case '6': + return 'FEA2'; + case '7': + return 'FEA3'; + case '8': + return 'FEA4'; + case '9': + return 'REA1'; + case '10': + return 'REA2'; + case '11': + return 'REA3'; + case '12': + return 'REA4'; + case '13': + return 'BEA1'; + case '14': + return 'BEA2'; + case '15': + return 'BEA3'; + case '16': + return 'BEA4'; + default: + return value; + } + }, + convertDropdownAnalog(value) { + switch (value) { + case '1': + case '2': + case '3': + case '4': + return 'AA' + value; + default: + return value; + } + }, + convertDropdownAxis(value, axis) { + switch (value) { + case 'AA1': + case 'AA2': + case 'AA3': + case 'AA4': + value = value.substr(2, 2); + break; + } + return "AXIS_" + axis + value; + }, + convertDropdownSensor1(value) { + switch (value) { + case Lang.template.item_switch: + case '1': + return 1; + case Lang.template.item_infrared: + case '2': + return 2; + case Lang.template.item_magnetic: + case '3': + return 3; + case Lang.template.item_rotation: + case '4': + return 4; + case Lang.template.item_color: + case '5': + return 5; + case Lang.template.item_acceleration: + case '6': + return 6; + case Lang.template.item_ultrasonic: + case '7': + return 7; + case Lang.template.item_heart_rate: + case '8': + return 8; + case Lang.template.item_illuminance: + case '9': + return 9; + case Lang.template.item_sound: + case '10': + return 10; + case Lang.template.item_tilt: + case '11': + return 11; + case Lang.template.item_pressure: + case '12': + return 12; + case Lang.template.item_multi_touch: + case '13': + return 13; + case Lang.template.item_compass: + case '14': + return 14; + case Lang.template.item_3acceleration: + case '15': + return 15; + case Lang.template.item_multi_switch: + case '16': + return 16; + } + }, + convertDropdownSensor2(value) { + switch (value) { + case Lang.template.item_infinite_rotation: + case '1': + return 1; + case Lang.template.item_compass: + case '2': + return 2; + default: + return value; + } + }, + convertDropdownKey(value) { + switch (value) { + case Lang.template.item_key_1: + case '1': + return 0; + case Lang.template.item_key_2: + case '2': + return 1; + case Lang.template.item_key_3: + case '3': + return 2; + case Lang.template.item_key_4: + case '4': + return 3; + case Lang.template.item_key_5: + case '5': + return 4; + case Lang.template.item_key_6: + case '6': + return 5; + case Lang.template.item_key_7: + case '7': + return 6; + case Lang.template.item_key_8: + case '8': + return 7; + default: + return value; + } + }, + convertDropdownOnOff(value) { + switch (value) { + case Lang.template.item_on: + case '1': + return 1; + case Lang.template.item_off: + case '0': + return 0; + default: + return value + } + + }, + convertDropdownDC(value) { + switch (value) { + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + return 'DC' + value; + default: + return value; + } + }, + convertDropdownServo(value) { + switch (value) { + case '1': + case '2': + case '3': + case '4': + return 'Servo' + value; + default: + return value; + } + }, + convertDropdownPort(value) { + switch (value) { + case '1': + case '2': + case '3': + case '4': + return 'B' + value; + default: + return value; + } + }, + convertDropdownSensorTransfer(value) { + switch (value) { + case '1': + case Lang.template.item_value: + return 1; + case '2': + case Lang.template.item_angle: + return 2; + case '3': + case Lang.template.item_absolute_angle: + return 3; + case '4': + case Lang.template.item_number_of_rotations: + return 4; + default: + value; + } + }, + convertDropdownPitch(pitch) { + // 배열의 인덱스 1번부터 음표 + const index = (pitch % 12) + 1; + + let value = 0; + if (36 <= pitch && pitch <= 47) { + value = Entry.ProboConnect.Melody[index]; + } else if (48 <= pitch && pitch <= 59) { + value = Entry.ProboConnect.Melody[index] >> 1; + } else if (60 <= pitch && pitch <= 71) { + value = Entry.ProboConnect.Melody[index] >> 2; + } else if (72 <= pitch && pitch <= 83) { + value = Entry.ProboConnect.Melody[index] >> 3; + } else { + value = Entry.ProboConnect.Melody[0]; + } + return value; + }, + convertDropdownNote(value) { + switch (value) { + case Lang.template.item_note_whole: + case '1': + return 'n1'; + case Lang.template.item_note_half: + case '2': + return 'n2'; + case Lang.template.item_note_quarter: + case '4': + return 'n4'; + case Lang.template.item_note_eighth: + case '8': + return 'n8'; + case Lang.template.item_note_sixteenth: + case '16': + return 'n16'; + case Lang.template.item_note_thirty_second: + case '32': + return 'n32'; + default: + return value; + } + }, + convertDropdownMelody(value) { + switch (value) { + case Lang.template.item_melody_start: + case '1': + return 0; + case Lang.template.item_melody_end: + case '2': + return 1; + case Lang.template.item_melody_level_up: + case '3': + return 2; + case Lang.template.item_melody_level_down: + case '4': + return 3; + default: + return value; + } + }, + convertDropdownColor1(value) { + switch (value) { + case Lang.template.item_color_red: + return 0; + case Lang.template.item_color_green: + return 1; + case Lang.template.item_color_blue: + return 2; + case Lang.template.item_color_yellow: + return 3; + case Lang.template.item_color_black: + return 4; + case Lang.template.item_color_white: + return 5; + default: + return value - 1; + } + }, + convertDropdownColor2(value) { + switch (value) { + case Lang.template.item_color_red: + case '1': + return 1; + case Lang.template.item_color_green: + case '2': + return 23; + case Lang.template.item_color_blue: + case '3': + return 45; + case Lang.template.item_color_cyan: + case '4': + return 34; + case Lang.template.item_color_magenta: + case '5': + return 56; + case Lang.template.item_color_yellow: + case '6': + return 12; + case '7': + case Lang.template.item_color_white: + return 67; + default: + return value; + } + }, +}; + +Entry.ProboConnect.setLanguage = function() { + return { + ko: { + template: { + item_switch: '스위치', + item_infrared: '적외선', + item_magnetic: '자석', + item_rotation: '회전', + item_color: '컬러', + item_acceleration: '가속도', + item_ultrasonic: '초음파', + item_heart_rate: '심박', + item_illuminance: '조도', + item_temperature: '온도', + item_sound: '소리', + item_tilt: '기울기', + item_pressure: '압력', + item_multi_touch: '멀티키', + item_compass: '나침반', + item_3acceleration: '3가속', + item_multi_switch: '분배기', + item_infinite_rotation: '무한회전', + item_color_red: '빨간색', + item_color_green: '초록색', + item_color_blue: '파란색', + item_color_cyan: '청녹색', + item_color_magenta: '자홍색', + item_color_yellow: '노란색', + item_color_black: '검정색', + item_color_white: '하얀색', + item_value: '값', + item_angle: '각도', + item_absolute_angle: '절대각도', + item_number_of_rotations: '회전 수', + item_key_1: '키1', + item_key_2: '키2', + item_key_3: '키3', + item_key_4: '키4', + item_key_5: '키5', + item_key_6: '키6', + item_key_7: '키7', + item_key_8: '키8', + item_all: '모두', + item_on: '켜기', + item_off: '끄기', + item_note_whole: '온', + item_note_half: '2분', + item_note_quarter: '4분', + item_note_eighth: '8분', + item_note_sixteenth: '16분', + item_note_thirty_second: '32분', + item_pitch_do: '도', + item_pitch_do_sharp: '도#', + item_pitch_re: '레', + item_pitch_re_sharp: '레#', + item_pitch_mi: '미', + item_pitch_fa: '파', + item_pitch_fa_sharp: '파#', + item_pitch_sol: '솔', + item_pitch_sol_sharp: '솔#', + item_pitch_ra: '라', + item_pitch_ra_sharp: '라#', + item_pitch_si: '시', + item_melody_start: '시작음', + item_melody_end: '종료음', + item_melody_level_up: '레벨 업', + item_melody_level_down: '레벨 다운', + + connect_remote_event: '%1 리모컨 %2 키를 눌렀을 때', + connect_digital_event: '%1 디지털 입력 %2 이(가) 들어왔을 때', + + connect_senser_setting: '입력포트 %1 을(를) %2 센서로 설정 %3', + + connect_remote_input: '리모컨 입력 %1', + connect_digital_input: '디지털 입력 %1', + connect_analog_input: '아날로그 입력 %1', + connect_3axis_acceler_x: '3가속도 %1의 X축', + connect_3axis_acceler_y: '3가속도 %1의 Y축', + connect_3axis_acceler_z: '3가속도 %1의 Z축', + connect_value_mapping: '%1 의 %2 ~ %3 값을 %4 ~ %5 (으)로 변환', + connect_color_input_b: '컬러 센서 %1 이(가) %2 인가?', + connect_color_input_r: '컬러 센서 %1 의 색상', + connect_infinite_setting: '%1 센서 %2 을 %3 값으로 정하기 %4', + connect_infinite_mm_diameter: '%1 센서 %2 지름 %3 의 mm 값', + connect_infinite_transform_input: '%1 센서 %2 의 %3', + connect_multi_sensor: '멀티키 센서 %1의 %2', + connect_multi_switch: '분배 스위치 %1의 %2', + connect_eeprom_buffset: 'EEPROM %1 주소의 값 호출하기 %2', + connect_eeprom_address_value: 'EEPROM 주소의 값', + + connect_port_output: '출력핀 %1 을(를) %2 %3', + connect_servo_output: '서보 모터 %1 의 위치를 %2 로 이동 %3', + connect_s_dc_output: 'S 모터 %1 을(를) %2 속도로 회전 %3', + connect_dc_output: 'DC 모터 %1 을(를) %2 속도로 회전 %3', + connect_melody_note_output: '%1 을(를) %2 음표로 연주하기 %3', + connect_melody_sec_output: '%1 을(를) %2 초 동안 연주하기 %3', + connect_melody_output: '%1 을(를) 연주하기 %2', + connect_value_sec_output: '%1 값을(를) %2 초 동안 연주하기 %3', + connect_value_output: '%1 값을(를) 연주하기 %2', + connect_melody_track_output: '%1 을(를) %2초 간격으로 재생하기 %3', + connect_melody_off: '멜로디 중지 %1', + connect_rgbled_on_output: 'RGB LED %1 을(를) %2 으로 켜기 %3', + connect_rgbled_off_output: 'RGB LED %1 을(를) 끄기 %2', + connect_rgbled_dimming_output: 'RGB LED %1 을(를) %2 으로 디밍 %3', + connect_rgbled_flashing_output: 'RGB LED %1 %2 으로 %3 초 간격 %4', + connect_fnd_output: 'FND를 %1 (으)로 설정 %2', + connect_fnd_off: 'FND 끄기 %1', + connect_eeprom_write: 'EEPROM %1 주소에 %2 값 설정하기 %3', + }, + }, + en: { + template: { + item_switch: 'Switch', + item_infrared: 'Infrared', + item_magnetic: 'Magnetic', + item_rotation: 'Rotation', + item_color: 'Color', + item_acceleration: 'Acceleration', + item_ultrasonic: 'Ultrasonic', + item_heart_rate: 'Heart Rate', + item_illuminance: 'Illuminance', + item_temperature: 'Temperature', + item_sound: 'Sound', + item_tilt: 'Tilt', + item_pressure: 'Pressure', + item_multi_touch: 'Multi Touch', + item_compass: 'Compass', + item_3acceleration: '3Acceleration', + item_multi_switch: 'Multi Switch', + item_infinite_rotation: 'Infinite Rotation', + item_color_red: 'Red', + item_color_green: 'Green', + item_color_blue: 'Blue', + item_color_cyan: 'Cyan', + item_color_magenta: 'Magenta', + item_color_yellow: 'Yellow', + item_color_black: 'Black', + item_color_white: 'White', + item_value: 'Value', + item_angle: 'Angle', + item_absolute_angle: 'Absolute Angle', + item_number_of_rotations: 'Number of Rotations', + item_key_1: 'Key1', + item_key_2: 'Key2', + item_key_3: 'Key3', + item_key_4: 'Key4', + item_key_5: 'Key5', + item_key_6: 'Key6', + item_key_7: 'Key7', + item_key_8: 'Key8', + item_all: 'All', + item_on: 'On', + item_off: 'Off', + item_note_whole: 'Whole', + item_note_half: 'Half', + item_note_quarter: 'Quarter', + item_note_eighth: 'Eighth', + item_note_sixteenth: 'Sixteenth', + item_note_thirty_second: 'Thirty-Second', + item_pitch_do: 'do', + item_pitch_do_sharp: 'xdo', + item_pitch_re: 're', + item_pitch_re_sharp: 'xre', + item_pitch_mi: 'mi', + item_pitch_fa: 'fa', + item_pitch_fa_sharp: 'xfa', + item_pitch_sol: 'sol', + item_pitch_sol_sharp: 'xsol', + item_pitch_ra: 'ra', + item_pitch_ra_sharp: 'xra', + item_pitch_si: 'si', + item_melody_start: 'Start', + item_melody_end: 'End', + item_melody_level_up: 'Level up', + item_melody_level_down: 'Level down', + + connect_remote_event: '%1 When %2 remote control key pressed', + connect_digital_event: '%1 When %2 digital pin input', + + connect_senser_setting: 'Set input port %1 to %2 sensor %3', + + connect_remote_input: 'Remote control %1', + connect_digital_input: 'Read digital pin %1', + connect_analog_input: 'Read analog pin %1', + connect_3axis_acceler_x: '3acceleration %1 and X', + connect_3axis_acceler_y: '3acceleration %1 and Y', + connect_3axis_acceler_z: '3acceleration %1 and Z', + connect_value_mapping: '%1 to value %2 ~ %3 change %4 ~ %5', + connect_color_input_b: 'Is color sensor %1 %2 ?', + connect_color_input_r: 'Color of color sensor %1', + connect_infinite_setting: 'Set %1 sensor %2 to %3 value %4', + connect_infinite_mm_diameter: 'The move distance(in mm) when the %1 sensor %2 is %3 mm in diameter', + connect_infinite_transform_input: '%1 rotation sensor %2 to %3', + connect_multi_sensor: 'Multi sensor %1 key %2', + connect_multi_switch: 'A key number of the multi-switch sensor %1 = %2', + connect_eeprom_buffset:'Calling the value of EEPROM %1 address', + connect_eeprom_address_value: 'Value of EEPROM address', + + connect_dc_output: 'DC motor %1 velocity %2 %3', + connect_servo_output: 'Servo motor %1 position %2 %3', + connect_s_dc_output: 'Servo motor %1 speed %2 %3', + connect_port_output: 'Set digital pint %1 as %2 %3', + connect_melody_note_output: 'Play key %1 for %2 note %3', + connect_melody_sec_output: 'Play key %1 for %2 secs %3', + connect_melody_output: 'Play key %1 %2', + connect_value_sec_output: 'Play value %1 for %2 secs %3', + connect_value_output: 'Play value %1 %2', + connect_melody_track_output: 'Play sound %1 for %2 secs %3', + connect_melody_off: 'Stop tone %1', + connect_rgbled_on_output: 'Turn on RGB LED %1 to %2 %3', + connect_rgbled_off_output: 'Turn off RGB LED %1 %2', + connect_rgbled_dimming_output: 'Dimming RGB LED %1 to %2 %3', + connect_rgbled_flashing_output: 'RGB LED %1 Blinking %2 at %3 second intervals %4', + connect_fnd_output: 'Set FND to %1 %2', + connect_fnd_off: 'Turn off FND %1', + connect_eeprom_write: 'Set EEPROM %1 address to %2 %3', + }, + }, + }; +}; + +Entry.ProboConnect.blockMenuBlocks = [ + 'connect_dropdown_remote', + 'connect_dropdown_digital', + 'connect_dropdown_analog', + 'connect_dropdown_sensor_1', + 'connect_dropdown_sensor_2', + 'connect_dropdown_color_1', + 'connect_dropdown_color_2', + 'connect_dropdown_sensor_transfer', + 'connect_dropdown_key', + 'connect_dropdown_dc_1_all', + 'connect_dropdown_servo_1_4', + 'connect_dropdown_port_1_4', + 'connect_dropdown_on_off', + 'connect_dropdown_velocity', + 'connect_dropdown_servo_position', + 'connect_dropdown_note', + 'connect_dropdown_time_1', + 'connect_dropdown_time_2', + 'connect_dropdown_time_3', + 'connect_dropdown_pitch', + 'connect_dropdown_melody', + + //event + 'connect_remote_event', + 'connect_digital_event', + + //input + 'connect_senser_setting', + 'connect_remote_input', + 'connect_digital_input', + 'connect_analog_input', + 'connect_3axis_acceler_x', + 'connect_3axis_acceler_y', + 'connect_3axis_acceler_z', + 'connect_value_mapping', + 'connect_color_input_b', + 'connect_color_input_r', + 'connect_infinite_setting', + 'connect_infinite_mm_diameter', + 'connect_infinite_transform_input', + 'connect_multi_sensor', + 'connect_multi_switch', + 'connect_eeprom_buffset', + 'connect_eeprom_address_value', + + //output + 'connect_dc_output', + 'connect_servo_output', + 'connect_s_dc_output', + 'connect_port_output', + 'connect_melody_note_output', + 'connect_melody_sec_output', + 'connect_melody_output', + 'connect_value_sec_output', + 'connect_value_output', + 'connect_melody_track_output', + 'connect_melody_off', + 'connect_rgbled_on_output', + 'connect_rgbled_off_output', + 'connect_rgbled_flashing_output', + 'connect_rgbled_dimming_output', + 'connect_fnd_output', + 'connect_fnd_off', + // EEPROM + 'connect_eeprom_write', +]; + +// 블록 생성 +Entry.ProboConnect.getBlocks = function() { + return { + ///======================================================================================== + /// Dropdown block + ///======================================================================================== + connect_dropdown_remote: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['R_1', '1'], + ['R_2', '2'], + ['R_3', '3'], + ['R_4', '4'], + ['R_5', '5'], + ['R_6', '6'], + ['R_7', '7'], + ['R_8', '8'], + ['R_L1', '9'], + ['R_L2', '10'], + ['R_R1', '11'], + ['R_R2', '12'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_digital: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['A1', '1'], + ['A2', '2'], + ['A3', '3'], + ['A4', '4'], + ['FEA1', '5'], + ['FEA2', '6'], + ['FEA3', '7'], + ['FEA4', '8'], + ['REA1', '9'], + ['REA2', '10'], + ['REA3', '11'], + ['REA4', '12'], + ['BEA1', '13'], + ['BEA2', '14'], + ['BEA3', '15'], + ['BEA4', '16'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_analog: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['AA1', '1'], + ['AA2', '2'], + ['AA3', '3'], + ['AA4', '4'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_sensor_1: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_switch, '1'], + [Lang.template.item_infrared, '2'], + [Lang.template.item_magnetic, '3'], + [Lang.template.item_rotation, '4'], + [Lang.template.item_color, '5'], + [Lang.template.item_acceleration, '6'], + [Lang.template.item_ultrasonic, '7'], + [Lang.template.item_heart_rate, '8'], + [Lang.template.item_illuminance, '9'], + [Lang.template.item_sound, '10'], + [Lang.template.item_tilt, '11'], + [Lang.template.item_pressure, '12'], + [Lang.template.item_multi_touch, '13'], + [Lang.template.item_compass, '14'], + [Lang.template.item_3acceleration, '15'], + [Lang.template.item_multi_switch, '16'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_sensor_2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_infinite_rotation, '1'], + [Lang.template.item_compass, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_color_1: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_color_red, '1'], + [Lang.template.item_color_green, '2'], + [Lang.template.item_color_blue, '3'], + [Lang.template.item_color_yellow, '4'], + [Lang.template.item_color_black, '5'], + [Lang.template.item_color_white, '6'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_color_2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_color_red, '1'], + [Lang.template.item_color_green, '2'], + [Lang.template.item_color_blue, '3'], + [Lang.template.item_color_cyan, '4'], + [Lang.template.item_color_magenta, '5'], + [Lang.template.item_color_yellow, '6'], + [Lang.template.item_color_white, '7'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_sensor_transfer: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_value, '1'], + [Lang.template.item_angle, '2'], + [Lang.template.item_absolute_angle, '3'], + [Lang.template.item_number_of_rotations, '4'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_key: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_key_1, '1'], + [Lang.template.item_key_2, '2'], + [Lang.template.item_key_3, '3'], + [Lang.template.item_key_4, '4'], + [Lang.template.item_key_5, '5'], + [Lang.template.item_key_6, '6'], + [Lang.template.item_key_7, '7'], + [Lang.template.item_key_8, '8'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_dc_1_all: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 'DC1'], + ['2', 'DC2'], + ['3', 'DC3'], + ['4', 'DC4'], + ['1,2', 'DC5'], + ['3,4', 'DC6'], + [Lang.template.item_all, 'DC7'], + ], + value: 'DC1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_servo_1_4: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 'Servo1'], + ['2', 'Servo2'], + ['3', 'Servo3'], + ['4', 'Servo4'], + ], + value: 'Servo1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_velocity: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['20', '20'], + ['15', '15'], + ['10', '10'], + ['5', '5'], + ['0', '0'], + ['-5', '-5'], + ['-10', '-10'], + ['-15', '-15'], + ['-20', '-20'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_servo_position: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', '1'], + ['20', '20'], + ['40', '40'], + ['60', '60'], + ['80', '80'], + ['100', '100'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_port_1_4: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['1', 'B1'], + ['2', 'B2'], + ['3', 'B3'], + ['4', 'B4'], + ], + value: 'B1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_on_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_on, '1'], + [Lang.template.item_off, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_note: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_note_whole, '1'], + [Lang.template.item_note_half, '2'], + [Lang.template.item_note_quarter, '4'], + [Lang.template.item_note_eighth, '8'], + [Lang.template.item_note_sixteenth, '16'], + [Lang.template.item_note_thirty_second, '32'], + ], + value: '4', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_time_1: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0.1', '0.1'], + ['0.3', '0.3'], + ['0.5', '0.5'], + ['0.7', '0.7'], + ['1', '1'], + ['2', '2'], + ], + value: '0.5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_time_2: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0.1', '0.1'], + ['0.3', '0.3'], + ['0.5', '0.5'], + ['0.7', '0.7'], + ['1', '1'], + ['2', '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_time_3: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + ['0.05', '0.05'], + ['0.1', '0.1'], + ['0.2', '0.2'], + ['0.5', '0.5'], + ['1', '1'], + ], + value: '0.5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + connect_dropdown_pitch: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'DropdownExtra', + options: [ + [Lang.template.item_pitch_do + ' (36)', '36'], + [Lang.template.item_pitch_do_sharp + ' (37)', '37'], + [Lang.template.item_pitch_re + ' (38)', '38'], + [Lang.template.item_pitch_re_sharp + ' (39)', '39'], + [Lang.template.item_pitch_mi + ' (40)', '40'], + [Lang.template.item_pitch_fa + ' (41)', '41'], + [Lang.template.item_pitch_fa_sharp + ' (42)', '42'], + [Lang.template.item_pitch_sol + ' (43)', '43'], + [Lang.template.item_pitch_sol_sharp + ' (44)', '44'], + [Lang.template.item_pitch_ra + ' (45)', '45'], + [Lang.template.item_pitch_ra_sharp + ' (46)', '46'], + [Lang.template.item_pitch_si + ' (47)', '47'], + + [Lang.template.item_pitch_do + ' (48)', '48'], + [Lang.template.item_pitch_do_sharp + ' (49)', '49'], + [Lang.template.item_pitch_re + ' (50)', '50'], + [Lang.template.item_pitch_re_sharp + ' (51)', '51'], + [Lang.template.item_pitch_mi + ' (52)', '52'], + [Lang.template.item_pitch_fa + ' (53)', '53'], + [Lang.template.item_pitch_fa_sharp + ' (54)', '54'], + [Lang.template.item_pitch_sol + ' (55)', '55'], + [Lang.template.item_pitch_sol_sharp + ' (56)', '56'], + [Lang.template.item_pitch_ra + ' (57)', '57'], + [Lang.template.item_pitch_ra_sharp + ' (58)', '58'], + [Lang.template.item_pitch_si + ' (59)', '59'], + + [Lang.template.item_pitch_do + ' (60)', '60'], + [Lang.template.item_pitch_do_sharp + ' (61)', '61'], + [Lang.template.item_pitch_re + ' (62)', '62'], + [Lang.template.item_pitch_re_sharp + ' (63)', '63'], + [Lang.template.item_pitch_mi + ' (64)', '64'], + [Lang.template.item_pitch_fa + ' (65)', '65'], + [Lang.template.item_pitch_fa_sharp + ' (66)', '66'], + [Lang.template.item_pitch_sol + ' (67)', '67'], + [Lang.template.item_pitch_sol_sharp + ' (68)', '68'], + [Lang.template.item_pitch_ra + ' (69)', '69'], + [Lang.template.item_pitch_ra_sharp + ' (70)', '70'], + [Lang.template.item_pitch_si + ' (71)', '71'], + + [Lang.template.item_pitch_do + ' (72)', '72'], + [Lang.template.item_pitch_do_sharp + ' (73)', '73'], + [Lang.template.item_pitch_re + ' (74)', '74'], + [Lang.template.item_pitch_re_sharp + ' (75)', '75'], + [Lang.template.item_pitch_mi + ' (76)', '76'], + [Lang.template.item_pitch_fa + ' (77)', '77'], + [Lang.template.item_pitch_fa_sharp + ' (78)', '78'], + [Lang.template.item_pitch_sol + ' (79)', '79'], + [Lang.template.item_pitch_sol_sharp + ' (80)', '80'], + [Lang.template.item_pitch_ra + ' (81)', '81'], + [Lang.template.item_pitch_ra_sharp + ' (82)', '82'], + [Lang.template.item_pitch_si + ' (83)', '83'], + ], + value: '60', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + const value = script.getField('PARAM0'); + return value; + } + }, + connect_dropdown_melody: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + template: '%1', + params: [ + { + type: 'Dropdown', + options: [ + [Lang.template.item_melody_start, '1'], + [Lang.template.item_melody_end, '2'], + [Lang.template.item_melody_level_up, '3'], + [Lang.template.item_melody_level_down, '4'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + def: { + params: [ + null + ], + }, + paramsKeyMap: { + PARAM0: 0, + }, + events: {}, + func: function(sprite, script) { + return script.getField('PARAM0'); + } + }, + ///======================================================================================== + /// Event block + ///======================================================================================== + // 리모컨 R_1 키를 눌렀을 때 + connect_remote_event: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_event', + params: [ + { + type: 'Indicator', + img: 'block_icon/start_icon_hardware.svg', + size: 14, + position: { + x: 0, + y: -2, + }, + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'connect_dropdown_remote', + }, + ], + type: 'connect_remote_event', + }, + paramsKeyMap: { + PARAM1: 1, + }, + class: 'event', + isNotFor: ['ProboConnect'], + event: 'event_remote_input', + func(sprite, script) { + const btn = Entry.ProboConnect.convertDropdownRemote( + script.getStringValue('PARAM1') + ); + if (Entry.hw.portData.InputData.Remote[btn] == 1 ) { + return script.callReturn(); + } + return this.die(); + }, + }, + // 디지털 입력 A1 이(가) 들어왔을 때 + connect_digital_event: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_event', + params: [ + { + type: 'Indicator', + img: 'block_icon/start_icon_hardware.svg', + size: 14, + position: { + x: 0, + y: -2, + }, + }, + { + type: 'Block', + accept: 'string', + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'connect_dropdown_digital', + }, + ], + type: 'connect_digital_event', + }, + paramsKeyMap: { + PARAM1: 1, + }, + class: 'event', + isNotFor: ['ProboConnect'], + event: 'event_digital_input', + func(sprite, script) { + const port = Entry.ProboConnect.convertDropdownDigital( + script.getStringValue('PARAM1') + ); + switch(port) { + case 'FEA1': + case 'FEA2': + case 'FEA3': + case 'FEA4': + case 'REA1': + case 'REA2': + case 'REA3': + case 'REA4': + case 'BEA1': + case 'BEA2': + case 'BEA3': + case 'BEA4': + if (Entry.hw.portData.InputData.Digital[port] == 1) { + if (Entry.ProboConnect.EdgeFlag[port] == 0) { + Entry.ProboConnect.EdgeFlag[port] = 1; + return script.callReturn(); + } + } else { + Entry.ProboConnect.EdgeFlag[port] = 0; + } + break; + default: + if (Entry.hw.portData.InputData.Digital[port] == 1 ) { + return script.callReturn(); + } + break; + } + + return this.die(); + }, + }, + ///======================================================================================== + /// Input block + ///======================================================================================== + // 입력포트 AA1 을(를) 스위치 센서로 설정 + connect_senser_setting: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_sensor_1', + }, + null, + ], + type: 'connect_senser_setting', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'setting', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const sensor = Entry.ProboConnect.convertDropdownSensor1( + script.getStringValue('PARAM1') + ); + let index = 0; + switch (port) { + case 'AA1': + index = 0; + break; + case 'AA2': + index = 1; + break; + case 'AA3': + index = 2; + break; + case 'AA4': + index = 3; + break; + } + + let Aset = [0, 0, 0, 0]; + let value = [0, 0, 0, 0]; + + Aset[index] = sensor; + for (let i = 0; i < 4; i++) { + switch (Aset[i]) { + case 1: // 스위치 + case 2: // 적외선 + case 3: // 자석 + case 16: // 분배기 + value[i] = 1; + break; + case 4: // 회전 + case 9: // 조도 + case 7: // 초음파 + value[i] = 2; + break; + case 10: // 소리 + value[i] = 3; + break; + case 11: // 기울기 + value[i] = 4; + break; + case 12: // 압력 + value[i] = 5; + break; + case 8: // 심박 + value[i] = 6; + break; + case 5: // 컬러 + value[i] = 7; + break; + case 6: // 가속도 + value[i] = 8; + break; + case 14: // 나침반 + case 15: // 3가속 + value[i] = 9; + break; + case 13: // 멀티터치(멀티키) + value[i] = 11; + break; + } + } + + Entry.ProboConnect.SenserSet.AA1 = value[0]; + Entry.ProboConnect.SenserSet.AA2 = value[1]; + Entry.ProboConnect.SenserSet.AA3 = value[2]; + Entry.ProboConnect.SenserSet.AA4 = value[3]; + + Entry.hw.sendQueue['ASET2'] = (value[0] << 4) | value[1]; + Entry.hw.sendQueue['ASET1'] = (value[2] << 4) | value[3]; + + let fps = Entry.FPS || 60; + let timeValue = 60 / fps * 200; // 0.2초 + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + + }, + }, + // 리모컨 입력 R_1 + connect_remote_input: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_remote', + }, + ], + type: 'connect_remote_input', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const btn = Entry.ProboConnect.convertDropdownRemote( + script.getStringValue('PARAM0') + ); + return Entry.hw.portData.InputData.Remote[btn] == 1 ? true : false; + }, + }, + // 디지털 입력 A1 + connect_digital_input: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_digital', + }, + ], + type: 'connect_digital_input', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownDigital( + script.getStringValue('PARAM0') + ); + let rt = false; + switch(port) { + case 'FEA1': + case 'FEA2': + case 'FEA3': + case 'FEA4': + case 'REA1': + case 'REA2': + case 'REA3': + case 'REA4': + case 'BEA1': + case 'BEA2': + case 'BEA3': + case 'BEA4': + if (Entry.hw.portData.InputData.Digital[port] == 1) { + if (Entry.ProboConnect.EdgeFlag[port] == 0) { + Entry.ProboConnect.EdgeFlag[port] = 1; + rt = true; + } + } else { + Entry.ProboConnect.EdgeFlag[port] = 0; + } + break; + default: + rt = Entry.hw.portData.InputData.Digital[port] == 1 ? true : false; + break; + } + return rt; + }, + }, + // 아날로그 입력 AA1 + connect_analog_input: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_analog_input', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + let value = Entry.ProboConnect.SenserSet[port] == 5 + ? 255 - Entry.hw.portData.InputData.Analog[port] + : Entry.hw.portData.InputData.Analog[port]; + return value; + }, + }, + // 3가속도 AA1 의 X축 + connect_3axis_acceler_x: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_3axis_acceler_x', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const axis = Entry.ProboConnect.convertDropdownAxis( + script.getStringValue('PARAM0'), + "X" + ); + let value = (Entry.hw.portData.InputData.Acceler[axis]); + if (value & 0x80) { + value = (value - 255); + } + return Number(value / 10).toFixed(1); + }, + }, + // 3가속도 AA1의 Y축 + connect_3axis_acceler_y: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_3axis_acceler_y', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const axis = Entry.ProboConnect.convertDropdownAxis( + script.getStringValue('PARAM0'), + "Y" + ); + let value = (Entry.hw.portData.InputData.Acceler[axis]); + if (value & 0x80) { + value = (value - 255); + } + return Number(value / 10).toFixed(1); + }, + }, + // 3가속도 AA1 의 Z축 + connect_3axis_acceler_z: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_3axis_acceler_z', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const axis = Entry.ProboConnect.convertDropdownAxis( + script.getStringValue('PARAM0'), + "Z" + ); + let value = (Entry.hw.portData.InputData.Acceler[axis]); + if (value & 0x80) { + value = (value - 255); + } + return Number(value / 10).toFixed(1); + }, + }, + // AA1의 0 ~ 255 값을 0 ~ 100 (으)로 변환 + connect_value_mapping: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 255 ], + }, + { + type: 'number', + params: [ 0 ], + }, + { + type: 'number', + params: [ 100 ], + }, + ], + type: 'connect_value_mapping', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + PARAM2: 2, + PARAM3: 3, + PARAM4: 4, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const source1 = script.getNumberValue('PARAM1'); + const source2 = script.getNumberValue('PARAM2'); + const target1 = script.getNumberValue('PARAM3'); + const target2 = script.getNumberValue('PARAM4'); + + // Port 라는 key값을 가진 정보를 읽는다. + let data = 0; + if (Entry.ProboConnect.SenserSet[port] == 5) { + data = 255 - Entry.hw.portData.InputData.Analog[port]; + } else { + data = Entry.hw.portData.InputData.Analog[port]; + } + let value = 0; + let rate = (data - source1) / (source2 - source1); + let num = 0; + + if (target1 < target2) { + value = (target2 - target1) * rate; + num = value % 1; + if (num < 0.5) { + value -= num; + } + else { + value += 1 - num; + } + value = target1 + value; + if (value < target1) { + value = target1; + } else if (value > target2) { + value = target2; + } + } else { + value = (target1 - target2) * rate; + num = value % 1; + if (num < 0.5) { + value -= num; + } else { + value += 1 - num; + } + value = target1 - value; + if (value > target1) { + value = target1; + } else if (value < target2) { + value = target2; + } + } + return value; + }, + }, + // 컬러센서 AA1 이(가) 빨간색 색인가? + connect_color_input_b: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_color_1', + }, + ], + type: 'connect_color_input_b', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const target = Entry.ProboConnect.convertDropdownColor1( + script.getNumberValue('PARAM1') + ); + const value = Entry.hw.portData.InputData.Analog[port]; + const color = Entry.ProboConnect.Color; + return color[target][0] <= value && value <= color[target][1]; + }, + }, + // 컬러센서 AA1 의 색상 + connect_color_input_r: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + ], + type: 'connect_color_input_r', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const value = Entry.hw.portData.InputData.Analog[port]; + const color = Entry.ProboConnect.Color; + let colorName = ''; + for (let i = 0; i < 6; i++) { + if (color[i][0] <= value && value <= color[i][1]) { + switch (i) { + case 0: + colorName = Lang.template.item_color_red; + break; + case 1: + colorName = Lang.template.item_color_green; + break; + case 2: + colorName = Lang.template.item_color_blue; + break; + case 3: + colorName = Lang.template.item_color_yellow; + break; + case 4: + colorName = Lang.template.item_color_black; + break; + case 5: + colorName = Lang.template.item_color_white; + break; + } + } + } + return colorName; + }, + }, + // 무한회전 센서 AA1 을 0 값으로 정하기 + connect_infinite_setting: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + } + ], + def: { + params: [ + { + type: 'connect_dropdown_sensor_2', + }, + { + type: 'connect_dropdown_analog', + }, + { + type: 'number', + params: [ 0 ], + }, + null + ], + type: 'connect_infinite_setting', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + PARAM2: 2, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM1') + ); + let value = script.getNumberValue('PARAM2'); + let count = 0; + + if (value != 0) { + count = Number(value / 255).toFixed(0); + value = value % 255; + } else { + value = 0; + count = 0; + } + + Entry.ProboConnect.Infinite_Buff[port] = Entry.hw.portData.InputData.Analog[port]; + Entry.ProboConnect.Infinite_Start[port] = Entry.hw.portData.InputData.Analog[port]-value; + Entry.ProboConnect.Infinite_Count[port] = count; + + return script.callReturn(); + }, + }, + // 무한회전 센서 AA1 지름 53.5 의 mm 값 + connect_infinite_mm_diameter: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_sensor_2', + }, + { + type: 'connect_dropdown_analog', + }, + { + type: 'number', + params: [ 53.5 ], + }, + ], + type: 'connect_infinite_mm_diameter', + }, + paramsKeyMap: { + PARAM1: 1, + PARAM2: 2, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM1') + ); + const diameter = script.getNumberValue('PARAM2'); + let value = Entry.hw.portData.InputData.Analog[port]; + + if (value < Entry.ProboConnect.Infinite_Buff[port] - 150) { + + Entry.ProboConnect.Infinite_Count[port]++; + } else if (value > Entry.ProboConnect.Infinite_Buff[port] + 150) { + Entry.ProboConnect.Infinite_Count[port]--; + } + Entry.ProboConnect.Infinite_Buff[port] = value; + value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255); + + return Number( + 2 * + 3.141592 * + (diameter / 2) / + 255 * + value + ).toFixed(3); + }, + }, + // 무한회전 센서 AA1 의 값 + connect_infinite_transform_input: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_sensor_2', + }, + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_sensor_transfer', + }, + ], + type: 'connect_infinite_transform_input', + }, + paramsKeyMap: { + PARAM1: 1, + PARAM2: 2, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM1') + ); + const select = Entry.ProboConnect.convertDropdownSensorTransfer( + script.getStringValue('PARAM2') + ); + + let value = Entry.hw.portData.InputData.Analog[port]; + + if (value < (Entry.ProboConnect.Infinite_Buff[port] - 150)) { + Entry.ProboConnect.Infinite_Count[port]++; + } else if (value > (Entry.ProboConnect.Infinite_Buff[port] + 150)) { + Entry.ProboConnect.Infinite_Count[port]--; + } + Entry.ProboConnect.Infinite_Buff[port] = value; + value = (Entry.ProboConnect.Infinite_Buff[port] - Entry.ProboConnect.Infinite_Start[port]) + (Entry.ProboConnect.Infinite_Count[port] * 255); + + switch (select) { + case 2: + if (value > 0) { + return Math.floor((value%255) * 1.41732); + } else { + return Math.ceil((value%255) * 1.41732); + } + case 3: + return Number((360/255) * Entry.hw.portData.InputData.Analog[port]).toFixed(0); + case 4: + if (value > 0) { + return Math.floor(value / 255); + } else { + return Math.ceil(value / 255); + } + default: + return value; + } + }, + }, + // 멀티키 센서 AA1 의 키1 + connect_multi_sensor: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_key', + }, + ], + type: 'connect_multi_sensor', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const key = Entry.ProboConnect.convertDropdownKey( + script.getStringValue('PARAM1') + ); + const value = Entry.hw.portData.InputData.Analog[port] & (0x1 << key)? 1 : 0; + return value; + }, + }, + // 분배스위치 센서 AA1의 키1 + connect_multi_switch: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_analog', + }, + { + type: 'connect_dropdown_key', + }, + ], + type: 'connect_multi_switch', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownAnalog( + script.getStringValue('PARAM0') + ); + const key = Entry.ProboConnect.convertDropdownKey( + script.getStringValue('PARAM1') + ); + const analog = Entry.hw.portData.InputData.Analog[port]; + let value = -1; + if (1 <= analog && analog <= 19) { + value = 0; + } else if (26 <= analog && analog <= 44) { + value = 1; + } else if (53 <= analog && analog <= 77) { + value = 2; + } else if (83 <= analog && analog <= 101) { + value = 3; + } else if (107 <= analog && analog <= 125) { + value = 4; + } else if (139 <= analog && analog <= 157) { + value = 5; + } else if (160 <= analog && analog <= 178) { + value = 6; + } else if (191 <= analog && analog <= 209) { + value = 7; + } + return key === value ? 1 : 0; + }, + }, + connect_eeprom_buffset: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [{ type: 'number', params: ['0'] }, null], + type: 'connect_eeprom_buffset', + }, + paramsKeyMap: { + ADDRESS: 0, + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const address = script.getNumberValue('ADDRESS', script); + if (!script.isStart) { + Entry.ProboConnect.EEPROM.EEPROM_Count = Entry.hw.portData.InputData.EEPROM.EC; + Entry.hw.sendQueue['EEPR4'] = 0x40; + Entry.hw.sendQueue['EEPR3'] = address; + + script.isStart = true; + script.timeFlag = 1; + var timeValue = 0.05; + var fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + var blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.ProboConnect.EEPROM.EEPROM_Buff = + (Entry.hw.portData.InputData.EEPROM.EEPR2 << 8) + + Entry.hw.portData.InputData.EEPROM.EEPR1; + Entry.hw.sendQueue['EEPR4'] = 0; + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // EEPROM 주소의 값 + connect_eeprom_address_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + def: { + type: 'connect_eeprom_address_value', + }, + class: 'input', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + var value = 0; + const count = Entry.ProboConnect.EEPROM.EEPROM_Count; + if (Entry.hw.portData.InputData.EEPROM.EC != count) { + value = Entry.ProboConnect.EEPROM.EEPROM_Buff; + } + return value; + }, + }, + ///======================================================================================== + /// output block + ///======================================================================================== + // DC 모터 1을(를) 0 속도로 회전 + connect_dc_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_dc_1_all', + }, + { + type: 'connect_dropdown_velocity', + }, + null, + ], + type: 'connect_dc_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const motor = Entry.ProboConnect.convertDropdownDC( + script.getStringValue('PARAM0') + ); + const value = script.getNumberValue('PARAM1'); + switch (motor) { + case 'DC5': + Entry.hw.sendQueue['DC1'] = value; + Entry.hw.sendQueue['DC2'] = value; + break; + case 'DC6': + Entry.hw.sendQueue['DC3'] = value; + Entry.hw.sendQueue['DC4'] = value; + break; + case 'DC7': + Entry.hw.sendQueue['DC1'] = value; + Entry.hw.sendQueue['DC2'] = value; + Entry.hw.sendQueue['DC3'] = value; + Entry.hw.sendQueue['DC4'] = value; + break; + default: + Entry.hw.sendQueue[motor] = value; + break; + } + return script.callReturn(); + }, + }, + // 서보모터 1 의 위치를 1 로 이동 + connect_servo_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_servo_position', + }, + null, + ], + type: 'connect_servo_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const servo = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + let value = script.getNumberValue('PARAM1'); + if (value < 1) { + value = 0; + } else if (value > 100) { + value = 100; + } + + Entry.hw.sendQueue[servo] = value; + return script.callReturn(); + }, + }, + // S 모터 1 을(를) 0 속도로 회전 + connect_s_dc_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_velocity', + }, + null, + ], + type: 'connect_s_dc_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const motor = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + let value = script.getNumberValue('PARAM1'); + + if (value > 20) { + value = 20; + } else if (value < -20) { + value = -20; + } + value += 148; + + switch (motor) { + case 'Servo5': + Entry.hw.sendQueue['Servo1'] = value; + Entry.hw.sendQueue['Servo2'] = value; + break; + case 'Servo6': + Entry.hw.sendQueue['Servo3'] = value; + Entry.hw.sendQueue['Servo4'] = value; + break; + default: + Entry.hw.sendQueue[motor] = value; + break; + } + return script.callReturn(); + }, + }, + // 출력핀 1 을(를) 켜기 + connect_port_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_port_1_4', + }, + { + type: 'connect_dropdown_on_off', + }, + null + ], + type: 'connect_port_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const motor = Entry.ProboConnect.convertDropdownPort( + script.getStringValue('PARAM0') + ); + const value = Entry.ProboConnect.convertDropdownOnOff( + script.getNumberValue('PARAM1') + ); + + Entry.hw.sendQueue[motor] = value; + return script.callReturn(); + }, + }, + // 도(60) 을(를) 4분 음표로 연주하기 + connect_melody_note_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_pitch', + }, + { + type: 'connect_dropdown_note', + }, + null + ], + type: 'connect_melody_note_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const pitch = Entry.ProboConnect.convertDropdownPitch( + script.getNumberValue('PARAM0') + ); + const note = Entry.ProboConnect.convertDropdownNote( + script.getStringValue('PARAM1') + ); + + let timeValue = Entry.ProboConnect.Note[note]; + + Entry.hw.sendQueue['MEL2'] = pitch >> 8; + Entry.hw.sendQueue['MEL1'] = pitch; + + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue; + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // 도(60) 을(를) 0.5 초 동안 연주하기 + connect_melody_sec_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_pitch', + }, + { + type: 'connect_dropdown_time_1', + }, + null + ], + type: 'connect_melody_sec_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + const pitch = Entry.ProboConnect.convertDropdownPitch( + script.getNumberValue('PARAM0') + ); + let timeValue = script.getNumberValue('PARAM1'); + + Entry.hw.sendQueue['MEL2'] = pitch >> 8; + Entry.hw.sendQueue['MEL1'] = pitch; + + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // 도(60) 을(를) 연주하기 + connect_melody_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_pitch', + }, + null + ], + type: 'connect_melody_output', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const pitch = Entry.ProboConnect.convertDropdownPitch( + script.getNumberValue('PARAM0') + ); + + Entry.hw.sendQueue['MEL2'] = pitch >> 8; + Entry.hw.sendQueue['MEL1'] = pitch; + return script.callReturn(); + }, + }, + // 35391 값을 0.5 초 동안 연주하기 + connect_value_sec_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'number', + params: [ 35391 ], + }, + { + type: 'connect_dropdown_time_1', + }, + null + ], + type: 'connect_value_sec_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + + let melody = script.getNumberValue('PARAM0'); + let timeValue = script.getNumberValue('PARAM1'); + + Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; + Entry.hw.sendQueue['MEL1'] = melody & 0xff; + + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // 35391 값을(를) 연주하기 + connect_value_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'number', + params: [ 35391 ], + }, + null + ], + type: 'connect_value_output', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + let melody = script.getNumberValue('PARAM0'); + Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; + Entry.hw.sendQueue['MEL1'] = melody & 0xff; + return script.callReturn(); + }, + }, + // 시작음 을(를) 1 초 간격으로 재생하기 + connect_melody_track_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_melody', + }, + { + type: 'connect_dropdown_time_2', + }, + null + ], + type: 'connect_melody_track_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + function getTrackStep(track,script){ + if(!script.isStart){ + script.isStart = true; + script.trackStep = 0; + } + else { + script.trackStep++; + } + let timeValue = script.getNumberValue('PARAM1'); + script.timeFlag = 1; + let melody = Entry.ProboConnect.Track[track][script.trackStep]; + Entry.hw.sendQueue['MEL2'] = (melody >> 8) & 0xff; + Entry.hw.sendQueue['MEL1'] = melody & 0xff; + + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + Entry.TimeWaitManager.add( + script.block.id, + function() { + script.timeFlag = 0; + }, + timeValue + ); + } + const TR = Entry.ProboConnect.convertDropdownMelody( + script.getStringValue('PARAM0') + ); + if (!script.isStart) { + switch(TR) { + case 0 : + script.maxStep = 6; + break; + case 1 : + script.maxStep = 7; + break; + case 2 : + script.maxStep = 3; + break; + case 3 : + script.maxStep = 3; + break; + } + getTrackStep(TR,script); + return script; + } else if (script.timeFlag == 1) { + return script; + } else if (script.trackStep < script.maxStep){ + getTrackStep(TR,script); + return script; + } else { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + + delete script.trackStep; + delete script.maxStep; + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + // 멜로디 중지 + connect_melody_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + null + ], + type: 'connect_melody_off', + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + Entry.hw.sendQueue['MEL2'] = 0; + Entry.hw.sendQueue['MEL1'] = 0; + return script.callReturn(); + }, + }, + // RGB LED 1 을(를) 빨간색 으로 켜기 + connect_rgbled_on_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_color_2', + }, + null + ], + type: 'connect_rgbled_on_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + const color = Entry.ProboConnect.convertDropdownColor2( + script.getStringValue('PARAM1') + ); + Entry.hw.sendQueue[port] = color; + return script.callReturn(); + }, + }, + // RGB LED 을(를) 끄기 + connect_rgbled_off_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + null + ], + type: 'connect_rgbled_off_output', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + Entry.hw.sendQueue[port] = 0; + }, + }, + // RGB LED 1 빨간색으로 0.5초 간격 + connect_rgbled_flashing_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_color_2', + }, + { + type: 'connect_dropdown_time_3', + }, + null + ], + type: 'connect_rgbled_flashing_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + PARAM2: 2, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + const color = Entry.ProboConnect.convertDropdownColor2( + script.getStringValue('PARAM1') + ); + const sec = script.getNumberValue('PARAM2'); + let value = 0; + switch (sec) { + case 0.05: + value = color + 0; + break; + case 0.1: + value = color + 1; + break; + case 0.2: + value = color + 2; + break; + case 0.5: + value = color + 3; + break; + case 1: + value = color + 4; + break; + } + Entry.hw.sendQueue[port] = value; + return script.callReturn(); + }, + }, + // RGB LED 1을(를) 빨간색으로 디밍 + connect_rgbled_dimming_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'connect_dropdown_servo_1_4', + }, + { + type: 'connect_dropdown_color_2', + }, + null + ], + type: 'connect_rgbled_dimming_output', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const port = Entry.ProboConnect.convertDropdownServo( + script.getStringValue('PARAM0') + ); + let color = 0; + switch (script.getStringValue('PARAM1')) { + case '1': + color = 90; + break; + case '2': + color = 92; + break; + case '3': + color = 94; + break; + case '4': + color = 93; + break; + case '5': + color = 95; + break; + case '6': + color = 91; + break; + case '7': + color = 96; + break; + } + Entry.hw.sendQueue[port] = color; + return script.callReturn(); + }, + }, + // FND를 0 (으)로 설정 + connect_fnd_output: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'number', + params: [ 0 ], + }, + null + ], + type: 'connect_fnd_output', + }, + paramsKeyMap: { + PARAM0: 0, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const fnd = script.getNumberValue('PARAM0'); + Entry.hw.sendQueue['FND'] = fnd; + return script.callReturn(); + }, + }, + // FND 끄기 + connect_fnd_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + null + ], + type: 'connect_fnd_off', + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + Entry.hw.sendQueue['FND'] = 100; + return script.callReturn(); + }, + }, + // EEPROM 0 주소에 0 값 설정하기 + connect_eeprom_write: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + def: { + params: [ + { + type: 'number', + params: [ 0 ] + }, + { + type: 'number', + params: [ 0 ] + }, + null, + ], + type: 'connect_eeprom_write', + }, + paramsKeyMap: { + PARAM0: 0, + PARAM1: 1, + }, + class: 'output', + isNotFor: ['ProboConnect'], + func: function(sprite, script) { + const address = script.getNumberValue('PARAM0'); + const value = script.getNumberValue('PARAM1'); + if (!script.isStart) { + Entry.hw.update(); + Entry.hw.sendQueue['EEPR4'] = 0x80; + Entry.hw.sendQueue['EEPR3'] = address; + Entry.hw.sendQueue['EEPR2'] = (value >> 8) & 0xff; + Entry.hw.sendQueue['EEPR1'] = value & 0xff; + script.isStart = true; + script.timeFlag = 1; + let timeValue = 0.05; + let fps = Entry.FPS || 60; + timeValue = 60 / fps * timeValue * 1000; + + let blockId = script.block.id; + Entry.TimeWaitManager.add( + blockId, + function() { + script.timeFlag = 0; + }, + timeValue + ); + return script; + } else if (script.timeFlag == 1) { + return script; + } else { + Entry.hw.update(); + Entry.hw.sendQueue['EEPR4'] = 0x40; + Entry.hw.sendQueue['EEPR3'] = address; + Entry.hw.sendQueue['EEPR2'] = 0; + Entry.hw.sendQueue['EEPR1'] = 0; + + setTimeout(function() { + Entry.hw.update(); + Entry.hw.sendQueue['EEPR4'] = 0; + Entry.hw.sendQueue['EEPR3'] = 0; + Entry.hw.sendQueue['EEPR2'] = 0; + Entry.hw.sendQueue['EEPR1'] = 0; + }, 100); + + delete script.timeFlag; + delete script.isStart; + Entry.engine.isContinue = false; + return script.callReturn(); + } + }, + }, + }; +}; + +module.exports = Entry.ProboConnect; diff --git a/src/playground/blocks/hardware/block_robotis.js b/src/playground/blocks/hardware/block_robotis.js index f143a5bc05..e0af1d006f 100644 --- a/src/playground/blocks/hardware/block_robotis.js +++ b/src/playground/blocks/hardware/block_robotis.js @@ -52,7 +52,8 @@ Entry.Robotis_carCont = { return script.callReturn(); } // clear portData only if not RB-100 practical kit - if (Entry.hw.hwModule.id != "7.A,7.B") { + if (Entry.hw.hwModule.id != "7.A,7.B" && + Entry.hw.hwModule.id != "7.C" ) { Entry.hw.portData = {}; } setTimeout(function() { diff --git a/src/playground/blocks/hardware/block_robotisRBKoala.js b/src/playground/blocks/hardware/block_robotisRBKoala.js index 5952d9e67f..b92b23597f 100644 --- a/src/playground/blocks/hardware/block_robotisRBKoala.js +++ b/src/playground/blocks/hardware/block_robotisRBKoala.js @@ -2716,6 +2716,11 @@ Entry.Robotis_rb_koala.getBlocks = function() { return 0; } + + if (device_id_name == "DIST_110_DISTANCE") { + if (result > 1000) result = 1000; + } + return result; }, syntax: { @@ -2806,6 +2811,10 @@ Entry.Robotis_rb_koala.getBlocks = function() { return false; } + if (device_id_name == "DIST_110_DISTANCE") { + if (result > 1000) result = 1000; + } + switch(compareOP) { case 0: return result > compareValue; diff --git a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js index d300e6568e..4128d7b09c 100644 --- a/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js +++ b/src/playground/blocks/hardware/block_robotisRBPracticalAssembly.js @@ -43,40 +43,9 @@ Entry.Robotis_rb_P_Assembly = { setZero: function () { // instruction / address / length / value / default length Entry.Robotis_carCont.setRobotisData([ - [Entry.Robotis_rb.INSTRUCTION.WRITE, 21, 2, 20], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 40, 2, 0], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 66, 2, 0], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 5200, 1, 0], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 710, 2, 0], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 19, 1, 1], // bypass 모드 켜기 - [Entry.Robotis_rb.INSTRUCTION.WRITE, 4250, 1, 1], // huskylens 텍스트 지우기 - [Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE, 64, 1, 0xFE, 0], // torque off - [Entry.Robotis_rb.INSTRUCTION.WRITE, 23, 1, 1], // auto report 모드 켜기 + [Entry.Robotis_rb.INSTRUCTION.WRITE, 2100, 1, 1], // PracticeBot Finish ]); - Entry.Robotis_carCont.update(); - Entry.hw.sendQueue['setZero'] = [1]; - Entry.Robotis_carCont.setRobotisData(null); - Entry.Robotis_carCont.update(); - const start = new Date().getTime(); - while (true) { - if (new Date().getTime() - start > 1000) { - break; - } - } - Entry.hw.sendQueue['setZero'] = null; - Entry.Robotis_carCont.update(); - Entry.Robotis_carCont.setRobotisData([ - [Entry.Robotis_rb.INSTRUCTION.WRITE, 21, 2, 20], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 40, 2, 0], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 66, 2, 0], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 5200, 1, 0], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 710, 2, 0], - [Entry.Robotis_rb.INSTRUCTION.WRITE, 19, 1, 1], // bypass 모드 켜기 - [Entry.Robotis_rb.INSTRUCTION.WRITE, 4250, 1, 1], // huskylens 텍스트 지우기 - [Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE, 64, 1, 0xFE, 0], // torque off - [Entry.Robotis_rb.INSTRUCTION.WRITE, 23, 1, 1], // auto report 모드 켜기 - ]); - + camera_id_for_use = 0; Entry.Robotis_carCont.update(); }, id: ['7.A', '7.B'], @@ -104,6 +73,18 @@ Entry.Robotis_rb_P_Assembly.blockMenuBlocks = [ 'robotis_Practice_turn_at_line', 'robotis_Practice_drive_stop', + 'robotis_Practice_securitybot_init', + 'robotis_Practice_securitybot_hi', + 'robotis_Practice_securitybot_alert', + + 'robotis_Practice_petbot_happy', + 'robotis_Practice_petbot_sad', + + 'robotis_Practice_farmbot_init', + 'robotis_Practice_farmbot_seek', + 'robotis_Practice_farmbot_plant_type', + 'robotis_Practice_farmbot_harvest_or_not_and_go', + // 값 블록 'robotis_Practice_cm_ir_value', 'robotis_Practice_detectFrontObj', @@ -201,6 +182,18 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_Practice_turn_at_line: "교차로에서 %1 하고 멈추기 %2", robotis_Practice_drive_stop: "정지하기 %1", + robotis_Practice_securitybot_init: "보안로봇 초기화 %1", + robotis_Practice_securitybot_hi: "보안로봇 위아래로 흔들기 %1", + robotis_Practice_securitybot_alert: "보안로봇 좌우로 흔들기 %1", + + robotis_Practice_petbot_happy: "반려로봇 웃음 %1", + robotis_Practice_petbot_sad: "반려로봇 화남 %1", + + robotis_Practice_farmbot_init: "스마트팜 로봇 초기화 %1", + robotis_Practice_farmbot_seek: "농작물 찾기 %1", + robotis_Practice_farmbot_plant_type: "%1 농작물이면", + robotis_Practice_farmbot_harvest_or_not_and_go: "농작물 %1 돌아가기 %2", + // 값 블록 robotis_Practice_cm_ir_value: "%1 적외선센서 값", @@ -254,11 +247,11 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { // DXL 제어 - robotis_Practice_dxl_set_mode: "%1 번 모터 %2 모드로 설정 %3", - robotis_Practice_dxl_each_control: "%1 번 모터 %2°로 %3 초 동안 움직이기 %4", - robotis_Practice_dxl_set_position: "%1 번 모터 %2 속도로 %3° 위치로 회전 %4", - robotis_Practice_dxl_set_rotate: "%1 번 모터 %2 속도로 %3 으로 %4 %5", - robotis_Practice_dxl_set_multiturn_round: "%1 번 모터 %2 속도로 %3 바퀴 %4으로 회전 %5", + robotis_Practice_dxl_set_mode: "%1 모터 %2 모드로 설정 %3", + robotis_Practice_dxl_each_control: "%1 모터 %2°로 %3 초 동안 움직이기 %4", + robotis_Practice_dxl_set_position: "%1 모터 %2 속도로 %3° 위치로 회전 %4", + robotis_Practice_dxl_set_rotate: "%1 모터 %2 속도로 %3 으로 %4 %5", + robotis_Practice_dxl_set_multiturn_round: "%1 모터 %2 속도로 %3 바퀴 %4으로 회전 %5", @@ -266,10 +259,10 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_Practice_huskylens_connection_status: "AI 카메라: %1이면", robotis_Practice_huskylens_if_detected: "AI 카메라: %1 이/가 표시되면", - robotis_Practice_huskylens_block_value_closest_to_center: "AI 카메라: 화면 중앙과 가장 가까운 사각형의 %1", - robotis_Practice_huskylens_arrow_value_closest_to_center: "AI 카메라: 화면 중앙과 가장 가까운 화살표의 %1", + robotis_Practice_huskylens_block_value_closest_to_center: "AI 카메라: 화면 중앙과 가까운 %1의 %2", + robotis_Practice_huskylens_arrow_value_closest_to_center: "AI 카메라: 화면 중앙과 가까운 화살표의 %1", robotis_Practice_huskylens_number_of_learned_id: "AI 카메라: 학습한 ID의 갯수", - robotis_Practice_huskylens_block_value_of_id: "AI 카메라: 감지된 ID가 %1인 사각형의 %2", + robotis_Practice_huskylens_block_value_of_id: "AI 카메라: 감지된 ID가 %1인 %2의 %3", robotis_Practice_huskylens_arrow_value_of_id: "AI 카메라: 감지된 ID가 %1인 화살표의 %2", robotis_Practice_huskylens_if_learned_id: "AI 카메라: ID가 %1인 데이터를 학습하였으면", @@ -745,8 +738,13 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_huskylens_mode_color_recognition: "색상인식", robotis_huskylens_mode_tag_recognition: "태그인식", robotis_huskylens_mode_object_classification: "물체분류", - robotis_huskylens_block: "사각형", - robotis_huskylens_arrow: "화살표", + robotis_huskylens_target_face: "얼굴", + robotis_huskylens_target_object: "사물", + robotis_huskylens_target_color: "색상", + robotis_huskylens_target_tag: "태그", + robotis_huskylens_target_qr: "QR코드", + robotis_huskylens_target_block: "사각형", + robotis_huskylens_target_arrow: "화살표", robotis_huskylens_center_block_center_x: "중심 X좌표", robotis_huskylens_center_block_center_y: "중심 Y좌표", robotis_huskylens_center_block_width: "너비", @@ -756,6 +754,11 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_huskylens_center_arrow_origin_y: "시작점 Y좌표", robotis_huskylens_center_arrow_target_x: "끝점 X좌표", robotis_huskylens_center_arrow_target_y: "끝점 Y좌표", + + robotis_plant_ripe: "빨간색으로 잘 익은", + robotis_plant_unripe: "초록색으로 덜 익은", + robotis_harvest: "수확하고", + robotis_not_harvest: "수확하지 않고", }, }, en: { @@ -771,6 +774,18 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_Practice_stop_at_cross: "Stop at cross %1 %2", robotis_Practice_turn_at_line: "%1 at cross and stop %2", robotis_Practice_drive_stop: "Stop %1", + + robotis_Practice_securitybot_init: "Security robot init %1", + robotis_Practice_securitybot_hi: "Security robot shake up and down %1", + robotis_Practice_securitybot_alert: "Security robot shake left and right %1", + + robotis_Practice_petbot_happy: "Petbot laugh %1", + robotis_Practice_petbot_sad: "Petbot angry %1", + + robotis_Practice_farmbot_init: "SmartFarm Robot init %1", + robotis_Practice_farmbot_seek: "Look for plant %1", + robotis_Practice_farmbot_plant_type: "If it is %1 plant", + robotis_Practice_farmbot_harvest_or_not_and_go: "%1 the plant and go back %2", @@ -832,10 +847,10 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_Practice_huskylens_connection_status: "AI Camera: If %1", robotis_Practice_huskylens_if_detected: "AI Camera: If %1 is displayed", - robotis_Practice_huskylens_block_value_closest_to_center: "AI Camera: %1 of the rectangle closest to the center of the screen", + robotis_Practice_huskylens_block_value_closest_to_center: "AI Camera: %2 of the %1 closest to the center of the screen", robotis_Practice_huskylens_arrow_value_closest_to_center: "AI Camera: %1 of the arrow closest to the center of the screen", robotis_Practice_huskylens_number_of_learned_id: "AI Camera: the number of learned ID", - robotis_Practice_huskylens_block_value_of_id: "AI Camera: %2 of rectangle with detected ID %1", + robotis_Practice_huskylens_block_value_of_id: "AI Camera: %3 of %2 with detected ID %1", robotis_Practice_huskylens_arrow_value_of_id: "AI Camera: %2 of arrow with detected ID %1", robotis_Practice_huskylens_if_learned_id: "AI Camera: If learned data with ID %1", @@ -1116,8 +1131,8 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_huskylens_mode_color_recognition: "Color recognition", robotis_huskylens_mode_tag_recognition: "Tag recognition", robotis_huskylens_mode_object_classification: "Object classification", - robotis_huskylens_block: "Rectangle", - robotis_huskylens_arrow: "Arrow", + robotis_huskylens_target_block: "Rectangle", + robotis_huskylens_target_arrow: "Arrow", robotis_huskylens_center_block_center_x: "Center X", robotis_huskylens_center_block_center_y: "Center Y", robotis_huskylens_center_block_width: "Width", @@ -1127,6 +1142,11 @@ Entry.Robotis_rb_P_Assembly.setLanguage = function () { robotis_huskylens_center_arrow_origin_y: "Origin Y", robotis_huskylens_center_arrow_target_x: "Target X", robotis_huskylens_center_arrow_target_y: "Target Y", + + robotis_plant_ripe: "ripe in red", + robotis_plant_unripe: "green and unripe", + robotis_harvest: "Harvest", + robotis_not_harvest: "Skip harvesting", }, } } @@ -1136,6 +1156,7 @@ let dxl_last_valid_value = []; let rb100_last_valid_value = []; let bg_color = 0; let beat_per_minute = 75; +let camera_id_for_use = 0; const _doevent = ms => new Promise(res => setTimeout(res, ms)); async function wait(nTime) { await _doevent(nTime); } @@ -1381,6 +1402,13 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { if (rightDirection == '2') { rightSpeed = -rightSpeed; } + + if (leftSpeed < 0) { + leftSpeed = 256 + leftSpeed; + } + if (rightSpeed < 0) { + rightSpeed = 256 + rightSpeed; + } data_value = leftSpeed + rightSpeed * 256; @@ -1578,7 +1606,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { let data_address = 580; let data_length = 8; let angleValue = 0; - let id = 33 + wheelSide; + let id = 51 + wheelSide; let data_buf = []; let i = 0; let speed = 150; @@ -1998,6 +2026,422 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { py: ['Robotis.rb100_follow_line(%1)'], }, }, + robotis_Practice_securitybot_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_securitybot_init', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2110, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 1100 + ); + }, + syntax: { + js: [], + py: ['Robotis.securitybot_init()'], + }, + }, + robotis_Practice_securitybot_hi: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_securitybot_hi', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2111, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotis.securitybot_hi()'], + }, + }, + robotis_Practice_securitybot_alert: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_securitybot_alert', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2112, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotis.securitybot_alert()'], + }, + }, + robotis_Practice_petbot_happy: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_petbot_happy', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2121, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 7100 + ); + }, + syntax: { + js: [], + py: ['Robotis.petbot_happy()'], + }, + }, + robotis_Practice_petbot_sad: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_petbot_sad', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2122, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 2500 + ); + }, + syntax: { + js: [], + py: ['Robotis.petbot_sad()'], + }, + }, + + + robotis_Practice_farmbot_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_farmbot_init', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2130, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_init()'], + }, + }, + robotis_Practice_farmbot_seek: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_farmbot_seek', + }, + paramsKeyMap: { + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, 2131, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + 200 + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_seek()'], + }, + }, + robotis_Practice_farmbot_plant_type: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_plant_ripe, '1'], + [Lang.Blocks.robotis_plant_unripe, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [ + null, + ], + type: 'robotis_Practice_farmbot_plant_type', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + var scope = script.executor.scope; + var compareValue = script.getNumberValue('TYPE'); + + var result = Entry.hw.portData[2134]; + + if(result == undefined) { + return false; + } + + return (result == compareValue); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_is_type(%1)'], + }, + }, + robotis_Practice_farmbot_harvest_or_not_and_go: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_harvest, '1'], + [Lang.Blocks.robotis_not_harvest, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + null, + ], + type: 'robotis_Practice_farmbot_harvest_or_not_and_go', + }, + paramsKeyMap: { + ACTION: 0, + }, + class: 'robotis_rb100_practice_special', + isNotFor: ['Robotis_rb_P_Assembly'], + func: function (sprite, script) { + // instruction / address / length / value / default length + + let action = script.getNumberValue('ACTION', script); + let address = 2132; + let wait_time = 6000; + + switch (action) + { + case 1: + address = 2132; + wait_time = 6500; + break; + + case 2: + address = 2133; + wait_time = 2100; + break; + } + + var data_sendqueue = [ + [ + Entry.Robotis_rb.INSTRUCTION.WRITE, address, 1, 1 + ] + ]; + return Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + wait_time + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_harvest_or_not_and_go(%1)'], + }, + }, @@ -4895,18 +5339,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -4932,7 +5376,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - '1', + '52', null, null, ], @@ -5005,18 +5449,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5038,7 +5482,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - null, + '52', { type: 'number', params: ['0'], @@ -5123,18 +5567,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5156,7 +5600,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - '1', + '52', '50', '0', null, @@ -5234,18 +5678,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5285,7 +5729,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - '1', + '52', '50', null, null, @@ -5326,8 +5770,8 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { // cw일 경우 음수처리 if (dxl_direction == 1) data_value = -data_value; - // 알쥐나 알라 우측 바퀴인 경우 reverse mode이므로 방향 반대 - if (dxl_id == 33 || dxl_id == 35) data_value = -data_value; + // 바퀴형 로봇인 경우 reverse mode이므로 방향 반대 + if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) data_value = -data_value; data_value = data_value * dxl_move; @@ -5361,18 +5805,18 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - ["1", '1'], - ["2", '2'], //Lang.Blocks.robotis_common_green_color - ["3", '3'], - ["4", '4'], - ["5", '5'], - ["6", '6'], - ["7", '7'], - ["8", '8'], - ["51", '51'], - ["52", '52'], + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ["ID 1", '1'], + ["ID 2", '2'], + ["ID 3", '3'], + ["ID 4", '4'], + ["ID 5", '5'], + ["ID 6", '6'], + ["ID 7", '7'], + ["ID 8", '8'], ], - value: '1', + value: '52', fontSize: 11, bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, @@ -5405,7 +5849,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { events: {}, def: { params: [ - '1', + '52', '50', '1', null, @@ -5470,6 +5914,11 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { if (dxl_round < 0) dxl_round = 0; else if (dxl_round > 100) dxl_round = 100; + // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대 + if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) { + dxl_round = -dxl_round; + } + data_value_3 = dxl_round * 4096; if (dxl_direction == 1) data_value_3 = -data_value_3; @@ -6387,6 +6836,20 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { skeleton: 'basic_string_field', statements: [], params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_huskylens_target_face, '0'], + [Lang.Blocks.robotis_huskylens_target_object, '1'], + [Lang.Blocks.robotis_huskylens_target_color, '2'], + [Lang.Blocks.robotis_huskylens_target_tag, '3'], + [Lang.Blocks.robotis_huskylens_target_qr, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, { type: 'Dropdown', options: [ @@ -6406,11 +6869,13 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { def: { params: [ null, + null, ], type: 'robotis_Practice_huskylens_block_value_closest_to_center', }, paramsKeyMap: { - DATA_TYPE: 0, + TARGET: 0, + DATA_TYPE: 1, }, class: 'robotis_rb100_custom_huskylens', isNotFor: ['Robotis_rb_P_Assembly'], @@ -6540,6 +7005,20 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { bgColor: EntryStatic.colorSet.block.darken.HARDWARE, arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_huskylens_target_face, '0'], + [Lang.Blocks.robotis_huskylens_target_object, '1'], + [Lang.Blocks.robotis_huskylens_target_color, '2'], + [Lang.Blocks.robotis_huskylens_target_tag, '3'], + [Lang.Blocks.robotis_huskylens_target_qr, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, { type: 'Dropdown', options: [ @@ -6559,12 +7038,14 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { params: [ null, null, + null, ], type: 'robotis_Practice_huskylens_block_value_of_id', }, paramsKeyMap: { ID: 0, - TYPE: 1, + TARGET: 1, + TYPE: 2, }, class: 'robotis_rb100_custom_huskylens', isNotFor: ['Robotis_rb_P_Assembly'], @@ -6577,20 +7058,23 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { var data_length = 2; var data_value = script.getNumberValue('ID'); - var data_sendqueue = [ - [ - data_instruction, - data_address, - data_length, - data_value, - ], - ]; - - Entry.Robotis_carCont.postCallReturn( - script, - data_sendqueue, - Entry.Robotis_openCM70.delay - ); + if (camera_id_for_use != data_value) { + var data_sendqueue = [ + [ + data_instruction, + data_address, + data_length, + data_value, + ], + ]; + + Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + Entry.Robotis_openCM70.delay + ); + camera_id_for_use = data_value; + } data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER @@ -6670,20 +7154,23 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { var data_length = 2; var data_value = script.getNumberValue('ID'); - var data_sendqueue = [ - [ - data_instruction, - data_address, - data_length, - data_value, - ], - ]; - - Entry.Robotis_carCont.postCallReturn( - script, - data_sendqueue, - Entry.Robotis_openCM70.delay - ); + if (camera_id_for_use != data_value) { + var data_sendqueue = [ + [ + data_instruction, + data_address, + data_length, + data_value, + ], + ]; + + Entry.Robotis_carCont.postCallReturn( + script, + data_sendqueue, + Entry.Robotis_openCM70.delay + ); + camera_id_for_use = data_value; + } data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN @@ -6760,8 +7247,12 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { { type: 'Dropdown', options: [ - [Lang.Blocks.robotis_huskylens_block, '0'], - [Lang.Blocks.robotis_huskylens_arrow, '1'], + [Lang.Blocks.robotis_huskylens_target_face, '0'], + [Lang.Blocks.robotis_huskylens_target_object, '1'], + [Lang.Blocks.robotis_huskylens_target_color, '2'], + [Lang.Blocks.robotis_huskylens_target_tag, '3'], + [Lang.Blocks.robotis_huskylens_target_qr, '4'], + [Lang.Blocks.robotis_huskylens_target_arrow, '5'], ], value: '0', fontSize: 11, @@ -6786,7 +7277,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { var data_address = 4005; // block var detect_type = script.getNumberValue('DETECT_TYPE'); - if (detect_type == 1) data_address = 4006; // arrow + if (detect_type == 5) data_address = 4006; // arrow var result = Entry.hw.portData[data_address]; @@ -6921,10 +7412,17 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { var x = script.getNumberValue('X', script); var y = script.getNumberValue('Y', script); var text = script.getStringValue('TEXT', script); - var text_len = text.length; var data_buf = []; var i = 0; + // Encode the text as UTF-8 + let encoder = new TextEncoder(); + let utf8Array = encoder.encode(text); + + // utf8Array is now a Uint8Array containing the UTF-8 bytes of the text + let text_len = utf8Array.length; + + if (text_len > 45) text_len = 45; if (x < -160) x = 160; else if (x > 160) x = 160; @@ -6942,7 +7440,7 @@ Entry.Robotis_rb_P_Assembly.getBlocks = function () { data_buf.push(0); data_buf.push(0); for (i = 0; i < text_len; i++) { - data_buf.push(text[i]); + data_buf.push(utf8Array[i]); } var data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; diff --git a/src/playground/blocks/hardware/block_telliot_Base.js b/src/playground/blocks/hardware/block_telliot_Base.js new file mode 100644 index 0000000000..8e8ce0c5f5 --- /dev/null +++ b/src/playground/blocks/hardware/block_telliot_Base.js @@ -0,0 +1,235 @@ +'use strict'; + +const PreAction = { + STOP: 0x00, + MOVE_FORWARD: 0x01, + MOVE_BACKWARD: 0x02, + TURN_LEFT: 0x03, + TURN_RIGHT: 0x04, + + ACTION_UNKNOWN: 0xFF, +} + +class TelliotBase { + constructor() { + this.resetState(); + } + + setZero() { + this.resetState(); + Entry.hw.update(); + } + + afterReceive = function (data) { + const keys = data.state ? Object.keys(data.state) : []; + keys.forEach(key => { + this.state[key] = data.state[key]; + // console.log(typeof (this.state.sensors)); + }); + + // console.log('[afterReceive] : ' + keys); + // console.log('[afterReceive] : ', data.state); + } + + afterSend = function () { + this.resetState(); + Entry.hw.sendQueue = {}; + } + + resetState() { + this.state = { + sensors: 0, + rfid: [] + }; + } + + async delay(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + async request(func, subkey, value, updateNow = false) { + const test = [] + if (!Entry.hw.sendQueue[func]) + Entry.hw.sendQueue[func] = {}; + + if (subkey) { + Entry.hw.sendQueue[func][subkey.toString()] = value; + } else { + Entry.hw.sendQueue[func] = value; + } + + console.log('[' + func + '] : ' + value); + + console.log(test) + + if (updateNow) + Entry.hw.update(); + + // 딜레이 추가 + + } + + async req_add_chatbot(sprite, script) { + const ask = script.getStringValue('AI_CHATBOT_ASK'); + const resp = script.getStringValue('AI_CHATBOT_RESP'); + + console.log('[req_chatbot] : ' + ask + ' => ' + resp); + await this.request('add_chatbot', null, { ask, resp }, true); + return script.callReturn(); + } + + async req_voice_trigger(sprite, script) { + await this.request('req_voice_trigger_click', null, 1); + return script.callReturn(); + } + + async req_speech_to_text(sprite, script) { + await this.request('req_stt', null, 1); + return script.callReturn(); + } + + async req_text_to_speech(sprite, script) { + const stot = script.getStringValue('TEXT_TO_SPEECH'); + + console.log('[req_tts] : ' + stot); + await this.request('req_tts', null, stot, true); + await this.delay(3000); + return script.callReturn(); + } + + async req_add_prompt(sprite, script) { + const ai_prompt = script.getStringValue('AI_PROMPT'); + + console.log('[add_prompt] : ' + ai_prompt); + await this.request('add_prompt', null, ai_prompt, true); + return script.callReturn(); + } + + async req_predefined_action(sprite, script) { + const action_stridx = script.getStringValue('PREDEFINED_MOTION_ID'); + const action_value = script.getNumberValue('PREDEFINED_MOTION_VALUE'); + let action_id = PreAction.ACTION_UNKNOWN; + + switch (action_stridx) { + case 'forward': + action_id = PreAction.MOVE_FORWARD; + break; + case 'backward': + action_id = PreAction.MOVE_BACKWARD; + break; + case 'left': + action_id = PreAction.TURN_LEFT; + break; + case 'right': + action_id = PreAction.TURN_RIGHT; + break; + } + + await this.request('pre_action', null, { action_id, action_value }, true); + await this.delay(1250); + return script.callReturn(); + } + + async req_action_stop(sprite, script) { + const action_id = PreAction.STOP; + const action_value = 0; + + await this.request('pre_action', null, { action_id, action_value }, true); + return script.callReturn(); + } + + async req_motor_control(sprite, script) { + const port = script.getStringValue('MOTOR_PORT_ID'); + const motor_value = script.getNumberValue('MOTOR_PORT_VALUE'); + const dir = script.getStringValue('MOTOR_DIRECTION'); + var motor_id, motor_dir; + + switch (port) { + case 'left wheel': motor_id = 0; break; + case 'right wheel': motor_id = 1; break; + case 'left foot': motor_id = 0; break; + case 'right foot': motor_id = 1; break; + case 'left Leg': motor_id = 2; break; + case 'right Leg': motor_id = 3; break; + case 'left arm': motor_id = 4; break; + case 'right arm': motor_id = 5; break; + case 'head': motor_id = 6; break; + } + + switch (dir) { + case 'clockwise': + motor_dir = 0; + break; + case 'counterclockwise': + motor_dir = 1; + break; + } + + await this.request('motor_ctrl', null, { motor_id, motor_dir, motor_value }, true); + return script.callReturn(); + } + + async req_line_trace(sprite, script) { + const dir = script.getStringField('LINE_TRACE_DIR'); + var line_color = 0; + var line_dir; + + switch (dir) { + case 'forward': + line_dir = 0; + break; + case 'backward': + line_dir = 1; + break; + } + + await this.request('line_trace', null, { line_color, line_dir }, true); + return script.callReturn(); + } + + req_detect_object(sprite, script) { + const obj = script.getStringField('OBJECT_DETECT'); + var sensor_id = 0; + var detect_object = 0; + + if (obj === 'detected') + detect_object = 1; + else + detect_object = 0; + console.log(this.state.sensors) + console.log('[req_detect_object] : ' + this.state.sensors); + if (detect_object === 1 && this.state.sensors !== 0 && typeof (this.state.sensors) === 'number') { + console.log('1111111111111111') + return true; + } else if (detect_object === 0 && this.state.sensors.length === 0) { + console.log('22222222222222222') + return true; + } else { + console.log('123981237980123091238079231809') + return false; + } + } + + req_rfid_tag_detect(sprite, script) { + const tag = script.getStringField('TAG_DETECT'); + var tag_id = 0; + + switch (tag) { + case 'circle': tag_id = 0; break; + case 'rectangle': tag_id = 1; break; + case 'triangle': tag_id = 2; break; + case 'star': tag_id = 3; break; + case 'diamond': tag_id = 4; break; + case 'heart': tag_id = 5; break; + } + + console.log('[req_rfid_tag_detect] : ' + tag_id + ' ' + this.state.rfid); + if (this.state.rfid[tag_id]) { + return true; + } else { + return false; + } + } +} + +module.exports = { TelliotBase, PreAction }; diff --git a/src/playground/blocks/hardware/block_telliot_lite.js b/src/playground/blocks/hardware/block_telliot_lite.js new file mode 100644 index 0000000000..8f86b32bc2 --- /dev/null +++ b/src/playground/blocks/hardware/block_telliot_lite.js @@ -0,0 +1,678 @@ +'use strict'; +const {TelliotBase, PreAction} = require('./block_telliot_Base.js'); + +class TelliotLite extends TelliotBase { + constructor() { + super(); + + this.id = '60.1'; + this.name = 'GoldenKidsAICar'; + this.url = 'https://www.iotedcorp.com'; + this.imageName = 'telliot_lite.png'; + this.title = { + ko: '금쪽이 카', + en: 'GoldenKidsAICar', + }; + this.blockMenuBlocks = this.getBlockMenuBlocks(); + } + + getBlockMenuBlocks() { + return [ + // Telliot Car flow + 'telliot_car_move', + 'telliot_car_turn', + 'telliot_car_stop', + 'telliot_car_wheel_move', + 'telliot_car_line_move', + + // Telliot Car sensors + 'telliot_car_sensor_is_detected', + 'telliot_car_sensor_RFID_detect', +// 'telliot_car_camera_detect', + + // AI +// 'telliot_car_chatbot', +// 'telliot_car_voice_command', + 'telliot_car_voice_trigger', +// 'telliot_car_STT', + 'telliot_car_TTS', + + // AI prompt +// 'telliot_car_add_prompt', +// 'telliot_car_set_prompt' + ]; + } + + setLanguage() { + return { + ko: { + template: { + // Telliot Car flow + telliot_car_move: '%1(으)로 %2초간 이동하기 %3', + telliot_car_turn: '%1으로 회전하기 %2', + telliot_car_stop: '현재 위치에서 정지하기 %1', + //telliot_car_wheel_move: '%1 모터를 %2 만큼 %3으로 회전하기 %4', + telliot_car_line_move : '라인을 따라 앞으로 이동 하기 %2', + + // Telliot Car sensors + telliot_car_sensor_is_detected : '거리 센서가 물체를 %1 했을때 %2', + telliot_car_sensor_RFID_detect : '태그가 %1모양이 감지되었을때 %2', +// telliot_car_camera_detect : '카메라에 %1 되었을때 %2', + + // AI +// telliot_car_chatbot : '%1 라고 말하면 %2라고 대답하기 %3', +// telliot_car_voice_command : '%1라고 말하면 %2', + telliot_car_voice_trigger: '금쪽이 스피커에 음성 명령어 전달하기 %1', +// telliot_car_STT: '텔리엇에 전달한 음성을 문자로 전달 받기 %1', + telliot_car_TTS: '%1을 금쪽이 스피커에서 듣기 %2', + + // AI prompt + telliot_car_add_prompt : '%1 프롬프트 추가하기 %2', +// telliot_car_set_prompt : '%1 프롬프트로 설정하기' + + }, + }, + en: { + template: { + // Telliot Car flow + telliot_car_move: 'Move %1 during %2sec %3', + telliot_car_turn: 'Rotate %2 degree to the %1 %3', + telliot_car_stop: 'Stop at current position %1', + //telliot_car_wheel_move: '%1 모터를 %2 만큼 %3 회전하기 %4', + telliot_car_line_move : '라인을 따라 앞으로 이동하기 %2', + + // Telliot Car sensors + telliot_car_sensor_is_detected : ' 거리 센서가 %1 했을때 %2', + telliot_car_sensor_RFID_detect : '태그가 %1모양이 감지 되었을때 %2', +// telliot_car_camera_detect : '카메라에 %1 되었을때 %2', + + // AI +// telliot_car_chatbot : '%1 라고 말하면 %2라고 대답하기 %3', +// telliot_car_voice_command : '%1라고 말하면 %2', + telliot_car_voice_trigger: 'Send voice command to Speaker %1', +// telliot_car_STT: 'Receive speech to text from telliot %1', + telliot_car_TTS: 'Speech from %1 %2', + + // AI prompt +// telliot_car_add_prompt : 'Add %1 prompt %2', +// telliot_car_set_prompt : 'Set %1 prompt' + }, + }, + }; + } + + getBlocks() { + return { + // Telliot Car flow + telliot_car_move : { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['앞', 'forward'], + ['뒤', 'backward'], + ], + value: 'forward', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 11, + }, + ], + events: {}, + def: { + params : [null, null, null], + type: 'telliot_car_move', + }, + paramsKeyMap: { + PREDEFINED_MOTION_ID: 0, + PREDEFINED_MOTION_VALUE: 1, + }, + class: 'telliot_car_flow', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_predefined_action(sprite, script) + }, + + telliot_car_turn : { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['왼쪽', 'left'], + ['오른쪽', 'right'], + ], + value: 'left', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + // { + // type: 'Dropdown', + // options: [ + // ['15', '15'], + // ['30', '30'], + // ['45', '45'], + // ['60', '60'], + // ['75', '75'], + // ['90', '90'], + // ['105', '105'], + // ['120', '120'], + // ['135', '135'], + // ['150', '150'], + // ['165', '165'], + // ['180', '180'], + // ], + // value: '45', + // fontSize: 11, + // bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + // arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + // }, + { + type : 'Indicator', + img : 'block_icon/hardware_icon.svg', + size : 11, + }, + ], + events: {}, + def: { + params : [null, null, null], + type: 'telliot_car_turn', + }, + paramsKeyMap: { + PREDEFINED_MOTION_ID: 0, + PREDEFINED_MOTION_VALUE: 1, + }, + class: 'telliot_car_flow', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_predefined_action(sprite, script) + }, + + telliot_car_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 : 11, + }, + ], + events: {}, + def: { + params: [null], + type: 'telliot_car_stop', + }, + class: 'telliot_car_flow', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_action_stop(sprite, script) + }, + + // telliot_car_wheel_move : { + // color: EntryStatic.colorSet.block.default.HARDWARE, + // outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + // skeleton: 'basic', + // statements: [], + // params: [ + // { + // type: 'Dropdown', + // options: [ + // ['왼쪽 바퀴', 'left wheel'], + // ['오른쪽 바퀴', 'right wheel'], + // ], + // value: 'left wheel', + // fontSize: 11, + // bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + // arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + // }, + // { + // type: 'Block', + // accept: 'string', + // defaultType: 'number', + // }, + // { + // type: 'Dropdown', + // options: [ + // ['시계방향', 'clockwise'], + // ['반시계방향', 'counterclockwise'], + // ], + // value: 'clockwise', + // fontSize: 11, + // bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + // arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + // }, + // { + // type : 'Indicator', + // img : 'block_icon/hardware_icon.svg', + // size : 11, + // }, + // ], + // events: {}, + // def: { + // params : [ + // null, + // { + // type: 'number', + // params: ['100'], + // }, + // null, + // null, + // ], + // type: 'telliot_car_wheel_move', + // }, + // paramsKeyMap: { + // MOTOR_PORT_ID: 0, + // MOTOR_PORT_VALUE: 1, + // MOTOR_DIRECTION: 2, + // }, + // class: 'telliot_car_flow', + // //isNotFor : ['TelliotLite'], + // func: (sprite, script) => this.req_motor_control(sprite, script) + // }, + + telliot_car_line_move : { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['앞으로', 'forward'], + // ['뒤로', 'backward'], + ], + value: 'forward', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type : 'Indicator', + img : 'block_icon/hardware_icon.svg', + size : 11, + }, + ], + events: {}, + def: { + params : [null, null], + type: 'telliot_car_line_move', + }, + paramsKeyMap: { + LINE_TRACE_DIR: 0, + }, + class: 'telliot_car_flow', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_line_trace(sprite, script) + }, + + // Telliot Car sensors + telliot_car_sensor_is_detected : { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['감지', 'detected'], + ['미감지', 'not detected'], + ], + value: 'detected', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type : 'Indicator', + img : 'block_icon/hardware_icon.svg', + size : 11, + }, + ], + events: {}, + def: { + params : [null, null], + type: 'telliot_car_sensor_is_detected', + }, + paramsKeyMap: { + OBJECT_DETECT: 0, + }, + class: 'telliot_car_sensors', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_detect_object(sprite, script), + }, + + telliot_car_sensor_RFID_detect : { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['동그라미', 'circle'], + ['네모', 'rectangle'], + ['세모', 'triangle'], + ['별', 'star'], + ['다이아몬드', 'diamond'], + ['하트', 'heart'], + ], + value: 'circle', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type : 'Indicator', + img : 'block_icon/hardware_icon.svg', + size : 11, + }, + ], + events: {}, + def: { + params : [null, null], + type: 'telliot_car_sensor_RFID_detect', + }, + paramsKeyMap: { + TAG_DETECT: 0, + }, + class: 'telliot_car_sensors', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_rfid_tag_detect(sprite, script), + }, + +// telliot_car_camera_detect : { +// 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: 'telliot_lite_STT', +// }, +// class: 'telliot_ai', +// //isNotFor : ['TelliotLite'], +// func(sprite, script) { +// return script.callReturn(); +// }, +// }, +// + // AI + telliot_car_chatbot : { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'string', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'string', + }, + { + type : 'Indicator', + img : 'block_icon/hardware_icon.svg', + size : 11, + }, + ], + events: {}, + def: { + params : [ + { + type: 'text', + params: ['<질문>'], + }, + { + type: 'text', + params: ['<답변>'], + }, + null, + ], + type: 'telliot_car_chatbot', + }, + paramsKeyMap: { + AI_CHATBOT_ASK: 0, + AI_CHATBOT_RESP: 1, + }, + class: 'telliot_ai', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_add_chatbot(sprite, script) + }, + + telliot_car_voice_command : { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'string', + }, + { + type : 'Indicator', + img : 'block_icon/hardware_icon.svg', + size : 11, + }, + ], + events: {}, + def: { + params : [ + { + type: 'text', + params: [''], + }, + null + ], + type: 'telliot_car_voice_command', + }, + paramsKeyMap: { + CAR_CHATBOT_CMD: 0, + }, + class: 'telliot_ai', + isNotFor : ['GoldenKidsAICar'], + func(sprite, script) { + return script.callReturn(); + }, + }, + + // Voice Capture + telliot_car_voice_trigger: { + 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 : 11, + }, + ], + events: {}, + def: { + params: [null], + type: 'telliot_car_voice_trigger', + }, + class: 'telliot_ai', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_voice_trigger(sprite, script) + }, + + // Speech to Text + telliot_car_STT: { + 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 : 11, + }, + ], + events: {}, + def: { + params : [null], + type: 'telliot_car_STT', + }, + class: 'telliot_ai', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_speech_to_text(sprite, script) + }, + + // Text To Speech + telliot_car_TTS: { + 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 : 11, + }, + ], + events: {}, + def: { + params: [ + { + type: 'text', + params: [''], + }, + null + ], + type: 'telliot_car_TTS', + }, + paramsKeyMap: { + TEXT_TO_SPEECH: 0, + }, + class: 'telliot_ai', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_text_to_speech(sprite, script) + }, + + // AI prompt + telliot_car_add_prompt : { + 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 : 11, + }, + ], + events: {}, + def: { + params : [ + { + type: 'text', + params: [''], + }, + null + ], + type: 'telliot_car_add_prompt', + }, + paramsKeyMap: { + AI_PROMPT: 0, + }, + class: 'telliot_ai', + isNotFor : ['GoldenKidsAICar'], + func: (sprite, script) => this.req_add_prompt(sprite, script) + }, + +// telliot_car_set_prompt : { +// 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: 'telliot_lite_STT', +// }, +// class: 'telliot_ai', +// //isNotFor : ['TelliotLite'], +// func: (sprite, script) => this.req_speech_to_text(sprite, script) +// }, + }; + }; + + setZero () { + super.setZero(); + } + + afterReceive (data) { + super.afterReceive(data); + } + + afterSend () { + super.afterSend(); + } +} + +module.exports = new TelliotLite(); +//module.exports = Entry.TelliotLite; diff --git a/src/playground/blocks/hardware/block_whalesbot_eagle_1001.js b/src/playground/blocks/hardware/block_whalesbot_eagle_1001.js new file mode 100644 index 0000000000..556a5a4bad --- /dev/null +++ b/src/playground/blocks/hardware/block_whalesbot_eagle_1001.js @@ -0,0 +1,1464 @@ +'use strict'; +import _range from 'lodash/range'; +import DataTable from '../../../class/DataTable'; +import entryModuleLoader from '../../../class/entryModuleLoader'; +import metadata from '../hardwareLite/metadata_whalesbot_drone_lite.json'; + +Entry.WhalesbotEagle1001 = { + id: '62.1', + name: 'whalesbot_eagle_1001', + url: '', + imageName: '', + title: { + ko: 'Whalesbot Eagle 1001', + en: '웨일스봇 Eagle 1001', + }, + simulatorPopup: null, + unsupportBlockExist: false, + setZero: function() {}, + sendCmd(msgString) { + let sq = Entry.hw.sendQueue; + sq['cmd'] = msgString; + Entry.hw.update(); + delete sq['cmd']; + }, + + exportProject() { + let project = {}; + + project.objects = Entry.container.toJSON(); + const objects = project.objects; + project.scenes = Entry.scene.toJSON(); + project.variables = Entry.variableContainer.getVariableJSON(); + project.messages = Entry.variableContainer.getMessageJSON(); + project.functions = Entry.variableContainer.getFunctionJSON(); + project.tables = DataTable.getTableJSON(); + project.speed = Entry.FPS; + project.interface = Entry.captureInterfaceState(); + project.expansionBlocks = Entry.expansionBlocks; + project.aiUtilizeBlocks = Entry.aiUtilizeBlocks; + project.hardwareLiteBlocks = Entry.hardwareLiteBlocks; + project.learning = Entry.aiLearning?.toJSON(); + project.externalModules = entryModuleLoader.moduleList; + project.externalModulesLite = entryModuleLoader.moduleListLite; + + if (!objects || !objects.length) { + return false; + } + + return project; + } +}; + +Entry.WhalesbotEagle1001.setLanguage = function() { + return { + ko: { + template: { + whalesbot_eagle_1001_openning_3d_simulator: '3D 시뮬레이터를 엽니 다', + whalesbot_eagle_1001_clean:'삭제', + whalesbot_eagle_1001_restart: '재시작', + whalesbot_eagle_1001_entering_pitch_mode:'준비모드 시작하기', + whalesbot_eagle_1001_exit_pitch_mode:'준비모드 끝내기', + whalesbot_eagle_1001_automatic_take_off_height:'자동 이륙 높이 %1 cm', + whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset:'자동 이륙 고도 %1 cm 속도 %2 X 오프셋 %3 도 Y 오프셋 %4 도 으로 이동하기', + whalesbot_eagle_1001_automatic_landing:'드로착륙', + whalesbot_eagle_1001_automatic_descent_speed_offset:'자동 낙하 속도 %1 X 오프셋 %2 도 Y 오프셋 %3 도', + whalesbot_eagle_1001_set_the_flight_speed:'설정된 비행 속도는 %1 cm/s', + whalesbot_eagle_1001_get_setting_speed:'설정 속도 가져오기', + whalesbot_eagle_1001_rise:'위로 %1 cm', + whalesbot_eagle_1001_down:'아래로 %1 cm', + whalesbot_eagle_1001_fly_forward:'앞으로 %1 cm', + whalesbot_eagle_1001_fly_backward:'뒤로 %1 cm', + whalesbot_eagle_1001_fly_left:'왼쪽으로 %1 cm', + whalesbot_eagle_1001_fly_right:'오른쪽으로 %1 cm', + whalesbot_eagle_1001_turn_left:'왼쪽으로 회전 %1 °', + whalesbot_eagle_1001_turn_right:'오른쪽으로 회전 %1 °', + whalesbot_eagle_1001_fly_in_the_specified_direction:'속도 %1 , 방향 %2 으로이동하기', + whalesbot_eagle_1001_flight_designated:'지정된 거리를 비행합니다 x %1 cm y %2 cm z%3 cm 속도 %4 cm/s', + whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control:'리모컨 4개 채널 로드 설정 Pitch %1 Roll %2 액셀러레이터 %3 Yaw %4', + whalesbot_eagle_1001_stop_moving_and_hover:'호버링기능', + whalesbot_eagle_1001_hover_at_specified_altitude:'지정된 높이에 서스펜션 %1 cm', + whalesbot_eagle_1001_emergency_stop:'긴급정지', + whalesbot_eagle_1001_set_the_steering_gear:'스티어링기어 ID 설정 포트 %1 속도 %2 각도 %3', + whalesbot_eagle_1001_execute_script:'스크립트 실행', + }, + Device: { + whalesbot_eagle_1001: 'whalesbot_eagle_1001', + }, + Menus: { + whalesbot_eagle_1001: 'WhalesbotEagle1001', + }, + Blocks: { + whalesbot_eagle_1001_toast_status_title: "드론 상태", + whalesbot_eagle_1001_toast_download_success: "다운로드 코드가 성공했습니다", + whalesbot_eagle_1001_toast_download_failed: "다운로드 코드가 실패했습니다", + whalesbot_eagle_1001_toast_clean_failed: "깨끗한 코드가 실패했습니다", + whalesbot_eagle_1001_toast_clean_success: "깨끗한 코드 성공", + whalesbot_eagle_1001_toast_unsupport_block_title: "지원되지 않는 블록", + whalesbot_eagle_1001_toast_unsupport_block_msg: "하드웨어에서는 일부 블록이 지원되지 않습니다" + } + }, + en: { + template: { + whalesbot_eagle_1001_openning_3d_simulator: 'Open 3D Simulator', + whalesbot_eagle_1001_clean:'Clean', + whalesbot_eagle_1001_restart: 'Restart', + whalesbot_eagle_1001_entering_pitch_mode:'Entering Pitch Mode', + whalesbot_eagle_1001_exit_pitch_mode:'Exit Pitch Mode', + whalesbot_eagle_1001_automatic_take_off_height:'Automatic Take Off Height %1 cm', + whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset:'Automatic Take Off Altitude %1 cm, Speed %2, X offset %3 degree, Y offset %4 degree', + whalesbot_eagle_1001_automatic_landing:'Automatic Landing', + whalesbot_eagle_1001_automatic_descent_speed_offset:'Automatic Descent Speed %1, X offset %2 degree, Y offset %3 degree', + whalesbot_eagle_1001_set_the_flight_speed:'Set The Flight Speed To %1 cm/s', + whalesbot_eagle_1001_get_setting_speed:'Get Setting Speed', + whalesbot_eagle_1001_rise:'Rise %1 cm', + whalesbot_eagle_1001_down:'Down %1 cm', + whalesbot_eagle_1001_fly_forward:'Fly Forward %1 cm', + whalesbot_eagle_1001_fly_backward:'Fly Backward %1 cm', + whalesbot_eagle_1001_fly_left:'Fly Left %1 cm', + whalesbot_eagle_1001_fly_right:'Fly Right %1 cm', + whalesbot_eagle_1001_turn_left:'Turn Left %1 °', + whalesbot_eagle_1001_turn_right:'Turn Right %1 °', + whalesbot_eagle_1001_fly_in_the_specified_direction:'Fly In The Specified Direction Speed %1 cm/s Direction %2 °', + whalesbot_eagle_1001_flight_designated:'Flight Designated Distance X %1 cm Y %2 cm Z %3 cm Speed %4 cm/s', + whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control:'Set The Four Channel Lever Quantity Of Remote Control Pitch %1° Roll %2° Throttle %3° Roll %4°', + whalesbot_eagle_1001_stop_moving_and_hover:'Stop Moving And Hover', + whalesbot_eagle_1001_hover_at_specified_altitude:'Hover At a Specified Altitude %1 cm', + whalesbot_eagle_1001_emergency_stop:'Emergency Stop', + whalesbot_eagle_1001_set_the_steering_gear:'Set The Steering Gear Port %1 Speed %2 cm/s Angle %3 °', + whalesbot_eagle_1001_execute_script:'Execute Script', + }, + Device: { + whalesbot_eagle_1001: 'whalesbot_eagle_1001', + }, + Menus: { + whalesbot_eagle_1001: 'WhalesbotEagle1001', + }, + Blocks: { + whalesbot_eagle_1001_toast_status_title: "Drone Status", + whalesbot_eagle_1001_toast_download_success: "Download code successed", + whalesbot_eagle_1001_toast_download_failed: "Download code failed", + whalesbot_eagle_1001_toast_clean_failed: "Clean code failed", + whalesbot_eagle_1001_toast_clean_success: "Clean code success", + whalesbot_eagle_1001_toast_unsupport_block_title: "Unsupport Block", + whalesbot_eagle_1001_toast_unsupport_block_msg: "There is some blocks is not supported by hardware" + } + }, + }; +}; + +Entry.WhalesbotEagle1001.blockMenuBlocks = [ + // 'whalesbot_eagle_1001_openning_3d_simulator', + 'whalesbot_eagle_1001_entering_pitch_mode', + 'whalesbot_eagle_1001_exit_pitch_mode', + 'whalesbot_eagle_1001_automatic_take_off_height', + 'whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset', + 'whalesbot_eagle_1001_automatic_landing', + 'whalesbot_eagle_1001_automatic_descent_speed_offset', + 'whalesbot_eagle_1001_set_the_flight_speed', + 'whalesbot_eagle_1001_get_setting_speed', + 'whalesbot_eagle_1001_rise', + 'whalesbot_eagle_1001_down', + 'whalesbot_eagle_1001_fly_forward', + 'whalesbot_eagle_1001_fly_backward', + 'whalesbot_eagle_1001_fly_left', + 'whalesbot_eagle_1001_fly_right', + 'whalesbot_eagle_1001_turn_left', + 'whalesbot_eagle_1001_turn_right', + 'whalesbot_eagle_1001_fly_in_the_specified_direction', + 'whalesbot_eagle_1001_flight_designated', + 'whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control', + 'whalesbot_eagle_1001_stop_moving_and_hover', + 'whalesbot_eagle_1001_hover_at_specified_altitude', + 'whalesbot_eagle_1001_emergency_stop', + 'whalesbot_eagle_1001_set_the_steering_gear', + 'whalesbot_eagle_1001_execute_script', + 'whalesbot_eagle_1001_clean', + 'whalesbot_eagle_1001_restart' +]; + +// 블록 생성 +Entry.WhalesbotEagle1001.getBlocks = function() { + let _this = this; + let sourceCode; + + const defaultSpeed = "10"; + const defaultAltitude = "50"; + const defaultOffset = "0"; + + const wbOperators = { + "EQUAL": "==", + "NOT_EQUAL": "!=", + "GREATER": ">", + "GREATER_OR_EQUAL": ">=", + "LESS": "<", + "LESS_OR_EQUAL": "<=", + "AND": "&&", + "OR": "||", + }; + + const wbVariables = { + "whalesbot_eagle_1001_get_setting_speed": "fly_state(SETSPEED)" + } + + const startBlocks = [ + "when_run_button_click", + "when_some_key_pressed", + "mouse_clicked", + "mouse_click_cancled", + "when_object_click", + "when_object_click_canceled", + ] + + let globlalCVariables = {} + + function _getParameter (parameter) { + let param = parameter.params[0] != "" ? parameter.params[0] : "0" + if (parameter.type != "text" && parameter.type != "number" && parameter.type != "get_variable") { + param = wbVariables[parameter.type] + } else if (parameter.type == "get_variable") { + param = globlalCVariables[parameter.params[0]] + } + return param + } + + function _generateConditions (params) { + let left = _getParameter(params[0]) + let operator = params[1] != undefined ? wbOperators[params[1]] : "0" + let right = _getParameter(params[2]) + return { left, operator, right } + } + + function generateCCode (block) { + switch (block.type) { + // LOOP + case 'repeat_basic': + let times = _getParameter(block.params[0]); + return `\tfor(int i=0; i<${times}; ++i) {\n${block.statements[0].map((generateCCode)).join('')}\t}\n`; + + case 'repeat_inf': + return `\twhile(1) {\n${block.statements[0].map(generateCCode).join('')}\t}\n`; + + case 'repeat_while_true': + let rpWhileDecision = { + "type": block.params[0].type, + "params": block.params[0].params, + }; + return `\twhile(!(${generateCCode(rpWhileDecision)})) {\n${block.statements[0].map(generateCCode).join('')}\t}\n`; + + case 'wait_second': + let second = _getParameter(block.params[0]); + return `\twait(${second});\n`; + + case 'wait_until_true': + let waitUntilTrueDecision = { + "type": block.params[0].type, + "params": block.params[0].params, + }; + return `\twhile(!(${generateCCode(waitUntilTrueDecision)})) {\n\t}\n`; + + case 'stop_repeat': + return `\tbreak;\n`; + + // CONDITION + case '_if': + let ifDecision = { + "type": block.params[0].type, + "params": block.params[0].params, + }; + return `\tif(${generateCCode(ifDecision)}) {\n${block.statements[0].map(generateCCode).join('')}\t}\n`; + + case 'if_else': + let ifElseDecision = { + "type": block.params[0].type, + "params": block.params[0].params, + }; + return `\tif(${generateCCode(ifElseDecision)}) {\n${block.statements[0].map(generateCCode).join('')}\t} else {\n${block.statements[1].map(generateCCode).join('')}\t}\n`; + + // DECISION + case 'boolean_and_or': + let boolAndOrBasicLeftValue = generateCCode(block.params[0]); + let boolAndOrBasicOperator = wbOperators[block.params[1]]; + let boolAndOrBasicRightValue = generateCCode(block.params[2]); + return `(${boolAndOrBasicLeftValue} ${boolAndOrBasicOperator} ${boolAndOrBasicRightValue})`; + + case 'boolean_not': + let boolNotDecision = generateCCode(block.params[1]); + return `!(${boolNotDecision})`; + + case 'boolean_basic_operator': + let boolBasicCondition = "0" + if (block.params[0].params[0] != null) { + let boolBasicLeftValue = _generateConditions(block.params).left; + let boolBasicOperator = _generateConditions(block.params).operator; + let boolBasicRightValue = _generateConditions(block.params).right; + boolBasicCondition = `(${boolBasicLeftValue} ${boolBasicOperator} ${boolBasicRightValue})`; + } + return `${boolBasicCondition}`; + + // VARIABLE + case 'True': + return "0"; + + case 'False': + return "0"; + + case 'set_variable': + let variableName = globlalCVariables[block.params[0]]; + let variableValue = _getParameter(block.params[1]); + return `\t${variableName} = ${variableValue};\n`; + + case 'change_variable': + let changedVariableName = globlalCVariables[block.params[0]]; + let changedVariableValue = _getParameter(block.params[1]); + return `\t${changedVariableName} += ${changedVariableValue};\n`; + + // HARDWARE + case 'whalesbot_eagle_1001_entering_pitch_mode': + return '\tfly_unlock();\n'; + + case 'whalesbot_eagle_1001_exit_pitch_mode': + return '\tfly_lock();\n'; + + case 'whalesbot_eagle_1001_automatic_take_off_height': + let takeOffHeight = _getParameter(block.params[0]); + return `\tfly_start(${takeOffHeight});\n`; + + case 'whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset': + let takeOffAltitude = _getParameter(block.params[0]) != "" ? _getParameter(block.params[0]) : defaultAltitude; + let takeOffSpeed = _getParameter(block.params[1]) != "" ? _getParameter(block.params[1]) : defaultSpeed; + let takeOffXoffset = (-10.00 <= _getParameter(block.params[2]) || _getParameter(block.params[2]) <= 10.00) ? _getParameter(block.params[2]) : defaultOffset; + let takeOffYoffset = (-10.00 <= _getParameter(block.params[3]) || _getParameter(block.params[3]) <= 10.00) ? _getParameter(block.params[3]) : defaultOffset; + return `\tfly_start_2(${takeOffAltitude},${takeOffSpeed},${takeOffXoffset},${takeOffYoffset});\n` + + case 'whalesbot_eagle_1001_automatic_landing': + return `\tfly_land();\n`; + + case 'whalesbot_eagle_1001_automatic_descent_speed_offset': + let automaticSpeed = _getParameter(block.params[0]) != "" ? _getParameter(block.params[0]) : defaultSpeed; + let automaticXoffset = (-10.00 <= _getParameter(block.params[1]) || _getParameter(block.params[1]) <= 10.00) ? _getParameter(block.params[1]) : defaultOffset; + let automaticYoffset = (-10.00 <= _getParameter(block.params[2]) || _getParameter(block.params[2]) <= 10.00) ? _getParameter(block.params[2]) : defaultOffset; + return `\tfly_land_2(${automaticSpeed},${automaticXoffset},${automaticYoffset});\n` + + case 'whalesbot_eagle_1001_set_the_flight_speed': + let speed = _getParameter(block.params[0]); + return `\tfly_setspeed(${speed});\n`; + + case 'whalesbot_eagle_1001_get_setting_speed': + return `\tfly_state(SETSPEED);\n`; + + case 'whalesbot_eagle_1001_rise': + let up = _getParameter(block.params[0]); + return `\tfly_moveto(UP,${up});\n`; + + case 'whalesbot_eagle_1001_down': + let down = _getParameter(block.params[0]); + return `\tfly_moveto(DOWN,${down});\n`; + + case 'whalesbot_eagle_1001_fly_forward': + let front = _getParameter(block.params[0]); + return `\tfly_moveto(FRONT,${front});\n`; + + case 'whalesbot_eagle_1001_fly_backward': + let back = _getParameter(block.params[0]); + return `\tfly_moveto(BACK,${back});\n`; + + case 'whalesbot_eagle_1001_fly_left': + let left = _getParameter(block.params[0]); + return `\tfly_moveto(LEFT,${left});\n`; + + case 'whalesbot_eagle_1001_fly_right': + let right = _getParameter(block.params[0]); + return `\tfly_moveto(RIGHT,${right});\n`; + + case 'whalesbot_eagle_1001_turn_left': + let turnLeft = _getParameter(block.params[0]); + if (0 > turnLeft || turnLeft > 360) { + turnLeft = 360 + } + return `\tfly_turn(CCW,${turnLeft});\n`; + + case 'whalesbot_eagle_1001_turn_right': + let turnRight = _getParameter(block.params[0]); + if (0 > turnRight || turnRight > 360) { + turnRight = 360 + } + return `\tfly_turn(CW,${turnRight});\n`; + + case 'whalesbot_eagle_1001_fly_in_the_specified_direction': + let dirSpeed = _getParameter(block.params[0]); + let dirDirection = _getParameter(block.params[1]); + if (0 > dirDirection || dirDirection > 360) { + dirDirection = 360 + } + return `\tfly_dir(${dirSpeed},${dirDirection});\n`; + + case 'whalesbot_eagle_1001_flight_designated': + let disX = _getParameter(block.params[0]); + let disY = _getParameter(block.params[1]); + let disZ = _getParameter(block.params[2]); + let disSpeed = _getParameter(block.params[3]); + return `\tfly_move_dis(${disX},${disY},${disZ},${disSpeed});\n`; + + case 'whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control': + let pitch = _getParameter(block.params[0]); + let roll = _getParameter(block.params[1]); + let throttle = _getParameter(block.params[2]); + let yaw = _getParameter(block.params[3]); + return `\tfly_move(${pitch},${roll},${throttle},${yaw});\n`; + + case 'whalesbot_eagle_1001_stop_moving_and_hover': + return `\tfly_hover();\n`; + + case 'whalesbot_eagle_1001_hover_at_specified_altitude': + let hoverSpecifiedAltitude = (_getParameter(block.params[0]) == "" || _getParameter(block.params[0]) < 20) ? "20" : _getParameter(block.params[0]); + hoverSpecifiedAltitude = (_getParameter(block.params[0]) > 200) ? "200" : _getParameter(block.params[0]); + return `\tfly_hover_laser(${hoverSpecifiedAltitude});\n`; + + case 'whalesbot_eagle_1001_emergency_stop': + return `\tfly_lock();\n`; + + case 'whalesbot_eagle_1001_set_the_steering_gear': + let servoSpeed = _getParameter(block.params[1]); + let servoAngle = _getParameter(block.params[2]); + if (0 > servoAngle || servoAngle > 360) { + servoAngle = 360 + } + return `\tSetServo(P2,${servoSpeed},${servoAngle});\n`; + + default: + if (!startBlocks.includes(block.type)) { + _this.unsupportBlockExist = true; + } + return ''; + } + } + + function setUpCVariables (variable) { + if (variable.visible) { + const varName = `var_${variable.name}` + globlalCVariables[variable.id] = varName + const varValue = variable.value; + return `float ${varName} = ${varValue};\n` + } + return "" + } + + function openedSimulatorPopup () { + if (_this.simulatorPopup == null) { + return false; + } + return !_this.simulatorPopup.closed; + } + + return { + whalesbot_eagle_1001_openning_3d_simulator: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_eagle_1001_openning_3d_simulator', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func (sprite, script) { + const width = window.innerWidth * 0.8; + const height = window.innerHeight * 0.8; + _this.simulatorPopup = window.open( + metadata.simulator_url, + 'DroneSimulatorPopup', + `width=${width},height=${height}` + ); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_openning_3d_simulator()'] }, + }, + whalesbot_eagle_1001_restart: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/moving_icon.svg', + size: 11, + }, + ], + events: {}, + def: { + type: 'whalesbot_eagle_1001_restart', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func (sprite, script) { + _this.sendCmd('restartCode'); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_restart()'] }, + }, + whalesbot_eagle_1001_clean: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/moving_icon.svg', + size: 11, + }, + ], + events: {}, + def: { + type: 'whalesbot_eagle_1001_clean', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func (sprite, script) { + _this.sendCmd('stopCode'); + Entry.toast.success( + Lang.Blocks.whalesbot_eagle_1001_toast_status_title, + Lang.Blocks.whalesbot_eagle_1001_toast_clean_success + ); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_clean()'] }, + }, + whalesbot_eagle_1001_entering_pitch_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_eagle_1001_entering_pitch_mode', + }, + paramsKeyMap: {}, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func (sprite, script) { + // console.log("whalesbot_eagle_1001_entering_pitch_mode"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_entering_pitch_mode()'] }, + }, + whalesbot_eagle_1001_exit_pitch_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_eagle_1001_exit_pitch_mode', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + const project = _this.exportProject(); + const listVariables = project.variables; + const rawScript = project.objects[0].script; + const allScript = JSON.parse(rawScript); + const droneScript = allScript.filter((arr) => arr.length > 2); + + let sourceCode = `#include "whalesbot.h"\n${listVariables.map(setUpCVariables).join('')}\nvoid user_main() {\n`; + sourceCode += `${droneScript[0].map(generateCCode).join('')}}\n\nuser_main();`; + + if (_this.unsupportBlockExist) { + Entry.toast.alert( + Lang.Blocks.whalesbot_eagle_1001_toast_unsupport_block_title, + Lang.Blocks.whalesbot_eagle_1001_toast_unsupport_block_msg + ) + _this.unsupportBlockExist = false; + Entry.engine.toggleStop(); + return; + } + + // console.log(sourceCode) + + if (openedSimulatorPopup()) { + Entry.toast.success( + Lang.Blocks.whalesbot_eagle_1001_toast_status_title, + Lang.Blocks.whalesbot_eagle_1001_toast_download_success + ); + return; + } + + _this.sendCmd(sourceCode); + + Entry.toast.success( + Lang.Blocks.whalesbot_drone_toast_status_title, + Lang.Blocks.whalesbot_drone_toast_download_success + ); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_exit_pitch_mode()'] }, + }, + whalesbot_eagle_1001_automatic_take_off_height: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_eagle_1001_automatic_take_off_height', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_automatic_take_off_height") + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_automatic_take_off_height();'] }, + }, + whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset: { + 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', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + ], + type: 'whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset', + }, + paramsKeyMap: { + altitude: 0, + speed: 1, + x: 2, + y: 3, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset") + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_automatic_take_off_altitude_speed_offset();'] }, + }, + whalesbot_eagle_1001_automatic_landing: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_eagle_1001_automatic_landing', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_automatic_landing") + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_automatic_landing()'] }, + }, + whalesbot_eagle_1001_automatic_descent_speed_offset: { + 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', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_eagle_1001_automatic_descent_speed_offset', + }, + paramsKeyMap: { + speed: 0, + x: 1, + y: 2, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_automatic_descent_speed_offset") + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_automatic_descent_speed_offset()'] }, + }, + whalesbot_eagle_1001_set_the_flight_speed: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + ], + type: 'whalesbot_eagle_1001_set_the_flight_speed', + }, + paramsKeyMap: { + SPEED: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_set_the_flight_speed") + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_set_the_flight_speed()'] }, + }, + whalesbot_eagle_1001_get_setting_speed: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [], + events: {}, + def: { + type: 'whalesbot_eagle_1001_get_setting_speed', + }, + paramsKeyMap: {}, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_get_setting_speed"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_get_setting_speed()'] }, + }, + whalesbot_eagle_1001_rise: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_eagle_1001_rise', + }, + paramsKeyMap: { + value: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_rise"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_rise();'] }, + }, + whalesbot_eagle_1001_down: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_eagle_1001_down', + }, + paramsKeyMap: { + value: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_down"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_down();'] }, + }, + whalesbot_eagle_1001_fly_forward: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_eagle_1001_fly_forward', + }, + paramsKeyMap: { + value: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_fly_forward"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_forward();'] }, + }, + whalesbot_eagle_1001_fly_backward: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_eagle_1001_fly_backward', + }, + paramsKeyMap: { + value: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_fly_backward"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_backward();'] }, + }, + whalesbot_eagle_1001_fly_left: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_eagle_1001_fly_left', + }, + paramsKeyMap: { + value: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_fly_left"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_left();'] }, + }, + whalesbot_eagle_1001_fly_right: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_eagle_1001_fly_right', + }, + paramsKeyMap: { + value: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_fly_right"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_right();'] }, + }, + whalesbot_eagle_1001_turn_left: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['90'], + }, + ], + type: 'whalesbot_eagle_1001_turn_left', + }, + paramsKeyMap: { + value: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_turn_left"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_turn_left();'] }, + }, + whalesbot_eagle_1001_turn_right: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['90'], + }, + ], + type: 'whalesbot_eagle_1001_turn_right', + }, + paramsKeyMap: { + value: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_turn_right"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_turn_right();'] }, + }, + whalesbot_eagle_1001_fly_in_the_specified_direction: { + 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', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['30'], + }, + { + type: 'number', + params: ['0'], + }, + ], + type: 'whalesbot_eagle_1001_fly_in_the_specified_direction', + }, + paramsKeyMap: { + speed: 0, + direction: 1, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_fly_in_the_specified_direction"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_fly_in_the_specified_direction();'] }, + }, + whalesbot_eagle_1001_flight_designated: { + 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', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['30'], + }, + ], + type: 'whalesbot_eagle_1001_flight_designated', + }, + paramsKeyMap: { + x: 0, + y: 1, + z: 2, + speed: 3, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_flight_designated"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_flight_designated();'] }, + }, + whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control: { + 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', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + ], + type: 'whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control', + }, + paramsKeyMap: { + pitch: 0, + roll: 1, + throttle: 2, + yaw: 3, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_set_the_four_channel_lever_quantity_of_remote_control();'] }, + }, + whalesbot_eagle_1001_stop_moving_and_hover: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [], + events: {}, + def: { + params: [], + type: 'whalesbot_eagle_1001_stop_moving_and_hover', + }, + paramsKeyMap: {}, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_stop_moving_and_hover"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_stop_moving_and_hover();'] }, + }, + whalesbot_eagle_1001_hover_at_specified_altitude: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['20'], + }, + ], + type: 'whalesbot_eagle_1001_hover_at_specified_altitude', + }, + paramsKeyMap: { + altitude: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_hover_at_specified_altitude"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_hover_at_specified_altitude();'] }, + }, + whalesbot_eagle_1001_emergency_stop: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [], + events: {}, + def: { + type: 'whalesbot_eagle_1001_emergency_stop', + }, + paramsKeyMap: {}, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_emergency_stop") + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_emergency_stop()'] }, + }, + whalesbot_eagle_1001_set_the_steering_gear: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['P2', 'P2'], + ], + value: 'P2', + fontSize: 10, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['40'], + }, + { + type: 'number', + params: ['90'], + }, + ], + type: 'whalesbot_eagle_1001_set_the_steering_gear', + }, + paramsKeyMap: { + port: 0, + speed: 1, + angle: 2, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + // console.log("whalesbot_eagle_1001_set_the_steering_gear"); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_set_the_steering_gear();'] }, + }, + whalesbot_eagle_1001_execute_script: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/moving_icon.svg', + size: 11, + }, + ], + events: {}, + def: { + type: 'whalesbot_eagle_1001_execute_script', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'whalesbot_eagle_1001', + isNotFor: ['whalesbot_eagle_1001'], + func(sprite, script) { + if (openedSimulatorPopup()) { + _this.simulatorPopup.postMessage({ + script: sourceCode + }, '*'); + return; + } + _this.sendCmd('runCode'); + }, + syntax: { js: [], py: ['Entry.whalesbot_eagle_1001_execute_script()'] }, + }, + }; +}; + +module.exports = Entry.WhalesbotEagle1001; diff --git a/src/playground/blocks/hardwareLite/block_codewiz_lite.js b/src/playground/blocks/hardwareLite/block_codewiz_lite.js index ab40ebcc77..2abc6b12bc 100644 --- a/src/playground/blocks/hardwareLite/block_codewiz_lite.js +++ b/src/playground/blocks/hardwareLite/block_codewiz_lite.js @@ -1,6 +1,6 @@ 'use strict'; -(function() { +(function () { Entry.CodeWizLite = new (class CodeWizLite { constructor() { this.id = '011201'; @@ -245,7 +245,7 @@ this.HUSKY = { CENT_X: 160, CENT_Y: 120, - getDist: function(x, y) { + getDist: function (x, y) { return Math.sqrt(Math.pow(this.CENT_X - x, 2) + Math.pow(this.CENT_Y - y, 2)); }, }; @@ -385,11 +385,7 @@ // } // return Entry.generateHash(6) + opcode; // Symbol을 쓰면 hw로 넘길수있나 -> 있으면 지금과 비교해서 속도는? - return ( - Date.now() - .toString() - .substring(6) + opcode - ); + return Date.now().toString().substring(6) + opcode; } // 코드위즈에 보낼 데이터를 만드는 함수입니다. @@ -954,7 +950,7 @@ }, isNotFor: ['CodeWizLite'], class: 'CodeWizLite_default_sensor', - func: function(sprite, script) { + func: function (sprite, script) { var sensor = script.getField('SENSOR', script); var hw_sensorData = Entry.CodeWizLite.sensorData; return hw_sensorData[sensor] ?? 0; @@ -989,7 +985,7 @@ }, isNotFor: ['CodeWizLite'], class: 'CodeWizLite_default_sensor', - func: function(sprite, script) { + func: function (sprite, script) { var sensor = script.getField('GYRO_TYPE', script); var hw_sensorData = Entry.CodeWizLite.sensorData; return hw_sensorData[sensor] ?? 0; @@ -1025,7 +1021,7 @@ }, isNotFor: ['CodeWizLite'], class: 'CodeWizLite_default_sensor', - func: function(sprite, script) { + func: function (sprite, script) { var sensor = script.getField('SWITCH', script); var hw_sensorData = Entry.CodeWizLite.sensorData; return hw_sensorData[sensor] ?? false; @@ -1065,7 +1061,7 @@ }, isNotFor: ['CodeWizLite'], class: 'CodeWizLite_default_sensor', - func: function(sprite, script) { + func: function (sprite, script) { var sensor = script.getField('SWITCH', script); var hw_sensorData = Entry.CodeWizLite.sensorData; return hw_sensorData[sensor] ?? 0; diff --git a/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js b/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js index a8b6c78a22..a0a1deda00 100644 --- a/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js +++ b/src/playground/blocks/hardwareLite/block_neo_cannon_lite.js @@ -1,6 +1,6 @@ 'use strict'; -(function() { +(function () { Entry.NeoCannonLite = new (class NeoCannonLite { constructor() { this.id = '410201'; @@ -30,6 +30,11 @@ 'neocannonlite_rgb_led_color_picker', 'neocannonlite_rgb_led_pwm', 'neocannonlite_rgb_led_off', + 'neocannonlite_neopixel_color_picker', + 'neocannonlite_neopixel_color_picker_all_on', + 'neocannonlite_neopixel', + 'neocannonlite_neopixel_all_on', + 'neocannonlite_neopixel_all_off', ]; this.portData = { baudRate: 115200, @@ -41,7 +46,7 @@ constantServing: true, }; this.__toneTable = { - '0': 0, + 0: 0, C: 1, CS: 2, D: 3, @@ -56,18 +61,18 @@ B: 12, }; this.__toneMap = { - '1': [33, 65, 131, 262, 523, 1046, 2093, 4186], - '2': [35, 69, 139, 277, 554, 1109, 2217, 4435], - '3': [37, 73, 147, 294, 587, 1175, 2349, 4699], - '4': [39, 78, 156, 310, 622, 1245, 2637, 4978], - '5': [41, 82, 165, 330, 659, 1319, 2794, 5274], - '6': [44, 87, 175, 349, 698, 1397, 2849, 5588], - '7': [46, 92, 185, 370, 740, 1480, 2960, 5920], - '8': [49, 98, 196, 392, 784, 1568, 3136, 6272], - '9': [52, 104, 208, 415, 831, 1661, 3322, 6645], - '10': [55, 110, 220, 440, 880, 1760, 3520, 7040], - '11': [58, 117, 233, 466, 932, 1865, 3729, 7459], - '12': [62, 123, 247, 494, 988, 1976, 3951, 7902], + 1: [33, 65, 131, 262, 523, 1046, 2093, 4186], + 2: [35, 69, 139, 277, 554, 1109, 2217, 4435], + 3: [37, 73, 147, 294, 587, 1175, 2349, 4699], + 4: [39, 78, 156, 310, 622, 1245, 2637, 4978], + 5: [41, 82, 165, 330, 659, 1319, 2794, 5274], + 6: [44, 87, 175, 349, 698, 1397, 2849, 5588], + 7: [46, 92, 185, 370, 740, 1480, 2960, 5920], + 8: [49, 98, 196, 392, 784, 1568, 3136, 6272], + 9: [52, 104, 208, 415, 831, 1661, 3322, 6645], + 10: [55, 110, 220, 440, 880, 1760, 3520, 7040], + 11: [58, 117, 233, 466, 932, 1865, 3729, 7459], + 12: [62, 123, 247, 494, 988, 1976, 3951, 7902], }; this.setZero(); } @@ -93,7 +98,7 @@ } setZero() { - this.txData = new Array(14).fill(0); + this.txData = new Array(68).fill(0); this.sensorData = { VIBE: 0, @@ -107,6 +112,26 @@ D9: 0, D10: 0, ANGLE: 0, + NEOPIXEL: [ + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + { RED: 0, GREEN: 0, BLUE: 0 }, + ], }; if (Entry.hwLite && Entry.hwLite.serial) { @@ -161,9 +186,10 @@ const txData = this.txData; let checkSum = 0; const dataLen = txData.length; + const pixelNum = 18; txData[0] = 0xff; - txData[1] = 0x0e; + txData[1] = 0x44; txData[2] = 0x01; txData[3] = 0x03; txData[4] = workerData.OCTAVE; @@ -174,7 +200,12 @@ txData[9] = workerData.D9; txData[10] = workerData.D10; txData[11] = workerData.ANGLE; - txData[13] = 0xa; + for (let i = 0; i < pixelNum; i++) { + txData[i * 3 + 12] = workerData.NEOPIXEL[i].RED; + txData[i * 3 + 13] = workerData.NEOPIXEL[i].GREEN; + txData[i * 3 + 14] = workerData.NEOPIXEL[i].BLUE; + } + txData[dataLen - 1] = 0xa; for (let i = 2; i < dataLen - 2; i++) { checkSum += txData[i]; @@ -471,6 +502,76 @@ return script.callReturn(); } + setNeopixel(script) { + let num = script.getNumberValue('NUM', script); + const redPower = script.getNumberValue('RED', script); + const greenPower = script.getNumberValue('GREEN', script); + const bluePower = script.getNumberValue('BLUE', script); + + num = num % 18; + + this.workerData.NEOPIXEL[num].RED = redPower; + this.workerData.NEOPIXEL[num].GREEN = greenPower; + this.workerData.NEOPIXEL[num].BLUE = bluePower; + return script.callReturn(); + } + + setAllNeopixel(script) { + const redPower = script.getNumberValue('RED', script); + const greenPower = script.getNumberValue('GREEN', script); + const bluePower = script.getNumberValue('BLUE', script); + + for (let num = 0; num < 18; num++) { + this.workerData.NEOPIXEL[num].RED = redPower; + this.workerData.NEOPIXEL[num].GREEN = greenPower; + this.workerData.NEOPIXEL[num].BLUE = bluePower; + } + + return script.callReturn(); + } + + setNeopixelPicker(script) { + let num = script.getNumberValue('NUM', script); + const color = script.getStringField('COLOR'); + + num = num % 18; + + const redPower = parseInt(color.substr(1, 2), 16); + const greenPower = parseInt(color.substr(3, 2), 16); + const bluePower = parseInt(color.substr(5, 2), 16); + + this.workerData.NEOPIXEL[num].RED = redPower; + this.workerData.NEOPIXEL[num].GREEN = greenPower; + this.workerData.NEOPIXEL[num].BLUE = bluePower; + return script.callReturn(); + } + + setAllNeopixelPicker(script) { + const color = script.getStringField('COLOR'); + + const redPower = parseInt(color.substr(1, 2), 16); + const greenPower = parseInt(color.substr(3, 2), 16); + const bluePower = parseInt(color.substr(5, 2), 16); + + for (let num = 0; num < 18; num++) { + this.workerData.NEOPIXEL[num].RED = redPower; + this.workerData.NEOPIXEL[num].GREEN = greenPower; + this.workerData.NEOPIXEL[num].BLUE = bluePower; + } + + return script.callReturn(); + } + + setNeopixelOff(script) { + for (let num = 0; num < 18; num++) { + this.workerData.NEOPIXEL[num].RED = 0; + this.workerData.NEOPIXEL[num].GREEN = 0; + this.workerData.NEOPIXEL[num].BLUE = 0; + } + + return script.callReturn(); + } + // Block setLanguage() { return { @@ -493,6 +594,13 @@ neocannonlite_rgb_led_color_picker: 'RGB LED %1 %2', neocannonlite_rgb_led_pwm: 'RGB LED 빨강 %1 초록 %2 파랑 %3 %4', neocannonlite_rgb_led_off: 'RGB LED 끄기 %1', + neocannonlite_neopixel_color_picker: '네오픽셀 %1번 %2 (으)로 켜기 %3', + neocannonlite_neopixel: '네오픽셀 %1번 빨 %2 녹 %3 파 %4 (으)로 켜기 %5', + neocannonlite_neopixel_color_picker_all_on: + '네오픽셀 전체 %1 (으)로 켜기 %2', + neocannonlite_neopixel_all_on: + '네오픽셀 전체 빨 %1 녹 %2 파 %3 (으)로 켜기 %4', + neocannonlite_neopixel_all_off: '네오픽셀 전체 끄기 %1', }, Device: { neocannonlite: '네오캐논', @@ -520,6 +628,11 @@ neocannonlite_rgb_led_color_picker: 'RGB LED %1 %2', neocannonlite_rgb_led_pwm: 'RGB LED R %1 G %2 B %3 %4', neocannonlite_rgb_led_off: 'RGB LED OFF', + neocannonlite_neopixel_color_picker: 'Neopixel number %1 turn on %2 %3', + neocannonlite_neopixel: 'Neopixel number %1 turn on R %2 G %3 B %4 %5', + neocannonlite_neopixel_color_picker_all_on: 'All Neopixel turn on %1 %2', + neocannonlite_neopixel_all_on: 'All Neopixel turn on R %1 G %2 B %3 %4', + neocannonlite_neopixel_all_off: 'All Neopixel turn off %1', }, Device: { neocannonlite: 'neocannonlite', @@ -1604,6 +1717,314 @@ ], }, }, + neocannonlite_neopixel_color_picker: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + null, + null, + ], + type: 'neocannonlite_neopixel_color_picker', + }, + paramsKeyMap: { + NUM: 0, + COLOR: 1, + }, + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], + func(sprite, script) { + return Entry.NeoCannonLite.setNeopixelPicker(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannonLite.neopixelColorPicker(%1, %2)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neocannonlite_neopixel: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + null, + ], + type: 'neocannonlite_neopixel', + }, + paramsKeyMap: { + NUM: 0, + RED: 1, + GREEN: 2, + BLUE: 3, + }, + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], + func(sprite, script) { + return Entry.NeoCannonLite.setNeopixel(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannonLite.neopixel(%1, %2, %3, %4)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neocannonlite_neopixel_color_picker_all_on: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Color', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'neocannonlite_neopixel_color_picker_all_on', + }, + paramsKeyMap: { + COLOR: 0, + }, + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], + func(sprite, script) { + return Entry.NeoCannonLite.setAllNeopixelPicker(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannonLite.neopixelColorPickerAllOn(%1)', + textParams: [ + { + type: 'Color', + converter: Entry.block.converters.returnStringValue, + }, + ], + }, + ], + }, + }, + neocannonlite_neopixel_all_on: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['100'], + }, + null, + ], + type: 'neocannonlite_neopixel_all_on', + }, + paramsKeyMap: { + RED: 0, + GREEN: 1, + BLUE: 2, + }, + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], + func(sprite, script) { + return Entry.NeoCannonLite.setAllNeopixel(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannonLite.neopixelAllON(%1, %2, %3)', + textParams: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + ], + }, + ], + }, + }, + neocannonlite_neopixel_all_off: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'neocannonlite_neopixel_all_off', + }, + paramsKeyMap: {}, + class: 'NeoCannonLiteNeopixel', + isNotFor: ['NeoCannonLite'], + func(sprite, script) { + return Entry.NeoCannonLite.setNeopixelOff(script); + }, + syntax: { + js: [], + py: [ + { + syntax: 'NeoCannonLite.neopixelAllOFF()', + textParams: [], + }, + ], + }, + }, }; } })(); diff --git a/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js b/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js new file mode 100644 index 0000000000..420a9d2edc --- /dev/null +++ b/src/playground/blocks/hardwareLite/block_robotis_robotai_lite.js @@ -0,0 +1,7689 @@ +'use strict'; + +const INST_NONE = 0; +const INST_READ = 2; +const INST_WRITE = 3; +const INST_DXL_SYNCWRITE = 4; +const INST_DXL_REGWRITE = 5; +const INST_DXL_ACTION = 6; +const INST_BYPASS_READ = 0xa2; +const INST_BYPASS_WRITE = 0xa3; + +const INST_STATUS = 0x55; + +const PACKET_STATE_IDLE = 0; +const PACKET_STATE_RESERVED = 1; +const PACKET_STATE_ID = 2; +const PACKET_STATE_LENGTH_L = 3; +const PACKET_STATE_LENGTH_H = 4; +const PACKET_STATE_DATA = 5; +const PACKET_STATE_CRC_L = 6; +const PACKET_STATE_CRC_H = 7; + +const DEFAULT_DELAY = 50; + +const rxPacket = { + header: [0, 0, 0], + reserved: 0, + id: 0, + cmd: 0, + error: 0, + type: 0, + index: 0, + packetLength: 0, + paramLength: 0, + crc: 0, + crcReceived: 0, + checksum: 0, + checksumReceived: 0, + data: [], +}; + +const addrMap = [ + [0, 4, 302], + [4, 1, 42], + [5, 1, 44], + [6, 1, 45], + [7, 1, 47], + [8, 1, 50], + [9, 1, 51], + [10, 1, 52], + [11, 1, 68], + [12, 2, 70], + [14, 2, 72], + [16, 2, 74], + [18, 2, 76], + [20, 2, 78], + [22, 2, 80], + [24, 2, 82], + [26, 2, 84], + [28, 1, 86], + [29, 1, 87], + [30, 2, 88], + [32, 2, 90], + [34, 1, 112], + [35, 1, 118], + [36, 1, 119], + [37, 1, 122], + [38, 1, 123], + [39, 1, 124], + [40, 1, 125], + [41, 1, 160], + [42, 1, 220], + [43, 2, 360], + [45, 2, 362], + [47, 2, 364], + [49, 2, 366], + [51, 2, 368], + [53, 2, 370], + [55, 1, 372], + [56, 1, 373], + [57, 1, 374], + [58, 1, 375], + [59, 1, 376], + [60, 1, 377], + [61, 1, 378], + [62, 1, 379], + [63, 1, 380], + [64, 1, 381], + [65, 1, 382], + [66, 1, 383], + [67, 1, 500], + [68, 1, 501], + [69, 8, 502], + [77, 1, 700], + [78, 1, 810], + [79, 1, 2134], + [80, 1, 5015], + [81, 1, 5030], + [82, 1, 5031], + [83, 1, 5040], +]; + +const addrMap2 = [ + [153, 1, 4000], + [154, 2, 4003], + [156, 1, 4005], + [157, 1, 4006], + [158, 2, 4009], + [160, 2, 4011], + [162, 2, 4013], + [164, 2, 4015], + [166, 2, 4017], + [168, 2, 4019], + [170, 2, 4021], + [172, 2, 4023], + [174, 2, 4025], + [176, 2, 4027], + [178, 1, 4031], + [179, 1, 4032], + [180, 1, 4033], + [181, 2, 4036], + [183, 2, 4038], + [185, 2, 4040], + [187, 2, 4042], + [189, 2, 4044], + [191, 2, 4046], + [193, 2, 4048], + [195, 2, 4050], +]; + +const crcTable = [ + 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011, 0x8033, 0x0036, 0x003c, 0x8039, + 0x0028, 0x802d, 0x8027, 0x0022, 0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072, + 0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041, 0x80c3, 0x00c6, 0x00cc, 0x80c9, + 0x00d8, 0x80dd, 0x80d7, 0x00d2, 0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1, + 0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1, 0x8093, 0x0096, 0x009c, 0x8099, + 0x0088, 0x808d, 0x8087, 0x0082, 0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192, + 0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1, 0x01e0, 0x81e5, 0x81ef, 0x01ea, + 0x81fb, 0x01fe, 0x01f4, 0x81f1, 0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2, + 0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151, 0x8173, 0x0176, 0x017c, 0x8179, + 0x0168, 0x816d, 0x8167, 0x0162, 0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132, + 0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101, 0x8303, 0x0306, 0x030c, 0x8309, + 0x0318, 0x831d, 0x8317, 0x0312, 0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321, + 0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371, 0x8353, 0x0356, 0x035c, 0x8359, + 0x0348, 0x834d, 0x8347, 0x0342, 0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1, + 0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2, 0x83a3, 0x03a6, 0x03ac, 0x83a9, + 0x03b8, 0x83bd, 0x83b7, 0x03b2, 0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381, + 0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291, 0x82b3, 0x02b6, 0x02bc, 0x82b9, + 0x02a8, 0x82ad, 0x82a7, 0x02a2, 0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2, + 0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1, 0x8243, 0x0246, 0x024c, 0x8249, + 0x0258, 0x825d, 0x8257, 0x0252, 0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261, + 0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231, 0x8213, 0x0216, 0x021c, 0x8219, + 0x0208, 0x820d, 0x8207, 0x0202, +]; + +const rb100_last_valid_value = []; +let bg_color = 0; +let beat_per_minute = 75; +let camera_id_for_use = 0; + +(function () { + Entry.RobotisRobotaiLite = new (class RobotisRobotaiLite { + constructor() { + this.id = '070B01'; + this.url = 'http://www.robotis.com'; + this.imageName = 'robotis_robotai_lite.png'; + this.name = 'RobotisRobotaiLite'; + this.blockMenuBlocks = [ + // 주행 제어 + 'robotis_robotai_lite_drive_simple', + 'robotis_robotai_lite_drive_advanced', + 'robotis_robotai_lite_drive_seperate', + 'robotis_robotai_lite_drive_angle', + 'robotis_robotai_lite_go_distance', + 'robotis_robotai_lite_turn_angle', + 'robotis_robotai_lite_follow_line', + 'robotis_robotai_lite_stop_at_cross', + 'robotis_robotai_lite_turn_at_line', + 'robotis_robotai_lite_drive_stop', + + 'robotis_robotai_lite_securitybot_init', + 'robotis_robotai_lite_securitybot_hi', + 'robotis_robotai_lite_securitybot_alert', + + 'robotis_robotai_lite_petbot_happy', + 'robotis_robotai_lite_petbot_sad', + + 'robotis_robotai_lite_farmbot_init', + 'robotis_robotai_lite_farmbot_seek', + 'robotis_robotai_lite_farmbot_plant_type', + 'robotis_robotai_lite_farmbot_harvest_or_not_and_go', + + // 값 블록 + 'robotis_robotai_lite_cm_ir_value', + 'robotis_robotai_lite_detectFrontObj', + 'robotis_robotai_lite_cm_ir_compare', + 'robotis_robotai_lite_cm_btn_value', + 'robotis_robotai_lite_cm_joystick_value', + 'robotis_robotai_lite_mic', + 'robotis_robotai_lite_detectSound_compare', + 'robotis_robotai_lite_imu', + 'robotis_robotai_lite_roll_pitch', + 'robotis_robotai_lite_environment_value', + 'robotis_robotai_lite_line_cross_compare', + //'robotis_robotai_lite_distance_compare', + 'robotis_robotai_lite_environment_compare', + 'robotis_robotai_lite_dxl_value', + + // 소리 + 'robotis_robotai_lite_scale_simple', + 'robotis_robotai_lite_scale_advanced', + 'robotis_robotai_lite_rest_simple', + 'robotis_robotai_lite_rest_advanced', + 'robotis_robotai_lite_beat_per_minute', + 'robotis_robotai_lite_Hello', + 'robotis_robotai_lite_effectSound', + 'robotis_robotai_lite_record', + 'robotis_robotai_lite_playRecord', + + // LCD 제어 + 'robotis_robotai_lite_screen', + 'robotis_robotai_lite_anim_screen', + 'robotis_robotai_lite_icon_screen_food_plant', + 'robotis_robotai_lite_icon_screen_animal_human', + 'robotis_robotai_lite_icon_screen_object_tool', + 'robotis_robotai_lite_icon_screen_vehicle_number', + 'robotis_robotai_lite_text_screen', + 'robotis_robotai_lite_text_screen_redraw', + 'robotis_robotai_lite_pixel', + 'robotis_robotai_lite_LCDColor', + 'robotis_robotai_lite_LCD_Flash', + 'robotis_robotai_lite_LCDBright', + + // LED 제어 + 'robotis_robotai_lite_cm_led', + 'robotis_robotai_lite_cm_led_pattern', + + // 다이나믹셀 제어 + 'robotis_robotai_lite_dxl_set_mode', + 'robotis_robotai_lite_dxl_each_control', + 'robotis_robotai_lite_dxl_set_position', + 'robotis_robotai_lite_dxl_set_rotate', + 'robotis_robotai_lite_dxl_set_multiturn_round', + + // AI 카메라 값 블록 + 'robotis_robotai_lite_ai_camera_connection_status', + 'robotis_robotai_lite_ai_camera_if_detected', + + 'robotis_robotai_lite_ai_camera_block_value_closest_to_center', + 'robotis_robotai_lite_ai_camera_arrow_value_closest_to_center', + 'robotis_robotai_lite_ai_camera_number_of_learned_id', + 'robotis_robotai_lite_ai_camera_block_value_of_id', + 'robotis_robotai_lite_ai_camera_arrow_value_of_id', + + 'robotis_robotai_lite_ai_camera_if_learned_id', + 'robotis_robotai_lite_ai_camera_if_detected_id_type', + + // AI Camera 제어 + 'robotis_robotai_lite_ai_camera_set_mode', + 'robotis_robotai_lite_ai_camera_print_custom_text', + 'robotis_robotai_lite_ai_camera_clear_custom_text', + ]; + this.portData = { + baudRate: 115200, + dataBits: 8, + parity: 'none', + stopBits: 1, + connectionType: 'bytestream', + bufferSize: 128, + constantServing: true, + }; + this.duration = 15; + this.setZero(); + + this.timeouts = []; + + this.robotisBuffer = []; // buffer to transmit to H/W + this.receiveBuffer = []; // buffer to receive from H/W + this.dataBuffer = []; // saved control table value buffer + + this.packetReceiveState = 0; + this.headerCount = 0; + + this.dxlPositions = []; + + this.pirPir = []; + this.pirTemperature = []; + this.pirHumidity = []; + this.pirBrightness = []; + this.distanceDistance = []; + this.distanceButton = []; + this.distanceBrightness = []; + } + + setZero() { + this.timeouts = []; + this.__removeAllTimeouts(); + this.robotisBuffer = []; + this.robotisBuffer.push([INST_WRITE, 2100, 1, 1]); + camera_id_for_use = 0; + if (Entry.hwLite && Entry.hwLite.serial) { + Entry.hwLite.serial.update(); + } + } + + __removeTimeout(id) { + clearTimeout(id); + const idx = this.timeouts.indexOf(id); + if (idx >= 0) { + this.timeouts.splice(idx, 1); + } + } + + __removeAllTimeouts() { + const timeouts = this.timeouts; + for (const i in timeouts) { + clearTimeout(timeouts[i]); + } + this.timeouts = []; + } + + getMonitorPort() { + return { ...this.sensory, ...this.motoring, ...this.lineTracer }; + } + + writePacket(id, address, length, value) { + if (length > 256) { + console.log(`######### invalid length: ${length}`); + return null; + } + console.log('######### writePacket'); + const packet = []; + let i = 0; + packet.push(0xff); + packet.push(0xff); + packet.push(0xfd); + packet.push(0x00); + packet.push(id); + packet.push(length + 5); + packet.push(0x00); + packet.push(INST_WRITE); + packet.push(this.getLowByte(address)); + packet.push(this.getHighByte(address)); + switch (length) { + case 1: + packet.push(this.getLowByte(value)); + break; + case 2: + packet.push(this.getLowByte(value)); + packet.push(this.getHighByte(value)); + break; + case 4: + packet.push(this.getLowByte(this.getLowWord(value))); + packet.push(this.getHighByte(this.getLowWord(value))); + packet.push(this.getLowByte(this.getHighWord(value))); + packet.push(this.getHighByte(this.getHighWord(value))); + break; + default: + for (i = 0; i < length; i++) { + if (typeof value[i] == 'number') { + packet.push(value[i]); + } else if (typeof value[i] == 'string') { + packet.push(value[i].charCodeAt(0)); + } + } + break; + } + const crc = this.updateCRC(0, packet, packet.length); + packet.push(this.getLowByte(crc)); + packet.push(this.getHighByte(crc)); + return packet; + } + + makeWord(a, b) { + return (a & 0xff) | ((b & 0xff) << 8); + } + + getLowByte(a) { + return a & 0xff; + } + + getHighByte(a) { + return (a >> 8) & 0xff; + } + + getLowWord(a) { + return a & 0xffff; + } + + getHighWord(a) { + return (a >> 16) & 0xffff; + } + + updateCRC(crcAccum, dataBlkPtr, dataBlkSize) { + let i = 0; + let j = 0; + let crc = crcAccum; + + for (j = 0; j < dataBlkSize; j++) { + i = ((crc >> 8) ^ dataBlkPtr[j]) & 0xff; + crc = (crc << 8) ^ crcTable[i]; + } + + return crc; + } + + removeStuffing(buffer, length) { + let i = 0; + let stuffLength = 0; + let index = 0; + + for (i = 0; i < length; i++) { + if (i >= 2) { + if (buffer[i - 2] == 0xff && buffer[i - 1] == 0xff && buffer[i] == 0xfd) { + i++; + stuffLength++; + } + } + buffer[index++] = buffer[i]; + } + + return stuffLength; + } + + postCallReturn(script, data, ms) { + /* + if (data == null) { + Entry.engine.isContinue = false; + return script.callReturn(); + } else if (data.length == 0) { + Entry.engine.isContinue = false; + return script.callReturn(); + } + */ + if (!script.isStart) { + script.isStart = true; + script.timeFlag = 1; + for (let i = 0; i < data.length; i++) { + this.robotisBuffer.push(data[i]); + } + //delay ms + setTimeout(() => { + script.timeFlag = 0; + }, ms); + return script; + } else if (script.timeFlag) { + return script; + } else { + delete script.isStart; + delete script.timeFlag; + Entry.engine.isContinue = false; + return script.callReturn(); + } + } + + setLanguage() { + return { + ko: { + template: { + // 주행 제어 + robotis_robotai_lite_drive_simple: '속도 %1 (으)로 %2 하기 %3', + robotis_robotai_lite_drive_advanced: + '왼쪽바퀴 %1 속도로 %2 하기, 오른쪽바퀴 %3 속도로 %4 하기 %5', + robotis_robotai_lite_drive_seperate: + '%1 바퀴 %2 속도로 %3 으로 회전하기 %4', + robotis_robotai_lite_drive_angle: '%1 바퀴 %2 도만큼 %3 으로 회전하기 %4', + robotis_robotai_lite_go_distance: '%1 cm %2 하기 %3', + robotis_robotai_lite_turn_angle: '%1 도 %2 하기%3', + robotis_robotai_lite_follow_line: '%1 속도로 라인 따라가기 %2', + robotis_robotai_lite_stop_at_cross: '교차로 %1 에서 멈추기 %2', + robotis_robotai_lite_turn_at_line: '교차로에서 %1 하고 멈추기 %2', + robotis_robotai_lite_drive_stop: '정지하기 %1', + + robotis_robotai_lite_securitybot_init: '보안로봇 초기화 %1', + robotis_robotai_lite_securitybot_hi: '보안로봇 위아래로 흔들기 %1', + robotis_robotai_lite_securitybot_alert: '보안로봇 좌우로 흔들기 %1', + + robotis_robotai_lite_petbot_happy: '반려로봇 웃음 %1', + robotis_robotai_lite_petbot_sad: '반려로봇 화남 %1', + + robotis_robotai_lite_farmbot_init: '스마트팜 로봇 초기화 %1', + robotis_robotai_lite_farmbot_seek: '농작물 찾기 %1', + robotis_robotai_lite_farmbot_plant_type: '%1 농작물이면', + robotis_robotai_lite_farmbot_harvest_or_not_and_go: '농작물 %1 돌아가기 %2', + + // 값 블록 + robotis_robotai_lite_cm_ir_value: '%1 적외선센서 값', + robotis_robotai_lite_cm_ir_compare: '%1 적외선센서 값이 %2 보다 %3', + robotis_robotai_lite_detectFrontObj: '적외선센서의 %1에 물체가 있으면', // 거리센서를 사용하지 않을 경우 + robotis_robotai_lite_cm_btn_value: '제어기의 %1 버튼을 클릭했을때', + robotis_robotai_lite_cm_joystick_value: + '제어기의 노랑 조이스틱 위치가 %1 이면', + robotis_robotai_lite_mic: '소리의 크기(dB)', + robotis_robotai_lite_detectSound_compare: '소리가 제어기의 %1에서 들리면', + robotis_robotai_lite_imu: '%1축의 %2 값', + robotis_robotai_lite_roll_pitch: '제어기의 %1 값', + robotis_robotai_lite_line_cross_compare: '교차로 모양이 %1이면', + robotis_robotai_lite_environment_value: '%1 값', + robotis_robotai_lite_environment_compare: '%1 값이 %2보다 %3', + robotis_robotai_lite_dxl_value: '%1의 각도값', + + // 소리 + robotis_robotai_lite_scale_simple: '옥타브%1 로 %2 음을 %3로 연주하기 %4', + robotis_robotai_lite_scale_advanced: + '옥타브%1 로 %2 음을 %3박자 연주하기 %4', + robotis_robotai_lite_rest_simple: '%1 %2', + robotis_robotai_lite_rest_advanced: '쉼표 %1 박자 %2', + robotis_robotai_lite_beat_per_minute: '연주 빠르기를 %1 (으)로 정하기 %2', + robotis_robotai_lite_Hello: '로봇 %1 말하기 %2', + robotis_robotai_lite_effectSound: '효과음 %1 재생하기 %2', + robotis_robotai_lite_record: '소리 %1번에 녹음하기 %2', + robotis_robotai_lite_playRecord: '소리 %1번을 재생하기 %2', + + // LCD 제어 + robotis_robotai_lite_screen: '화면 표정을 %1 %2 (으)로 정하기 %3', + robotis_robotai_lite_anim_screen: + '화면 애니메이션을 %1 %2 (으)로 정하기 %3', + robotis_robotai_lite_icon_screen_food_plant: + '화면에 [음식/식물]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5', + robotis_robotai_lite_icon_screen_animal_human: + '화면에 [동물/사람]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5', + robotis_robotai_lite_icon_screen_object_tool: + '화면에 [물건/도구]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5', + robotis_robotai_lite_icon_screen_vehicle_number: + '화면에 [탈것/숫자]중 %1를 (%2, %3)위치에 %4 크기로 표시 %5', + robotis_robotai_lite_text_screen: + '화면에 %1를 (%2, %3)위치에 %4 로 %5으로 표시 %6', + robotis_robotai_lite_pixel: '화면 (%1, %2)위치에 %3 색 점 표시 %4', + robotis_robotai_lite_text_screen_redraw: + '화면에 %1를 (%2, %3)위치에 %4으로 새로 표시 %5', + robotis_robotai_lite_LCDColor: '화면 색상을 %1 (으)로 정하기 %2', + robotis_robotai_lite_LCD_Flash: + '화면을 %1과 %2으로 %3초 간격으로 깜박이기 %4', + robotis_robotai_lite_LCDBright: '화면 밝기를 %1 (으)로 정하기 %2', + + // LED 제어 + robotis_robotai_lite_cm_led: '로봇 %1 LED %2 %3', + robotis_robotai_lite_cm_led_pattern: 'LED %1 %2로 깜박이기 %3', + + // DXL 제어 + robotis_robotai_lite_dxl_set_mode: '%1 모터 %2 모드로 설정 %3', + robotis_robotai_lite_dxl_each_control: + '%1 모터 %2°로 %3 초 동안 움직이기 %4', + robotis_robotai_lite_dxl_set_position: + '%1 모터 %2 속도로 %3° 위치로 회전 %4', + robotis_robotai_lite_dxl_set_rotate: '%1 모터 %2 속도로 %3 으로 %4 %5', + robotis_robotai_lite_dxl_set_multiturn_round: + '%1 모터 %2 속도로 %3 바퀴 %4으로 회전 %5', + + // ai_camera 값 블록 + robotis_robotai_lite_ai_camera_connection_status: 'AI 카메라: %1이면', + robotis_robotai_lite_ai_camera_if_detected: 'AI 카메라: %1 이/가 표시되면', + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: + 'AI 카메라: 화면 중앙과 가까운 %1의 %2', + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: + 'AI 카메라: 화면 중앙과 가까운 화살표의 %1', + robotis_robotai_lite_ai_camera_number_of_learned_id: + 'AI 카메라: 학습한 ID의 갯수', + robotis_robotai_lite_ai_camera_block_value_of_id: + 'AI 카메라: 감지된 ID가 %1인 %2의 %3', + robotis_robotai_lite_ai_camera_arrow_value_of_id: + 'AI 카메라: 감지된 ID가 %1인 화살표의 %2', + + robotis_robotai_lite_ai_camera_if_learned_id: + 'AI 카메라: ID가 %1인 데이터를 학습하였으면', + robotis_robotai_lite_ai_camera_if_detected_id_type: + 'AI 카메라: ID가 %1인 %2데이터를 인식하였으면', + + // AI 카메라 제어 + robotis_robotai_lite_ai_camera_set_mode: + 'AI 카메라: 모드를 %1(으)로 설정 %2', + robotis_robotai_lite_ai_camera_print_custom_text: + 'AI 카메라: 화면 위치 (%1,%2)에 %3를 보여주기%4', + robotis_robotai_lite_ai_camera_clear_custom_text: + 'AI 카메라: 화면의 글 지우기 %1', + }, + Helper: { + // 주행 제어 + robotis_robotai_lite_drive_simple: + '로봇아이를 지정한 속도와 방향으로 주행\n속도범위: -100 ~ 100\n속도단위: %', + robotis_robotai_lite_drive_advanced: + '로봇아이의 좌,우 바퀴를 각각 지정한 속도와 방향으로 회전\n속도범위: -100 ~ 100\n속도단위: %', + robotis_robotai_lite_drive_seperate: + '로봇아이의 지정한 바퀴를 지정한 속도와 방향으로 회전\n속도범위: -100 ~ 100\n속도단위: %', + robotis_robotai_lite_drive_angle: + '로봇아이의 지정한 바퀴를 지정한 방향과 지정한 각도만큼 회전\n각도범위: -5760 ~ 5760\n각도단위: 도', + robotis_robotai_lite_go_distance: + '지정거리만큼 앞 또는 뒤로 이동\n거리범위: -1000 ~ 1000\n거리단위: mm', + robotis_robotai_lite_turn_angle: + '지정한 각도와 방향으로 제자리회전\n각도범위: -360 ~ 360\n각도단위: 도', + robotis_robotai_lite_follow_line: '지정한 수준의 속도로 라인 따라가기 시작', + robotis_robotai_lite_stop_at_cross: '지정한 교차로에서 멈추기', + robotis_robotai_lite_turn_at_line: '교차로에서 지정한 회전을 하고 멈추기', + robotis_robotai_lite_drive_stop: '로봇아이 정지하기', + + robotis_robotai_lite_securitybot_init: + '보안로봇을 초기화합니다. 두 모터를 관절모드로 설정하고 카메라를 얼굴인식모드로 설정합니다.', + robotis_robotai_lite_securitybot_hi: + '보안로봇이 "사용자를 확인하였습니다." 문구를 화면에 표시하고 팔을 위아래로 흔듭니다.', + robotis_robotai_lite_securitybot_alert: + '보안로봇 "사용자가 아닙니다." 문구를 화면에 표시하고 몸을 좌우로 흔듭니다.', + + robotis_robotai_lite_petbot_happy: + '반려로봇이 웃는 표정을 하고 "즐거워요" 라고 말을 하면서 제자리에서 한바퀴 회전합니다.', + robotis_robotai_lite_petbot_sad: + '반려로봇이 화난 표정을 하고 "무서워요" 라고 말을 하면서 뒤로 5cm 후진합니다.', + + robotis_robotai_lite_farmbot_init: + '스마트팜 로봇을 초기화 합니다. 1번 모터를 시작위치로 이동시키고 카메라를 색상인식모드로 설정합니다.', + robotis_robotai_lite_farmbot_seek: '농작물을 발견하면 가까이로 이동합니다.', + robotis_robotai_lite_farmbot_plant_type: '농작물의 유형을 판단합니다.', + robotis_robotai_lite_farmbot_harvest_or_not_and_go: + '농작물을 수확하거나 수확하지 않습니다. 그 이후 우측으로 회전합니다.', + + // 값 블록 + robotis_robotai_lite_cm_ir_value: '지정한 번호의 IR 센서 값(범위: 0 ~ 200)', + robotis_robotai_lite_cm_ir_compare: + "지정한 번호의 IR 센서 값과 지정한 값의 비교식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_detectFrontObj: + "지정한 방향의 적외선센서에 물체가 감지되면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_cm_btn_value: + "지정한 버튼이 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_cm_joystick_value: + "조이스틱 위치가 지정한 상태이면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_mic: + '마이크로 감지된 소리의 세기를 데시벨(dB)로 표시합니다.', + robotis_robotai_lite_detectSound_compare: + "소리가 나는 방향이 지정한 방향과 동일하면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_imu: + '지정한 축의 지정한 가속도센서/자이로센서의 값\n범위: -100 ~ 100', + robotis_robotai_lite_roll_pitch: + 'roll/pitch 값\nroll: -180° ~ 180°, pitch: -90° ~ 90°', + robotis_robotai_lite_environment_value: + '지정한 센서값\n움직임센서: 0(움직임 없음) / 1(움직임 있음)\n밝기범위: 0 ~ 100%\n온도범위: -25°C ~ 85°C', + robotis_robotai_lite_environment_compare: + "지정한 센서값의 지정한 수식이 맞으면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_line_cross_compare: + "지정한 교차로 모양이면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_dxl_value: + '지정한 모터의 위치 각도값\n범위: -180° ~ 180°', + + // 소리 + robotis_robotai_lite_scale_simple: '지정한 옥타브, 음계, 음표로 연주하기', + robotis_robotai_lite_scale_advanced: '지정한 옥타브, 음계, 박자로 연주하기', + robotis_robotai_lite_rest_simple: '지정한 쉼표 쉬기', + robotis_robotai_lite_rest_advanced: '지정한 박자 쉬기', + robotis_robotai_lite_beat_per_minute: + '연주 빠르기를 지정하기 (BPM)\n범위: 10 ~ 600', + robotis_robotai_lite_Hello: '로봇이 지정한 말소리를 재생하기', + robotis_robotai_lite_effectSound: '로봇이 지정한 효과음을 재생하기', + robotis_robotai_lite_record: '지정번호 보관함에 녹음하여 저장하기', + robotis_robotai_lite_playRecord: '지정번호 보관함의 녹음음성을 재생하기', + + // LCD 제어 + robotis_robotai_lite_screen: '제어기 화면배경의 캐릭터와 표정을 설정', + robotis_robotai_lite_anim_screen: + '제어기 화면 애니메이션의 캐릭터와 표정을 설정', + robotis_robotai_lite_icon_screen_food_plant: + '화면에 [음식/식물]중 특정 아이콘을 표시할 위치와 크기를 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_icon_screen_animal_human: + '화면에 [동물/사람]중 특정 아이콘을 표시할 위치와 크기를 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_icon_screen_object_tool: + '화면에 [물건/도구]중 특정 아이콘을 표시할 위치와 크기를 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_icon_screen_vehicle_number: + '화면에 [탈것/숫자]중 특정 아이콘을 표시할 위치와 크기를 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_text_screen: + '화면에 지정한 문구를 표시할 위치와 폰트크기, 색상을 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120', + robotis_robotai_lite_text_screen_redraw: + '화면에 지정한 문구를 새롭게(문구의 배경 지움) 표시할 위치와 색상을 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120\n크기: 0 ~ 200', + robotis_robotai_lite_pixel: + '화면에 표시할 점의 위치와 색상을 설정\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120', + robotis_robotai_lite_LCDBright: '화면 밝기를 설정\n밝기범위: 1% ~ 100%', + robotis_robotai_lite_LCDColor: '화면 색상을 설정', + robotis_robotai_lite_LCD_Flash: '화면이 깜박이는 2가지 색상과 간격을 지정', + + // LED 제어 + robotis_robotai_lite_cm_led: '제어기의 지정한 LED를 켜거나 끄기', + robotis_robotai_lite_cm_led_pattern: '제어기의 깜박임 패턴 설정', + + // DXL 제어 + robotis_robotai_lite_dxl_set_mode: '지정한 ID의 모터의 동작모드를 설정', + robotis_robotai_lite_dxl_each_control: + '지정한 ID의 모터가 지정한 각도로 지정한 시간(초)동안 움직이도록 설정', + robotis_robotai_lite_dxl_set_position: + '지정한 ID의 모터가 지정한 속도로 지정한 각도로 움직이도록 설정', + robotis_robotai_lite_dxl_set_rotate: + '지정한 ID의 모터의 회전 속도와 방향을 설정', + robotis_robotai_lite_dxl_set_multiturn_round: + '지정한 ID의 모터가 지정한 속도와 방향으로 지정한 바퀴만큼 회전', + + // AI Camera 값 블록 + robotis_robotai_lite_ai_camera_connection_status: + "AI 카메라가 연결된 상태이면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_ai_camera_if_detected: + "AI 카메라의 LCD화면에 선택한 기호(사각형/화살표)가 표시되면 '참', 아니면 '거짓'으로 판단합니다.", + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: + 'AI 카메라 화면 중앙과 가장 가까운 사각형의 X좌표/Y좌표/너비/높이/학습ID', + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: + 'AI 카메라 화면 중앙과 가장 가까운 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표/학습ID', + robotis_robotai_lite_ai_camera_number_of_learned_id: + 'AI 카메라가 학습한 ID의 갯수', + robotis_robotai_lite_ai_camera_block_value_of_id: + 'AI 카메라가 감지한 사각형중 지정한 ID의 사각형의 X좌표/Y좌표/너비/높이', + robotis_robotai_lite_ai_camera_arrow_value_of_id: + 'AI 카메라가 감지한 화살표중 지정한 ID의 화살표의 시작점X좌표/시작점Y좌표/끝점X좌표/끝점Y좌표', + + robotis_robotai_lite_ai_camera_if_learned_id: + "AI 카메라가 지정한 ID인 데이터를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.", + robotis_robotai_lite_ai_camera_if_detected_id_type: + "AI 카메라가 지정한 ID인 지정한 데이터(사각형/화살표)를 학습하였으면 '참', 아니면 '거짓'으로 판단합니다.", + + // AI 카메라 제어 + robotis_robotai_lite_ai_camera_set_mode: 'AI 카메라의 모드를 설정', + robotis_robotai_lite_ai_camera_print_custom_text: + 'AI 카메라 화면의 지정한 위치에 지정한 문구 출력\nX좌표: -160 ~ 160\nY좌표: -120 ~ 120', + robotis_robotai_lite_ai_camera_clear_custom_text: + 'AI 카메라 화면에 표시한 모든 문구 지우기', + }, + Blocks: { + robotis_red: '빨강', + robotis_orange: '주황', + robotis_yellow: '노랑', + robotis_green: '초록', + robotis_blue: '파랑', + robotis_brown: '갈색', + robotis_black: '검정', + robotis_white: '흰색', + robotis_left: '왼쪽', + robotis_center: '중앙', + robotis_right: '오른쪽', + robotis_both: '양쪽', + robotis_rgee: '알쥐', + robotis_rla: '알라', + robotis_kkokdu: '꼭두', + robotis_korean1: '안녕하세요', + robotis_korean2: '반가워요', + robotis_korean3: '알겠어요', + robotis_korean4: '아니에요', + robotis_korean5: '모르겠어요', + robotis_korean6: '좋아요', + robotis_korean7: '싫어요', + robotis_korean8: '이름을말하세요', + robotis_korean9: '무엇을도와줄까?', + robotis_korean10: '잘했어', + robotis_korean11: '괜찮아', + robotis_korean12: '다시해보자', + robotis_korean13: '고마워', + robotis_korean14: '다시말해줄래?', + robotis_korean15: '최고야!', + robotis_korean16: '신나요', + robotis_korean17: '즐거워요', + robotis_korean18: '미안해요', + robotis_korean19: '화나요', + robotis_korean20: '부끄러워요', + robotis_korean21: '무서워요', + robotis_korean22: '속상해요', + robotis_korean23: '사랑해요', + robotis_korean24: '예뻐요', + robotis_korean25: '신기해요', + robotis_korean26: '초조해요', + robotis_korean27: '앞으로가자', + robotis_korean28: '뒤로가자', + robotis_korean29: '일어나자', + robotis_korean30: '넘어졌네?', + robotis_korean31: '오예', + robotis_korean32: '아싸', + robotis_korean33: '어머', + robotis_korean34: '이런', + robotis_korean35: '오호', + robotis_korean36: '하하하', + robotis_korean37: '호호호', + robotis_korean38: '졸려', + robotis_korean39: '자장가를들려줘', + robotis_korean40: '안녕', + robotis_korean41: '배고프다', + robotis_korean42: '도토리땡긴다', + robotis_korean43: '아.씻고싶어', + robotis_korean44: '비누목욕시간이야', + robotis_korean45: '심심한데', + robotis_korean46: '간식먹을까', + robotis_korean47: '아파요', + robotis_korean48: '약은없나요?', + robotis_korean49: '어디로가야하지?', + robotis_korean50: '와아도착이다', + robotis_korean51: '왼쪽으로가자', + robotis_korean52: '오른쪽으로가자', + robotis_korean53: '깜짝이야', + robotis_korean54: '찾았다', + robotis_korean55: '여긴없네', + robotis_korean56: '혹시나불렀어?', + robotis_korean57: '내려주세요', + robotis_korean58: '앗', + robotis_korean59: '힝', + robotis_korean60: '이익', + robotis_dog: '개', + robotis_frog: '개구리', + robotis_cat: '고양이', + robotis_chicken: '닭', + robotis_tiger: '호랑이', + robotis_mouse: '쥐', + robotis_ambul: '앰뷸런스', + robotis_Horn: '경적(빵빵)', + robotis_siren: '사이렌(경찰차)', + robotis_whistle: '호루라기', + robotis_gun: '총소리', + robotis_clap: '박수소리', + robotis_melody1: '멜로디1', + robotis_melody2: '멜로디2', + robotis_melody3: '멜로디3', + robotis_melody4: '멜로디4', + robotis_forward: '앞으로', + robotis_backward: '뒤로', + robotis_acceleration: '가속도', + robotis_gyro: '자이로', + robotis_run: '실행', + robotis_cancel: '취소', + robotis_push: '눌림', + robotis_notPush: '안눌림', + robotis_play: '연주', + robotis_rest: '쉼표', + robotis_face01: '와하하', + robotis_face02: '싱글벙글', + robotis_face03: '큭큭큭', + robotis_face04: '냠냠', + robotis_face05: '겁먹음', + robotis_face06: '답답', + robotis_face07: '갸우뚱', + robotis_face08: '어벙벙', + robotis_face09: '고함', + robotis_face10: '화남', + robotis_face11: '킁킁(왼쪽)', + robotis_face12: '킁킁(오른쪽)', + robotis_face13: '킁킁(아래)', + robotis_face14: '안심', + robotis_face15: '기절', + robotis_face16: '헤롱헤롱', + robotis_face17: '하품', + robotis_face18: '졸림', + robotis_face19: '잠듦', + robotis_face20: '마음앓이', + robotis_face21: '폭풍눈물', + robotis_face22: '목욕', + robotis_face23: '햐트뿅뿅', + + robotis_flashing1: '깜박임1', + robotis_flashing2: '깜박임2', + robotis_flashing3: '깜박임3', + robotis_flashing4: '깜박임4', + robotis_flashing5: '깜박임5', + robotis_flashing6: '깜박임6', + robotis_flashing7: '깜박임7', + robotis_flashing8: '깜박임8', + robotis_flashing9: '깜박임9', + robotis_moveF: '전진', + robotis_moveB: '후진', + robotis_moveL: '좌회전', + robotis_moveR: '우회전', + robotis_moveU: 'U턴', + robotis_moveL_in_place: '제자리 좌회전', + robotis_moveR_in_place: '제자리 우회전', + robotis_moveU_in_place: '제자리 U턴', + robotis_moveRG1: '일어서기', + robotis_moveRG2: '앉기', + robotis_moveRG3: '발버둥', + robotis_moveRG4: '발들기', + robotis_stop: '정지', + robotis_roll: '좌우 회전각 (roll)', + robotis_pitch: '앞뒤 회전각 (pitch)', + robotis_direction_forward: '전진방향', + robotis_direction_backward: '후진방향', + robotis_stMotion1: '기본자세', + robotis_stMotion2: '전진', + robotis_stMotion3: '우전진', + robotis_stMotion4: '좌전진', + robotis_stMotion5: '후진', + robotis_stMotion6: '오른쪽으로', + robotis_stMotion7: '왼쪽으로', + robotis_stMotion8: '우회전', + robotis_stMotion9: '좌회전', + robotis_spMotion1: '오른손 들기', + robotis_spMotion2: '오른손 내리기', + robotis_spMotion3: '왼손 들기', + robotis_spMotion4: '왼손 내리기', + robotis_spMotion5: '양손 들기', + robotis_spMotion6: '양손 내리기', + robotis_spMotion7: '뒤로 넘어지기', + robotis_spMotion8: '앞으로 넘어지기', + robotis_spMotion9: '앞으로 일어서기', + robotis_spMotion10: '뒤로 일어서기', + robotis_spMotion11: '방어', + robotis_spMotion12: '공격1', + robotis_spMotion13: '공격2', + robotis_spMotion14: '공격3', + robotis_spMotion15: '공격4', + robotis_screen1: '가위', + robotis_screen2: '바위', + robotis_screen3: '보', + robotis_icon_food_plant_1: '우유', + robotis_icon_food_plant_2: '나무', + robotis_icon_food_plant_3: '스프', + robotis_icon_food_plant_4: '케익', + robotis_icon_food_plant_5: '물', + robotis_icon_food_plant_6: '주스', + robotis_icon_food_plant_7: '당근', + robotis_icon_food_plant_8: '사과', + robotis_icon_food_plant_9: '오렌지', + robotis_icon_food_plant_10: '고기', + robotis_icon_food_plant_11: '화분', + robotis_icon_food_plant_12: '장미', + robotis_icon_food_plant_13: '포도', + robotis_icon_food_plant_14: '감자', + robotis_icon_food_plant_15: '사탕', + robotis_icon_food_plant_16: '치즈', + robotis_icon_food_plant_17: '식빵', + robotis_icon_food_plant_18: '꽃들', + robotis_icon_food_plant_19: '커피', + robotis_icon_food_plant_20: '튤립', + robotis_icon_food_plant_21: '바나나', + robotis_icon_food_plant_22: '과일들', + robotis_icon_food_plant_23: '햄버거', + robotis_icon_food_plant_24: '피자', + robotis_icon_animal_human_1: '시바견', + robotis_icon_animal_human_2: '강아지', + robotis_icon_animal_human_3: '곰', + robotis_icon_animal_human_4: '새', + robotis_icon_animal_human_5: '오리', + robotis_icon_animal_human_6: '사자', + robotis_icon_animal_human_7: '호랑이', + robotis_icon_animal_human_8: '말', + robotis_icon_animal_human_9: '양', + robotis_icon_animal_human_10: '상어1(왼쪽)', + robotis_icon_animal_human_11: '상어1(오른쪽)', + robotis_icon_animal_human_12: '상어2(왼쪽)', + robotis_icon_animal_human_13: '상어2(오른쪽)', + robotis_icon_animal_human_14: '물고기1', + robotis_icon_animal_human_15: '물고기2', + robotis_icon_animal_human_16: '물고기3', + robotis_icon_animal_human_17: '문어', + robotis_icon_animal_human_18: '원숭이', + robotis_icon_animal_human_19: '닭', + robotis_icon_animal_human_20: '돼지', + robotis_icon_animal_human_21: '사람(살찐)', + robotis_icon_animal_human_22: '사람(수영복)', + robotis_icon_animal_human_23: '아기', + robotis_icon_animal_human_24: '사람(달리는)', + robotis_icon_animal_human_25: '사람(노래하는)', + robotis_icon_animal_human_26: '사람(앉은)', + robotis_icon_animal_human_27: '사람(화난)', + robotis_icon_animal_human_28: '사람(만세)', + robotis_icon_animal_human_29: '왕', + robotis_icon_animal_human_30: '왕자', + robotis_icon_animal_human_31: '공주', + robotis_icon_animal_human_32: '요리사', + robotis_icon_animal_human_33: '의사', + robotis_icon_animal_human_34: '간호사', + robotis_icon_object_tool_1: '가방', + robotis_icon_object_tool_2: '상자', + robotis_icon_object_tool_3: '머그컵', + robotis_icon_object_tool_4: '모자(중절모)', + robotis_icon_object_tool_5: '모자(캡모자)', + robotis_icon_object_tool_6: '열쇠', + robotis_icon_object_tool_7: '장난감', + robotis_icon_object_tool_8: '책', + robotis_icon_object_tool_9: '곰인형', + robotis_icon_object_tool_10: '드럼', + robotis_icon_object_tool_11: '메모장', + robotis_icon_object_tool_12: '볼펜', + robotis_icon_object_tool_13: '책상', + robotis_icon_object_tool_14: '테이블', + robotis_icon_object_tool_15: '의자', + robotis_icon_object_tool_16: '침대', + robotis_icon_object_tool_17: '텐트', + robotis_icon_object_tool_18: '접시', + robotis_icon_object_tool_19: '축구공', + robotis_icon_object_tool_20: '종', + robotis_icon_object_tool_21: '손목시계', + robotis_icon_object_tool_22: '신발', + robotis_icon_object_tool_23: '전등', + robotis_icon_object_tool_24: '라디오', + robotis_icon_object_tool_25: '지폐', + robotis_icon_object_tool_26: '자', + robotis_icon_object_tool_27: '카메라', + robotis_icon_object_tool_28: '스푼', + robotis_icon_object_tool_29: '건반', + robotis_icon_object_tool_30: '달력', + robotis_icon_object_tool_31: '칼', + robotis_icon_object_tool_32: '풍선', + robotis_icon_object_tool_33: '물통', + robotis_icon_object_tool_34: '나무막대(세로)', + robotis_icon_object_tool_35: '나무막대(가로)', + robotis_icon_object_tool_36: '낚시바늘', + robotis_icon_vehicle_number_1: '자동차', + robotis_icon_vehicle_number_2: '버스', + robotis_icon_vehicle_number_3: '트럭', + robotis_icon_vehicle_number_4: '지프', + robotis_icon_vehicle_number_5: '자전거', + robotis_icon_vehicle_number_6: '전철', + robotis_icon_vehicle_number_7: '기차', + robotis_icon_vehicle_number_8: '비행기', + robotis_icon_vehicle_number_9: '전투기(세로)', + robotis_icon_vehicle_number_10: '전투기(가로)', + robotis_icon_vehicle_number_11: '로켓', + robotis_icon_vehicle_number_12: '어선', + robotis_icon_vehicle_number_13: '여객선', + robotis_icon_vehicle_number_14: '잠수항(왼쪽)', + robotis_icon_vehicle_number_15: '잠수함(오른쪽)', + robotis_icon_vehicle_number_16: '비행기(왼쪽)', + robotis_icon_vehicle_number_17: '비행기(오른쪽)', + robotis_icon_vehicle_number_18: '비행기(윗쪽)', + robotis_icon_vehicle_number_19: '우주선(왼쪽)', + robotis_icon_vehicle_number_20: '우주선(오른쪽)', + robotis_icon_vehicle_number_21: '우주선(윗쪽)', + robotis_icon_vehicle_number_22: '주사위(1)', + robotis_icon_vehicle_number_23: '주사위(2)', + robotis_icon_vehicle_number_24: '주사위(3)', + robotis_icon_vehicle_number_25: '주사위(4)', + robotis_icon_vehicle_number_26: '주사위(5)', + robotis_icon_vehicle_number_27: '주사위(6)', + robotis_icon_vehicle_number_28: '0', + robotis_icon_vehicle_number_29: '1', + robotis_icon_vehicle_number_30: '2', + robotis_icon_vehicle_number_31: '3', + robotis_icon_vehicle_number_32: '4', + robotis_icon_vehicle_number_33: '5', + robotis_icon_vehicle_number_34: '6', + robotis_icon_vehicle_number_35: '7', + robotis_icon_vehicle_number_36: '8', + robotis_icon_vehicle_number_37: '9', + robotis_icon_vehicle_number_38: '10', + robotis_speed_fast: '빠른 속도', + robotis_speed_midium: '중간 속도', + robotis_speed_slow: '느린 속도', + robotis_clockwise: '시계방향', + robotis_counterclockwise: '반시계방향', + robotis_up: '들기', + robotis_down: '내리기', + robotis_if_greater: '크면', + robotis_if_smaller: '작으면', + robotis_if_equal: '같으면', + robotis_front_right: '앞 오른쪽', + robotis_front_left: '앞 왼쪽', + robotis_bottom_right: '아래 오른쪽', + robotis_bottom_left: '아래 왼쪽', + robotis_side_right: '우측', + robotis_side_left: '좌측', + robotis_front_ir_sensor: '적외선센서', + robotis_distance_sensor: '거리센서', + robotis_front: '앞', + robotis_right: '오른쪽', + robotis_left_wheel: '왼쪽바퀴', + robotis_right_wheel: '오른쪽바퀴', + // https://namu.wiki/w/%EC%9D%8C%ED%91%9C + robotis_beat_sound_8th_note: '8분음표 (♪)', + robotis_beat_sound_dotted_8th_note: '점8분음표 (♪.)', + robotis_beat_sound_quarter_note: '4분음표 (♩)', + robotis_beat_sound_dotted_quarter_note: '점4분음표 (♩.)', + robotis_beat_sound_half_note: '2분음표 (𝅗𝅥)', + robotis_beat_sound_dotted_half_note: '점2분음표 (𝅗𝅥.)', + robotis_beat_sound_whole_note: '온음표 (𝅝)', + robotis_beat_sound_dotted_note: '점온음표 (𝅝.)', + robotis_beat_rest_8th_note: '8분쉼표 (𝄾)', + robotis_beat_rest_dotted_8th_note: '점8분쉼표 (𝄾.)', + robotis_beat_rest_quarter_note: '4분쉼표 (𝄽)', + robotis_beat_rest_dotted_quarter_note: '점4분쉼표 (𝄽.)', + robotis_beat_rest_half_note: '2분쉼표 (𝄼)', + robotis_beat_rest_dotted_half_note: '점2분쉼표 (𝄼˙)', + robotis_beat_rest_whole_note: '온쉼표 (𝄻)', + robotis_beat_rest_dotted_note: '점온쉼표 (𝄻˙)', + robotis_line_cross_type_0: '|', + robotis_line_cross_type_1: ' (공백)', + robotis_line_cross_type_5: '🞣', + robotis_line_cross_type_6: '⏉', + robotis_line_cross_type_7: '⊣', + robotis_line_cross_type_8: '⊢', + robotis_line_cross_type_9: '⏋', + robotis_line_cross_type_10: '⎾', + robotis_line_cross_type_11: '¦', + robotis_line_cross_type_12: '︙', + + robotis_dxl_mode_joint: '관절', + robotis_dxl_mode_wheel: '바퀴', + robotis_dxl_mode_multi_turn: '여러바퀴회전', + robotis_dxl_move_rotate: '회전', + robotis_dxl_move_stop: '정지', + robotis_dxl_rotate_cw: '시계방향', + robotis_dxl_rotate_ccw: '반시계방향', + robotis_dxl_value_angle: '각도', + robotis_dxl_value_velocity: '속도', + robotis_dxl_value_moving: '움직임', + + robotis_connected: '연결', + robotis_disconnected: '없음', + robotis_ai_camera_mode_face_recognition: '얼굴인식', + robotis_ai_camera_mode_object_tracking: '물체추적', + robotis_ai_camera_mode_object_recognition: '물체인식', + robotis_ai_camera_mode_line_tracking: '라인인식', + robotis_ai_camera_mode_color_recognition: '색상인식', + robotis_ai_camera_mode_tag_recognition: '태그인식', + robotis_ai_camera_mode_object_classification: '물체분류', + robotis_ai_camera_target_face: '얼굴', + robotis_ai_camera_target_object: '사물', + robotis_ai_camera_target_color: '색상', + robotis_ai_camera_target_tag: '태그', + robotis_ai_camera_target_qr: 'QR코드', + robotis_ai_camera_target_block: '사각형', + robotis_ai_camera_target_arrow: '화살표', + robotis_ai_camera_center_block_center_x: '중심 X좌표', + robotis_ai_camera_center_block_center_y: '중심 Y좌표', + robotis_ai_camera_center_block_width: '너비', + robotis_ai_camera_center_block_height: '높이', + robotis_ai_camera_center_leared_id: '학습ID', + robotis_ai_camera_center_arrow_origin_x: '시작점 X좌표', + robotis_ai_camera_center_arrow_origin_y: '시작점 Y좌표', + robotis_ai_camera_center_arrow_target_x: '끝점 X좌표', + robotis_ai_camera_center_arrow_target_y: '끝점 Y좌표', + + robotis_plant_ripe: '빨간색으로 잘 익은', + robotis_plant_unripe: '초록색으로 덜 익은', + robotis_harvest: '수확하고', + robotis_not_harvest: '수확하지 않고', + }, + }, + en: { + template: { + // 주행 제어 + robotis_robotai_lite_drive_simple: 'Move %2 with velocity %1 %3', + robotis_robotai_lite_drive_advanced: + 'Left wheel %2 with velocity %1, right wheel %4 with velocity %3 %5', + robotis_robotai_lite_drive_seperate: + '%1 wheel rotate %3 with velocity %2 %4', + robotis_robotai_lite_drive_angle: 'Rotate %1 wheel %2 degree %3 %4', + robotis_robotai_lite_go_distance: 'Moves %2 %1 cm %3', + robotis_robotai_lite_turn_angle: 'Rotates %1 degree(s) %2 in place %3', + robotis_robotai_lite_follow_line: 'Follow line with %1 speed %2', + robotis_robotai_lite_stop_at_cross: 'Stop at cross %1 %2', + robotis_robotai_lite_turn_at_line: '%1 at cross and stop %2', + robotis_robotai_lite_drive_stop: 'Stop %1', + + robotis_robotai_lite_securitybot_init: 'Security robot init %1', + robotis_robotai_lite_securitybot_hi: 'Security robot shake up and down %1', + robotis_robotai_lite_securitybot_alert: + 'Security robot shake left and right %1', + + robotis_robotai_lite_petbot_happy: 'Petbot laugh %1', + robotis_robotai_lite_petbot_sad: 'Petbot angry %1', + + robotis_robotai_lite_farmbot_init: 'SmartFarm Robot init %1', + robotis_robotai_lite_farmbot_seek: 'Look for plant %1', + robotis_robotai_lite_farmbot_plant_type: 'If it is %1 plant', + robotis_robotai_lite_farmbot_harvest_or_not_and_go: + '%1 the plant and go back %2', + + // 값 블록 + robotis_robotai_lite_cm_ir_value: 'Value of %1 IR Sensor', + robotis_robotai_lite_cm_ir_compare: + 'If the number %1 IR sensor value is %3 than %2', + robotis_robotai_lite_detectFrontObj: 'If %1 IR sensor detected an object', + robotis_robotai_lite_cm_btn_value: + "When the controller's %1 button is clicked", + robotis_robotai_lite_cm_joystick_value: + "If the controller's yellow joystick position is %1", + robotis_robotai_lite_mic: 'MIC volume(dB)', + robotis_robotai_lite_detectSound_compare: + 'If sound is detected from %1 of the robot', + robotis_robotai_lite_imu: "%1 axis' %2 value", + robotis_robotai_lite_roll_pitch: '%1 value of the controller', + robotis_robotai_lite_environment_value: '%1 value', + robotis_robotai_lite_environment_compare: 'If %1 value is %3 than %2', + robotis_robotai_lite_line_cross_compare: 'If the type of cross is %1', + robotis_robotai_lite_dxl_value: 'The angle of ID %1', + + // 소리 + robotis_robotai_lite_scale_simple: 'Play the note %2 as %3 in octave %1 %4', + robotis_robotai_lite_scale_advanced: + 'Play the note %2 in octave %1 for %3 beat %4', + robotis_robotai_lite_rest_simple: '%1 %2', + robotis_robotai_lite_rest_advanced: 'Rest %1 beat %2', + robotis_robotai_lite_beat_per_minute: 'Set playing speed to %1 %2', + robotis_robotai_lite_Hello: 'Robot speaks %1 %2', + robotis_robotai_lite_effectSound: 'Play sound effect %1 %2', + robotis_robotai_lite_record: 'Record to sound slot %1 %2', + robotis_robotai_lite_playRecord: 'Play sound from slot %1 %2', + + // LCD 제어 + robotis_robotai_lite_screen: 'Set screen expression to %1 %2 %3', + robotis_robotai_lite_anim_screen: 'Set screen animation to %1 %2 %3', + robotis_robotai_lite_icon_screen_food_plant: + 'Display %1 from [Food/Plants] at position (%2, %3) in size %4 %5', + robotis_robotai_lite_icon_screen_animal_human: + 'Display %1 from [Animal/Human] at position (%2, %3) in size %4 %5', + robotis_robotai_lite_icon_screen_object_tool: + 'Display %1 from [Object/Tool] at position (%2, %3) in size %4 %5', + robotis_robotai_lite_icon_screen_vehicle_number: + 'Display %1 from [Vehicle/Number] at position (%2, %3) in size %4 %5', + robotis_robotai_lite_text_screen: + 'Display %1 in %5 in %4 at (%2, %3) on the screen %6', + robotis_robotai_lite_text_screen_redraw: + 'Newly display %1 in %4 at (%2, %3) %5', + robotis_robotai_lite_pixel: 'Display %3 colored dot at (%1, %2) %4', + robotis_robotai_lite_LCDColor: 'Set screen color as %1 %2', + robotis_robotai_lite_LCD_Flash: + 'Blink the screen with %1 and %2 at intervals of %3 seconds %4', + robotis_robotai_lite_LCDBright: 'Set screen brightness as %1 %2', + + // LED 제어 + robotis_robotai_lite_cm_led: "%2 the robot's %1 LED %3", + robotis_robotai_lite_cm_led_pattern: 'LED %1 blinks at a %2 speed %3', + + // DXL 제어 + robotis_robotai_lite_dxl_set_mode: 'Set ID %1 motor as %2 mode %3', + robotis_robotai_lite_dxl_each_control: 'Move %1th motor %2° for %3 second', + robotis_robotai_lite_dxl_set_position: + 'Rotate ID %1 motor to angle %3° at speed %2 %4', + robotis_robotai_lite_dxl_set_rotate: '%4 ID %1 motor %3 at speed %2 %4', + robotis_robotai_lite_dxl_set_multiturn_round: + 'Rotate ID %1 motor %3 times %4 at speed %2 %5', + + // AI Camera 값 블록 + robotis_robotai_lite_ai_camera_connection_status: 'AI Camera: If %1', + robotis_robotai_lite_ai_camera_if_detected: 'AI Camera: If %1 is displayed', + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: + 'AI Camera: %2 of the %1 closest to the center of the screen', + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: + 'AI Camera: %1 of the arrow closest to the center of the screen', + robotis_robotai_lite_ai_camera_number_of_learned_id: + 'AI Camera: the number of learned ID', + robotis_robotai_lite_ai_camera_block_value_of_id: + 'AI Camera: %3 of %2 with detected ID %1', + robotis_robotai_lite_ai_camera_arrow_value_of_id: + 'AI Camera: %2 of arrow with detected ID %1', + + robotis_robotai_lite_ai_camera_if_learned_id: + 'AI Camera: If learned data with ID %1', + robotis_robotai_lite_ai_camera_if_detected_id_type: + 'AI Camera: If learned %2 data with ID %1', + + // AI 카메라 제어 + robotis_robotai_lite_ai_camera_set_mode: 'AI Camera: Set mode to %1 %2', + robotis_robotai_lite_ai_camera_print_custom_text: + 'AI Camera: Display %3 at screen position (%1, %2) %4', + robotis_robotai_lite_ai_camera_clear_custom_text: + 'AI Camera: Clear screen text %1', + }, + Blocks: { + // 주행 제어 + robotis_robotai_lite_drive_simple: + 'Drive the robot at the specified speed and direction\nSpeed range: -100 ~ 100\nSpeed unit: %', + robotis_robotai_lite_drive_advanced: + 'Rotate the left and right wheels of the robot at the specified speed and direction\nSpeed range: -100 ~ 100\nSpeed unit: %', + robotis_robotai_lite_drive_seperate: + 'Rotate the specified wheel of the robot at the specified speed and direction\nSpeed range: -100 ~ 100\nSpeed unit: %', + robotis_robotai_lite_drive_angle: + 'Rotate the specified wheel of the robot in the specified direction and by the specified angle\nAngle range: -5760 ~ 5760\nAngle unit: degrees', + robotis_robotai_lite_go_distance: + 'Move forward or backward by the specified distance\nDistance range: -1000 ~ 1000\nDistance unit: mm', + robotis_robotai_lite_turn_angle: + 'Rotate in place by the specified angle and direction\nAngle range: -360 ~ 360\nAngle unit: degrees', + robotis_robotai_lite_follow_line: + 'Start following the line at the specified speed', + robotis_robotai_lite_stop_at_cross: 'Stop at the specified intersection', + robotis_robotai_lite_turn_at_line: + 'Make the specified turn at the intersection and stop', + robotis_robotai_lite_drive_stop: 'Stop the robot', + + robotis_robotai_lite_securitybot_init: + 'Initializes the security robot. Sets both motors to joint mode and the camera to face recognition mode.', + robotis_robotai_lite_securitybot_hi: + 'The security robot displays the message "User identified" on the screen and waves its arms up and down.', + robotis_robotai_lite_securitybot_alert: + 'The security robot displays the message "Not a user" on the screen and shakes its body from side to side.', + + robotis_robotai_lite_petbot_happy: + 'The pet robot makes a smiling face, says "I’m happy," and spins around in place.', + robotis_robotai_lite_petbot_sad: + 'The pet robot makes an angry face, says "I’m scared," and moves 5cm backward.', + + robotis_robotai_lite_farmbot_init: + 'Initializes the smart farm robot. Moves motor 1 to the starting position and sets the camera to color recognition mode.', + robotis_robotai_lite_farmbot_seek: 'Moves closer when it detects crops.', + robotis_robotai_lite_farmbot_plant_type: 'Identifies the type of crop.', + robotis_robotai_lite_farmbot_harvest_or_not_and_go: + 'Decides whether to harvest the crop or not, then rotates to the right.', + + // 값 블록 + robotis_robotai_lite_cm_ir_value: + 'IR sensor value of the specified number (range: 0 ~ 200)', + robotis_robotai_lite_cm_ir_compare: + "If the IR sensor value of the specified number matches the specified value, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_detectFrontObj: + "It returns 'true' if an object is detected by the infrared sensor in the specified direction; otherwise, it returns 'false'.", + robotis_robotai_lite_cm_btn_value: + "If the specified button is clicked, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_cm_joystick_value: + "If the joystick position is in the specified state, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_mic: + 'Displays the intensity of the sound detected by the microphone in decibels (dB).', + robotis_robotai_lite_detectSound_compare: + "If the direction of the sound matches the specified direction, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_imu: + 'Value of the specified accelerometer/gyro sensor on the specified axis\nRange: -100 ~ 100', + robotis_robotai_lite_roll_pitch: + 'roll/pitch value\nroll: -180° ~ 180°, pitch: -90° ~ 90°', + robotis_robotai_lite_environment_value: + 'Value of the specified sensor\nMotion sensor: 0 (no movement) / 1 (movement)\nBrightness range: 0 ~ 100%\nTemperature range: -25°C ~ 85°C', + robotis_robotai_lite_environment_compare: + "If the specified equation of the specified sensor value is correct, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_line_cross_compare: + "If the specified intersection shape is correct, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_dxl_value: + 'Position angle value of the specified motor\nRange: -180° ~ 180°', + + // 소리 + robotis_robotai_lite_scale_simple: + 'Play with the specified octave, scale, and note', + robotis_robotai_lite_scale_advanced: + 'Play with the specified octave, scale, and beat', + robotis_robotai_lite_rest_simple: 'Rest for the specified rest note', + robotis_robotai_lite_rest_advanced: 'Rest for the specified beat', + robotis_robotai_lite_beat_per_minute: + 'Set the playing speed (BPM)\nRange: 10 ~ 600', + robotis_robotai_lite_Hello: 'Play the specified voice of the robot', + robotis_robotai_lite_effectSound: + 'Play the specified sound effect of the robot', + robotis_robotai_lite_record: + 'Record and save to the specified number storage', + robotis_robotai_lite_playRecord: + 'Play the recorded voice in the specified number storage', + + // LCD 제어 + robotis_robotai_lite_screen: + 'Set the character and expression of the controller screen background', + robotis_robotai_lite_anim_screen: + 'Set the character and expression of the controller screen animation', + robotis_robotai_lite_icon_screen_food_plant: + 'Set the position and size of a specific icon in [food/plant] on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_icon_screen_animal_human: + 'Set the position and size of a specific icon in [animal/human] on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_icon_screen_object_tool: + 'Set the position and size of a specific icon in [object/tool] on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_icon_screen_vehicle_number: + 'Set the position and size of a specific icon in [vehicle/number] on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_text_screen: + 'Set the position, font size, and color of the specified text on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120', + robotis_robotai_lite_text_screen_redraw: + 'Set the position and color of the specified text to be newly displayed (clearing the background of the text) on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120\nSize: 0 ~ 200', + robotis_robotai_lite_pixel: + 'Set the position and color of the dot to be displayed on the screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120', + robotis_robotai_lite_LCDBright: + 'Set the screen brightness\nBrightness range: 0% ~ 100%', + robotis_robotai_lite_LCDColor: 'Set the screen color', + robotis_robotai_lite_LCD_Flash: + 'Specify two colors and the interval for the screen to blink.', + + // LED 제어 + robotis_robotai_lite_cm_led: + 'Turn the specified LED of the controller on or off', + robotis_robotai_lite_cm_led_pattern: + 'Set the blinking pattern of LEDs of the controller', + + // DXL 제어 + robotis_robotai_lite_dxl_set_mode: + 'Set the operating mode of the motor with the specified ID', + robotis_robotai_lite_dxl_each_control: + 'Set the motor with the specified ID to move to the specified angle for the specified time (seconds)', + robotis_robotai_lite_dxl_set_position: + 'Set the motor with the specified ID to move to the specified angle at the specified speed', + robotis_robotai_lite_dxl_set_rotate: + 'Set the rotation speed and direction of the motor with the specified ID', + robotis_robotai_lite_dxl_set_multiturn_round: + 'Set the motor with the specified ID to rotate the specified number of turns at the specified speed and direction', + + // AI Camera 값 블록 + robotis_robotai_lite_ai_camera_connection_status: + "If the AI camera is connected, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_ai_camera_if_detected: + "If the selected symbol (rectangle/arrow) is displayed on the LCD screen of the AI camera, it is determined as 'true'; otherwise, 'false'.", + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: + 'X coordinate/Y coordinate/width/height/learning ID of the rectangle closest to the center of the AI camera screen', + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: + 'Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate/learning ID of the arrow closest to the center of the AI camera screen', + robotis_robotai_lite_ai_camera_number_of_learned_id: + 'Number of IDs learned by the AI camera', + robotis_robotai_lite_ai_camera_block_value_of_id: + 'X coordinate/Y coordinate/width/height of the rectangle with the specified ID detected by the AI camera', + robotis_robotai_lite_ai_camera_arrow_value_of_id: + 'Starting point X coordinate/starting point Y coordinate/end point X coordinate/end point Y coordinate of the arrow with the specified ID detected by the AI camera', + + robotis_robotai_lite_ai_camera_if_learned_id: + "If the AI camera has learned the data of the specified ID, it is determined as 'true'; otherwise, 'false'.", + robotis_robotai_lite_ai_camera_if_detected_id_type: + "If the AI camera has learned the specified data (rectangle/arrow) of the specified ID, it is determined as 'true'; otherwise, 'false'.", + + // AI 카메라 제어 + robotis_robotai_lite_ai_camera_set_mode: 'Set the mode of the AI camera', + robotis_robotai_lite_ai_camera_print_custom_text: + 'Print the specified text at the specified position on the AI camera screen\nX coordinate: -160 ~ 160\nY coordinate: -120 ~ 120', + robotis_robotai_lite_ai_camera_clear_custom_text: + 'Clear all the text displayed on the AI camera screen', + }, + + Blocks: { + robotis_red: 'Red', + robotis_orange: 'Orange', + robotis_yellow: 'Yellow', + robotis_green: 'Green', + robotis_blue: 'Blue', + robotis_brown: 'Brown', + robotis_black: 'Black', + robotis_white: 'White', + robotis_left: 'Left', + robotis_center: 'Center', + robotis_right: 'Right', + robotis_both: 'Both', + robotis_rgee: 'R-GEE', + robotis_rla: 'KODALA', + robotis_kkokdu: 'TIG', + robotis_korean1: 'Hello!', + robotis_korean2: 'Great to see you.', + robotis_korean3: 'Okay ~', + robotis_korean4: 'No!', + robotis_korean5: "I don't know.", + robotis_korean6: 'I like it.', + robotis_korean7: "I don't like it.", + robotis_korean8: 'What is your name? ', + robotis_korean9: 'How can I help you? ', + robotis_korean10: 'Great job! ', + robotis_korean11: "It's alright.", + robotis_korean12: "Let's do it again! ", + robotis_korean13: 'Thank you! ', + robotis_korean14: 'Can you say that one more time?', + robotis_korean15: 'Awesome!', + robotis_korean16: "I'm excited! ", + robotis_korean17: "I'm having a great time! ", + robotis_korean18: "I'm sorry.", + robotis_korean19: "I'm angry! ", + robotis_korean20: "I'm embarassed.", + robotis_korean21: "I'm scared.", + robotis_korean22: "I'm upset.", + robotis_korean23: 'I love you.', + robotis_korean24: 'Very pretty! ', + robotis_korean25: 'Interesting.', + robotis_korean26: "I'm nervous.", + robotis_korean27: "Let's move forward! ", + robotis_korean28: "Let's move backward! ", + robotis_korean29: "Let's stand up! ", + robotis_korean30: 'Did you fall down? ', + robotis_korean31: 'Oh Yeah~', + robotis_korean32: 'Sweet! ', + robotis_korean33: 'Oh no', + robotis_korean34: 'My My ', + robotis_korean35: 'Whoo hoo! ', + robotis_korean36: 'Ha Ha Ha', + robotis_korean37: 'Ho Ho Ho ', + robotis_korean38: "I'm sleepy.", + robotis_korean39: 'Sing me a bedtime song! ', + robotis_korean40: 'Hello!', + robotis_korean41: "I'm hungry.", + robotis_korean42: "I'm craving an acorn! ", + robotis_korean43: 'I want to take a bath! ', + robotis_korean44: 'Time for a bath! ', + robotis_korean45: "I'm bored. ", + robotis_korean46: 'Do you want a snack? ', + robotis_korean47: "I'm sick.", + robotis_korean48: 'Do you have any medicine? ', + robotis_korean49: 'Where do we have to go? ', + robotis_korean50: "We're here! ", + robotis_korean51: "Let's go to the left side! ", + robotis_korean52: "Let's go to the right side! ", + robotis_korean53: 'Oh my, you scared me! ', + robotis_korean54: 'Found you! ', + robotis_korean55: "There's nothing here. ", + robotis_korean56: 'Did you call me?', + robotis_korean57: 'Please let me down. ', + robotis_korean58: 'Oops! ', + robotis_korean59: 'Hmmph! ', + robotis_korean60: 'Eek! ', + robotis_dog: 'Dog', + robotis_frog: 'Frog', + robotis_cat: 'Cat', + robotis_chicken: 'Rooster', + robotis_tiger: 'Tiger', + robotis_mouse: 'Mouse', + robotis_ambul: 'Ambulance', + robotis_Horn: 'CarHorn', + robotis_siren: 'Siren', + robotis_whistle: 'Whistle', + robotis_gun: 'Gunshot', + robotis_clap: 'Clap', + robotis_melody1: 'Melody1', + robotis_melody2: 'Melody2', + robotis_melody3: 'Melody3', + robotis_melody4: 'Melody4', + robotis_forward: 'Forward', + robotis_backward: 'Backward', + robotis_acceleration: 'acceleration', + robotis_gyro: 'gyro', + robotis_run: 'Run', + robotis_cancel: 'Cancel', + robotis_push: 'Pressed', + robotis_notPush: 'Unpressed', + robotis_play: 'Play', + robotis_rest: 'Rest', + robotis_face01: 'Haha', + robotis_face02: 'Smile', + robotis_face03: 'Laugh', + robotis_face04: 'Yum Yum', + robotis_face05: 'Scared', + robotis_face06: 'Uncomfortable', + robotis_face07: 'Confused', + robotis_face08: 'Dazed', + robotis_face09: 'Yell', + robotis_face10: 'Angry', + robotis_face11: 'Sniff (Left)', + robotis_face12: 'Sniff (Right)', + robotis_face13: 'Sniff (Down)', + robotis_face14: 'Whew', + robotis_face15: 'Faint', + robotis_face16: 'Dizzy', + robotis_face17: 'Yawn', + robotis_face18: 'Sleepy', + robotis_face19: 'Sleep', + robotis_face20: 'Sad', + robotis_face21: 'Cry', + robotis_face22: 'Bath', + robotis_face23: 'Heart-Eyes', + robotis_flashing1: 'Flashing1', + robotis_flashing2: 'Flashing2', + robotis_flashing3: 'Flashing3', + robotis_flashing4: 'Flashing4', + robotis_flashing5: 'Flashing5', + robotis_flashing6: 'Flashing6', + robotis_flashing7: 'Flashing7', + robotis_flashing8: 'Flashing8', + robotis_flashing9: 'Flashing9', + robotis_moveF: 'Forward', + robotis_moveB: 'Backward', + robotis_moveL: 'LeftTurn', + robotis_moveR: 'RightTurn', + robotis_moveU: 'U-turn', + robotis_moveL_in_place: 'Turn left in place', + robotis_moveR_in_place: 'Trun right in place', + robotis_moveU_in_place: 'U-turn in place', + robotis_moveRG1: 'Stand', + robotis_moveRG2: 'Sit', + robotis_moveRG3: 'Struggle', + robotis_moveRG4: 'RaiseFeet', + robotis_stop: 'Stop', + robotis_roll: 'Left-right rotate angle (roll)', + robotis_pitch: 'Forward-backward rotate angle (pitch)', + robotis_direction_forward: 'Forward', + robotis_direction_backward: 'Backward', + robotis_stMotion1: 'Standard', + robotis_stMotion2: 'Forward', + robotis_stMotion3: 'TurnRight', + robotis_stMotion4: 'TurnLeft', + robotis_stMotion5: 'Backward', + robotis_stMotion6: 'ToRight', + robotis_stMotion7: 'ToLeft', + robotis_stMotion8: 'TurnAroundRight', + robotis_stMotion9: 'TurnAroundLeft', + robotis_spMotion1: 'RightHandUp', + robotis_spMotion2: 'RightHandDown', + robotis_spMotion3: 'LeftHandUp', + robotis_spMotion4: 'LeftHandDown', + robotis_spMotion5: 'BothHandsUp', + robotis_spMotion6: 'BothHandsDown', + robotis_spMotion7: 'FallBackward', + robotis_spMotion8: 'FallForward', + robotis_spMotion9: 'StandForward', + robotis_spMotion10: 'StandBackward', + robotis_spMotion11: 'Defence', + robotis_spMotion12: 'Offense1', + robotis_spMotion13: 'Offense2', + robotis_spMotion14: 'Offense3', + robotis_spMotion15: 'Offense4', + robotis_screen1: 'Sissor', + robotis_screen2: 'Rock', + robotis_screen3: 'Paper', + robotis_dxl_mode_joint: 'Joint', + robotis_dxl_mode_wheel: 'Wheel', + robotis_dxl_mode_multi_turn: 'Multi-turn', + robotis_dxl_move_rotate: 'Rotate', + robotis_dxl_move_stop: 'Stop', + robotis_dxl_rotate_cw: 'clockwise', + robotis_dxl_rotate_ccw: 'counter clockwise', + robotis_dxl_value_angle: 'angle', + robotis_dxl_value_velocity: 'velocity', + robotis_dxl_value_moving: 'moving', + robotis_icon_food_plant_1: 'Milk', + robotis_icon_food_plant_2: 'Tree', + robotis_icon_food_plant_3: 'Soup', + robotis_icon_food_plant_4: 'Cake', + robotis_icon_food_plant_5: 'Water', + robotis_icon_food_plant_6: 'Juice', + robotis_icon_food_plant_7: 'Carrot', + robotis_icon_food_plant_8: 'Apple', + robotis_icon_food_plant_9: 'Orange', + robotis_icon_food_plant_10: 'Meat', + robotis_icon_food_plant_11: 'Flowerpot', + robotis_icon_food_plant_12: 'Rose', + robotis_icon_food_plant_13: 'Grape', + robotis_icon_food_plant_14: 'Potato', + robotis_icon_food_plant_15: 'Candy', + robotis_icon_food_plant_16: 'Cheese', + robotis_icon_food_plant_17: 'Bread', + robotis_icon_food_plant_18: 'Flowers', + robotis_icon_food_plant_19: 'Coffee', + robotis_icon_food_plant_20: 'Tulip', + robotis_icon_food_plant_21: 'Banana', + robotis_icon_food_plant_22: 'Fruits', + robotis_icon_food_plant_23: 'Hamburger', + robotis_icon_food_plant_24: 'Pizza', + robotis_icon_animal_human_1: 'Shiba Dog', + robotis_icon_animal_human_2: 'Puppy', + robotis_icon_animal_human_3: 'Bear', + robotis_icon_animal_human_4: 'Bird', + robotis_icon_animal_human_5: 'Duck', + robotis_icon_animal_human_6: 'Lion', + robotis_icon_animal_human_7: 'Tiger', + robotis_icon_animal_human_8: 'Horse', + robotis_icon_animal_human_9: 'Sheep', + robotis_icon_animal_human_10: 'Shark 1 (Left)', + robotis_icon_animal_human_11: 'Shark 1 (Right)', + robotis_icon_animal_human_12: 'Shark 2 (Left)', + robotis_icon_animal_human_13: 'Shark 2 (Right)', + robotis_icon_animal_human_14: 'Fish 1', + robotis_icon_animal_human_15: 'Fish 2', + robotis_icon_animal_human_16: 'Fish 3', + robotis_icon_animal_human_17: 'Octopus', + robotis_icon_animal_human_18: 'Monkey', + robotis_icon_animal_human_19: 'Chicken', + robotis_icon_animal_human_20: 'Pig', + robotis_icon_animal_human_21: 'Person (Chubby)', + robotis_icon_animal_human_22: 'Person (Swimsuit)', + robotis_icon_animal_human_23: 'Baby', + robotis_icon_animal_human_24: 'Person (Running)', + robotis_icon_animal_human_25: 'Person (Singing)', + robotis_icon_animal_human_26: 'Person (Sitting)', + robotis_icon_animal_human_27: 'Person (Angry)', + robotis_icon_animal_human_28: 'Person (Cheering)', + robotis_icon_animal_human_29: 'King', + robotis_icon_animal_human_30: 'Prince', + robotis_icon_animal_human_31: 'Princess', + robotis_icon_animal_human_32: 'Chef', + robotis_icon_animal_human_33: 'Doctor', + robotis_icon_animal_human_34: 'Nurse', + robotis_icon_object_tool_1: 'Bag', + robotis_icon_object_tool_2: 'Box', + robotis_icon_object_tool_3: 'Mug', + robotis_icon_object_tool_4: 'Hat (Fedora)', + robotis_icon_object_tool_5: 'Hat (Cap)', + robotis_icon_object_tool_6: 'Key', + robotis_icon_object_tool_7: 'Toy', + robotis_icon_object_tool_8: 'Book', + robotis_icon_object_tool_9: 'Teddy Bear', + robotis_icon_object_tool_10: 'Drum', + robotis_icon_object_tool_11: 'Notebook', + robotis_icon_object_tool_12: 'Pen', + robotis_icon_object_tool_13: 'Desk', + robotis_icon_object_tool_14: 'Table', + robotis_icon_object_tool_15: 'Chair', + robotis_icon_object_tool_16: 'Bed', + robotis_icon_object_tool_17: 'Tent', + robotis_icon_object_tool_18: 'Plate', + robotis_icon_object_tool_19: 'Soccer Ball', + robotis_icon_object_tool_20: 'Bell', + robotis_icon_object_tool_21: 'Watch', + robotis_icon_object_tool_22: 'Shoes', + robotis_icon_object_tool_23: 'Lamp', + robotis_icon_object_tool_24: 'Radio', + robotis_icon_object_tool_25: 'Banknote', + robotis_icon_object_tool_26: 'Ruler', + robotis_icon_object_tool_27: 'Camera', + robotis_icon_object_tool_28: 'Spoon', + robotis_icon_object_tool_29: 'Keyboard', + robotis_icon_object_tool_30: 'Calendar', + robotis_icon_object_tool_31: 'Knife', + robotis_icon_object_tool_32: 'Balloon', + robotis_icon_object_tool_33: 'Water Bottle', + robotis_icon_object_tool_34: 'Wooden Stick (Horizontal)', + robotis_icon_object_tool_35: 'Wooden Stick (Vertical)', + robotis_icon_object_tool_36: 'Fishing Hook', + robotis_icon_vehicle_number_1: 'Car', + robotis_icon_vehicle_number_2: 'Bus', + robotis_icon_vehicle_number_3: 'Truck', + robotis_icon_vehicle_number_4: 'Jeep', + robotis_icon_vehicle_number_5: 'Bicycle', + robotis_icon_vehicle_number_6: 'Subway', + robotis_icon_vehicle_number_7: 'Train', + robotis_icon_vehicle_number_8: 'Airplane', + robotis_icon_vehicle_number_9: 'Fighter Jet (Vertical)', + robotis_icon_vehicle_number_10: 'Fighter Jet (Horizontal)', + robotis_icon_vehicle_number_11: 'Rocket', + robotis_icon_vehicle_number_12: 'Fishing Boat', + robotis_icon_vehicle_number_13: 'Passenger Ship', + robotis_icon_vehicle_number_14: 'Submarine (Left)', + robotis_icon_vehicle_number_15: 'Submarine (Right)', + robotis_icon_vehicle_number_16: 'Airplane (Left)', + robotis_icon_vehicle_number_17: 'Airplane (Right)', + robotis_icon_vehicle_number_18: 'Airplane (Top)', + robotis_icon_vehicle_number_19: 'Spaceship (Left)', + robotis_icon_vehicle_number_20: 'Spaceship (Right)', + robotis_icon_vehicle_number_21: 'Spaceship (Top)', + robotis_icon_vehicle_number_22: 'Dice (1)', + robotis_icon_vehicle_number_23: 'Dice (2)', + robotis_icon_vehicle_number_24: 'Dice (3)', + robotis_icon_vehicle_number_25: 'Dice (4)', + robotis_icon_vehicle_number_26: 'Dice (5)', + robotis_icon_vehicle_number_27: 'Dice (6)', + robotis_icon_vehicle_number_28: '0', + robotis_icon_vehicle_number_29: '1', + robotis_icon_vehicle_number_30: '2', + robotis_icon_vehicle_number_31: '3', + robotis_icon_vehicle_number_32: '4', + robotis_icon_vehicle_number_33: '5', + robotis_icon_vehicle_number_34: '6', + robotis_icon_vehicle_number_35: '7', + robotis_icon_vehicle_number_36: '8', + robotis_icon_vehicle_number_37: '9', + robotis_icon_vehicle_number_38: '10', + robotis_speed_fast: 'Fast Speed', + robotis_speed_midium: 'Medium Speed', + robotis_speed_slow: 'Slow Speed', + robotis_clockwise: 'Clockwise', + robotis_counterclockwise: 'Counterclockwise', + robotis_up: 'Lift', + robotis_down: 'Lower', + robotis_if_greater: 'If Greater', + robotis_if_smaller: 'If Smaller', + robotis_if_equal: 'If Equal', + robotis_front_right: 'Front Right', + robotis_front_left: 'Front Left', + robotis_bottom_right: 'Bottom Right', + robotis_bottom_left: 'Bottom Left', + robotis_side_right: 'Right Edge', + robotis_side_left: 'Left Edge', + robotis_front_ir_sensor: 'Infrared Sensor', + robotis_distance_sensor: 'Distance Sensor', + robotis_front: 'Front', + robotis_right: 'Right', + robotis_left_wheel: 'Left Wheel', + robotis_right_wheel: 'Right Wheel', + robotis_beat_sound_8th_note: 'Eighth Note (♪)', + robotis_beat_sound_dotted_8th_note: 'Dotted Eighth Note (♪.)', + robotis_beat_sound_quarter_note: 'Quarter Note (♩)', + robotis_beat_sound_dotted_quarter_note: 'Dotted Quarter Note (♩.)', + robotis_beat_sound_half_note: 'Half Note (𝅗𝅥)', + robotis_beat_sound_dotted_half_note: 'Dotted Half Note (𝅗𝅥.)', + robotis_beat_sound_whole_note: 'Whole Note (𝅝)', + robotis_beat_sound_dotted_note: 'Dotted Whole Note (𝅝.)', + robotis_beat_rest_8th_note: 'Eighth Rest (𝄾)', + robotis_beat_rest_dotted_8th_note: 'Dotted Eighth Rest (𝄾.)', + robotis_beat_rest_quarter_note: 'Quarter Rest (𝄽)', + robotis_beat_rest_dotted_quarter_note: 'Dotted Quarter Rest (𝄽.)', + robotis_beat_rest_half_note: 'Half Rest (𝄼)', + robotis_beat_rest_dotted_half_note: 'Dotted Half Rest (𝄼˙)', + robotis_beat_rest_whole_note: 'Whole Rest (𝄻)', + robotis_beat_rest_dotted_note: 'Dotted Whole Rest (𝄻˙)', + robotis_line_cross_type_0: '|', + robotis_line_cross_type_1: ' (Blank)', + robotis_line_cross_type_5: '🞣', + robotis_line_cross_type_6: '⏉', + robotis_line_cross_type_7: '⊣', + robotis_line_cross_type_8: '⊢', + robotis_line_cross_type_9: '⏋', + robotis_line_cross_type_10: '⎾', + robotis_line_cross_type_11: '¦', + robotis_line_cross_type_12: '︙', + robotis_connected: 'Connected', + robotis_disconnected: 'Not connected', + robotis_ai_camera_mode_face_recognition: 'Face recognition', + robotis_ai_camera_mode_object_tracking: 'Object tracking', + robotis_ai_camera_mode_object_recognition: 'Object recognition', + robotis_ai_camera_mode_line_recognition: 'Line tracking', + robotis_ai_camera_mode_color_recognition: 'Color recognition', + robotis_ai_camera_mode_tag_recognition: 'Tag recognition', + robotis_ai_camera_mode_object_classification: 'Object classification', + robotis_ai_camera_target_block: 'Rectangle', + robotis_ai_camera_target_arrow: 'Arrow', + robotis_ai_camera_center_block_center_x: 'Center X', + robotis_ai_camera_center_block_center_y: 'Center Y', + robotis_ai_camera_center_block_width: 'Width', + robotis_ai_camera_center_block_height: 'Height', + robotis_ai_camera_center_leared_id: 'Learned ID', + robotis_ai_camera_center_arrow_origin_x: 'Origin X', + robotis_ai_camera_center_arrow_origin_y: 'Origin Y', + robotis_ai_camera_center_arrow_target_x: 'Target X', + robotis_ai_camera_center_arrow_target_y: 'Target Y', + + robotis_plant_ripe: 'ripe in red', + robotis_plant_unripe: 'green and unripe', + robotis_harvest: 'Harvest', + robotis_not_harvest: 'Skip harvesting', + }, + }, + }; + } + getBlocks() { + return { + robotis_robotai_lite_drive_simple: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveF, '1'], + [Lang.Blocks.robotis_moveB, '2'], + [Lang.Blocks.robotis_moveL_in_place, '3'], + [Lang.Blocks.robotis_moveR_in_place, '4'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [5, null, null], + type: 'robotis_robotai_lite_drive_simple', + }, + paramsKeyMap: { + SPEED: 0, + DIRECTION: 1, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + const speed = script.getNumberValue('SPEED', script); + const direction = script.getField('DIRECTION', script); + + const data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + const data_address = 710; + const data_length = 2; + let data_value = 0; + + switch (direction) { + case '1': + data_value = speed * 256 + speed; + break; + case '2': + data_value = (256 - speed) * 256 + (256 - speed); + break; + case '3': + data_value = speed * 256 + (256 - speed); + break; + case '4': + data_value = (256 - speed) * 256 + speed; + break; + default: + data_value = 0; + break; + } + + const data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.go_simple(%1, %2)'], + }, + }, + robotis_robotai_lite_drive_stop: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_drive_stop', + }, + paramsKeyMap: { + DIRECTION: 0, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 710; + let data_length = 2; + let data_value = 0; + + let data_sendqueue = [ + [data_instruction, 5200, 1, 0], + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.stop(%1, %2)'], + }, + }, + robotis_robotai_lite_drive_advanced: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveF, '1'], + [Lang.Blocks.robotis_moveB, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveF, '1'], + [Lang.Blocks.robotis_moveB, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['5'], + }, + null, + { + type: 'number', + params: ['5'], + }, + null, + ], + type: 'robotis_robotai_lite_drive_advanced', + }, + paramsKeyMap: { + LEFT_SPEED: 0, + LEFT_DIRECTION: 1, + RIGHT_SPEED: 2, + RIGHT_DIRECTION: 3, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let leftSpeed = script.getNumberValue('LEFT_SPEED', script); + const leftDirection = script.getField('LEFT_DIRECTION', script); + let rightSpeed = script.getNumberValue('RIGHT_SPEED', script); + const rightDirection = script.getField('RIGHT_DIRECTION', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 710; + let data_length = 2; + let data_value = 0; + + if (leftSpeed < -100) { + leftSpeed = -100; + } else if (leftSpeed > 100) { + leftSpeed = 100; + } + + if (rightSpeed < -100) { + rightSpeed = -100; + } else if (rightSpeed > 100) { + rightSpeed = 100; + } + + if (leftDirection == '2') { + leftSpeed = -leftSpeed; + } + if (rightDirection == '2') { + rightSpeed = -rightSpeed; + } + + if (leftSpeed < 0) { + leftSpeed = 256 + leftSpeed; + } + if (rightSpeed < 0) { + rightSpeed = 256 + rightSpeed; + } + + data_value = leftSpeed + rightSpeed * 256; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.go_advanced(%1, %2)'], + }, + }, + robotis_robotai_lite_drive_seperate: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left, '1'], + [Lang.Blocks.robotis_right, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_direction_forward, '1'], + [Lang.Blocks.robotis_direction_backward, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['5'], + }, + null, + ], + type: 'robotis_robotai_lite_drive_seperate', + }, + paramsKeyMap: { + WHEEL_SIDE: 0, + WHEEL_SPEED: 1, + WHEEL_DIRECTION: 2, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let wheelSide = script.getNumberValue('WHEEL_SIDE', script); + let wheelSpeed = script.getNumberValue('WHEEL_SPEED', script); + let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script); + + let leftSpeed = 0; + let rightSpeed = 0; + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 710; + let data_length = 2; + let data_value = 0; + + if (wheelSpeed < -100) { + wheelSpeed = -100; + } else if (wheelSpeed > 100) { + wheelSpeed = 100; + } + + wheelSpeed = (wheelSpeed + 256) % 256; + if (wheelDirection == '2') { + wheelSpeed = (256 - wheelSpeed) % 256; + } + + if (wheelSide == 1) { + leftSpeed = wheelSpeed; + rightSpeed = 127; // 속도제어 안함 + } else { + leftSpeed = 127; // 속도제어 안함 + rightSpeed = wheelSpeed; + } + + data_value = leftSpeed + rightSpeed * 256; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 25 //DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.go_seperate(%1, %2)'], + }, + }, + robotis_robotai_lite_drive_angle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left, '1'], + [Lang.Blocks.robotis_right, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_direction_forward, '1'], + [Lang.Blocks.robotis_direction_backward, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['15'], + }, + null, + ], + type: 'robotis_robotai_lite_drive_angle', + }, + paramsKeyMap: { + WHEEL_SIDE: 0, + WHEEL_ANGLE: 1, + WHEEL_DIRECTION: 2, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let wheelSide = script.getNumberValue('WHEEL_SIDE', script); + let wheelAngle = script.getNumberValue('WHEEL_ANGLE', script); + let wheelDirection = script.getNumberValue('WHEEL_DIRECTION', script); + + const data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 580; + let data_length = 8; + let angleValue = 0; + let id = 51 + wheelSide; + let data_buf = []; + let i = 0; + let speed = 150; + + if (wheelDirection == '2') { + wheelAngle = -wheelAngle; + } + + wheelAngle = Math.round((wheelAngle * 4096) / 360); + + if (wheelAngle > 65535) { + wheelAngle = 65535; + } else if (wheelAngle < -65535) { + wheelAngle = -65535; + } + + angleValue = wheelAngle; + if (wheelAngle < 0) { + angleValue = 65536 + angleValue; + } + + data_buf.push(id); + data_buf.push(0); + data_buf.push(speed % 256); + data_buf.push(Math.floor(speed / 256)); + data_buf.push(angleValue % 256); + data_buf.push(Math.floor(angleValue / 256) % 256); + if (wheelAngle >= 0) { + data_buf.push(0); + data_buf.push(0); + } else { + data_buf.push(0xff); + data_buf.push(0xff); + } + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.go_angle(%1, %2)'], + }, + }, + robotis_robotai_lite_go_distance: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveF, '1'], + [Lang.Blocks.robotis_moveB, '-1'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['10'], + }, + null, + ], + type: 'robotis_robotai_lite_go_distance', + }, + + paramsKeyMap: { + DISTANCE: 0, + DIRECTION: 1, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(entity, script) { + let distance = script.getNumberValue('DISTANCE', script); + let direction = script.getField('DIRECTION', script); + + if (distance > 1000) { + distance = 1000; + } else if (distance < -1000) { + distance = -1000; + } + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 270; + let data_length = 4; + let data_value = Math.floor(10 * distance * direction); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + data_sendqueue.push([data_instruction, 66, 2, 50491]); + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 150 * Math.abs(distance) + 1200 + //DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.dxl_each_control(%1)'] }, + }, + + robotis_robotai_lite_turn_angle: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveL_in_place, '1'], + [Lang.Blocks.robotis_moveR_in_place, '-1'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['90'], + }, + null, + ], + type: 'robotis_robotai_lite_turn_angle', + }, + + paramsKeyMap: { + ANGLE: 0, + DIRECTION: 1, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(entity, script) { + let angle = script.getNumberValue('ANGLE', script); + let direction = script.getNumberValue('DIRECTION', script); + + angle *= direction; + + if (angle > 720) { + angle = 720; + } else if (angle < -720) { + angle = -720; + } + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 270; + let data_length = 4; + let data_value = Math.floor(angle); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + data_sendqueue.push([data_instruction, 66, 2, 50492]); + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + Math.abs(angle) * 16 + 1500 + //DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.dxl_each_control(%1)'] }, + }, + robotis_robotai_lite_follow_line: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['느린', '1'], + ['보통', '2'], + ['빠른', '3'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_follow_line', + }, + paramsKeyMap: { + SPEED: 0, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let speed_level = script.getNumberValue('SPEED', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 5200; + let data_length = 1; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, speed_level], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.follow_line(%1)'], + }, + }, + robotis_robotai_lite_stop_at_cross: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_line_cross_type_5, '5'], + [Lang.Blocks.robotis_line_cross_type_6, '6'], + [Lang.Blocks.robotis_line_cross_type_7, '7'], + [Lang.Blocks.robotis_line_cross_type_8, '8'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_stop_at_cross', + }, + paramsKeyMap: { + CROSS: 0, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + async func(sprite, script) { + // instruction / address / length / value / default length + let cross_type = script.getNumberValue('CROSS', script); + let data_address = 5201; + + // max 10 seconds + for (let i = 0; i < 100; i++) { + await Entry.Utils.sleep(100); + if (Entry.RobotisRobotaiLite.dataBuffer[data_address] == cross_type) { + break; + } + if (Entry.engine.isState('stop') == true) { + break; + } + } + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 5200, 1, 0]]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.stop_at_cross(%1)'], + }, + }, + robotis_robotai_lite_turn_at_line: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_moveL_in_place, '0'], + [Lang.Blocks.robotis_moveR_in_place, '1'], + [Lang.Blocks.robotis_moveU_in_place, '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_turn_at_line', + }, + paramsKeyMap: { + TURN_TYPE: 0, + }, + class: 'robotis_robotai_lite_move', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let turn_type = script.getNumberValue('TURN_TYPE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 66; + let data_length = 2; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, 50045 + turn_type], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.follow_line(%1)'], + }, + }, + robotis_robotai_lite_securitybot_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_securitybot_init', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2110, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 1100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.securitybot_init()'], + }, + }, + robotis_robotai_lite_securitybot_hi: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_securitybot_hi', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2111, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotailite.securitybot_hi()'], + }, + }, + robotis_robotai_lite_securitybot_alert: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_securitybot_alert', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2112, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotailite.securitybot_alert()'], + }, + }, + robotis_robotai_lite_petbot_happy: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_petbot_happy', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2121, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 7100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.petbot_happy()'], + }, + }, + robotis_robotai_lite_petbot_sad: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_petbot_sad', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2122, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 2500 + ); + }, + syntax: { + js: [], + py: ['Robotailite.petbot_sad()'], + }, + }, + + robotis_robotai_lite_farmbot_init: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_farmbot_init', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2130, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 3000 + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_init()'], + }, + }, + robotis_robotai_lite_farmbot_seek: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_farmbot_seek', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, 2131, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn(script, data_sendqueue, 200); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_seek()'], + }, + }, + robotis_robotai_lite_farmbot_plant_type: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_plant_ripe, '1'], + [Lang.Blocks.robotis_plant_unripe, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_farmbot_plant_type', + }, + paramsKeyMap: { + TYPE: 0, + }, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let compareValue = script.getNumberValue('TYPE'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[2134]; + + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotis.farmbot_is_type(%1)'], + }, + }, + robotis_robotai_lite_farmbot_harvest_or_not_and_go: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_harvest, '1'], + [Lang.Blocks.robotis_not_harvest, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_farmbot_harvest_or_not_and_go', + }, + paramsKeyMap: { + ACTION: 0, + }, + class: 'robotis_robotai_lite_special', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let action = script.getNumberValue('ACTION', script); + let address = 2132; + let wait_time = 6000; + + switch (action) { + case 1: + address = 2132; + wait_time = 6500; + break; + + case 2: + address = 2133; + wait_time = 2100; + break; + } + + let data_sendqueue = [[Entry.Robotis_rb.INSTRUCTION.WRITE, address, 1, 1]]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + wait_time + ); + }, + syntax: { + js: [], + py: ['Robotis.farmbot_harvest_or_not_and_go(%1)'], + }, + }, + + robotis_robotai_lite_cm_ir_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_front_right, '360'], + [Lang.Blocks.robotis_front_left, '362'], + [Lang.Blocks.robotis_bottom_right, '364'], + [Lang.Blocks.robotis_bottom_left, '366'], + [Lang.Blocks.robotis_side_right, '368'], + [Lang.Blocks.robotis_side_left, '370'], + ], + value: '360', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_cm_ir_value', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + const scope = script.executor.scope; + + const data_default_address = script.getNumberValue('VALUE'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_default_address]; + if (result == undefined) { + result = rb100_last_valid_value[data_default_address]; + } else { + rb100_last_valid_value[data_default_address] = result; + } + if (typeof result == 'undefined') { + return 0; + } + return Math.round((result % 65536) / 2); + }, + syntax: { + js: [], + py: ['Robotailite.ir_value(%1)'], + }, + }, + robotis_robotai_lite_cm_ir_compare: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_front_right, '360'], + [Lang.Blocks.robotis_front_left, '362'], + [Lang.Blocks.robotis_bottom_right, '364'], + [Lang.Blocks.robotis_bottom_left, '366'], + [Lang.Blocks.robotis_side_right, '368'], + [Lang.Blocks.robotis_side_left, '370'], + ], + value: '360', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_if_greater, '0'], + [Lang.Blocks.robotis_if_smaller, '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, 50, null], + type: 'robotis_robotai_lite_cm_ir_compare', + }, + paramsKeyMap: { + VALUE: 0, + COMPARE_VAL: 1, + COMPARE_OP: 2, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = script.getNumberValue('VALUE'); + let compareValue = script.getNumberValue('COMPARE_VAL'); + let compareOP = script.getNumberValue('COMPARE_OP'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (result == undefined) { + return false; + } + + result = Math.round((result % 65536) / 2); + + switch (compareOP) { + case 0: + return result > compareValue; + case 1: + return result < compareValue; + default: + return false; + } + }, + syntax: { + js: [], + py: ['Robotailite.ir_compare(%1)'], + }, + }, + robotis_robotai_lite_detectFrontObj: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_front, '0'], + [Lang.Blocks.robotis_right, '1'], + [Lang.Blocks.robotis_left, '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_detectFrontObj', + }, + paramsKeyMap: { + DIRECTION: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + // instruction / address / length / value / default length + let direction = script.getNumberValue('DIRECTION'); + let ir_1 = 0; + let ir_2 = 0; + + if (direction == 0) { + ir_1 = Entry.RobotisRobotaiLite.dataBuffer[360]; + ir_2 = Entry.RobotisRobotaiLite.dataBuffer[362]; + if (ir_1 == undefined) { + ir_1 = 0; + } + if (ir_2 == undefined) { + ir_2 = 0; + } + return ir_1 > 100 || ir_2 > 100; + } else if (direction == 1) { + ir_1 = Entry.RobotisRobotaiLite.dataBuffer[368]; + if (ir_1 == undefined) { + ir_1 = 0; + } + return ir_1 > 100; + } else if (direction == 2) { + ir_1 = Entry.RobotisRobotaiLite.dataBuffer[370]; + if (ir_1 == undefined) { + ir_1 = 0; + } + return ir_1 > 100; + } + }, + syntax: { + js: [], + py: ['Robotailite.detectFrontObj()'], + }, + }, + robotis_robotai_lite_cm_btn_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_blue, '47'], + [Lang.Blocks.robotis_red, '44'], + ], + value: '47', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_cm_btn_value', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = script.getNumberValue('VALUE'); + let compareValue = 1; + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.btn_value(%1)'], + }, + }, + robotis_robotai_lite_cm_joystick_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_center, '0'], + ['←', '1'], + ['→', '2'], + ['↑', '3'], + ['↓', '4'], + ['↖', '5'], + ['↗', '6'], + ['↙', '7'], + ['↘', '8'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_cm_joystick_value', + }, + paramsKeyMap: { + COMPARE_VAL: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 50; + let compareValue = script.getNumberValue('COMPARE_VAL', script); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.joystick_value()'], + }, + }, + robotis_robotai_lite_mic: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_mic', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + async func(sprite, script) { + let scope = script.executor.scope; + let data_address = 119; + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + return result; + }, + syntax: { + js: [], + py: ['Robotailite.mic()'], + }, + }, + robotis_robotai_lite_detectSound_compare: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left, '1'], + [Lang.Blocks.robotis_center, '0'], + [Lang.Blocks.robotis_right, '255'], + ], + value: '255', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_detectSound_compare', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 5031; + let compareValue = script.getNumberValue('VALUE'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.detectSound_compare(%1)'], + }, + }, + robotis_robotai_lite_imu: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['x', '78'], //72 + ['y', '80'], //74 + ['z', '82'], //76 + ], + value: '78', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_acceleration, '0'], //72 + [Lang.Blocks.robotis_gyro, '6'], //74 + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_imu', + }, + paramsKeyMap: { + AXIS: 0, + MODE: 1, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = + script.getField('AXIS', script) - script.getField('MODE', script); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + return result; + }, + syntax: { + js: [], + py: ['Robotailite.imu()'], + }, + }, + robotis_robotai_lite_roll_pitch: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_roll, '70'], //72 + [Lang.Blocks.robotis_pitch, '88'], //74 + ], + value: '70', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_roll_pitch', + }, + paramsKeyMap: { + AXIS: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = script.getNumberValue('AXIS'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + return result; + }, + syntax: { + js: [], + py: ['Robotailite.roll_pitch(%1)'], + }, + }, + robotis_robotai_lite_environment_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_sensing_temperature, '28'], + [Lang.Blocks.robotis_sensing_humidity, '29'], + [Lang.Blocks.robotis_sensing_brightness, '30'], + [Lang.Blocks.robotis_sensing_motion, '27'], + ], + value: '28', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_environment_value', + }, + paramsKeyMap: { + ADDR: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = script.getNumberValue('ADDR'); + + let result = 0; + + switch (data_address) { + case 28: + result = Entry.RobotisRobotaiLite.pirTemperature[0]; + break; + + case 29: + result = Entry.RobotisRobotaiLite.pirHumidity[0]; + break; + + case 30: + result = Entry.RobotisRobotaiLite.pirBrightness[0]; + break; + + case 27: + result = Entry.RobotisRobotaiLite.pirPir[0]; + break; + } + + if (typeof result == 'undefined') { + return 0; + } else { + // temperature + if (data_address == 28) { + result = result % 256; + if (result > 128) { + result = result - 256; + } + } + } + return result; + }, + syntax: { + js: [], + py: ['Robotailite.environment_value(%1)'], + }, + }, + robotis_robotai_lite_environment_compare: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_sensing_temperature, '28'], + [Lang.Blocks.robotis_sensing_humidity, '29'], + [Lang.Blocks.robotis_sensing_brightness, '30'], + [Lang.Blocks.robotis_sensing_motion, '27'], + ], + value: '28', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + value: 'asdfasdf', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_if_greater, '0'], + [Lang.Blocks.robotis_if_smaller, '1'], + [Lang.Blocks.robotis_if_equal, '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: [0], + }, + null, + ], + type: 'robotis_robotai_lite_environment_compare', + }, + paramsKeyMap: { + ADDR: 0, + COMPARE_VAL: 1, + COMPARE_OP: 2, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + let data_address = script.getNumberValue('ADDR'); + let compareValue = script.getNumberValue('COMPARE_VAL'); + let compareOP = script.getNumberValue('COMPARE_OP'); + + let result = 0; + + switch (data_address) { + case 28: + result = Entry.RobotisRobotaiLite.pirTemperature[0]; + break; + + case 29: + result = Entry.RobotisRobotaiLite.pirHumidity[0]; + break; + + case 30: + result = Entry.RobotisRobotaiLite.pirBrightness[0]; + break; + + case 27: + result = Entry.RobotisRobotaiLite.pirPir[0]; + break; + } + + if (typeof result == 'undefined') { + return false; + } + + switch (compareOP) { + case 0: + return result > compareValue; + case 1: + return result < compareValue; + case 2: + return result == compareValue; + default: + return false; + } + }, + syntax: { + js: [], + py: ['Robotailite.environment_compare(%1)'], + }, + }, + robotis_robotai_lite_dxl_value: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_value_angle, '1'], + [Lang.Blocks.robotis_dxl_value_velocity, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [52, null], + type: 'robotis_robotai_lite_dxl_value', + }, + paramsKeyMap: { + ID: 0, + TYPE: 1, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + let dxl_id = script.getNumberValue('ID'); + //var data_type = script.getNumberValue('TYPE'); + + let result = Entry.RobotisRobotaiLite.dxlPositions[dxl_id]; + + if (typeof result == 'undefined') { + return 0; + } + result = 180 - Math.round((result * 360) / 4096); + while (result < -180) { + result += 360; + } + while (result > 180) { + result -= 360; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.get_dxl_value(%1)'], + }, + }, + robotis_robotai_lite_line_cross_compare: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_line_cross_type_5, '5'], + [Lang.Blocks.robotis_line_cross_type_6, '6'], + [Lang.Blocks.robotis_line_cross_type_7, '7'], + [Lang.Blocks.robotis_line_cross_type_8, '8'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_line_cross_compare', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'robotis_robotai_lite_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 5201; + let compareValue = script.getNumberValue('VALUE'); + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.line_cross_compare(%1)'], + }, + }, + + robotis_robotai_lite_screen: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_kkokdu, '3'], + [Lang.Blocks.robotis_rla, '2'], + [Lang.Blocks.robotis_rgee, '0'], + ], + value: '3', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_car_anim01, '2817'], + [Lang.Blocks.robotis_car_anim02, '2818'], + [Lang.Blocks.robotis_car_anim03, '2819'], + [Lang.Blocks.robotis_car_anim04, '2820'], + [Lang.Blocks.robotis_car_anim05, '2821'], + + [Lang.Blocks.robotis_car_anim06, '2822'], + //[Lang.Blocks.robotis_car_anim07, '2823'], + [Lang.Blocks.robotis_car_anim08, '2824'], + [Lang.Blocks.robotis_car_anim09, '2825'], + [Lang.Blocks.robotis_car_anim10, '2826'], + + [Lang.Blocks.robotis_car_anim11, '2827'], + [Lang.Blocks.robotis_car_anim12, '2828'], + //[Lang.Blocks.robotis_car_anim13, '2829'], + [Lang.Blocks.robotis_car_anim14, '2830'], + [Lang.Blocks.robotis_car_anim15, '2831'], + + [Lang.Blocks.robotis_car_anim16, '2832'], + [Lang.Blocks.robotis_car_anim17, '2833'], + [Lang.Blocks.robotis_car_anim18, '2834'], + [Lang.Blocks.robotis_car_anim19, '2835'], + ], + value: '2817', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_screen', + }, + paramsKeyMap: { + ROBOT_TYPE: 0, + BACKGROUND: 1, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let robotType = script.getNumberValue('ROBOT_TYPE', script); + let screenValue = script.getNumberValue('BACKGROUND', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 163; + let data_length = 2; + let data_value = screenValue + robotType * 256; + + if (robotType == 0) { + switch (screenValue) { + case 2817: + data_value = 2841; + break; + + case 2818: + data_value = 2842; + break; + + case 2819: + data_value = 2820; + break; + + case 2820: + data_value = 2817; + break; + + case 2821: + data_value = 2819; + break; + + case 2822: + data_value = 2818; + break; + + //case 2823: + // break; + + case 2824: + data_value = 2826; + break; + + case 2825: + data_value = 2836; + break; + + case 2826: + data_value = 2837; + break; + + case 2827: + data_value = 2843; + break; + + case 2828: + data_value = 2831; + break; + + //case 2829: + // break; + + case 2830: + data_value = 2833; + break; + + case 2831: + data_value = 2834; + break; + + case 2832: + data_value = 2828; + break; + + case 2833: + data_value = 2827; + break; + + case 2834: + data_value = 2829; + break; + + case 2835: + data_value = 2840; + break; + + default: + data_value = 2841; + break; + } + } + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + [3, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { js: [], py: ['Robotailite.screen(%1)'] }, + }, + + robotis_robotai_lite_anim_screen: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_kkokdu, '1'], + [Lang.Blocks.robotis_rla, '0'], + [Lang.Blocks.robotis_rgee, '-1'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_car_anim01, '30978'], + [Lang.Blocks.robotis_car_anim02, '30981'], + //[Lang.Blocks.robotis_car_anim03, '30982'], + [Lang.Blocks.robotis_car_anim04, '30983'], + [Lang.Blocks.robotis_car_anim05, '30984'], + + [Lang.Blocks.robotis_car_anim06, '30985'], + [Lang.Blocks.robotis_car_anim07, '30986'], + [Lang.Blocks.robotis_car_anim08, '30987'], + [Lang.Blocks.robotis_car_anim09, '30988'], + [Lang.Blocks.robotis_car_anim10, '30989'], + + [Lang.Blocks.robotis_car_anim11, '30990'], + [Lang.Blocks.robotis_car_anim12, '30991'], + //[Lang.Blocks.robotis_car_anim13, '30992'], + [Lang.Blocks.robotis_car_anim14, '30993'], + [Lang.Blocks.robotis_car_anim15, '30994'], + + [Lang.Blocks.robotis_car_anim16, '30995'], + [Lang.Blocks.robotis_car_anim17, '30996'], + [Lang.Blocks.robotis_car_anim18, '30997'], + [Lang.Blocks.robotis_car_anim19, '30998'], + ], + value: '30978', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_anim_screen', + }, + paramsKeyMap: { + ROBOT_TYPE: 0, + BACKGROUND: 1, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let robotType = script.getNumberValue('ROBOT_TYPE', script); + let screenValue = script.getNumberValue('BACKGROUND', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 163; + let data_length = 2; + let data_value = screenValue; + + if (robotType >= 0) { + data_value += 256 * robotType; + } else { + switch (screenValue) { + case 30978: + data_value = 30724; + break; + + case 30981: + data_value = 30761; + break; + + //case 30982: + // break; + + case 30983: + data_value = 30748; + break; + + case 30984: + data_value = 30750; + break; + + case 30985: + data_value = 30749; + break; + + //case 30986: + // break; + + case 30987: + data_value = 30739; + break; + + case 30988: + data_value = 30751; + break; + + case 30989: + data_value = 30752; + break; + + case 30990: + data_value = 30762; + break; + + case 30991: + data_value = 30736; + break; + + //case 30992: + // break; + + case 30993: + data_value = 30742; + break; + + case 30994: + data_value = 30743; + break; + + case 30995: + data_value = 30734; + break; + + case 30996: + data_value = 30733; + break; + + case 30997: + data_value = 30732; + break; + + case 30998: + data_value = 30760; + break; + + default: + data_value = 30724; + break; + } + } + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + [3, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY //+ 1000 + ); + }, + syntax: { js: [], py: ['Robotailite.animation_screen(%1)'] }, + }, + robotis_robotai_lite_icon_screen_food_plant: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_icon_food_plant_1, '10496'], + [Lang.Blocks.robotis_icon_food_plant_2, '10497'], + [Lang.Blocks.robotis_icon_food_plant_3, '10498'], + [Lang.Blocks.robotis_icon_food_plant_4, '10499'], + [Lang.Blocks.robotis_icon_food_plant_5, '10500'], + [Lang.Blocks.robotis_icon_food_plant_6, '10501'], + [Lang.Blocks.robotis_icon_food_plant_7, '10502'], + [Lang.Blocks.robotis_icon_food_plant_8, '10503'], + [Lang.Blocks.robotis_icon_food_plant_9, '10504'], + [Lang.Blocks.robotis_icon_food_plant_10, '10505'], + [Lang.Blocks.robotis_icon_food_plant_11, '10506'], + [Lang.Blocks.robotis_icon_food_plant_12, '10507'], + [Lang.Blocks.robotis_icon_food_plant_13, '10508'], + [Lang.Blocks.robotis_icon_food_plant_14, '10509'], + [Lang.Blocks.robotis_icon_food_plant_15, '10510'], + [Lang.Blocks.robotis_icon_food_plant_16, '10511'], + [Lang.Blocks.robotis_icon_food_plant_17, '10512'], + [Lang.Blocks.robotis_icon_food_plant_18, '10513'], + [Lang.Blocks.robotis_icon_food_plant_19, '10514'], + [Lang.Blocks.robotis_icon_food_plant_20, '10515'], + [Lang.Blocks.robotis_icon_food_plant_21, '10516'], + [Lang.Blocks.robotis_icon_food_plant_22, '10517'], + [Lang.Blocks.robotis_icon_food_plant_23, '10518'], + [Lang.Blocks.robotis_icon_food_plant_24, '10519'], + ], + value: '10496', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 50, + null, + ], + type: 'robotis_robotai_lite_icon_screen_food_plant', + }, + paramsKeyMap: { + ICON: 0, + X: 1, + Y: 2, + SIZE: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let iconNum = script.getField('ICON', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let size = script.getNumberValue('SIZE', script) * 2; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 166; + let data_length = 2; + let data_value = 10496; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + if (size < 0) { + size = 0; + } else if (size > 400) { + size = 400; + } + + data_value = iconNum; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size], + [data_instruction, data_address, data_length, data_value], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.icon_screen_food_and_plant(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_icon_screen_animal_human: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_icon_animal_human_1, '10752'], + [Lang.Blocks.robotis_icon_animal_human_2, '10753'], + [Lang.Blocks.robotis_icon_animal_human_3, '10754'], + [Lang.Blocks.robotis_icon_animal_human_4, '10755'], + [Lang.Blocks.robotis_icon_animal_human_5, '10756'], + [Lang.Blocks.robotis_icon_animal_human_6, '10757'], + [Lang.Blocks.robotis_icon_animal_human_7, '10758'], + [Lang.Blocks.robotis_icon_animal_human_8, '10759'], + [Lang.Blocks.robotis_icon_animal_human_9, '10760'], + [Lang.Blocks.robotis_icon_animal_human_10, '11787'], + [Lang.Blocks.robotis_icon_animal_human_11, '11788'], + [Lang.Blocks.robotis_icon_animal_human_12, '11789'], + [Lang.Blocks.robotis_icon_animal_human_13, '11790'], + [Lang.Blocks.robotis_icon_animal_human_14, '11805'], + [Lang.Blocks.robotis_icon_animal_human_15, '11806'], + [Lang.Blocks.robotis_icon_animal_human_16, '11807'], + [Lang.Blocks.robotis_icon_animal_human_17, '11808'], + [Lang.Blocks.robotis_icon_animal_human_18, '10761'], + [Lang.Blocks.robotis_icon_animal_human_19, '10762'], + [Lang.Blocks.robotis_icon_animal_human_20, '10763'], + [Lang.Blocks.robotis_icon_animal_human_21, '10764'], + [Lang.Blocks.robotis_icon_animal_human_22, '10765'], + [Lang.Blocks.robotis_icon_animal_human_23, '10766'], + [Lang.Blocks.robotis_icon_animal_human_24, '10767'], + [Lang.Blocks.robotis_icon_animal_human_25, '10768'], + [Lang.Blocks.robotis_icon_animal_human_26, '10769'], + [Lang.Blocks.robotis_icon_animal_human_27, '10770'], + [Lang.Blocks.robotis_icon_animal_human_28, '10771'], + [Lang.Blocks.robotis_icon_animal_human_29, '10772'], + [Lang.Blocks.robotis_icon_animal_human_30, '10773'], + [Lang.Blocks.robotis_icon_animal_human_31, '10774'], + [Lang.Blocks.robotis_icon_animal_human_32, '10775'], + [Lang.Blocks.robotis_icon_animal_human_33, '10776'], + [Lang.Blocks.robotis_icon_animal_human_34, '10777'], + ], + value: '10752', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 50, + null, + ], + type: 'robotis_robotai_lite_icon_screen_animal_human', + }, + paramsKeyMap: { + ICON: 0, + X: 1, + Y: 2, + SIZE: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let iconNum = script.getField('ICON', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let size = script.getNumberValue('SIZE', script) * 2; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 166; + let data_length = 2; + let data_value = 10496; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + if (size < 0) { + size = 0; + } else if (size > 400) { + size = 400; + } + + data_value = iconNum; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size], + [data_instruction, data_address, data_length, data_value], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.icon_screen_animal_and_human(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_icon_screen_object_tool: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_icon_object_tool_1, '11008'], + [Lang.Blocks.robotis_icon_object_tool_2, '11009'], + [Lang.Blocks.robotis_icon_object_tool_3, '11010'], + [Lang.Blocks.robotis_icon_object_tool_4, '11011'], + [Lang.Blocks.robotis_icon_object_tool_5, '11012'], + [Lang.Blocks.robotis_icon_object_tool_6, '11013'], + [Lang.Blocks.robotis_icon_object_tool_7, '11014'], + [Lang.Blocks.robotis_icon_object_tool_8, '11015'], + [Lang.Blocks.robotis_icon_object_tool_9, '11016'], + [Lang.Blocks.robotis_icon_object_tool_10, '11017'], + [Lang.Blocks.robotis_icon_object_tool_11, '11018'], + [Lang.Blocks.robotis_icon_object_tool_12, '11019'], + [Lang.Blocks.robotis_icon_object_tool_13, '11020'], + [Lang.Blocks.robotis_icon_object_tool_14, '11021'], + [Lang.Blocks.robotis_icon_object_tool_15, '11022'], + [Lang.Blocks.robotis_icon_object_tool_16, '11023'], + [Lang.Blocks.robotis_icon_object_tool_17, '11024'], + [Lang.Blocks.robotis_icon_object_tool_18, '11025'], + [Lang.Blocks.robotis_icon_object_tool_19, '11026'], + [Lang.Blocks.robotis_icon_object_tool_20, '11027'], + [Lang.Blocks.robotis_icon_object_tool_21, '11028'], + [Lang.Blocks.robotis_icon_object_tool_22, '11029'], + [Lang.Blocks.robotis_icon_object_tool_23, '11030'], + [Lang.Blocks.robotis_icon_object_tool_24, '11031'], + [Lang.Blocks.robotis_icon_object_tool_25, '11032'], + [Lang.Blocks.robotis_icon_object_tool_26, '11033'], + [Lang.Blocks.robotis_icon_object_tool_27, '11034'], + [Lang.Blocks.robotis_icon_object_tool_28, '11035'], + [Lang.Blocks.robotis_icon_object_tool_29, '11036'], + [Lang.Blocks.robotis_icon_object_tool_30, '11037'], + [Lang.Blocks.robotis_icon_object_tool_31, '11038'], + [Lang.Blocks.robotis_icon_object_tool_32, '11039'], + [Lang.Blocks.robotis_icon_object_tool_33, '11040'], + [Lang.Blocks.robotis_icon_object_tool_34, '11801'], + [Lang.Blocks.robotis_icon_object_tool_35, '11802'], + [Lang.Blocks.robotis_icon_object_tool_36, '11809'], + ], + value: '11008', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 50, + null, + ], + type: 'robotis_robotai_lite_icon_screen_object_tool', + }, + paramsKeyMap: { + ICON: 0, + X: 1, + Y: 2, + SIZE: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let iconNum = script.getField('ICON', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let size = script.getNumberValue('SIZE', script) * 2; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 166; + let data_length = 2; + let data_value = 10496; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + if (size < 0) { + size = 0; + } else if (size > 400) { + size = 400; + } + + data_value = iconNum; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size], + [data_instruction, data_address, data_length, data_value], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.icon_screen_object_and_tool(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_icon_screen_vehicle_number: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_icon_vehicle_number_1, '11264'], + [Lang.Blocks.robotis_icon_vehicle_number_2, '11265'], + [Lang.Blocks.robotis_icon_vehicle_number_3, '11266'], + [Lang.Blocks.robotis_icon_vehicle_number_4, '11267'], + [Lang.Blocks.robotis_icon_vehicle_number_5, '11268'], + [Lang.Blocks.robotis_icon_vehicle_number_6, '11269'], + [Lang.Blocks.robotis_icon_vehicle_number_7, '11270'], + [Lang.Blocks.robotis_icon_vehicle_number_8, '11271'], + [Lang.Blocks.robotis_icon_vehicle_number_9, '11272'], + [Lang.Blocks.robotis_icon_vehicle_number_10, '11273'], + [Lang.Blocks.robotis_icon_vehicle_number_11, '11274'], + [Lang.Blocks.robotis_icon_vehicle_number_12, '11275'], + [Lang.Blocks.robotis_icon_vehicle_number_13, '11276'], + [Lang.Blocks.robotis_icon_vehicle_number_14, '11776'], + [Lang.Blocks.robotis_icon_vehicle_number_15, '11777'], + [Lang.Blocks.robotis_icon_vehicle_number_16, '11778'], + [Lang.Blocks.robotis_icon_vehicle_number_17, '11779'], + [Lang.Blocks.robotis_icon_vehicle_number_18, '11780'], + [Lang.Blocks.robotis_icon_vehicle_number_19, '11781'], + [Lang.Blocks.robotis_icon_vehicle_number_20, '11782'], + [Lang.Blocks.robotis_icon_vehicle_number_21, '11783'], + [Lang.Blocks.robotis_icon_vehicle_number_22, '11277'], + [Lang.Blocks.robotis_icon_vehicle_number_23, '11278'], + [Lang.Blocks.robotis_icon_vehicle_number_24, '11279'], + [Lang.Blocks.robotis_icon_vehicle_number_25, '11280'], + [Lang.Blocks.robotis_icon_vehicle_number_26, '11281'], + [Lang.Blocks.robotis_icon_vehicle_number_27, '11282'], + [Lang.Blocks.robotis_icon_vehicle_number_28, '11283'], + [Lang.Blocks.robotis_icon_vehicle_number_29, '11284'], + [Lang.Blocks.robotis_icon_vehicle_number_30, '11285'], + [Lang.Blocks.robotis_icon_vehicle_number_31, '11286'], + [Lang.Blocks.robotis_icon_vehicle_number_32, '11287'], + [Lang.Blocks.robotis_icon_vehicle_number_33, '11288'], + [Lang.Blocks.robotis_icon_vehicle_number_34, '11289'], + [Lang.Blocks.robotis_icon_vehicle_number_35, '11290'], + [Lang.Blocks.robotis_icon_vehicle_number_36, '11291'], + [Lang.Blocks.robotis_icon_vehicle_number_37, '11292'], + [Lang.Blocks.robotis_icon_vehicle_number_38, '11293'], + ], + value: '11264', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 50, + null, + ], + type: 'robotis_robotai_lite_icon_screen_vehicle_number', + }, + paramsKeyMap: { + ICON: 0, + X: 1, + Y: 2, + SIZE: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let iconNum = script.getField('ICON', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let size = script.getNumberValue('SIZE', script) * 2; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 166; + let data_length = 2; + let data_value = 10496; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + if (size < 0) { + size = 0; + } else if (size > 400) { + size = 400; + } + + data_value = iconNum; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 130, 2, x], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 132, 2, y], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 149, 2, size], + [data_instruction, data_address, data_length, data_value], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.icon_screen_vehicle_and_number(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_text_screen: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_screen_text_font_small, '0'], + [Lang.Blocks.robotis_screen_text_font_big, '1'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + ' ', + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + null, + null, + ], + type: 'robotis_robotai_lite_text_screen', + }, + paramsKeyMap: { + TEXT: 0, + X: 1, + Y: 2, + FONT: 3, + COLOR: 4, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let text = script.getStringValue('TEXT', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let font = script.getNumberValue('FONT', script); + let color = script.getNumberValue('COLOR', script); + let data_buf = []; + let i = 0; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 900; + let data_length = 2; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + let encoder = new TextEncoder('utf-8'); + let byteArray = encoder.encode(text); + + data_buf.push(x % 256); + data_buf.push(Math.floor(x / 256)); + data_buf.push(y % 256); + data_buf.push(Math.floor(y / 256)); + data_buf.push(font); + data_buf.push(0); + data_buf.push(0); + data_buf.push(color); + data_buf.push(byteArray.length); + for (i = 0; i < byteArray.length; i++) { + data_buf.push(byteArray[i]); + } + + data_length = 9 + byteArray.length; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 200 + ); + }, + syntax: { + js: [], + py: ['Robotailite.text_screen(%1,%2,%3,%4,%5)'], + }, + }, + robotis_robotai_lite_pixel: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + null, + ], + type: 'robotis_robotai_lite_pixel', + }, + paramsKeyMap: { + X: 0, + Y: 1, + COLOR: 2, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let color = script.getNumberValue('COLOR', script); + let data_buf = []; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 130; + let data_length = 11; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + data_buf.push(x % 256); + data_buf.push(Math.floor(x / 256)); + data_buf.push(y % 256); + data_buf.push(Math.floor(y / 256)); + data_buf.push(0); + data_buf.push(0); + data_buf.push(0); + data_buf.push(0); + data_buf.push(0); + data_buf.push(0); + data_buf.push(color); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 161, 2, 1 * 256 + 8], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.pixel(%1,%2,%3)'], + }, + }, + robotis_robotai_lite_text_screen_redraw: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + ' ', + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + null, + ], + type: 'robotis_robotai_lite_text_screen_redraw', + }, + paramsKeyMap: { + TEXT: 0, + X: 1, + Y: 2, + COLOR: 3, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let text = script.getStringValue('TEXT', script); + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let font = 0; + let color = script.getNumberValue('COLOR', script); + let data_buf = []; + let i = 0; + + if (x < -160) { + x = -160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = -120; + } else if (y > 120) { + y = 120; + } + + let encoder = new TextEncoder('utf-8'); + let byteArray = encoder.encode(text); + + data_buf.push(x % 256); + data_buf.push(Math.floor(x / 256)); + data_buf.push(y % 256); + data_buf.push(Math.floor(y / 256)); + data_buf.push(font); + data_buf.push(1); + data_buf.push(bg_color); + data_buf.push(color); + data_buf.push(byteArray.length); + for (i = 0; i < byteArray.length; i++) { + data_buf.push(byteArray[i]); + } + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 900; + let data_length = 9 + byteArray.length; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 162, 1, 1], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.text_screen_redraw(%1,%2,%3,%4)'], + }, + }, + robotis_robotai_lite_LCDBright: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [50], + type: 'robotis_robotai_lite_LCDBright', + }, + paramsKeyMap: { + BRIGHT: 0, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let bright = script.getNumberValue('BRIGHT', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 180; + let data_length = 1; + let data_value = 0; + + bright = Math.min(Math.max(bright, 0), 100); + + data_value = bright; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.LCDBright(%1)'], + }, + }, + robotis_robotai_lite_LCDColor: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '224', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_LCDColor', + }, + paramsKeyMap: { + COLOR: 0, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let color = script.getNumberValue('COLOR', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 163; + let data_length = 2; + let data_value = 0; + + data_value = color; + bg_color = color; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, 2817], + [data_instruction, data_address, data_length, data_value], + [3, 162, 1, 1], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.LCDColor(%1)'], + }, + }, + robotis_robotai_lite_LCD_Flash: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '224', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_red, '224'], + [Lang.Blocks.robotis_orange, '244'], + [Lang.Blocks.robotis_yellow, '252'], + [Lang.Blocks.robotis_green, '28'], + [Lang.Blocks.robotis_blue, '3'], + [Lang.Blocks.robotis_darkblue, '2'], + [Lang.Blocks.robotis_purple, '130'], + [Lang.Blocks.robotis_brown, '173'], + [Lang.Blocks.robotis_black, '0'], + [Lang.Blocks.robotis_white, '255'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [0.3, '3'], + [0.4, '4'], + [0.5, '5'], + [0.6, '6'], + [0.7, '7'], + [0.8, '8'], + [0.9, '9'], + [1.0, '10'], + [1.1, '11'], + [1.2, '12'], + [1.3, '13'], + [1.4, '14'], + [1.5, '15'], + [1.6, '16'], + [1.7, '17'], + [1.8, '18'], + [1.9, '19'], + [2.0, '20'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_LCD_Flash', + }, + paramsKeyMap: { + COLOR_ON: 0, + COLOR_OFF: 1, + PERIOD: 2, + }, + class: 'robotis_robotai_lite_lcd', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + const color_on = script.getNumberValue('COLOR_ON', script); + const color_off = script.getNumberValue('COLOR_OFF', script); + const period = script.getNumberValue('PERIOD', script); + const colors = color_on + (color_off << 8); + + // 0x8000: use flashing mode, + // (period << 8): on time (0.1 sec) + // period: off time (0.1 sec) + const time_parameter = 0x8000 + (period << 8) + period; + + let data_sendqueue = [ + [Entry.Robotis_rb.INSTRUCTION.WRITE, 158, 2, colors], + [Entry.Robotis_rb.INSTRUCTION.WRITE, 163, 2, time_parameter], + ]; + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + 100 + ); + }, + syntax: { + js: [], + py: ['Robotailite.LCD_Flash(%1, %2, %3)'], + }, + }, + + robotis_robotai_lite_cm_led: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left, '1'], + [Lang.Blocks.robotis_right, '2'], + [Lang.Blocks.robotis_both, '3'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_common_on, '1'], + [Lang.Blocks.robotis_common_off, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null, null], + type: 'robotis_robotai_lite_cm_led', + }, + paramsKeyMap: { + RB_LED: 0, + VALUE: 1, + }, + class: 'robotis_robotai_lite_led', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmLed = script.getField('RB_LED', script); + let value = script.getField('VALUE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 40; + let data_length = 1; + let data_value = 0; + + if (cmLed == 1) { + data_value = 200 * value; + } else if (cmLed == 2) { + data_address = 41; + data_value = 200 * value; + } else if (cmLed == 3) { + data_address = 40; + data_length = 2; + data_value = 200 * 257 * value; + } else { + data_value = value * cmLed; + } + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.led(%1, %2)'] }, + }, + robotis_robotai_lite_cm_led_pattern: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_pattern1, '11'], + [Lang.Blocks.robotis_pattern2, '21'], + [Lang.Blocks.robotis_pattern3, '31'], + ], + value: '11', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_speed_fast, '0'], + [Lang.Blocks.robotis_speed_midium, '1'], + [Lang.Blocks.robotis_speed_slow, '2'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null, null], + type: 'robotis_robotai_lite_cm_led_pattern', + }, + paramsKeyMap: { + PATTERN: 0, + SPEED: 1, + }, + class: 'robotis_robotai_lite_led', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let pattern = script.getNumberValue('PATTERN', script); + let speed = script.getNumberValue('SPEED', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 40; + let data_length = 1; + let data_value = 0; + + data_value = pattern + speed; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.led_pattern(%1, %2)'] }, + }, + + robotis_robotai_lite_dxl_set_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_mode_joint, '3'], + [Lang.Blocks.robotis_dxl_mode_wheel, '1'], + [Lang.Blocks.robotis_dxl_mode_multi_turn, '4'], + ], + value: '3', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: ['52', null, null], + type: 'robotis_robotai_lite_dxl_set_mode', + }, + paramsKeyMap: { + DXL_ID: 0, + DXL_MODE: 1, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let dxl_id = script.getNumberValue('DXL_ID', script); + let dxl_mode = script.getField('DXL_MODE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE; + let data_address = 0; + let data_length = 0; + let data_value = 0; + + data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[0]; + data_length = Entry.Robotis_rb.CONTROL_TABLE.DXL_OPERATING_MODE[1]; + + data_value = dxl_mode; + + let data_sendqueue = [ + [ + data_instruction, + Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0], + Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1], + dxl_id, + 0, + ], + [data_instruction, data_address, data_length, dxl_id, data_value], + [ + data_instruction, + Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[0], + Entry.Robotis_rb.CONTROL_TABLE.DXL_TORQUE_ENABLE[1], + dxl_id, + 1, + ], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_dxl_mode(%1, %2)'], + }, + }, + robotis_robotai_lite_dxl_each_control: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + '52', + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['1'], + }, + ], + type: 'robotis_robotai_lite_dxl_each_control', + }, + + paramsKeyMap: { + DXLNUM: 0, + ANGLE: 1, + TIME: 2, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(entity, script) { + let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE; + let data_address = 0; + let data_length = 0; + + data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0]; + data_length = + Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] + + Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1]; + + let dxlID = script.getField('DXLNUM', script); + let angle = script.getNumberValue('ANGLE', script); + let time = script.getNumberValue('TIME', script) * 1000; + let data_buf = []; + + let engValue = 2048; + engValue = Math.floor(2048 - Math.round(angle * 4096) / 360); + let velocity = 0; + + if (time == 0) { + velocity = 0; + } else { + velocity = Math.round( + Math.floor( + (60 * + Math.abs( + engValue - Entry.RobotisRobotaiLite.dxlPositions[dxlID] + ) * + 1000) / + 4096 / + time + ) / 0.229 + ); + } + + data_buf.push(velocity % 256); + data_buf.push(Math.floor(velocity / 256)); + data_buf.push(0); + data_buf.push(0); + + data_buf.push(engValue % 256); + data_buf.push(Math.floor(engValue / 256)); + data_buf.push(0); + data_buf.push(0); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, dxlID, data_buf], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + time + DEFAULT_DELAY + //DEFAULT_DELAY + ); + }, + syntax: { js: [], py: ['Robotailite.dxl_each_control(%1,%2,%3)'] }, + }, + robotis_robotai_lite_dxl_set_position: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: ['52', '50', '0', null], + type: 'robotis_robotai_lite_dxl_set_position', + }, + paramsKeyMap: { + DXL_ID: 0, + DXL_SPEED: 1, + DXL_ANGLE: 2, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let dxl_id = script.getNumberValue('DXL_ID', script); + let dxl_speed = script.getNumberValue('DXL_SPEED', script); + let dxl_angle = script.getNumberValue('DXL_ANGLE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE; + let data_address = 0; + let data_length = 0; + let data_buf = []; + + data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[0]; + data_length = + Entry.Robotis_rb.CONTROL_TABLE.DXL_PROFILE_VELOCITY[1] + + Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_POSITION[1]; + + if (dxl_speed < 0) { + dxl_speed = 0; + } else if (dxl_speed > 100) { + dxl_speed = 100; + } + + data_buf.push((dxl_speed * 10) % 256); + data_buf.push(Math.floor((dxl_speed * 10) / 256)); + data_buf.push(0); + data_buf.push(0); + + if (dxl_angle < -179) { + dxl_angle = -179; + } else if (dxl_angle > 180) { + dxl_angle = 180; + } + + dxl_angle = 180 - dxl_angle; + + data_buf.push(Math.floor((dxl_angle * 4096) / 360) % 256); + data_buf.push(Math.floor((dxl_angle * 4096) / 360 / 256)); + data_buf.push(0); + data_buf.push(0); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, dxl_id, data_buf], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_dxl_position(%1, %2, %3)'], + }, + }, + robotis_robotai_lite_dxl_set_rotate: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_rotate_cw, '1'], + [Lang.Blocks.robotis_dxl_rotate_ccw, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_move_rotate, '1'], + [Lang.Blocks.robotis_dxl_move_stop, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: ['52', '50', null, null, null], + type: 'robotis_robotai_lite_dxl_set_rotate', + }, + paramsKeyMap: { + DXL_ID: 0, + DXL_SPEED: 1, + DXL_DIRECTION: 2, + DXL_MOVE: 3, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let dxl_id = script.getNumberValue('DXL_ID', script); + let dxl_speed = script.getNumberValue('DXL_SPEED', script); + let dxl_direction = script.getNumberValue('DXL_DIRECTION', script); + let dxl_move = script.getNumberValue('DXL_MOVE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.BYPASS_WRITE; + let data_address = 0; + let data_length = 0; + let data_value = 0; + + data_address = Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[0]; + data_length = Entry.Robotis_rb.CONTROL_TABLE.DXL_GOAL_VELOCITY[1]; + + if (dxl_speed < 0) { + dxl_speed = 0; + } else if (dxl_speed > 100) { + dxl_speed = 100; + } + + data_value = dxl_speed * 10; + + // cw일 경우 음수처리 + if (dxl_direction == 1) { + data_value = -data_value; + } + + // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대 + if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) { + data_value = -data_value; + } + + data_value = data_value * dxl_move; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, dxl_id, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_dxl_rotate(%1, %2, %3, %4)'], + }, + }, + robotis_robotai_lite_dxl_set_multiturn_round: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_left_wheel, '52'], + [Lang.Blocks.robotis_right_wheel, '51'], + ['ID 1', '1'], + ['ID 2', '2'], + ['ID 3', '3'], + ['ID 4', '4'], + ['ID 5', '5'], + ['ID 6', '6'], + ['ID 7', '7'], + ['ID 8', '8'], + ], + value: '52', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dxl_rotate_cw, '1'], + [Lang.Blocks.robotis_dxl_rotate_ccw, '2'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: ['52', '50', '1', null, null], + type: 'robotis_robotai_lite_dxl_set_multiturn_round', + }, + paramsKeyMap: { + DXL_ID: 0, + DXL_SPEED: 1, + DXL_ROUND: 2, + DXL_DIRECTION: 3, + }, + class: 'robotis_robotai_lite_dxl', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let dxl_id = script.getNumberValue('DXL_ID', script); + let dxl_speed = script.getNumberValue('DXL_SPEED', script); + let dxl_round = script.getNumberValue('DXL_ROUND', script); + let dxl_direction = script.getNumberValue('DXL_DIRECTION', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address_1 = 0; + let data_length_1 = 0; + let data_value_1 = 0; + let data_address_2 = 0; + let data_length_2 = 0; + let data_value_2 = 0; + let data_address_3 = 0; + let data_length_3 = 0; + let data_value_3 = 0; + + let data_sendqueue = []; + let result = undefined; + + if (dxl_id == 0 || dxl_speed == 0 || dxl_round == 0) { + return; + } + + data_address_1 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[0]; + data_length_1 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_ID[1]; + + data_address_2 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[0]; + data_length_2 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_SPEED[1]; + + if (dxl_speed < 0) { + dxl_speed = 0; + } else if (dxl_speed > 100) { + dxl_speed = 100; + } + + data_value_2 = dxl_speed * 10; + + data_address_3 = + Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[0]; + data_length_3 = Entry.Robotis_rb.CONTROL_TABLE.CM_DXL_MULTITURN_DISTANCE[1]; + + if (dxl_round < 0) { + dxl_round = 0; + } else if (dxl_round > 100) { + dxl_round = 100; + } + + // 바퀴형 로봇 우측 바퀴인 경우 reverse mode이므로 방향 반대 + if (dxl_id == 33 || dxl_id == 35 || dxl_id == 51) { + dxl_round = -dxl_round; + } + + data_value_3 = dxl_round * 4096; + + if (dxl_direction == 1) { + data_value_3 = -data_value_3; + } + + data_sendqueue = [ + [data_instruction, data_address_1, data_length_1, dxl_id], + [data_instruction, data_address_2, data_length_2, data_value_2], + [data_instruction, data_address_3, data_length_3, data_value_3], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_dxl_multiturn_round(%1, %2, %3, %4)'], + }, + }, + + robotis_robotai_lite_scale_simple: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ], + value: '4', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.General.note_c + '', '1'], + [Lang.General.note_c + '#', '2'], + [Lang.General.note_d + '', '3'], + [Lang.General.note_d + '#', '4'], + [Lang.General.note_e + '', '5'], + [Lang.General.note_f + '', '6'], + [Lang.General.note_f + '#', '7'], + [Lang.General.note_g + '', '8'], + [Lang.General.note_g + '#', '9'], + [Lang.General.note_a + '', '10'], + [Lang.General.note_a + '#', '11'], + [Lang.General.note_b + '', '12'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_beat_sound_8th_note, '3'], + [Lang.Blocks.robotis_beat_sound_dotted_8th_note, '4'], + [Lang.Blocks.robotis_beat_sound_quarter_note, '5'], + [Lang.Blocks.robotis_beat_sound_dotted_quarter_note, '6'], + [Lang.Blocks.robotis_beat_sound_half_note, '7'], + [Lang.Blocks.robotis_beat_sound_dotted_half_note, '8'], + [Lang.Blocks.robotis_beat_sound_whole_note, '9'], + [Lang.Blocks.robotis_beat_sound_dotted_note, '10'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null, null, null], + type: 'robotis_robotai_lite_scale_simple', + }, + paramsKeyMap: { + CM_BUZZER_OCTAV: 0, + CM_BUZZER_INDEX: 1, + CM_BUZZER_NOTE: 2, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script); + let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script); + let cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script); + let cmBuzzerTime = 0; + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 0; + let data_value = 0; + let interval = 0; + let data_buf = []; + + switch (cmBuzzerNote) { + case 3: + cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute / 2); + break; + + case 4: + cmBuzzerTime = Math.round( + ((60 * 1000) / beat_per_minute / 2) * 1.5 + ); + break; + + case 5: + cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute); + break; + + case 6: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 1.5); + break; + + case 7: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 2); + break; + + case 8: + cmBuzzerTime = Math.round( + ((60 * 1000) / beat_per_minute) * 2 * 1.5 + ); + break; + + case 9: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 4); + break; + + case 10: + cmBuzzerTime = Math.round( + ((60 * 1000) / beat_per_minute) * 4 * 1.5 + ); + break; + } + + data_address = 740; + // data_value_1 = cmBuzzerTime * 10; + // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력 - console.log(parseInt(0.59 * 10)); max 는 5초 + data_value = cmBuzzerTime; + if (data_value < 0) { + data_value = 0; + } + if (data_value > 50000) { + data_value = 50000; + } + + data_buf.push(data_value % 256); + data_buf.push(Math.floor(data_value / 256)); + + data_value = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12; + data_buf.push(Math.floor(data_value)); + + // console.log("buzzer send"); + let data_sendqueue = [[data_instruction, data_address, 3, data_buf]]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + cmBuzzerTime + interval + ); + }, + syntax: { + js: [], + py: ['Robotailite.scale_simple(%1, %2, %3)'], + }, + }, + robotis_robotai_lite_scale_advanced: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ], + value: '4', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.General.note_c + '', '1'], + [Lang.General.note_c + '#', '2'], + [Lang.General.note_d + '', '3'], + [Lang.General.note_d + '#', '4'], + [Lang.General.note_e + '', '5'], + [Lang.General.note_f + '', '6'], + [Lang.General.note_f + '#', '7'], + [Lang.General.note_g + '', '8'], + [Lang.General.note_g + '#', '9'], + [Lang.General.note_a + '', '10'], + [Lang.General.note_a + '#', '11'], + [Lang.General.note_b + '', '12'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null, 1, null], + type: 'robotis_robotai_lite_scale_advanced', + }, + paramsKeyMap: { + CM_BUZZER_OCTAV: 0, + CM_BUZZER_INDEX: 1, + CM_BUZZER_BEAT: 2, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerIndex = script.getNumberValue('CM_BUZZER_INDEX', script); + let cmBuzzerOffset = script.getNumberValue('CM_BUZZER_OCTAV', script); + let cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script); + let cmBuzzerTime = 0; + + cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address_1 = 0; + let data_length_1 = 0; + let data_value_1 = 0; + let data_address_2 = 0; + let data_length_2 = 0; + let data_value_2 = 0; + let interval = 0; + + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * cmBuzzerBeat); + + data_address_1 = 740; + data_length_1 = 2; + // data_value_1 = cmBuzzerTime * 10; + // TODO 텍스트 입력으로 바꾸고 최대는 5초 : 0.5 초 하려면 5를 입력 - console.log(parseInt(0.59 * 10)); max 는 5초 + data_value_1 = cmBuzzerTime; + if (data_value_1 < 0) { + data_value_1 = 0; + } + if (data_value_1 > 50000) { + data_value_1 = 50000; + } + + data_address_2 = 742; + data_length_2 = 1; + data_value_2 = cmBuzzerIndex + (cmBuzzerOffset - 1) * 12; + + // console.log("buzzer send"); + let data_sendqueue = [ + [data_instruction, data_address_1, data_length_1, data_value_1], + [data_instruction, data_address_2, data_length_2, data_value_2], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + cmBuzzerTime + interval + ); + }, + syntax: { + js: [], + py: ['Robotailite.scale_advanced(%1, %2, %3)'], + }, + }, + robotis_robotai_lite_rest_simple: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_beat_rest_8th_note, '3'], + [Lang.Blocks.robotis_beat_rest_quarter_note, '5'], + [Lang.Blocks.robotis_beat_rest_half_note, '7'], + [Lang.Blocks.robotis_beat_rest_whole_note, '9'], + ], + value: '5', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_rest_simple', + }, + paramsKeyMap: { + CM_BUZZER_NOTE: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerNote = script.getNumberValue('CM_BUZZER_NOTE', script); + let cmBuzzerTime = 0; + + let interval = 0; + + switch (cmBuzzerNote) { + case 3: + cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute / 2); + break; + + case 5: + cmBuzzerTime = Math.round((60 * 1000) / beat_per_minute); + break; + + case 7: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 2); + break; + + case 9: + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * 4); + break; + } + + let data_sendqueue = []; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + cmBuzzerTime + interval + ); + }, + syntax: { + js: [], + py: ['Robotailite.rest_simple(%1)'], + }, + }, + robotis_robotai_lite_rest_advanced: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [1, null], + type: 'robotis_robotai_lite_rest_advanced', + }, + paramsKeyMap: { + CM_BUZZER_BEAT: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerBeat = script.getNumberValue('CM_BUZZER_BEAT', script); + let cmBuzzerTime = 0; + + let interval = 0; + + cmBuzzerBeat = Math.min(Math.max(cmBuzzerBeat, 0), 100); + + cmBuzzerTime = Math.round(((60 * 1000) / beat_per_minute) * cmBuzzerBeat); + + let data_sendqueue = []; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + cmBuzzerTime + interval + ); + }, + syntax: { + js: [], + py: ['Robotailite.rest_advanced(%1)'], + }, + }, + robotis_robotai_lite_beat_per_minute: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [75, null], + type: 'robotis_robotai_lite_beat_per_minute', + }, + paramsKeyMap: { + CM_BUZZER_BPM: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmBuzzerBpm = script.getNumberValue('CM_BUZZER_BPM', script); + + beat_per_minute = Math.min(Math.max(cmBuzzerBpm, 10), 600); + + // console.log("buzzer send"); + let data_sendqueue = []; + + return Entry.RobotisRobotaiLite.postCallReturn(script, data_sendqueue, 0); + }, + syntax: { + js: [], + py: ['Robotailite.set_bpm(%1)'], + }, + }, + + robotis_robotai_lite_Hello: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_korean1, '0'], + [Lang.Blocks.robotis_korean2, '1'], + [Lang.Blocks.robotis_korean3, '2'], + [Lang.Blocks.robotis_korean4, '3'], + [Lang.Blocks.robotis_korean5, '4'], + [Lang.Blocks.robotis_korean6, '5'], + [Lang.Blocks.robotis_korean7, '6'], + [Lang.Blocks.robotis_korean8, '7'], + [Lang.Blocks.robotis_korean9, '8'], + [Lang.Blocks.robotis_korean10, '9'], + [Lang.Blocks.robotis_korean11, '10'], + [Lang.Blocks.robotis_korean12, '11'], + [Lang.Blocks.robotis_korean13, '12'], + [Lang.Blocks.robotis_korean14, '13'], + [Lang.Blocks.robotis_korean15, '14'], + [Lang.Blocks.robotis_korean16, '15'], + [Lang.Blocks.robotis_korean17, '16'], + [Lang.Blocks.robotis_korean18, '17'], + [Lang.Blocks.robotis_korean19, '18'], + [Lang.Blocks.robotis_korean20, '19'], + [Lang.Blocks.robotis_korean21, '20'], + [Lang.Blocks.robotis_korean22, '21'], + [Lang.Blocks.robotis_korean23, '22'], + [Lang.Blocks.robotis_korean24, '23'], + [Lang.Blocks.robotis_korean25, '24'], + [Lang.Blocks.robotis_korean26, '25'], + [Lang.Blocks.robotis_korean27, '26'], + [Lang.Blocks.robotis_korean28, '27'], + [Lang.Blocks.robotis_korean29, '28'], + [Lang.Blocks.robotis_korean30, '29'], + [Lang.Blocks.robotis_korean31, '30'], + [Lang.Blocks.robotis_korean32, '31'], + [Lang.Blocks.robotis_korean33, '32'], + [Lang.Blocks.robotis_korean34, '33'], + [Lang.Blocks.robotis_korean35, '34'], + [Lang.Blocks.robotis_korean36, '35'], + [Lang.Blocks.robotis_korean37, '36'], + [Lang.Blocks.robotis_korean38, '37'], + [Lang.Blocks.robotis_korean39, '38'], + [Lang.Blocks.robotis_korean40, '39'], + [Lang.Blocks.robotis_korean41, '40'], + [Lang.Blocks.robotis_korean42, '41'], + [Lang.Blocks.robotis_korean43, '42'], + [Lang.Blocks.robotis_korean44, '43'], + [Lang.Blocks.robotis_korean45, '44'], + [Lang.Blocks.robotis_korean46, '45'], + [Lang.Blocks.robotis_korean47, '46'], + [Lang.Blocks.robotis_korean48, '47'], + [Lang.Blocks.robotis_korean49, '48'], + [Lang.Blocks.robotis_korean50, '49'], + [Lang.Blocks.robotis_korean51, '50'], + [Lang.Blocks.robotis_korean52, '51'], + [Lang.Blocks.robotis_korean53, '52'], + [Lang.Blocks.robotis_korean54, '53'], + [Lang.Blocks.robotis_korean55, '54'], + [Lang.Blocks.robotis_korean56, '55'], + [Lang.Blocks.robotis_korean57, '56'], + [Lang.Blocks.robotis_korean58, '57'], + [Lang.Blocks.robotis_korean59, '58'], + [Lang.Blocks.robotis_korean60, '59'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_Hello', + }, + paramsKeyMap: { + HELLO: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmHello = script.getField('HELLO', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 110; + let data_length = 2; + let data_value = 0; + + data_value = 25601 + Number(cmHello); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + [data_instruction, 0, 2, 0], + ]; + + let extraTime = 0; + + if (cmHello == '38' || cmHello == '55') { + extraTime = 2000; + } + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 2000 + extraTime + ); + }, + syntax: { + js: [], + py: ['Robotailite.speak(%1)'], + }, + }, + robotis_robotai_lite_effectSound: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_dog, '0'], + [Lang.Blocks.robotis_frog, '1'], + [Lang.Blocks.robotis_cat, '2'], + [Lang.Blocks.robotis_chicken, '7'], + [Lang.Blocks.robotis_tiger, '19'], + [Lang.Blocks.robotis_mouse, '17'], + + [Lang.Blocks.robotis_ambul, '773'], + [Lang.Blocks.robotis_Horn, '781'], + [Lang.Blocks.robotis_siren, '774'], + [Lang.Blocks.robotis_whistle, '274'], + [Lang.Blocks.robotis_gun, '775'], + [Lang.Blocks.robotis_clap, '260'], + + [Lang.Blocks.robotis_melody1, '786'], + [Lang.Blocks.robotis_melody2, '787'], + [Lang.Blocks.robotis_melody3, '788'], + [Lang.Blocks.robotis_melody4, '789'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_effectSound', + }, + paramsKeyMap: { + HELLO: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let cmHello = script.getField('HELLO', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 110; + let data_length = 2; + let data_value = 0; + + data_value = Number(cmHello); + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + [data_instruction, 0, 2, 0], + ]; + + let extraTime = 0; + if ( + cmHello == '272' || + cmHello == '786' || + cmHello == '787' || + cmHello == '788' || + cmHello == '789' + ) { + //오리 + extraTime = 0; + if (cmHello == '788' || cmHello == '789') { + extraTime += 500; + } + } + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 3000 + extraTime + ); + }, + syntax: { + js: [], + py: ['Robotailite.effect_sound(%1)'], + }, + }, + robotis_robotai_lite_record: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['1', '0'], + ['2', '1'], + ['3', '2'], + ['4', '3'], + ['5', '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_record', + }, + paramsKeyMap: { + ROOM: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let roomNum = script.getField('ROOM', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 115; + let data_length = 1; + let data_value = 0; + + data_value = roomNum; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 6000 + ); + }, + syntax: { + js: [], + py: ['Robotailite.record(%1)'], + }, + }, + robotis_robotai_lite_playRecord: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['1', '0'], + ['2', '1'], + ['3', '2'], + ['4', '3'], + ['5', '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_playRecord', + }, + paramsKeyMap: { + ROOM: 0, + }, + class: 'robotis_robotai_lite_sound', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let roomNum = script.getField('ROOM', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 116; + let data_length = 1; + let data_value = 0; + + data_value = roomNum; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + 6000 + ); + }, + syntax: { + js: [], + py: ['Robotailite.playRecord(%1)'], + }, + }, + + robotis_robotai_lite_ai_camera_block_value_closest_to_center: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_target_face, '0'], + [Lang.Blocks.robotis_ai_camera_target_object, '1'], + [Lang.Blocks.robotis_ai_camera_target_color, '2'], + [Lang.Blocks.robotis_ai_camera_target_tag, '3'], + [Lang.Blocks.robotis_ai_camera_target_qr, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'], + [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'], + [Lang.Blocks.robotis_ai_camera_center_block_width, '2'], + [Lang.Blocks.robotis_ai_camera_center_block_height, '3'], + [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_ai_camera_block_value_closest_to_center', + }, + paramsKeyMap: { + TARGET: 0, + DATA_TYPE: 1, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4009; + let data_type = script.getNumberValue('DATA_TYPE'); + data_address += data_type * 2; + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_block_value_closest_to_center(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_arrow_value_closest_to_center: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'], + [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'], + [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'], + [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'], + [Lang.Blocks.robotis_ai_camera_center_leared_id, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_ai_camera_arrow_value_closest_to_center', + }, + paramsKeyMap: { + DATA_TYPE: 0, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4019; + let data_type = script.getNumberValue('DATA_TYPE'); + data_address += data_type * 2; + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_arrow_value_closest_to_center(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_number_of_learned_id: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [], + events: {}, + def: { + params: [], + type: 'robotis_robotai_lite_ai_camera_number_of_learned_id', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4003; + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_number_of_learned_id()'], + }, + }, + robotis_robotai_lite_ai_camera_block_value_of_id: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_target_face, '0'], + [Lang.Blocks.robotis_ai_camera_target_object, '1'], + [Lang.Blocks.robotis_ai_camera_target_color, '2'], + [Lang.Blocks.robotis_ai_camera_target_tag, '3'], + [Lang.Blocks.robotis_ai_camera_target_qr, '4'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_center_block_center_x, '0'], + [Lang.Blocks.robotis_ai_camera_center_block_center_y, '1'], + [Lang.Blocks.robotis_ai_camera_center_block_width, '2'], + [Lang.Blocks.robotis_ai_camera_center_block_height, '3'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, null, null], + type: 'robotis_robotai_lite_ai_camera_block_value_of_id', + }, + paramsKeyMap: { + ID: 0, + TARGET: 1, + TYPE: 2, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + // instruction / address / length / value / default length + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4029; // ID_FOR_USE + let data_length = 2; + let data_value = script.getNumberValue('ID'); + + if (data_value != camera_id_for_use) { + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + camera_id_for_use = data_value; + } + + data_address = 4036; // BLOCK_RESULT_BY_ID_X_CENTER + + data_address += script.getNumberValue('TYPE') * 2; + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_block_value_of_id(%1, %2)'], + }, + }, + robotis_robotai_lite_ai_camera_arrow_value_of_id: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['1', '1'], + ['2', '2'], + ['3', '3'], + ['4', '4'], + ['5', '5'], + ['6', '6'], + ['7', '7'], + ['8', '8'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_center_arrow_origin_x, '0'], + [Lang.Blocks.robotis_ai_camera_center_arrow_origin_y, '1'], + [Lang.Blocks.robotis_ai_camera_center_arrow_target_x, '2'], + [Lang.Blocks.robotis_ai_camera_center_arrow_target_y, '3'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null, null], + type: 'robotis_robotai_lite_ai_camera_arrow_value_of_id', + }, + paramsKeyMap: { + ID: 0, + TYPE: 1, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + + // instruction / address / length / value / default length + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4029; // ID_FOR_USE + let data_length = 2; + let data_value = script.getNumberValue('ID'); + + if (data_value != camera_id_for_use) { + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_value], + ]; + + Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + camera_id_for_use = data_value; + } + + data_address = 4044; // ARROW_RESULT_BY_ID_X_ORIGIN + + data_address += script.getNumberValue('TYPE') * 2; + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (typeof result == 'undefined') { + return 0; + } + + return result; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_arrow_value_of_id(%1, %2)'], + }, + }, + robotis_robotai_lite_ai_camera_connection_status: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_connected, '1'], + [Lang.Blocks.robotis_disconnected, '0'], + ], + value: '1', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_ai_camera_connection_status', + }, + paramsKeyMap: { + STATUS: 0, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4000; + let compareValue = script.getNumberValue('STATUS'); + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (result == undefined) { + return false; + } + + return result == compareValue; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_connection_status(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_if_detected: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_boolean_field', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_target_face, '0'], + [Lang.Blocks.robotis_ai_camera_target_object, '1'], + [Lang.Blocks.robotis_ai_camera_target_color, '2'], + [Lang.Blocks.robotis_ai_camera_target_tag, '3'], + [Lang.Blocks.robotis_ai_camera_target_qr, '4'], + [Lang.Blocks.robotis_ai_camera_target_arrow, '5'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_ai_camera_if_detected', + }, + paramsKeyMap: { + DETECT_TYPE: 0, + }, + class: 'robotis_robotai_lite_ai_camera_value', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + let scope = script.executor.scope; + let data_address = 4005; // block + let detect_type = script.getNumberValue('DETECT_TYPE'); + + if (detect_type == 5) { + data_address = 4006; + } // arrow + + let result = Entry.RobotisRobotaiLite.dataBuffer[data_address]; + + if (result == undefined) { + return false; + } + + return result == 1; + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_if_detected(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_set_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + [Lang.Blocks.robotis_ai_camera_mode_face_recognition, '0'], + [Lang.Blocks.robotis_ai_camera_mode_object_tracking, '1'], + [Lang.Blocks.robotis_ai_camera_mode_object_recognition, '2'], + [Lang.Blocks.robotis_ai_camera_mode_line_tracking, '3'], + [Lang.Blocks.robotis_ai_camera_mode_color_recognition, '4'], + [Lang.Blocks.robotis_ai_camera_mode_tag_recognition, '5'], + [Lang.Blocks.robotis_ai_camera_mode_object_classification, '6'], + ], + value: '0', + fontSize: 11, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [null], + type: 'robotis_robotai_lite_ai_camera_set_mode', + }, + paramsKeyMap: { + AI_CAMERA_MODE: 0, + }, + class: 'robotis_robotai_lite_ai_camera_set', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let ai_camera_mode = script.getField('AI_CAMERA_MODE', script); + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4001; + let data_length = 1; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, ai_camera_mode], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.set_ai_camera_mode(%1)'], + }, + }, + robotis_robotai_lite_ai_camera_print_custom_text: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Block', + accept: 'string', + }, + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + 'Hello!', + ], + type: 'robotis_robotai_lite_ai_camera_print_custom_text', + }, + paramsKeyMap: { + X: 0, + Y: 1, + TEXT: 2, + }, + class: 'robotis_robotai_lite_ai_camera_set', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + let x = script.getNumberValue('X', script); + let y = script.getNumberValue('Y', script); + let text = script.getStringValue('TEXT', script); + let text_len = text.length; + let data_buf = []; + let i = 0; + + if (x < -160) { + x = 160; + } else if (x > 160) { + x = 160; + } + + if (y < -120) { + y = 120; + } else if (y > 120) { + y = 120; + } + + if (x < 0) { + x = 65536 + x; + } + if (y < 0) { + y = 65536 + y; + } + + data_buf.push(x % 256); + data_buf.push(Math.floor(x / 256)); + data_buf.push(y % 256); + data_buf.push(Math.floor(y / 256)); + data_buf.push(0); + data_buf.push(0); + for (i = 0; i < text_len; i++) { + data_buf.push(text[i]); + } + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4200; + let data_length = 6 + text_len; + + let data_sendqueue = [ + [data_instruction, data_address, data_length, data_buf], + ]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_print_custom_text(%1,%2,%3)'], + }, + }, + robotis_robotai_lite_ai_camera_clear_custom_text: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Indicator', + img: 'block_icon/hardware_icon.svg', + size: 12, + }, + ], + events: {}, + def: { + params: [], + type: 'robotis_robotai_lite_ai_camera_clear_custom_text', + }, + paramsKeyMap: {}, + class: 'robotis_robotai_lite_ai_camera_set', + isNotFor: ['RobotisRobotaiLite'], + func(sprite, script) { + // instruction / address / length / value / default length + + let data_instruction = Entry.Robotis_rb.INSTRUCTION.WRITE; + let data_address = 4250; + let data_length = 1; + + let data_sendqueue = [[data_instruction, data_address, data_length, 1]]; + + return Entry.RobotisRobotaiLite.postCallReturn( + script, + data_sendqueue, + DEFAULT_DELAY + ); + }, + syntax: { + js: [], + py: ['Robotailite.ai_camera_clear_custom_text()'], + }, + }, + }; + } + + requestLocalData() { + let packet = null; + if (this.robotisBuffer.length > 0) { + const data = this.robotisBuffer.shift(); + const instruction = data[0]; + const address = data[1]; + const length = data[2]; + const value = data[3]; + const dataBuffer = data[4]; + let id = 0; + + switch (instruction) { + case INST_WRITE: + id = 200; + packet = this.writePacket(id, address, length, value); + break; + case INST_BYPASS_WRITE: + id = value; + packet = this.writePacket(id, address, length, dataBuffer); + break; + } + } + return packet; + } + + handleLocalData(data) { + let stuffLength = 0; + //console.log(`length: ${data.length}`); + for (let i = 0; i < data.length; i++) { + //this.receiveBuffer.push(data[i]); + const dataIn = data[i]; + + switch (this.packetReceiveState) { + case PACKET_STATE_IDLE: + if (this.headerCount >= 2) { + rxPacket.header[2] = dataIn; + + if ( + rxPacket.header[0] == 0xff && + rxPacket.header[1] == 0xff && + rxPacket.header[2] == 0xfd + ) { + this.headerCount = 0; + this.packetReceiveState = PACKET_STATE_RESERVED; + } else { + rxPacket.header[0] = rxPacket.header[1]; + rxPacket.header[1] = rxPacket.header[2]; + rxPacket.header[2] = 0; + } + } else { + rxPacket.header[this.headerCount] = dataIn; + this.headerCount++; + } + break; + + case PACKET_STATE_RESERVED: + if (dataIn == 0xfd) { + this.packetReceiveState = PACKET_STATE_IDLE; + } else { + rxPacket.reserved = dataIn; + this.packetReceiveState = PACKET_STATE_ID; + } + break; + + case PACKET_STATE_ID: + rxPacket.id = dataIn; + this.packetReceiveState = PACKET_STATE_LENGTH_L; + break; + + case PACKET_STATE_LENGTH_L: + rxPacket.packetLength = dataIn; + this.packetReceiveState = PACKET_STATE_LENGTH_H; + break; + + case PACKET_STATE_LENGTH_H: + rxPacket.packetLength |= dataIn << 8; + if (rxPacket.packetLength < 1000) { + this.packetReceiveState = PACKET_STATE_DATA; + } else { + this.packetReceiveState = PACKET_STATE_IDLE; + } + rxPacket.index = 0; + break; + + case PACKET_STATE_DATA: + rxPacket.data[rxPacket.index] = dataIn; + rxPacket.index++; + + if (rxPacket.index >= rxPacket.packetLength - 2) { + this.packetReceiveState = PACKET_STATE_CRC_L; + } + break; + + case PACKET_STATE_CRC_L: + rxPacket.crcReceived = dataIn; + this.packetReceiveState = PACKET_STATE_CRC_H; + break; + + case PACKET_STATE_CRC_H: + rxPacket.crcReceived |= dataIn << 8; + + stuffLength = this.removeStuffing(rxPacket.data, rxPacket.packetLength); + rxPacket.packetLength -= stuffLength; + + rxPacket.cmd = rxPacket.data[0]; + rxPacket.error = rxPacket.data[1]; + + if (rxPacket.cmd == INST_STATUS) { + //console.log(`rx length: ${rxPacket.packetLength}`); + if (rxPacket.packetLength >= 147) { + let tempValue = 0; + for (let i = 0; i < addrMap.length; i++) { + switch (addrMap[i][1]) { + case 1: + this.dataBuffer[addrMap[i][2]] = + rxPacket.data[2 + addrMap[i][0]]; + break; + + case 2: + tempValue = + rxPacket.data[2 + addrMap[i][0]] + + (rxPacket.data[2 + addrMap[i][0] + 1] << 8); + if (tempValue >= 32768) { + tempValue = tempValue - 65536; + } + this.dataBuffer[addrMap[i][2]] = tempValue; + break; + + case 4: + this.dataBuffer[addrMap[i][2]] = + rxPacket.data[2 + addrMap[i][0]] + + (rxPacket.data[2 + addrMap[i][0] + 1] << 8) + + (rxPacket.data[2 + addrMap[i][0] + 2] << 16) + + (rxPacket.data[2 + addrMap[i][0] + 3] << 24); + break; + } + } + + const dxlPositionStartAddr = + addrMap[addrMap.length - 1][0] + addrMap[addrMap.length - 1][1]; + + // DXL Position + for (let i = 0; i < 20; i++) { + const currentId = + rxPacket.data[2 + dxlPositionStartAddr + 3 * i]; + const currentPos = + rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 1] + + (rxPacket.data[2 + dxlPositionStartAddr + 3 * i + 2] << 8); + if (currentId != 0xff && currentPos != 0xffff) { + this.dxlPositions[currentId] = currentPos; + } + } + + const lineCategoryStartAddr = dxlPositionStartAddr + 3 * 20; + // line category + this.dataBuffer[5201] = rxPacket.data[2 + lineCategoryStartAddr]; + + const sensorStartAddr = lineCategoryStartAddr + 1; + + // 온습도+조도+동작감지센서값 + this.pirPir[0] = rxPacket.data[2 + sensorStartAddr]; + this.pirTemperature[0] = rxPacket.data[2 + sensorStartAddr + 1]; + this.pirHumidity[0] = rxPacket.data[2 + sensorStartAddr + 2]; + this.pirBrightness[0] = rxPacket.data[2 + sensorStartAddr + 3]; + + // 거리+버튼+조도센서값 + this.distanceDistance[0] = + rxPacket.data[2 + sensorStartAddr + 4] + + (rxPacket.data[2 + sensorStartAddr + 5] << 8); + this.distanceButton[0] = rxPacket.data[2 + sensorStartAddr + 6]; + this.distanceBrightness[0] = rxPacket.data[2 + sensorStartAddr + 7]; + + for (let i = 0; i < addrMap2.length; i++) { + switch (addrMap2[i][1]) { + case 1: + this.dataBuffer[addrMap2[i][2]] = + rxPacket.data[2 + addrMap2[i][0]]; + break; + + case 2: + tempValue = + rxPacket.data[2 + addrMap2[i][0]] + + (rxPacket.data[2 + addrMap2[i][0] + 1] << 8); + if (tempValue >= 32768) { + tempValue = tempValue - 65536; + } + this.dataBuffer[addrMap2[i][2]] = tempValue; + break; + + case 4: + this.dataBuffer[addrMap2[i][2]] = + rxPacket.data[2 + addrMap2[i][0]] + + (rxPacket.data[2 + addrMap2[i][0] + 1] << 8) + + (rxPacket.data[2 + addrMap2[i][0] + 2] << 16) + + (rxPacket.data[2 + addrMap2[i][0] + 3] << 24); + break; + } + } + } + } + + this.packetReceiveState = PACKET_STATE_IDLE; + break; + + default: + // code block + } + } + } + + requestInitialData() { + this.robotisBuffer = []; + this.robotisBuffer.push([INST_WRITE, 21, 2, 20]); + this.robotisBuffer.push([INST_WRITE, 19, 1, 1]); // bypass 모드 켜기 + this.robotisBuffer.push([INST_WRITE, 20, 1, 0]); // bypass port를 BLE로 설정 + this.robotisBuffer.push([INST_WRITE, 23, 1, 1]); // auto report 기능 켜기 + this.robotisBuffer.push([INST_WRITE, 4250, 1, 1]); // ai_camera 텍스트 지우기 + this.robotisBuffer.push([INST_WRITE, 722, 1, 0]); // dxl 토크 끄기 + //this.robotisBuffer.push([INST_WRITE, 63, 1, 1]); // 부저음 시간 설정 + //this.robotisBuffer.push([INST_WRITE, 60, 1, 70]); // 부저음 발생 + this.robotisBuffer.push([INST_WRITE, 113, 2, 1040]); // "띵" 효과음 발생 + /* + //const ping = [0xff, 0xff, 0xfd, 0x00, 0xc8, 0x03, 0x00, 0x01, 0x3b, 0xfa]; + // run entry mode + const packet = [ + 0xff, 0xff, 0xfd, 0x00, 0xc8, 0x07, 0x00, 0x03, 0x15, 0x00, 0x14, 0x00, 0xc1, 0xb3, + ]; + return packet; + */ + } + + async initialHandshake() { + const status = true; + let sendBuffer = null; + this.requestInitialData(); + while (this.robotisBuffer.length) { + const data = this.robotisBuffer.shift(); + const instruction = data[0]; + const address = data[1]; + const length = data[2]; + const value = data[3]; + const dataBuffer = data[4]; + let id = 0; + + switch (instruction) { + case INST_WRITE: + id = 200; + sendBuffer = this.writePacket(id, address, length, value); + break; + case INST_BYPASS_WRITE: + id = value; + sendBuffer = this.writePacket(id, address, length, dataBuffer); + break; + } + Entry.hwLite.serial.sendAsciiAsBuffer(sendBuffer); + if (instruction == INST_WRITE && address == 2100 && length == 1 && value == 1) { + this.robotisBuffer = []; + } + } + return status; + } + })(); +})(); + +module.exports = Entry.RobotisRobotaiLite; diff --git a/src/playground/blocks/hardwareLite/block_whalesbot_drone_lite.js b/src/playground/blocks/hardwareLite/block_whalesbot_drone_lite.js new file mode 100644 index 0000000000..fdb1fd55a3 --- /dev/null +++ b/src/playground/blocks/hardwareLite/block_whalesbot_drone_lite.js @@ -0,0 +1,2369 @@ +'use strict'; + +// - 라이프사이클 재점검 +// - Entry.hw 부분 Entry.hwLite로 수정 +// - portData 파라미터 확인 +// - 모니터링 로직 확인 + +import _range from 'lodash/range'; +import DataTable from '../../../class/DataTable'; +import entryModuleLoader from '../../../class/entryModuleLoader'; +import metadata from './metadata_whalesbot_drone_lite.json'; + +(function() { + Entry.WhalesbotDroneLite = new (class WhalesbotDroneLite { + constructor() { + this.id = '620101'; + this.name = 'WhalesbotDroneLite'; + this.url = 'https://gaion-edu.kr/'; + this.imageName = 'whalesbotlite.png'; + this.title = { + ko: 'Whalesbot Eagle1001', + en: 'Whalesbot Eagle1001', + }; + // duration도 미확인 + this.duration = 32; + this.blockMenuBlocks = [ + //'whalesbot_drone_openning_3d_simulator', + 'whalesbot_drone_entering_pitch_mode', + 'whalesbot_drone_exit_pitch_mode', + 'whalesbot_drone_automatic_take_off_height', + 'whalesbot_drone_automatic_take_off_altitude_speed_offset', + 'whalesbot_drone_automatic_landing', + 'whalesbot_drone_automatic_descent_speed_offset', + 'whalesbot_drone_set_the_flight_speed', + 'whalesbot_drone_get_setting_speed', + 'whalesbot_drone_rise', + 'whalesbot_drone_down', + 'whalesbot_drone_fly_forward', + 'whalesbot_drone_fly_backward', + 'whalesbot_drone_fly_left', + 'whalesbot_drone_fly_right', + 'whalesbot_drone_turn_left', + 'whalesbot_drone_turn_right', + 'whalesbot_drone_fly_in_the_specified_direction', + 'whalesbot_drone_flight_designated', + 'whalesbot_drone_set_the_four_channel_lever_quantity_of_remote_control', + 'whalesbot_drone_stop_moving_and_hover', + 'whalesbot_drone_hover_at_specified_altitude', + 'whalesbot_drone_emergency_stop', + 'whalesbot_drone_set_the_steering_gear', + 'whalesbot_drone_execute_script', + 'whalesbot_drone_clean', + 'whalesbot_drone_restart' + ]; + this.portData = { + baudRate: 115200, + dataBits: 8, + parity: 'none', + stopBits: 1, + bufferSize: 255, + constantServing: 'ReadOnly', + connectionType: 'bytestream', + }; + this.readablePorts = []; + this.remainValue = null; + this.decoder = new TextDecoder(); + this.nowdwpack = 0; + this.BT_INDEX_CMD_SEND = 2; + this.BT_INDEX_DATA_SEND = 3; + this.packlen = 128; + this.DATASENDLEN = 154; + this.BT_INDEX_SENDCHECKSUM = this.DATASENDLEN - 1; + this.DATAREVLEN = 160; + this.BT_INDEX_REVCHECKSUM = this.DATAREVLEN - 1; + this.BT_INDEX_CMD_REV = 8; + this.BT_INDEX_DATA_REV = 9 + this.BT_CMD_GETFLYSTATE1 = 0x50; + this.isDroneConnection = false; + this.countDroneConnectionAttempt = 0; + this.IsPicocStop = false; + this.revtmp = Buffer.alloc(this.DATAREVLEN); + this.revtemplength = 0 ; + this.revtmpdata = Buffer.alloc(this.DATAREVLEN); + this.revdata = Buffer.alloc(this.DATAREVLEN); + this.BT_CMD_DOWNLOAD = 0x62; + this.BT_CMD_DOWNLOAD_END = 0x64; + this.BT_CMD_PICOCSTOP = 0x68; + this.isDownloadDone = false; + this.isGetFlyState = false; + this.cmdType = { + 'Download': 1, + 'Stop': 2, + } + this.runCode = [ + 0x77, 0x78, 0x66, 0x1, 0x2, 0x2, 0x3, 0x3, 0x4, 0x4, 0x5, 0x5, + 0x6, 0x6, 0x7, 0x7, 0x8, 0x8, 0x9, 0x9, 0xa, 0xa, 0xb, 0xb, 0xc, 0xc, + 0xd, 0xd, 0xe, 0xe, 0xf, 0xf, 0x10, 0x10, 0x11, 0x11, 0x12, 0x12, 0x13, + 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, 0x18, 0x18, + 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, + 0x1f, 0x1f, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23, 0x24, 0x24, + 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, 0x28, 0x29, 0x29, 0x2a, 0x2a, + 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, 0x2e, 0x2e, 0x2f, 0x2f, 0x30, 0x30, + 0x31, 0x31, 0x32, 0x32, 0x33, 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, + 0x37, 0x37, 0x38, 0x38, 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c, + 0x3d, 0x3d, 0x3e, 0x3e, 0x3f, 0x3f, 0x40, 0x40, 0x41, 0x41, 0x42, 0x42, + 0x43, 0x43, 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x48, 0x48, + 0x49, 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x0, 0x56 + ]; + + this.getStateCode = [ + 0x77,0x78,0x50,0x1,0x2,0x2,0x3,0x3,0x4,0x4,0x5,0x5,0x6,0x6,0x7,0x7,0x8,0x8,0x9,0x9, + 0xa,0xa,0xb,0xb,0xc,0xc,0xd,0xd,0xe,0xe,0xf,0xf,0x10,0x10,0x11,0x11,0x12,0x12 + ,0x13,0x13,0x14,0x14,0x15,0x15,0x16,0x16,0x17,0x17,0x18,0x18,0x19,0x19,0x1a,0x1a + ,0x1b,0x1b,0x1c,0x1c,0x1d,0x1d,0x1e,0x1e,0x1f,0x1f,0x20,0x20,0x21,0x21,0x22,0x22 + ,0x23,0x23,0x24,0x24,0x25,0x25,0x26,0x26,0x27,0x27,0x28,0x28,0x29,0x29,0x2a,0x2a + ,0x2b,0x2b,0x2c,0x2c,0x2d,0x2d,0x2e,0x2e,0x2f,0x2f,0x30,0x30,0x31,0x31,0x32,0x32 + ,0x33,0x33,0x34,0x34,0x35,0x35,0x36,0x36,0x37,0x37,0x38,0x38,0x39,0x39,0x3a,0x3a + ,0x3b,0x3b,0x3c,0x3c,0x3d,0x3d,0x3e,0x3e,0x3f,0x3f,0x40,0x40,0x41,0x41,0x42,0x42 + ,0x43,0x43,0x44,0x44,0x45,0x45,0x46,0x46,0x47,0x47,0x48,0x48,0x49,0x49,0x4a,0x4a + ,0x4b,0x4b,0x0,0x6c + ]; + + this.stopCode = [ + 0x77, 0x78, 0x68, 0x1, 0x2, 0x2, 0x3, 0x3, 0x4, 0x4, 0x5, 0x5, + 0x6, 0x6, 0x7, 0x7, 0x8, 0x8, 0x9, 0x9, 0xa, 0xa, 0xb, 0xb, 0xc, + 0xc, 0xd, 0xd, 0xe, 0xe, 0xf, 0xf, 0x10, 0x10, 0x11, 0x11, 0x12, + 0x12, 0x13, 0x13, 0x14, 0x14, 0x15, 0x15, 0x16, 0x16, 0x17, 0x17, + 0x18, 0x18, 0x19, 0x19, 0x1a, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, + 0x1d, 0x1e, 0x1e, 0x1f, 0x1f, 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, + 0x23, 0x23, 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, + 0x28, 0x29, 0x29, 0x2a, 0x2a, 0x2b, 0x2b, 0x2c, 0x2c, 0x2d, 0x2d, + 0x2e, 0x2e, 0x2f, 0x2f, 0x30, 0x30, 0x31, 0x31, 0x32, 0x32, 0x33, + 0x33, 0x34, 0x34, 0x35, 0x35, 0x36, 0x36, 0x37, 0x37, 0x38, 0x38, + 0x39, 0x39, 0x3a, 0x3a, 0x3b, 0x3b, 0x3c, 0x3c, 0x3d, 0x3d, 0x3e, + 0x3e, 0x3f, 0x3f, 0x40, 0x40, 0x41, 0x41, 0x42, 0x42, 0x43, 0x43, + 0x44, 0x44, 0x45, 0x45, 0x46, 0x46, 0x47, 0x47, 0x48, 0x48, 0x49, + 0x49, 0x4a, 0x4a, 0x4b, 0x4b, 0x0, 0x54 + ]; + this.simulatorPopup = null; + this.setZero(); + this.unsupportBlockExist = false; + this.getStateTimeSleep = 500; + this.lock= false; + this.sensor = { + ACC_x: 0.0, + ACC_y: 0.0, + ACC_z: 0.0, + Gypo_x: 0.0, + Gypo_y: 0.0, + Gypo_z: 0.0, + SPL06_temp: 0.0, + SPL06_Press: 0.0, + SPL06_asl: 0.0, + Pitch: 0.0, + Roll: 0.0, + Yaw: 0.0, + Battery: 0.0, + LaserTof: 0.0, + GL_X: 0.0, + GL_Y: 0.0, + timertick: 0.0, + M1: 0, + M2: 0, + M3: 0, + M4: 0, + Debug_0: 0.0, + Debug_1: 0.0, + Debug_2: 0.0, + Debug_3: 0.0, + Debug_4: 0.0, + Debug_5: 0.0, + FusedHeight: 0.0, + VER: 100, + TYPE: "TYPE_EG_DUMMY", + ErrFly: 0, + asl_dis: 0.0, + startBaroAsl: 0.0, + LineNo: 0, + LineError: 0, + ErrorCode: 0, + state_position_x: 0.0, + state_position_y: 0.0, + state_position_z: 0.0, + state_velocity_x: 0.0, + state_velocity_y: 0.0, + state_velocity_z: 0.0, + btkey: 0, + btstick1: 0, + btstick2: 0, + btstick3: 0, + btstick4: 0, + btstick5: 0 + }; + this.BIT0 =0x01; + this.BIT1 =0x02; + this.BIT2 =0x04; + this.BIT3 =0x08; + this.BIT4 =0x10; + this.BIT5 =0x20; + this.BIT6 =0x40; + this.BIT7 =0x80; + + this.simulatorUrl = metadata.simulator_url; + } + + setZero() { + if (Entry.hwLite && Entry.hwLite.serial) { + Entry.hwLite.serial.update(); + } + } + + lockGetState(lock){ + this.lock = lock + } + + isLockGetState(){ + return this.lock; + } + + connectDrone(){ + this.getStateInterval = setInterval(()=>{ + if(this.countDroneConnectionAttempt == 0 || !this.isLockGetState()){ + this.sendPacket(this.getStateCode); + console.log("Connection Attempt",this.countDroneConnectionAttempt+1) + this.countDroneConnectionAttempt = this.countDroneConnectionAttempt +1 + if(this.isDroneConnection == false){ + if( this.countDroneConnectionAttempt == 4){ + console.log("Connection failed"); + this.countDroneConnectionAttempt = 0 ; + clearInterval(this.getStateInterval); + return + } + } + else{ + console.log("Connection succeed"); + console.log("Drone is connected") + this.isDroneConnection = true; + this.countDroneConnectionAttempt = 0 ; + clearInterval(this.getStateInterval); + } + } + },this.getStateTimeSleep) + this.getStateInterval; + + } + + waitRevData(data){ + var prevrevtemplength= this.revtemplength; + this.revtemplength += data.length; + // console.log(data.length); + console.log("prevrevtemplength: ",prevrevtemplength); + console.log("revtemplength: ",this.revtemplength); + if(this.revtemplength <= this.DATAREVLEN){ + for (let i = 0; i < data.length; i++) { + this.revtmpdata[prevrevtemplength +i] = data[i]; + } + if(this.revtemplength==this.DATAREVLEN){ + console.log("revtempdata") + console.log(this.revtmpdata); + console.log(this.revtmpdata[this.BT_INDEX_REVCHECKSUM]+"=="+this.calChecksum(this.revtmpdata)); + // if(parseInt(this.revtmpdata[this.BT_INDEX_REVCHECKSUM]) === this.calChecksum(this.revtmpdata) ){ + for (let i = 0; i 20){ + clearInterval(this.getStateInterval) + this.isDroneConnection = true; + console.log("Drone is already connected") + // this.waitRevData(data); + this.lockGetState(false); + console.log("Unlock senpacket GetState"); + } + } + // 디바이스에서 값을 읽어온다. + async handleLocalData(data) { + // const decoded = this.decoder.decode(data); + // console.log("Data received") + // console.log("Decoded: ", decoded); + console.log("data received: ",data); + if(this.isDroneConnection == false){ + this.lockGetState(true); + this.checkGetState(data) + return; + } + + this.waitRevData(data); + // this.monitorDownloadProgress(decoded); + } + + retHex(bytes) { + const l = Array.from(bytes).map(byte => '0x' + byte.toString(16).padStart(1, '0')); + return l; + } + + convertToBufferArray(input) { + const hexArray = input.split(','); + const byteArray = hexArray.map(hex => parseInt(hex, 16)); + const buffer = Buffer.from(byteArray); + return buffer; + } + + //디바이스에 값을 쓴다. + requestLocalData() { + // return this.getStateCode; + return null; + // return this.stopCode; + } + + async sendPacket(packet, hex=true, callback=null) + { + if(hex){ + await Entry.hwLite.serial.writer.write(Buffer.from(packet)) + } else { + console.log(this.retHex(packet).join(",")) + await Entry.hwLite.serial.writer.write(packet) + } + await new Promise(resolve => setTimeout(resolve, 250)); + } + + monitorDownloadProgress(data) + { + if (data && data.search("user_main();")) + { + console.log("Call user_main();"); + this.setDownloadStatus(true); + }else{ + this.setDownloadStatus(false); + } + } + + setDownloadStatus(status) + { + this.isDownloadDone = status; + } + + isDownloadSuccess() + { + return this.isDownloadDone; + } + + isLatestChunk(chunkData) + { + if(chunkData[this.BT_INDEX_CMD_SEND] == 0x64) + { + for(let i=0;i<=chunkData.length-1;i++) + { + if(chunkData[i] == 0xff + && chunkData[i+1] == 0x42 + && chunkData[i+2] == 0x43 + && chunkData[i+3] == 0x43 + && chunkData[i+4] == 0x44 + && chunkData[i+5] == 0x44 + ){ + return true; + } + } + } + + return false; + } + + generateBytesCode(type, Picocode="", nowdwpack=0) { + let ret = Buffer.alloc(this.DATASENDLEN); + + ret[0] = 0x77; + ret[1] = 0x78; + + ret[this.BT_INDEX_CMD_SEND] = this.BT_CMD_GETFLYSTATE1; + for (let i = this.BT_INDEX_DATA_SEND; i < this.BT_INDEX_SENDCHECKSUM - 1; i++) { + ret[i] = (Math.floor(i / 2)) & 0x000000ff; + } + + if (type == this.cmdType.Download) + { + ret[this.BT_INDEX_CMD_SEND] = this.BT_CMD_DOWNLOAD; + ret[this.BT_INDEX_DATA_SEND] = nowdwpack & 0x000000ff; + ret[this.BT_INDEX_DATA_SEND + 1] = ((nowdwpack & 0x0000ff00) / 256) | 0; + + if (nowdwpack * this.packlen > Picocode.length) { + ret[this.BT_INDEX_CMD_SEND] = this.BT_CMD_DOWNLOAD_END; + } + + for (let i = 0; i < this.packlen; i++) { + if (i + nowdwpack * this.packlen >= Picocode.length) { + ret[this.BT_INDEX_DATA_SEND + 2 + i] = 0xff; + } else { + ret[this.BT_INDEX_DATA_SEND + 2 + i] = Picocode.charCodeAt(i + nowdwpack * this.packlen); + } + } + }else if(type == this.cmdType.Stop) + { + ret[this.BT_INDEX_CMD_SEND] = this.BT_CMD_PICOCSTOP + } + + ret[this.BT_INDEX_SENDCHECKSUM] = this.calChecksum(ret); + console.log(ret[this.BT_INDEX_SENDCHECKSUM]); + return ret; + } + + calChecksum(data) { + let sum = 0; + const codelen = data.byteLength - 1; + for (let i = 2; i < codelen; i++) { + sum = sum + data[i]; + } + sum = (sum & 0xff); + sum = (~sum) & 0xff; + return +sum; + } + + VERSTR(){ + return (this.sensor.TYPE).toString() + "_" + parseInt(this.sensor.VER).toString() + + } + Errcode2Msg(ErrorCode){ + if (ErrorCode == 0){ + return "No Error" + } + if (ErrorCode == 1){ + return "can't assign to this" + } + if (ErrorCode == 2){ + return "NULL pointer dereference" + } + if (ErrorCode == 3){ + return "first argument to '?' should be a number" + } + if (ErrorCode == 4){ + return "can't get the address of this" + } + if (ErrorCode == 5){ + return "invalid operation" + } + if (ErrorCode == 6){ + return "invalid use of a NULL pointer" + } + if (ErrorCode == 7){ + return "not supported" + } + if (ErrorCode == 8){ + return "invalid expression" + } + if (ErrorCode == 9){ + return "array index must be an integer" + } + if (ErrorCode == 10){ + return "this Target is not an array" + } + if (ErrorCode == 11){ + return "need an structure or union member" + } + if (ErrorCode == 12){ + return "struct or union error" + } + if (ErrorCode == 13){ + return "doesn't have a member" + } + if (ErrorCode == 14){ + return "operator not expected here" + } + if (ErrorCode == 15){ + return "brackets not closed" + } + if (ErrorCode == 16){ + return "identifier not expected here" + } + if (ErrorCode == 17){ + return "macro arguments missing" + } + if (ErrorCode == 18){ + return "expression expected" + } + if (ErrorCode == 19){ + return "a void value isn't much use here" + } + if (ErrorCode == 20){ + return "value not expected here" + } + if (ErrorCode == 21){ + return "type not expected here" + } + if (ErrorCode == 22){ + return "brackets not closed" + } + if (ErrorCode == 23){ + return "ExpressionParseMacroCall out of memory" + } + if (ErrorCode == 24){ + return "too many arguments" + } + if (ErrorCode == 25){ + return "comma expected" + } + if (ErrorCode == 26){ + return "bad argument" + } + if (ErrorCode == 27){ + return "not enough arguments" + } + if (ErrorCode == 28){ + return "Macro undefined" + } + if (ErrorCode == 29){ + return "function - can't call" + } + if (ErrorCode == 30){ + return "ExpressionParseFunctionCall out of memory" + } + if (ErrorCode == 31){ + return "too many arguments" + } + if (ErrorCode == 32){ + return "comma expected" + } + if (ErrorCode == 33){ + return "bad argument" + } + if (ErrorCode == 34){ + return "not enough arguments" + } + if (ErrorCode == 35){ + return "undefined Fun name" + } + if (ErrorCode == 36){ + return "function body expected" + } + if (ErrorCode == 37){ + return "no value returned from a function returning" + } + if (ErrorCode == 38){ + return "couldn't find goto label" + } + if (ErrorCode == 39){ + return "expression expected" + } + if (ErrorCode == 40){ + return "integer value expected instead" + } + if (ErrorCode == 41){ + return "identifier expected" + } + if (ErrorCode == 42){ + return "undefined Identifier" + } + if (ErrorCode == 43){ + return "value expected" + } + if (ErrorCode == 44){ + return "#else without #if" + } + if (ErrorCode == 45){ + return "#endif without #if" + } + if (ErrorCode == 46){ + return "nested function definitions are not allowed" + } + if (ErrorCode == 47){ + return "too many parameters" + } + if (ErrorCode == 48){ + return "comma expected" + } + if (ErrorCode == 49){ + return "bad parameter" + } + if (ErrorCode == 50){ + return "main() should return an int or void" + } + if (ErrorCode == 51){ + return "bad parameters to main()" + } + if (ErrorCode == 52){ + return "bad function definition" + } + if (ErrorCode == 53){ + return "function definition expected" + } + if (ErrorCode == 54){ + return "Identifier is already defined" + } + if (ErrorCode == 55){ + return "} expected" + } + if (ErrorCode == 56){ + return "can't define a void variable" + } + if (ErrorCode == 57){ + return "close bracket expected" + } + if (ErrorCode == 58){ + return "Macro is already defined" + } + if (ErrorCode == 59){ + return "'(' expected" + } + if (ErrorCode == 60){ + return "statement expected" + } + if (ErrorCode == 61){ + return "';' expected" + } + if (ErrorCode == 62){ + return "')' expected" + } + if (ErrorCode == 63){ + return "'while' expected" + } + if (ErrorCode == 64){ + return "'{' expected" + } + if (ErrorCode == 65){ + return "filename.h expected" + } + if (ErrorCode == 66){ + return "'' expected" + } + if (ErrorCode == 67){ + return "value required in return" + } + if (ErrorCode == 68){ + return "value in return from a void function" + } + if (ErrorCode == 69){ + return "PicocParse out of memory" + } + if (ErrorCode == 70){ + return "parse error" + } + if (ErrorCode == 71){ + return "AssignFail" + } + if (ErrorCode == 72){ + return "TableSetIdentifier out of memory" + } + if (ErrorCode == 73){ + return "data type is already defined" + } + if (ErrorCode == 74){ + return "structure isn't defined" + } + if (ErrorCode == 75){ + return "struct/union definitions can only be globals" + } + if (ErrorCode == 76){ + return "invalid type in struct" + } + if (ErrorCode == 77){ + return "member already defined" + } + if (ErrorCode == 78){ + return "semicolon expected" + } + if (ErrorCode == 79){ + return "enum isn't defined" + } + if (ErrorCode == 80){ + return "enum definitions can only be globals" + } + if (ErrorCode == 81){ + return "bad type declaration" + } + if (ErrorCode == 82){ + return "']' expected" + } + if (ErrorCode == 83){ + return "Variable out of memory" + } + if (ErrorCode == 84){ + return "stack underrun" + } + if (ErrorCode == 85){ + return "VariableStack out of memory" + } + if (ErrorCode == 86){ + return "stack is empty - can't go back" + } + return "" +} + + ErrFly2String(ErrFly){ + let msg="" + const ERR_NONE =0 + const ERR_LOWBATT =this.BIT0 + const ERR_CODE =this.BIT1 + const ERR_TEMP =this.BIT3 + const ERR_SENSORS =this.BIT4 + const ERR_LOADER =this.BIT5 + const ERR_ANGLE =this.BIT6 + if (ErrFly == ERR_NONE){ + msg=msg +"NO_Error" + + } + if (ErrFly & ERR_LOWBATT == ERR_LOWBATT){ + msg= "Low_Battery" + " " + } + if (ErrFly & ERR_CODE == ERR_CODE){ + msg=msg + "Code_Error" + " " + } + if (ErrFly & ERR_TEMP == ERR_TEMP){ + msg=msg + "motherboard_temperature_is_too_high" + " " + } + if (ErrFly & ERR_SENSORS == ERR_SENSORS){ + msg=msg + "Sensor_Error" + " " + } + if (ErrFly & ERR_LOADER == ERR_LOADER){ + msg=msg + "Excessive_load" + " " + } + if (ErrFly & ERR_ANGLE == ERR_ANGLE){ + msg=msg + "Excessive_inclination_angle" + " " + } + return msg + + } + Sensor2String(){ + let SPLIT_STRING = "------------------------------------\n" + let msg = "STATE_PITCH= " + (Math.round(this.sensor.Pitch, 3)).toString() + "\n" + msg = msg + "STATE_ROLL= " + (Math.round(this.sensor.Roll, 3)).toString() + "\n" + msg = msg + "STATE_YAW= " + (Math.round(this.sensor.Yaw, 3)).toString() + "\n" + msg = msg + SPLIT_STRING + + msg = msg + "STATE_TEMP= " + (Math.round(this.sensor.SPL06_temp, 3)).toString() + "\n" + + msg = msg + "FusedHeight= " + (Math.round(this.sensor.FusedHeight, 3)).toString() + "\n" + + msg = msg + "BATTERY= " + (Math.round(this.sensor.Battery, 3)).toString() + "\n" + + msg = msg + "VER= " + this.VERSTR() + "\n" + msg = msg + SPLIT_STRING + msg = msg + "FLY_ERR= " + this.ErrFly2String(parseInt(this.sensor.ErrFly)) + "\n" + msg = msg + "LINE_NO= " + (this.sensor.LineNo) + "\n" + msg = msg + "ERROR_NO= " + (this.sensor.LineError) + "\n" + msg = msg + "ERROR_MSG= " + this.Errcode2Msg(this.sensor.ErrorCode) + "\n" + + msg = msg + "DEBUG1= " + (Math.round(this.sensor.Debug_0, 6)).toString() + "\n" + msg = msg + "DEBUG2= " + (Math.round(this.sensor.Debug_1, 6)).toString() + "\n" + msg = msg + "DEBUG3= " + (Math.round(this.sensor.Debug_2, 6)).toString() + "\n" + msg = msg + "DEBUG4= " + (Math.round(this.sensor.Debug_3, 6)).toString() + "\n" + msg = msg + "DEBUG5= " + (Math.round(this.sensor.Debug_4, 6)).toString() + "\n" + msg = msg + "DEBUG6= " + (Math.round(this.sensor.Debug_5, 6)).toString() + "\n" + return msg + } + + byte2float(offset) { + let buffer = new ArrayBuffer(4); + let view = new DataView(buffer); + + view.setUint8(3, this.revdata[offset + 0]); + view.setUint8(2, this.revdata[offset + 1]); + view.setUint8(1, this.revdata[offset + 2]); + view.setUint8(0, this.revdata[offset + 3]); + + // Đọc giá trị float từ ArrayBuffer dưới dạng big-endian + return view.getFloat32(0, false); // false chỉ định big-endian + } + + + getInjectStatus(revtmp) { + let revdata = Buffer.alloc(this.DATAREVLEN); + if (revtmp.byteLength == this.DATAREVLEN) + { + if(revtmp[0] == 0x77 && revtmp[1] == 0x78) + { + if (revtmp[this.BT_INDEX_REVCHECKSUM] == this.calChecksum(revtmp)) + { + for (let i = 0; i < revtmp.length; i++) { + revdata[i] = revtmp[i]; + } + } + } + } + + if (revdata[this.BT_INDEX_CMD_REV] === this.BT_CMD_DOWNLOAD || revdata[this.BT_INDEX_CMD_REV] === this.BT_CMD_DOWNLOAD_END) { + let isrevsame = true; + for (let i = 0; i < this.packlen; i++) { + if (revtmp !== revdata[i + this.BT_INDEX_CMD_REV]) { + isrevsame = false; + break; + } + } + if (isrevsame === true) { + this.nowdwpack = this.nowdwpack + 1; + } + if (revdata[this.BT_INDEX_CMD_REV] === this.BT_CMD_DOWNLOAD_END) { + // IsDownload = false; + console.log("download success"); + return true + } + } + else if(this.revdata[this.BT_INDEX_CMD_REV] == this.BT_CMD_GETFLYSTATE1){ + this.sensor.btkey = parseInt(revdata[2] + revdata[3] * 256) + this.sensor.btstick1 = parseInt(revdata[4]) + this.sensor.btstick2 = parseInt(revdata[5]) + this.sensor.btstick3 = parseInt(revdata[6]) + this.sensor.btstick4 = parseInt(revdata[7]) + this.sensor.ACC_x = this.byte2float(this.BT_INDEX_DATA_REV + 0 * 4) + this.sensor.ACC_y = this.byte2float(this.BT_INDEX_DATA_REV + 1 * 4) + this.sensor.ACC_z = this.byte2float(this.BT_INDEX_DATA_REV + 2 * 4) + this.sensor.Gypo_x = this.byte2float(this.BT_INDEX_DATA_REV + 3 * 4) + this.sensor.Gypo_y = this.byte2float(this.BT_INDEX_DATA_REV + 4 * 4) + this.sensor.Gypo_z = this.byte2float(this.BT_INDEX_DATA_REV + 5 * 4) + this.sensor.SPL06_temp = this.byte2float(this.BT_INDEX_DATA_REV + 6 * 4) + this.sensor.SPL06_Press = this.byte2float(this.BT_INDEX_DATA_REV + 7 * 4) + this.sensor.SPL06_asl = this.byte2float(this.BT_INDEX_DATA_REV + 8 * 4) + this.sensor.Pitch = this.byte2float(this.BT_INDEX_DATA_REV + 9 * 4) + this.sensor.Roll = this.byte2float(this.BT_INDEX_DATA_REV + 10 * 4) + this.sensor.Yaw = this.byte2float(this.BT_INDEX_DATA_REV + 11 * 4) + this.sensor.Battery = this.byte2float(this.BT_INDEX_DATA_REV + 12 * 4) + this.sensor.LaserTof = this.byte2float(this.BT_INDEX_DATA_REV + 13 * 4) + this.sensor.GL_X = this.byte2float(this.BT_INDEX_DATA_REV + 14 * 4) + this.sensor.GL_Y = this.byte2float(this.BT_INDEX_DATA_REV + 15 * 4) + this.sensor.timertick = this.byte2float(this.BT_INDEX_DATA_REV + 16 * 4) + this.sensor.M1 = parseInt(revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 0]) + this.sensor.M2 = parseInt(revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 1]) + this.sensor.M3 = parseInt(revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 2]) + this.sensor.M4 = parseInt(revdata[this.BT_INDEX_DATA_REV + 17 * 4 + 3]) + + this.sensor.state_velocity_x = this.byte2float(this.BT_INDEX_DATA_REV + 18 * 4) + this.sensor.state_velocity_y = this.byte2float(this.BT_INDEX_DATA_REV + 19 * 4) + this.sensor.state_velocity_z = this.byte2float(this.BT_INDEX_DATA_REV + 20 * 4) + + this.sensor.Debug_0 = this.byte2float(this.BT_INDEX_DATA_REV + 21 * 4) + this.sensor.Debug_1 = this.byte2float(this.BT_INDEX_DATA_REV + 22 * 4) + this.sensor.Debug_2 = this.byte2float(this.BT_INDEX_DATA_REV + 23 * 4) + this.sensor.Debug_3 = this.byte2float(this.BT_INDEX_DATA_REV + 24 * 4) + this.sensor.Debug_4 = this.byte2float(this.BT_INDEX_DATA_REV + 25 * 4) + this.sensor.Debug_5 = this.byte2float(this.BT_INDEX_DATA_REV + 26 * 4) + this.sensor.FusedHeight = this.byte2float(this.BT_INDEX_DATA_REV + 27 * 4) + + this.sensor.VER = parseInt(revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 0]) + this.sensor.ErrFly = parseInt(revdata[this.BT_INDEX_DATA_REV + 28 * 4 + 1]) + let msg = this.Sensor2String(); + console.log(msg); + } + + + return false; + } + + exportProject() { + let project = {}; + + project.objects = Entry.container.toJSON(); + const objects = project.objects; + project.scenes = Entry.scene.toJSON(); + project.variables = Entry.variableContainer.getVariableJSON(); + project.messages = Entry.variableContainer.getMessageJSON(); + project.functions = Entry.variableContainer.getFunctionJSON(); + project.tables = DataTable.getTableJSON(); + project.speed = Entry.FPS; + project.interface = Entry.captureInterfaceState(); + project.expansionBlocks = Entry.expansionBlocks; + project.aiUtilizeBlocks = Entry.aiUtilizeBlocks; + project.hardwareLiteBlocks = Entry.hardwareLiteBlocks; + project.learning = Entry.aiLearning?.toJSON(); + project.externalModules = entryModuleLoader.moduleList; + project.externalModulesLite = entryModuleLoader.moduleListLite; + + if (!objects || !objects.length) { + return false; + } + + return project; + } + + setLanguage() { + return { + ko: { + template: { + whalesbot_drone_openning_3d_simulator: '3D 시뮬레이터를 엽니 다', + whalesbot_drone_clean:'삭제', + whalesbot_drone_restart: '재시작', + whalesbot_drone_entering_pitch_mode:'준비모드 시작하기', + whalesbot_drone_exit_pitch_mode:'준비모드 끝내기', + whalesbot_drone_automatic_take_off_height:'자동 이륙 높이 %1 cm', + whalesbot_drone_automatic_take_off_altitude_speed_offset:'자동 이륙 고도 %1 cm 속도 %2 X 오프셋 %3 도 Y 오프셋 %4 도 으로 이동하기', + whalesbot_drone_automatic_landing:'드로착륙', + whalesbot_drone_automatic_descent_speed_offset:'자동 낙하 속도 %1 X 오프셋 %2 도 Y 오프셋 %3 도', + whalesbot_drone_set_the_flight_speed:'설정된 비행 속도는 %1 cm/s', + whalesbot_drone_get_setting_speed:'설정 속도 가져오기', + whalesbot_drone_rise:'위로 %1 cm', + whalesbot_drone_down:'아래로 %1 cm', + whalesbot_drone_fly_forward:'앞으로 %1 cm', + whalesbot_drone_fly_backward:'뒤로 %1 cm', + whalesbot_drone_fly_left:'왼쪽으로 %1 cm', + whalesbot_drone_fly_right:'오른쪽으로 %1 cm', + whalesbot_drone_turn_left:'왼쪽으로 회전 %1 °', + whalesbot_drone_turn_right:'오른쪽으로 회전 %1 °', + + whalesbot_drone_fly_in_the_specified_direction:'속도 %1 , 방향 %2 으로이동하기', + whalesbot_drone_flight_designated:'지정된 거리를 비행합니다 x %1 cm y %2 cm z%3 cm 속도 %4 cm/s', + whalesbot_drone_set_the_four_channel_lever_quantity_of_remote_control:'리모컨 4개 채널 로드 설정 Pitch %1 Roll %2 액셀러레이터 %3 Yaw %4', + whalesbot_drone_stop_moving_and_hover:'호버링기능', + whalesbot_drone_hover_at_specified_altitude:'지정된 높이에 서스펜션 %1 cm', + whalesbot_drone_emergency_stop:'긴급정지', + whalesbot_drone_set_the_steering_gear:'스티어링기어 ID 설정 포트 %1 속도 %2 각도 %3', + whalesbot_drone_execute_script:'스크립트 실행', + }, + Device: { + whalesbot_drone_lite: 'whalesbot_drone_lite', + }, + Menus: { + whalesbot_drone_lite: 'WhalesbotDroneLite', + }, + Blocks: { + whalesbot_drone_toast_status_title: "Drone Status", + whalesbot_drone_toast_download_success: "Download code successed", + whalesbot_drone_toast_download_failed: "Download code failed", + whalesbot_drone_toast_clean_failed: "Clean code failed", + whalesbot_drone_toast_clean_success: "Clean code success", + whalesbot_drone_toast_unsupport_block_title: "Unsupport Block", + whalesbot_drone_toast_unsupport_block_msg: "There is some blocks is not supported by hardware" + } + }, + en: { + template: { + whalesbot_drone_openning_3d_simulator: 'Open 3D Simulator', + whalesbot_drone_clean:'Clean', + whalesbot_drone_restart: 'Restart', + whalesbot_drone_entering_pitch_mode:'Entering Pitch Mode', + whalesbot_drone_exit_pitch_mode:'Exit Pitch Mode', + whalesbot_drone_automatic_take_off_height:'Automatic Take Off Height %1 cm', + whalesbot_drone_automatic_take_off_altitude_speed_offset:'Automatic Take Off Altitude %1 cm, Speed %2, X offset %3 degree, Y offset %4 degree', + whalesbot_drone_automatic_landing:'Automatic Landing', + whalesbot_drone_automatic_descent_speed_offset:'Automatic Descent Speed %1, X offset %2 degree, Y offset %3 degree', + whalesbot_drone_set_the_flight_speed:'Set The Flight Speed To %1 cm/s', + whalesbot_drone_get_setting_speed:'Get Setting Speed', + whalesbot_drone_rise:'Rise %1 cm', + whalesbot_drone_down:'Down %1 cm', + whalesbot_drone_fly_forward:'Fly Forward %1 cm', + whalesbot_drone_fly_backward:'Fly Backward %1 cm', + whalesbot_drone_fly_left:'Fly Left %1 cm', + whalesbot_drone_fly_right:'Fly Right %1 cm', + whalesbot_drone_turn_left:'Turn Left %1 °', + whalesbot_drone_turn_right:'Turn Right %1 °', + whalesbot_drone_fly_in_the_specified_direction:'Fly In The Specified Direction Speed %1 cm/s Direction %2 °', + whalesbot_drone_flight_designated:'Flight Designated Distance X %1 cm Y %2 cm Z %3 cm Speed %4 cm/s', + whalesbot_drone_set_the_four_channel_lever_quantity_of_remote_control:'Set The Four Channel Lever Quantity Of Remote Control Pitch %1° Roll %2° Throttle %3° Roll %4°', + whalesbot_drone_stop_moving_and_hover:'Stop Moving And Hover', + whalesbot_drone_hover_at_specified_altitude:'Hover At a Specified Altitude %1 cm', + whalesbot_drone_emergency_stop:'Emergency Stop', + whalesbot_drone_set_the_steering_gear:'Set The Steering Gear Port %1 Speed %2 cm/s Angle %3 °', + whalesbot_drone_execute_script:'Execute Script', + }, + Device: { + whalesbot_drone_lite: 'whalesbot_drone_lite', + }, + Menus: { + whalesbot_drone_lite: 'WhalesbotDroneLite', + }, + Blocks: { + whalesbot_drone_toast_status_title: "Drone Status", + whalesbot_drone_toast_download_success: "Download code successed", + whalesbot_drone_toast_download_failed: "Download code failed", + whalesbot_drone_toast_clean_failed: "Clean code failed", + whalesbot_drone_toast_clean_success: "Clean code success", + whalesbot_drone_toast_unsupport_block_title: "Unsupport Block", + whalesbot_drone_toast_unsupport_block_msg: "There is some blocks is not supported by hardware" + } + }, + }; + } + + getBlocks() { + let cFunctions = []; + let _this = this; + let sourceCode; + + const defaultSpeed = "10"; + const defaultAltitude = "50"; + const defaultOffset = "0"; + + const wbOperators = { + "EQUAL": "==", + "NOT_EQUAL": "!=", + "GREATER": ">", + "GREATER_OR_EQUAL": ">=", + "LESS": "<", + "LESS_OR_EQUAL": "<=", + "AND": "&&", + "OR": "||", + }; + + const wbVariables = { + "whalesbot_drone_get_setting_speed": "fly_state(SETSPEED)" + } + + const startBlocks = [ + "when_run_button_click", + "when_some_key_pressed", + "mouse_clicked", + "mouse_click_cancled", + "when_object_click", + "when_object_click_canceled", + ] + + let globlalCVariables = {} + + function _getParameter (parameter) { + let param = parameter.params[0] != "" ? parameter.params[0] : "0" + if (parameter.type != "text" && parameter.type != "number" && parameter.type != "get_variable") { + param = wbVariables[parameter.type] + } else if (parameter.type == "get_variable") { + param = globlalCVariables[parameter.params[0]] + } + return param + } + + function _generateConditions (params) { + let left = _getParameter(params[0]) + let operator = params[1] != undefined ? wbOperators[params[1]] : "0" + let right = _getParameter(params[2]) + return { left, operator, right } + } + + function generateCCode (block) { + switch (block.type) { + // LOOP + case 'repeat_basic': + let times = _getParameter(block.params[0]); + return `\tfor(int i=0; i<${times}; ++i) {\n${block.statements[0].map((generateCCode)).join('')}\t}\n`; + + case 'repeat_inf': + return `\twhile(1) {\n${block.statements[0].map(generateCCode).join('')}\t}\n`; + + case 'repeat_while_true': + let rpWhileDecision = { + "type": block.params[0].type, + "params": block.params[0].params, + }; + return `\twhile(!(${generateCCode(rpWhileDecision)})) {\n${block.statements[0].map(generateCCode).join('')}\t}\n`; + + case 'wait_second': + let second = _getParameter(block.params[0]); + return `\twait(${second});\n`; + + case 'wait_until_true': + let waitUntilTrueDecision = { + "type": block.params[0].type, + "params": block.params[0].params, + }; + return `\twhile(!(${generateCCode(waitUntilTrueDecision)})) {\n\t}\n`; + + case 'stop_repeat': + return `\tbreak;\n`; + + // CONDITION + case '_if': + let ifDecision = { + "type": block.params[0].type, + "params": block.params[0].params, + }; + return `\tif(${generateCCode(ifDecision)}) {\n${block.statements[0].map(generateCCode).join('')}\t}\n`; + + case 'if_else': + let ifElseDecision = { + "type": block.params[0].type, + "params": block.params[0].params, + }; + return `\tif(${generateCCode(ifElseDecision)}) {\n${block.statements[0].map(generateCCode).join('')}\t} else {\n${block.statements[1].map(generateCCode).join('')}\t}\n`; + + // DECISION + case 'boolean_and_or': + let boolAndOrBasicLeftValue = generateCCode(block.params[0]); + let boolAndOrBasicOperator = wbOperators[block.params[1]]; + let boolAndOrBasicRightValue = generateCCode(block.params[2]); + return `(${boolAndOrBasicLeftValue} ${boolAndOrBasicOperator} ${boolAndOrBasicRightValue})`; + + case 'boolean_not': + let boolNotDecision = generateCCode(block.params[1]); + return `!(${boolNotDecision})`; + + case 'boolean_basic_operator': + let boolBasicCondition = "0" + if (block.params[0].params[0] != null) { + let boolBasicLeftValue = _generateConditions(block.params).left; + let boolBasicOperator = _generateConditions(block.params).operator; + let boolBasicRightValue = _generateConditions(block.params).right; + boolBasicCondition = `(${boolBasicLeftValue} ${boolBasicOperator} ${boolBasicRightValue})`; + } + return `${boolBasicCondition}`; + + // VARIABLE + case 'True': + return "0"; + + case 'False': + return "0"; + + case 'set_variable': + let variableName = globlalCVariables[block.params[0]]; + let variableValue = _getParameter(block.params[1]); + return `\t${variableName} = ${variableValue};\n`; + + case 'change_variable': + let changedVariableName = globlalCVariables[block.params[0]]; + let changedVariableValue = _getParameter(block.params[1]); + return `\t${changedVariableName} += ${changedVariableValue};\n`; + + // HARDWARE + case 'whalesbot_drone_entering_pitch_mode': + return '\tfly_unlock();\n'; + + case 'whalesbot_drone_exit_pitch_mode': + return '\tfly_lock();\n'; + + case 'whalesbot_drone_automatic_take_off_height': + let takeOffHeight = _getParameter(block.params[0]); + return `\tfly_start(${takeOffHeight});\n`; + + case 'whalesbot_drone_automatic_take_off_altitude_speed_offset': + let takeOffAltitude = _getParameter(block.params[0]) != "" ? _getParameter(block.params[0]) : defaultAltitude; + let takeOffSpeed = _getParameter(block.params[1]) != "" ? _getParameter(block.params[1]) : defaultSpeed; + let takeOffXoffset = (-10.00 <= _getParameter(block.params[2]) || _getParameter(block.params[2]) <= 10.00) ? _getParameter(block.params[2]) : defaultOffset; + let takeOffYoffset = (-10.00 <= _getParameter(block.params[3]) || _getParameter(block.params[3]) <= 10.00) ? _getParameter(block.params[3]) : defaultOffset; + return `\tfly_start_2(${takeOffAltitude},${takeOffSpeed},${takeOffXoffset},${takeOffYoffset});\n` + + case 'whalesbot_drone_automatic_landing': + return `\tfly_land();\n`; + + case 'whalesbot_drone_automatic_descent_speed_offset': + let automaticSpeed = _getParameter(block.params[0]) != "" ? _getParameter(block.params[0]) : defaultSpeed; + let automaticXoffset = (-10.00 <= _getParameter(block.params[1]) || _getParameter(block.params[1]) <= 10.00) ? _getParameter(block.params[1]) : defaultOffset; + let automaticYoffset = (-10.00 <= _getParameter(block.params[2]) || _getParameter(block.params[2]) <= 10.00) ? _getParameter(block.params[2]) : defaultOffset; + return `\tfly_land_2(${automaticSpeed},${automaticXoffset},${automaticYoffset});\n` + + case 'whalesbot_drone_set_the_flight_speed': + let speed = _getParameter(block.params[0]); + return `\tfly_setspeed(${speed});\n`; + + case 'whalesbot_drone_get_setting_speed': + return `\tfly_state(SETSPEED);\n`; + + case 'whalesbot_drone_rise': + let up = _getParameter(block.params[0]); + return `\tfly_moveto(UP,${up});\n`; + + case 'whalesbot_drone_down': + let down = _getParameter(block.params[0]); + return `\tfly_moveto(DOWN,${down});\n`; + + case 'whalesbot_drone_fly_forward': + let front = _getParameter(block.params[0]); + return `\tfly_moveto(FRONT,${front});\n`; + + case 'whalesbot_drone_fly_backward': + let back = _getParameter(block.params[0]); + return `\tfly_moveto(BACK,${back});\n`; + + case 'whalesbot_drone_fly_left': + let left = _getParameter(block.params[0]); + return `\tfly_moveto(LEFT,${left});\n`; + + case 'whalesbot_drone_fly_right': + let right = _getParameter(block.params[0]); + return `\tfly_moveto(RIGHT,${right});\n`; + + case 'whalesbot_drone_turn_left': + let turnLeft = _getParameter(block.params[0]); + if (0 > turnLeft || turnLeft > 360) { + turnLeft = 360 + } + return `\tfly_turn(CCW,${turnLeft});\n`; + + case 'whalesbot_drone_turn_right': + let turnRight = _getParameter(block.params[0]); + if (0 > turnRight || turnRight > 360) { + turnRight = 360 + } + return `\tfly_turn(CW,${turnRight});\n`; + + case 'whalesbot_drone_fly_in_the_specified_direction': + let dirSpeed = _getParameter(block.params[0]); + let dirDirection = _getParameter(block.params[1]); + if (0 > dirDirection || dirDirection > 360) { + dirDirection = 360 + } + return `\tfly_dir(${dirSpeed},${dirDirection});\n`; + + case 'whalesbot_drone_flight_designated': + let disX = _getParameter(block.params[0]); + let disY = _getParameter(block.params[1]); + let disZ = _getParameter(block.params[2]); + let disSpeed = _getParameter(block.params[3]); + return `\tfly_move_dis(${disX},${disY},${disZ},${disSpeed});\n`; + + case 'whalesbot_drone_set_the_four_channel_lever_quantity_of_remote_control': + let pitch = _getParameter(block.params[0]); + let roll = _getParameter(block.params[1]); + let throttle = _getParameter(block.params[2]); + let yaw = _getParameter(block.params[3]); + return `\tfly_move(${pitch},${roll},${throttle},${yaw});\n`; + + case 'whalesbot_drone_stop_moving_and_hover': + return `\tfly_hover();\n`; + + case 'whalesbot_drone_hover_at_specified_altitude': + let hoverSpecifiedAltitude = (_getParameter(block.params[0]) == "" || _getParameter(block.params[0]) < 20) ? "20" : _getParameter(block.params[0]); + hoverSpecifiedAltitude = (_getParameter(block.params[0]) > 200) ? "200" : _getParameter(block.params[0]); + return `\tfly_hover_laser(${hoverSpecifiedAltitude});\n`; + + case 'whalesbot_drone_emergency_stop': + return `\tfly_lock();\n`; + + case 'whalesbot_drone_set_the_steering_gear': + let servoSpeed = _getParameter(block.params[1]); + let servoAngle = _getParameter(block.params[2]); + if (0 > servoAngle || servoAngle > 360) { + servoAngle = 360 + } + return `\tSetServo(P2,${servoSpeed},${servoAngle});\n`; + + default: + if (!startBlocks.includes(block.type)) { + _this.unsupportBlockExist = true; + } + return ''; + } + } + + function setUpCVariables (variable) { + if (variable.visible) { + const varName = `var_${variable.name}` + globlalCVariables[variable.id] = varName + const varValue = variable.value; + return `float ${varName} = ${varValue};\n` + } + return "" + } + + function openedSimulatorPopup () { + if (_this.simulatorPopup == null) { + return false; + } + return !_this.simulatorPopup.closed; + } + + return { + whalesbot_drone_openning_3d_simulator: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_drone_openning_3d_simulator', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func (sprite, script) { + const width = window.innerWidth * 0.8; + const height = window.innerHeight * 0.8; + _this.simulatorPopup = window.open( + metadata.simulator_url, + 'DroneSimulatorPopup', + `width=${width},height=${height}` + ); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_openning_3d_simulator()'] }, + }, + whalesbot_drone_restart: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/moving_icon.svg', + size: 11, + }, + ], + events: {}, + def: { + type: 'whalesbot_drone_restart', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func (sprite, script) { + await _this.sendPacket(_this.getStateCode); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_restart()'] }, + }, + whalesbot_drone_clean: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/moving_icon.svg', + size: 11, + }, + ], + events: {}, + def: { + type: 'whalesbot_drone_clean', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func (sprite, script) { + await _this.sendPacket(_this.stopCode); + await _this.sendPacket(_this.stopCode); + Entry.toast.success(Lang.Blocks.whalesbot_drone_toast_status_title, + Lang.Blocks.whalesbot_drone_toast_clean_success); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_clean()'] }, + }, + whalesbot_drone_entering_pitch_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_drone_entering_pitch_mode', + }, + paramsKeyMap: {}, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func (sprite, script) { + console.log("whalesbot_drone_entering_pitch_mode") + await _this.sendPacket(_this.getStateCode); + await _this.sendPacket(_this.getStateCode); + cFunctions.push(`fly_unlock();`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_entering_pitch_mode()'] }, + }, + whalesbot_drone_exit_pitch_mode: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_drone_exit_pitch_mode', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func(sprite, script) { + const project = _this.exportProject(); + const listVariables = project.variables; + const rawScript = project.objects[0].script; + const allScript = JSON.parse(rawScript); + const droneScript = allScript.filter((arr) => arr.length > 2); + + sourceCode = `#include "whalesbot.h"\n${listVariables.map(setUpCVariables).join('')}\nvoid user_main() {\n`; + sourceCode += `${droneScript[0].map(generateCCode).join('')}}\n\nuser_main();`; + + if (_this.unsupportBlockExist) { + Entry.toast.alert( + Lang.Blocks.whalesbot_drone_toast_unsupport_block_title, + Lang.Blocks.whalesbot_drone_toast_unsupport_block_msg + ) + _this.unsupportBlockExist = false; + Entry.engine.toggleStop(); + return; + } + console.log(sourceCode) + + if (openedSimulatorPopup()) { + Entry.toast.success( + Lang.Blocks.whalesbot_drone_toast_status_title, + Lang.Blocks.whalesbot_drone_toast_download_success + ); + return; + } + + let i = 0; + _this.setDownloadStatus(false); + _this.isGetFlyState = false; + + // get fly state + // await _this.sendPacket(_this.getStateCode); + // await _this.sendPacket(_this.getStateCode); + // Entry.hwLite.serial.flush(); + // download + _this.connectDrone(); + // send first chunk + if(_this.isDroneConnection == true){ + console.log("Send chunk 0"); + let byteCode = _this.generateBytesCode(_this.cmdType.Download, sourceCode, 0); + await _this.sendPacket(byteCode, false); + i++; + + while(true) + { + console.log("Send chunk ", i); + byteCode = _this.generateBytesCode(_this.cmdType.Download, sourceCode, i); + await _this.sendPacket(byteCode, false); + if(_this.isLatestChunk(byteCode)) + { + console.log("Latest chunk sent!"); + this.revdata = []; + Entry.toast.success(Lang.Blocks.whalesbot_drone_toast_status_title, + Lang.Blocks.whalesbot_drone_toast_download_success); + break; + } + i++; + } + } + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_exit_pitch_mode()'] }, + }, + whalesbot_drone_automatic_take_off_height: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_drone_automatic_take_off_height', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_automatic_take_off_height") + cFunctions.push(`fly_start(${script.getValue('VALUE')})`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_automatic_take_off_height();'] }, + }, + whalesbot_drone_automatic_take_off_altitude_speed_offset: { + 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', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['100'], + }, + { + type: 'number', + params: ['0'], + }, + { + type: 'number', + params: ['0'], + }, + ], + type: 'whalesbot_drone_automatic_take_off_altitude_speed_offset', + }, + paramsKeyMap: { + altitude: 0, + speed: 1, + x: 2, + y: 3, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_automatic_take_off_altitude_speed_offset") + cFunctions.push(`fly_start(${script.getValue('VALUE')})`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_automatic_take_off_altitude_speed_offset();'] }, + }, + whalesbot_drone_automatic_landing: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_drone_automatic_landing', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func(sprite, script) { + console.log("whalesbot_drone_automatic_landing") + cFunctions.push(`fly_land();`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_automatic_landing()'] }, + }, + whalesbot_drone_automatic_descent_speed_offset: { + 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', + defaultType: 'number', + }, + ], + events: {}, + def: { + type: 'whalesbot_drone_automatic_descent_speed_offset', + }, + paramsKeyMap: { + speed: 0, + x: 1, + y: 2, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func(sprite, script) { + console.log("whalesbot_drone_automatic_descent_speed_offset") + cFunctions.push(`fly_land_2();`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_automatic_descent_speed_offset()'] }, + }, + whalesbot_drone_set_the_flight_speed: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + ], + type: 'whalesbot_drone_set_the_flight_speed', + }, + paramsKeyMap: { + SPEED: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func(sprite, script) { + const speed = script.getValue('SPEED'); + console.log("whalesbot_drone_set_the_flight_speed") + cFunctions.push(`fly_setspeed(${speed});`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_set_the_flight_speed()'] }, + }, + whalesbot_drone_get_setting_speed: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_string_field', + statements: [], + params: [], + events: {}, + def: { + type: 'whalesbot_drone_get_setting_speed', + }, + paramsKeyMap: {}, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func(sprite, script) { + console.log("whalesbot_drone_get_setting_speed"); + cFunctions.push(`fly_state(SETSPEED);`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_get_setting_speed()'] }, + }, + whalesbot_drone_rise: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_drone_rise', + }, + paramsKeyMap: { + value: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_rise"); + const value = script.getValue('value'); + cFunctions.push(`fly_moveto(UP,${value})`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_rise();'] }, + }, + whalesbot_drone_down: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_drone_down', + }, + paramsKeyMap: { + value: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_down"); + const value = script.getValue('value'); + cFunctions.push(`fly_moveto(DOWN,${value})`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_down();'] }, + }, + whalesbot_drone_fly_forward: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_drone_fly_forward', + }, + paramsKeyMap: { + value: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_fly_forward"); + const value = script.getValue('value'); + cFunctions.push(`fly_moveto(FRONT,${value})`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_fly_forward();'] }, + }, + whalesbot_drone_fly_backward: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_drone_fly_backward', + }, + paramsKeyMap: { + value: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_fly_backward"); + const value = script.getValue('value'); + cFunctions.push(`fly_moveto(BACK,${value})`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_fly_backward();'] }, + }, + whalesbot_drone_fly_left: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_drone_fly_left', + }, + paramsKeyMap: { + value: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_fly_left"); + const value = script.getValue('value'); + cFunctions.push(`fly_moveto(LEFT,${value});`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_fly_left();'] }, + }, + whalesbot_drone_fly_right: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + null, + ], + type: 'whalesbot_drone_fly_right', + }, + paramsKeyMap: { + value: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_fly_right"); + const value = script.getValue('value'); + cFunctions.push(`fly_moveto(RIGHT,${value});`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_fly_right();'] }, + }, + whalesbot_drone_turn_left: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['90'], + }, + ], + type: 'whalesbot_drone_turn_left', + }, + paramsKeyMap: { + value: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_turn_left"); + const value = script.getValue('value'); + if (value < 0 && value > 360) { + value = 360 + } + cFunctions.push(`fly_turn(CCW,${value});`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_turn_left();'] }, + }, + whalesbot_drone_turn_right: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['90'], + }, + ], + type: 'whalesbot_drone_turn_right', + }, + paramsKeyMap: { + value: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_turn_right"); + const value = script.getValue('value'); + if (value < 0 && value > 360) { + value = 360 + } + cFunctions.push(`fly_turn(CW,${value});`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_turn_right();'] }, + }, + whalesbot_drone_fly_in_the_specified_direction: { + 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', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['30'], + }, + { + type: 'number', + params: ['0'], + }, + ], + type: 'whalesbot_drone_fly_in_the_specified_direction', + }, + paramsKeyMap: { + speed: 0, + direction: 1, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_fly_in_the_specified_direction"); + const speed = script.getValue('speed'); + const direction = script.getValue('direction'); + if (direction < 0 && direction > 360) { + direction = 360 + } + cFunctions.push(`fly_dir(${speed},${direction});`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_fly_in_the_specified_direction();'] }, + }, + whalesbot_drone_flight_designated: { + 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', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['30'], + }, + ], + type: 'whalesbot_drone_flight_designated', + }, + paramsKeyMap: { + x: 0, + y: 1, + z: 2, + speed: 3, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_flight_designated"); + const x = script.getValue('x'); + const y = script.getValue('y'); + const z = script.getValue('z'); + const speed = script.getValue('speed'); + cFunctions.push(`fly_move_dis(${x},${y},${z},${speed})`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_flight_designated();'] }, + }, + whalesbot_drone_set_the_four_channel_lever_quantity_of_remote_control: { + 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', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + { + type: 'number', + params: ['50'], + }, + ], + type: 'whalesbot_drone_set_the_four_channel_lever_quantity_of_remote_control', + }, + paramsKeyMap: { + pitch: 0, + roll: 1, + throttle: 2, + yaw: 3, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_set_the_four_channel_lever_quantity_of_remote_control"); + const pitch = script.getValue('pitch'); + const roll = script.getValue('roll'); + const throttle = script.getValue('throttle'); + const yaw = script.getValue('yaw'); + cFunctions.push(`fly_move(${pitch},${roll},${throttle},${yaw});`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_set_the_four_channel_lever_quantity_of_remote_control();'] }, + }, + whalesbot_drone_stop_moving_and_hover: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [], + events: {}, + def: { + params: [], + type: 'whalesbot_drone_stop_moving_and_hover', + }, + paramsKeyMap: {}, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_stop_moving_and_hover"); + cFunctions.push(`fly_hover();`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_stop_moving_and_hover();'] }, + }, + whalesbot_drone_hover_at_specified_altitude: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + { + type: 'number', + params: ['20'], + }, + ], + type: 'whalesbot_drone_hover_at_specified_altitude', + }, + paramsKeyMap: { + altitude: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_hover_at_specified_altitude"); + cFunctions.push(`fly_hover_laser();`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_hover_at_specified_altitude();'] }, + }, + whalesbot_drone_emergency_stop: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [], + events: {}, + def: { + type: 'whalesbot_drone_emergency_stop', + }, + paramsKeyMap: {}, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func(sprite, script) { + console.log("whalesbot_drone_emergency_stop") + cFunctions.push(`fly_lock();`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_emergency_stop()'] }, + }, + whalesbot_drone_set_the_steering_gear: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic', + statements: [], + params: [ + { + type: 'Dropdown', + options: [ + ['P2', 'P2'], + ], + value: 'P2', + fontSize: 10, + bgColor: EntryStatic.colorSet.block.darken.HARDWARE, + arrowColor: EntryStatic.colorSet.arrow.default.HARDWARE, + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + ], + events: {}, + def: { + params: [ + null, + { + type: 'number', + params: ['40'], + }, + { + type: 'number', + params: ['90'], + }, + ], + type: 'whalesbot_drone_set_the_steering_gear', + }, + paramsKeyMap: { + port: 0, + speed: 1, + angle: 2, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + func(sprite, script) { + console.log("whalesbot_drone_set_the_steering_gear"); + const speed = script.getValue('speed'); + const angle = script.getValue('angle'); + cFunctions.push(`SetServo(P2,${speed},${angle});`); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_set_the_steering_gear();'] }, + }, + whalesbot_drone_execute_script: { + color: EntryStatic.colorSet.block.default.HARDWARE, + outerLine: EntryStatic.colorSet.block.darken.HARDWARE, + fontColor: '#fff', + skeleton: 'basic_without_next', + statements: [], + params: [ + { + type: 'Block', + accept: 'string', + defaultType: 'number', + }, + { + type: 'Indicator', + img: 'block_icon/moving_icon.svg', + size: 11, + }, + ], + events: {}, + def: { + type: 'whalesbot_drone_execute_script', + }, + paramsKeyMap: { + VALUE: 0, + }, + class: 'arduino_value', + isNotFor: ['WhalesbotDroneLite'], + async func(sprite, script) { + if (openedSimulatorPopup()) { + _this.simulatorPopup.postMessage({ + function: "enteringPitchMode", + args: [], + script: sourceCode + }, '*'); + return; + } + await _this.sendPacket(_this.runCode); + }, + syntax: { js: [], py: ['Entry.whalesbot_drone_execute_script()'] }, + }, + }; + } + })(); +})(); + +module.exports = Entry.WhalesbotDroneLite; diff --git a/src/playground/blocks/hardwareLite/metadata_robotis_robotai_lite.json b/src/playground/blocks/hardwareLite/metadata_robotis_robotai_lite.json new file mode 100644 index 0000000000..e04525c172 --- /dev/null +++ b/src/playground/blocks/hardwareLite/metadata_robotis_robotai_lite.json @@ -0,0 +1,9 @@ +{ + "name": "RobotisRobotaiLite", + "version": "1.0.0", + "type": "hardware", + "title": "로봇아이(AI)", + "description": "로보티즈", + "imageName": "robotis_robotai_lite", + "moduleId": "070B01" +} diff --git a/src/playground/blocks/hardwareLite/metadata_whalesbot_drone_lite.json b/src/playground/blocks/hardwareLite/metadata_whalesbot_drone_lite.json new file mode 100644 index 0000000000..840453fca7 --- /dev/null +++ b/src/playground/blocks/hardwareLite/metadata_whalesbot_drone_lite.json @@ -0,0 +1,9 @@ +{ + "name": "WhalesbotDrone", + "version": "1.0.0", + "type": "hardware", + "title": "고래봇 드론", + "description": "Whalesbot", + "imageName": "whalesbot_drone", + "moduleId": "620101" +}