Metadata-Version: 2.4
Name: pykamilab
Version: 3.0.0
Summary: A Python Library For Kamibot-Pi (JupyterLab Desktop ready)
Home-page: http://www.moyalab.com
Author: devdio
Author-email: kei.devdio@gmail.com
License: GNU GPLv3
Keywords: Kamibot Pi,KamibotPi,Robot,JupyterLab
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Education
Classifier: Framework :: Jupyter
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: termcolor
Requires-Dist: pyserial<4,>=3.5
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

## pykamilab — Package for KamibotPi

KamibotPi 교육용 로봇을 USB 시리얼 동글로 제어하는 Python 라이브러리.
JupyterLab Desktop / Jupyter Notebook 환경에서 바로 사용할 수 있도록 설계됨.
(기존 `pyKamipi` 패키지의 후속 — 패키지명 변경 + 노트북 호환 개선)

### 설치

```bash
pip install pykamilab
```

JupyterLab Desktop 노트북에서는 셀에서 다음을 실행:

```python
%pip install pykamilab
```

> `!pip` 대신 `%pip`을 사용해야 현재 커널 환경에 설치됩니다.

### JupyterLab Desktop 빠른 시작

```python
import pykamilab

# 1) 포트 검색
pykamilab.list_ports()

# 2) 연결 — response_timeout 권장 (펌웨어 무응답 시 셀 자동 종료)
from pykamilab import KamibotPi
bot = KamibotPi('COM3', response_timeout=3.0)
bot.init()

# 3) 5cm 전진
bot.move_forward_unit(5, "-l")
bot.delay(1)
bot.stop()

# 4) 종료 (커널 유지)
bot.disconnect()
```

### `with` 문 사용 (자동 disconnect)

`KamibotPi`는 컨텍스트 매니저를 지원합니다. `with` 블록을 벗어나면
예외가 발생하더라도 `disconnect()`가 자동으로 호출되므로,
포트가 열린 채로 남아 다음 셀 실행을 막는 사고를 방지할 수 있습니다.

```python
import pykamilab

with pykamilab.KamibotPi('COM69') as bot:
    bot.init()
    bot.draw_rect(10)
    bot.delay(1)
# 여기서 블록을 벗어나면 자동으로 disconnect() 호출됨
```

- `bot.init()`은 블록 안에서 한 번 호출해 펌웨어를 준비 상태로 둡니다.
- 블록 내부의 예외도 `__exit__`에서 처리되어 포트는 정상적으로 닫힙니다.
- 노트북에서 사용하는 경우 생성자에 `response_timeout=3.0` 을 같이 넘겨
  펌웨어 무응답으로 셀이 멈추는 상황을 방지하는 것이 좋습니다.

```python
with pykamilab.KamibotPi('COM3', response_timeout=3.0) as bot:
    bot.init()
    bot.move_forward_unit(5, "-l")
    bot.delay(1)
    bot.stop()
```

### 환경별 포트 이름

- Windows: `COM3`, `COM8` 등
- macOS: `/dev/cu.usbserial-*` (`/dev/tty.*` 는 행 가능성)
- Linux: `/dev/ttyUSB*` 또는 `/dev/ttyACM*` (`dialout` 그룹 필요)

### 변경 사항 (v3.0.0)

- `sys.exit()` 호출 제거 — 노트북 커널이 살아 있는 상태로 예외 raise
- `KamibotPi(..., response_timeout=...)` 옵션 추가
- `pykamilab.list_ports()` 헬퍼 추가
- `close()`는 `disconnect()`의 alias (커널 안전)

### example

#### 콘트롤 모드

```
#-*-coding:utf-8-*-
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM8')

# ------------------------------------------------
# 콘트롤모드 go_dir_speed
# ------------------------------------------------
kamibot.go_dir_speed("f", 100, "f", 100)
kamibot.delay(1)

kamibot.go_dir_speed("b", 100, "f", 100)
kamibot.delay(1)

kamibot.go_dir_speed("f", 100, "b", 100)
kamibot.delay(1)

kamibot.go_dir_speed("b", 100, "b", 100)
kamibot.delay(1)
kamibot.stop()

# ------------------------------------------------
# 콘트롤모드 go_forward_speed
# ------------------------------------------------
kamibot.go_forward_speed(50, 50)
kamibot.delay(1)

kamibot.go_forward_speed(100, 50)
kamibot.delay(1)
kamibot.stop()

# ------------------------------------------------
# 콘트롤모드 go_backward_speed
# ------------------------------------------------
kamibot.go_backward_speed(50, 50)
kamibot.delay(1)

kamibot.go_backward_speed(100, 50)
kamibot.delay(1)
kamibot.stop()

# ------------------------------------------------
# 콘트롤모드 go_left_speed
# ------------------------------------------------
kamibot.go_left_speed(50)
kamibot.delay(1)

kamibot.go_left_speed(100)
kamibot.delay(1)
kamibot.stop()

# ------------------------------------------------
# 콘트롤모드 go_right_speed
# ------------------------------------------------
kamibot.go_right_speed(50)
kamibot.delay(1)

kamibot.go_right_speed(100)
kamibot.delay(1)
kamibot.stop()

# 카미봇 연결 해제
kamibot.close()

```

#### LED

```
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM3')

# ------------------------------------------------
# LED
# ------------------------------------------------
kamibot.turn_led(255, 0, 0)
kamibot.delay(1)
kamibot.turn_led(0, 255, 0)
kamibot.delay(1)
kamibot.turn_led(0, 0, 255)
kamibot.delay(1)


for i in range(8):
    kamibot.turn_led_idx(i)
    kamibot.delay(0.5)

for i in range(10):
    kamibot.turn_led(random.randrange(0,255), random.randrange(0,255), random.randrange(0,255))
    kamibot.delay(0.5)

for i in range(100):
    kamibot.turn_led(255, 0, 0)
    kamibot.turn_led(0, 0, 255)


# 카미봇 연결 해제
kamibot.close()
```

#### 거리를 지정해서 움직이기

```
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM3')

# ------------------------------------------------
# 정밀제어  move_forward_unit
# ------------------------------------------------
kamibot.move_forward_unit(10, "-l") # 10cm
kamibot.delay(1)
kamibot.stop()

kamibot.move_forward_unit(3, "-t") # 3sec
kamibot.delay(1)
kamibot.stop()


kamibot.move_forward_unit(50, "-s") # 50 step
kamibot.delay(1)
kamibot.stop()


# ------------------------------------------------
# 정밀제어  move_right_unit
# ------------------------------------------------
kamibot.move_right_unit(160, "-l")
kamibot.delay(1)
kamibot.stop()

# ------------------------------------------------
# 정밀제어  move_left_unit
# ------------------------------------------------
kamibot.move_left_unit(160, "-l")
kamibot.delay(1)
kamibot.stop()


# ------------------------------------------------
# 정밀제어  move_backward_unit
# ------------------------------------------------
kamibot.move_backward_unit(10, "-l")
kamibot.delay(1)
kamibot.stop()

# ------------------------------------------------
# 정밀제어  turn_continous
# ------------------------------------------------
kamibot.turn_continous("r", 100)
kamibot.delay(1)
kamibot.stop()


# ------------------------------------------------
# 정밀제어  move_step
# ------------------------------------------------
kamibot.move_step("f", 100, "f", 100)
kamibot.delay(1)
kamibot.stop()


# ------------------------------------------------
# 정밀제어  move_time
# ------------------------------------------------
kamibot.move_time("f", 10, "f", 10)
kamibot.delay(1)
kamibot.stop()

# ------------------------------------------------
# 제자리 회전 turn_right_speed, turn_left_speed
# ------------------------------------------------
kamibot.turn_right_speed(90, speed=100)
kamibot.delay(1)
kamibot.turn_left_speed(90, speed=100)
kamibot.delay(1)
kamibot.stop()


# 카미봇 연결 해제
kamibot.close()

```

#### 센서값 확인

```
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM3')

# ------------------------------------------------
# 물체감지 get_object_detect
# ------------------------------------------------
left, right = kamibot.get_object_detect()
print(f"left={left}, right={right}")
kamibot.delay(1)
kamibot.get_object_detect(False)


# ------------------------------------------------
# 라인센서 get_line_sensor
# ------------------------------------------------
left, center, right = kamibot.get_line_sensor()
print(f"left={left}, center={center}, right={right}")
kamibot.delay(1)

# ------------------------------------------------
# 컬러센서 get_color_sensor
# ------------------------------------------------
r, g, b = kamibot.get_color_elements()
print(f"r={r}, g={g}, b={b}")
idx = kamibot.get_color_sensor()
print(f"idx={idx}")
kamibot.get_color_elements(False)

# ------------------------------------------------
# 배터리 get_battery
# ------------------------------------------------
battery = kamibot.get_battery()
print(f"battery={battery}")
kamibot.delay(1)


# ------------------------------------------------
# 멜로디  melody
# ------------------------------------------------
kamibot.melody(45, 1)
kamibot.delay(1)

kamibot.beep()
kamibot.delay(1)


# 카미봇 연결 해제
kamibot.close()
```

#### Top모터 기본 동작

```
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM3')

# ------------------------------------------------
# 탑모터 제어  top_motor_degree
# ------------------------------------------------
kamibot.top_motor_degree("l", 180)  # 왼쪽 방향으로
kamibot.delay(1)

kamibot.top_motor_degree("r", 180)  # 오른쪽 방향으로
kamibot.delay(1)

# 카미봇 연결 해제
kamibot.close()
```

#### Top모터 절대위치

```
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM3')

kamibot.top_motor_abspos(0)
kamibot.delay(1)

kamibot.top_motor_abspos(90)
kamibot.delay(1)

kamibot.top_motor_abspos(180)
kamibot.delay(1)

# 카미봇 연결 해제
kamibot.close()

```

#### TOP모터 정해진 시간만큼 회전

```
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM3')

kamibot.top_motor_time("l", 10)
kamibot.delay(1)

kamibot.top_motor_time("r", 10)
kamibot.delay(1)

# 카미봇 연결 해제
kamibot.close()
```

#### 그리기

```
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM3')

# ------------------------------------------------
# 삼각형
# ------------------------------------------------
kamibot.draw_tri(10)
kamibot.delay(1)

# ------------------------------------------------
# 사각형
# ------------------------------------------------
kamibot.draw_rect(10)
kamibot.delay(1)

# ------------------------------------------------
# 오각형
# ------------------------------------------------
kamibot.draw_penta(10)
kamibot.delay(1)

# ------------------------------------------------
# 육각형
# ------------------------------------------------
kamibot.draw_hexa(10)
kamibot.delay(1)

# ------------------------------------------------
# 별
# ------------------------------------------------
kamibot.draw_star(10)
kamibot.delay(1)

# ------------------------------------------------
# 원그리기
# ------------------------------------------------
kamibot.draw_circle(10)
kamibot.delay(1)

# ------------------------------------------------
# 반원그리기
# ------------------------------------------------
kamibot.draw_semicircle(10, "l")
kamibot.delay(1)

# ------------------------------------------------
# 원호그리기
# ------------------------------------------------
kamibot.draw_arc(10, 3)
kamibot.delay(1)

# 카미봇 연결 해제
kamibot.close()

```

#### 맵보드

```
import random
from pykamilab import KamibotPi

# 카미봇 연결
kamibot = KamibotPi('COM3')

# ------------------------------------------------
# 라인트레이서
# ------------------------------------------------
kamibot.toggle_linetracer(True, 100)
kamibot.delay(10)
kamibot.toggle_linetracer(False)

# ------------------------------------------------
# 블록 맵보드
# ------------------------------------------------
kamibot.move_forward(1, '-b')
kamibot.move_backward(1)
kamibot.turn_left(1, "-b")
kamibot.turn_right(1, "-b")
kamibot.turn_back(1, "-b")

# ------------------------------------------------
# 라인 맵보드
# ------------------------------------------------
kamibot.move_forward(1)
kamibot.turn_left()
kamibot.turn_right()
kamibot.turn_back()


# 카미봇 연결 해제
kamibot.close()

```
