# การทำงานอัตโนมัติพื้นฐาน

บทนี้จะอธิบายถึงฟังก์ชันพื้นฐานอัตโนมัติที่ FIRERPA มีให้ แน่นอนว่ายังมีการใช้งานขั้นสูงที่จะอธิบายในภายหลัง ในบทนี้จะแนะนำอินเทอร์เฟซฟังก์ชันพื้นฐานที่ใช้กันบ่อย

## การรับข้อมูลอุปกรณ์

รับข้อมูลอุปกรณ์ปัจจุบัน เช่น ชื่ออุปกรณ์, ขนาดหน้าจอ, การหมุนหน้าจอ และแอปพลิเคชันปัจจุบัน

```python
d.device_info()
```

```python
>>> d.device_info()
productName: "bumblebee"
sdkInt: 34
displayHeight: 2400
displaySizeDpX: 411
displaySizeDpY: 914
displayWidth: 1080
screenOn: true
naturalOrientation: true
currentPackageName: "com.android.launcher3"
```

```python
>>> result = d.device_info()
>>> print (result.displayWidth)
1080
```

## การรับข้อมูลบริการ

รับข้อมูลของบริการปัจจุบัน เช่น เวอร์ชัน, ID เฉพาะของอุปกรณ์, เวอร์ชัน, ABI และข้อมูลอื่นๆ

```python
d.server_info()
```

```python
>>> d.server_info( )
uniqueId: "673abbe0-ff7b-9d82-1792-8876cb72cf56"
version: "8.28"
architecture: "arm64-v8a"
uptime: 293
secure: True
```

```python
>>> result = d.server_info()
>>> print (result.secure)
False
```

## ปิดหน้าจอ

อินเทอร์เฟซต่อไปนี้จะทำให้หน้าจอโทรศัพท์ปัจจุบันปิดลง ซึ่งเทียบเท่ากับการกดปุ่มเปิด/ปิดเครื่องหนึ่งครั้งเมื่อหน้าจอเปิดอยู่

```python
d.sleep()
```

## เปิดหน้าจอ

อินเทอร์เฟซต่อไปนี้จะทำให้หน้าจอโทรศัพท์ปัจจุบันเปิดขึ้น ซึ่งเทียบเท่ากับการกดปุ่มเปิด/ปิดเครื่องหนึ่งครั้งเมื่อหน้าจอปิดอยู่

```python
d.wake_up()
```

## หน้าจอเปิดอยู่หรือไม่

คุณสามารถใช้อินเทอร์เฟซต่อไปนี้เพื่อตรวจสอบว่าหน้าจอของอุปกรณ์ปัจจุบันเปิดอยู่หรือไม่ เพื่อตัดสินใจว่าจะสามารถดำเนินการต่อได้หรือไม่

```python
d.is_screen_on()
```

## หน้าจอล็อกอยู่หรือไม่

คุณสามารถใช้อินเทอร์เฟซต่อไปนี้เพื่อตรวจสอบว่าหน้าจอของอุปกรณ์ปัจจุบันถูกปลดล็อกอยู่หรือไม่ เพื่อตัดสินใจว่าจะสามารถดำเนินการต่อได้หรือไม่

```python
d.is_screen_locked()
```

## แสดง Toast

คุณสามารถใช้อินเทอร์เฟซต่อไปนี้เพื่อแสดงข้อความ Toast `Hello from Lamda!` บนหน้าจอโทรศัพท์

```python
d.show_toast("Hello from Lamda!")
```

## อ่านคลิปบอร์ด

อินเทอร์เฟซต่อไปนี้ใช้สำหรับอ่านเนื้อหาในคลิปบอร์ดปัจจุบันของโทรศัพท์ ยังไม่รองรับ Android 10+ ชั่วคราว

```python
d.get_clipboard()
```

## เขียนลงคลิปบอร์ด

อินเทอร์เฟซต่อไปนี้ใช้สำหรับเขียนเนื้อหาลงในคลิปบอร์ดของอุปกรณ์ปัจจุบัน

```python
d.set_clipboard("เนื้อหาคลิปบอร์ด")
```

## ปุ่มกดกายภาพ

คุณสามารถใช้วิธีการด้านล่างเพื่อจำลองการกดปุ่ม รองรับปุ่มต่างๆ กว่าสิบชนิด เช่น KEY_BACK, KEY_DOWN, KEY_HOME เป็นต้น

```python
d.press_key(Keys.KEY_BACK)
d.press_key(Keys.KEY_CAMERA)
d.press_key(Keys.KEY_CENTER)
d.press_key(Keys.KEY_DELETE)
d.press_key(Keys.KEY_DOWN)
d.press_key(Keys.KEY_ENTER)
d.press_key(Keys.KEY_HOME)
d.press_key(Keys.KEY_LEFT)
d.press_key(Keys.KEY_MENU)
d.press_key(Keys.KEY_POWER)
d.press_key(Keys.KEY_RECENT)
d.press_key(Keys.KEY_RIGHT)
d.press_key(Keys.KEY_SEARCH)
d.press_key(Keys.KEY_UP)
d.press_key(Keys.KEY_VOLUME_DOWN)
d.press_key(Keys.KEY_VOLUME_MUTE)
d.press_key(Keys.KEY_VOLUME_UP)
```

นอกจากนี้ เพื่อรองรับปุ่มอื่นๆ เพิ่มเติม คุณยังสามารถใช้วิธีนี้ในการจำลองได้ คุณสามารถค้นหาชื่อปุ่มที่รองรับทั้งหมดได้ในเอกสารทางการของ Android ที่นี่ [https://developer.android.com/reference/android/view/KeyEvent](https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_0)

```python
d.press_keycode(KeyCodes.KEYCODE_CALL)
```

## จับภาพหน้าจอ

เรามีวิธีการจับภาพหน้าจอเพื่อให้คุณสามารถบันทึกขั้นตอนการทำงานหรือทำการจดจำรูปภาพได้ การเรียกใช้ด้านล่างนี้หมายถึงการจับภาพที่มีคุณภาพ 60 และบันทึกเป็นไฟล์ screenshot.png ในไดเรกทอรีปัจจุบัน

```python
d.screenshot(60).save("screenshot.png")
```

```python
>>> result = d.screenshot(60)
>>> result
<lamda.types.BytesIO object at 0x7a28361d60>
>>> result.save("screenshot.png")
52917
>>> result.getvalue( )
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01....'
```

ปัจจุบัน เรารองรับการจับภาพหน้าจอเฉพาะส่วนและเฉพาะองค์ประกอบ (element) การจับภาพเฉพาะองค์ประกอบจะไม่ได้อธิบายในบทนี้ ที่นี่เราจะแนะนำการจับภาพเฉพาะส่วน คุณจำเป็นต้องเข้าใจแนวคิดและคำจำกัดความของพื้นที่ ในอินเทอร์เฟซของเรา พื้นที่จะถูกกำหนดโดย `Bound` ซึ่งประกอบด้วยพารามิเตอร์สี่ตัว: top, left, right, bottom หน้าจอ Android มีระบบพิกัดที่แตกต่างจากระบบพิกัดทั่วไป โดยมุมบนซ้ายของหน้าจออุปกรณ์ปัจจุบันคือจุดกำเนิด (origin) ซึ่งมีพิกัดเป็น x=0, y=0 สมมติว่าหน้าจอปัจจุบันเป็นแนวตั้ง มีความละเอียด 1080x1920 หากคุณต้องการจับภาพหน้าจอเฉพาะส่วนแบบเต็มจอ คุณสามารถทำได้ดังนี้

```python
d.screenshot(60, bound=Bound(top=0, left=0, right=1080, bottom=1920)).save("screenshot.png")
```

ซึ่งจะทำให้ได้ภาพหน้าจอแบบเต็มจอ แน่นอนว่านี่ไม่จำเป็น เพราะค่าเริ่มต้นคือการจับภาพเต็มจออยู่แล้ว ถ้าเราต้องการจับภาพขนาด 200x200 ที่มุมบนซ้าย จะทำอย่างไร? ก็ง่ายมาก เพียงแค่ทำตามด้านล่างนี้

```python
d.screenshot(60, bound=Bound(top=0, left=0, right=200, bottom=200)).save("screenshot.png")
```

ถึงตรงนี้ เราจะอธิบายความหมายของพารามิเตอร์เหล่านี้ ในพารามิเตอร์ top หมายถึงระยะห่างจากแกน Y ลงมา top พิกเซล, bottom หมายถึงระยะห่างจากแกน Y ลงมา bottom พิกเซล, ส่วน left และ right หมายถึงระยะห่างจากแกน X ไปทางขวา N พิกเซล โดยที่ top จะน้อยกว่า bottom เสมอ และ left จะน้อยกว่า right เสมอ ต่อไปเราจะสาธิตอีกหนึ่งตัวอย่าง คือการจับภาพขนาด 200x200 ที่มุมล่างขวาของหน้าจอ คุณเพียงแค่เรียกใช้อินเทอร์เฟซดังนี้

```python
d.screenshot(60, bound=Bound(top=1920-200, bottom=1920, left=1080-200, right=1080)).save("screenshot.png")
```

## คลิกที่จุดหนึ่งบนหน้าจอ

คุณสามารถใช้อินเทอร์เฟซต่อไปนี้เพื่อจำลองการคลิกบนหน้าจอ ในตัวอย่าง เราได้คลิกที่จุดพิกัด 100,100 บนหน้าจอ

```python
d.click(Point(x=100, y=100))
```

## กดค้างที่จุด A แล้วลากไปยังจุด B

ด้วยอินเทอร์เฟซต่อไปนี้ คุณสามารถลากวัตถุจากตำแหน่งจุด A ไปยังจุด B ได้ เช่น การลากไอคอนไปยังโฟลเดอร์

```python
A = Point(x=100, y=100)
B = Point(x=500, y=500)

d.drag(A, B)
```

## ปัดจากจุด A ไปยังจุด B

ด้วยอินเทอร์เฟซต่อไปนี้ คุณสามารถทำการปัด (swipe) จากพิกัด 100x100 ไปยังพิกัด 500x500 บนหน้าจอได้

```python
A = Point(x=100, y=100)
B = Point(x=500, y=500)

d.swipe(A, B)
```

## การปัดหลายจุดที่ซับซ้อนขึ้น

อินเทอร์เฟซต่อไปนี้สามารถจำลองการปัดหลายจุดได้ เช่น การเรียกใช้ด้านล่างนี้จะปัดจาก 100x100 ไปยัง 500x500 แล้วกลับมาที่ 200x200 ในการสาธิตนี้มีการปัดเพียงสามจุด แต่ในความเป็นจริงคุณสามารถระบุจุดได้มากขึ้น หรือแม้กระทั่งใช้เพื่อปลดล็อกแบบลากเส้น (pattern unlock)

```python
p1 = Point(x=100, y=100)
p2 = Point(x=500, y=500)
p3 = Point(x=200, y=200)

d.swipe_points(p1, p2, p3)
```

## เปิดการตั้งค่าด่วน

การเรียกใช้ด้านล่างนี้สามารถเปิดแถบการแจ้งเตือนบนหน้าจอได้ แต่จะอยู่ในสถานะเปิดครึ่งหนึ่ง

```python
d.open_quick_settings()
```

## เปิดแถบการแจ้งเตือน

การเรียกใช้ด้านล่างนี้สามารถเปิดแถบการแจ้งเตือนบนหน้าจอได้

```python
d.open_notification()
```

## การรับโครงสร้างหน้าเว็บ (Layout)

การเรียกใช้ด้านล่างนี้สามารถรับโครงสร้าง XML ของหน้าปัจจุบันได้ คุณยังสามารถแยกวิเคราะห์ (parse) ด้วยตนเองเพื่อรองรับการทำงานอัตโนมัติด้วย xpath

```python
d.dump_window_hierarchy()
```

```python
>>> result = d.dump_window_hierarchy()
>>> result
<lamda.types.BytesIO object at 0x7add660680>
>>> result.getvalue()
b'<?xml version=\'1.0\' encoding=\'UTF-8\' standalone=\'yes\' ?>\r\n<hierarchy rotation="0">\r\n  <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.android.systemui" content-desc="" checkable="false" checked="false" clickable="false"...
```

## รอให้หน้าต่างหยุดนิ่ง

คุณสามารถเรียกใช้คำสั่งต่อไปนี้เพื่อรอให้หน้าต่างปัจจุบันอยู่ในสถานะหยุดนิ่ง คล้ายกับ `implicitly_wait` ของ selenium พารามิเตอร์มีหน่วยเป็นมิลลิวินาที `5*1000` หมายถึงการรอ 5 วินาที โดย 1000 มิลลิวินาทีเท่ากับ 1 วินาที

```python
d.wait_for_idle(5*1000)
```

## การรับ Toast ล่าสุด

คุณสามารถเรียกใช้คำสั่งต่อไปนี้เพื่อรับข้อความ Toast ล่าสุดในระบบ แต่โปรดทราบว่ารองรับเฉพาะข้อความ Toast ที่ส่งโดย API ของระบบเท่านั้น ไม่สามารถรับข้อความที่มีลักษณะคล้าย Toast UI ที่สร้างโดยบุคคลที่สามได้

```python
d.get_last_toast()
```

```python
>>> result = d.get_last_toast()
>>> print (result)
timestamp: 1700000000000
package: "com.android.settings"
message: "\346\202\250\345\267\262\345\244\204\344\272\216\345\274\200\345\217\221\350\200\205\346\250\241\345\274\217\357\274\214\346\227\240\351\234\200\350\277\233\350\241\214\346\255\244\346\223\215\344\275\234\343\200\202"
>>> print (result.message)
คุณอยู่ในโหมดนักพัฒนาซอฟต์แวร์แล้ว ไม่จำเป็นต้องดำเนินการนี้
```