Compare commits

...

4 Commits

Author SHA1 Message Date
linesofcodes 19fb847b7d Fixed according to feedback 2026-01-10 17:12:32 +07:00
linesofcodes f72f0be591 Minor Fixes & Chapter 3 splitting 2026-01-01 11:29:17 +07:00
linesofcodes 1c627501dd Finish Flutter heading 2025-12-31 21:54:51 +07:00
linesofcodes f37340d485 Forced Stylistic Changes 2025-12-28 10:49:09 +07:00
40 changed files with 4882 additions and 2370 deletions
+16 -6
View File
@@ -1,5 +1,5 @@
#import "PageTemplate.typ": *
#show: page-theme
#show: chapter-page
#set enum(
indent: 3em,
numbering: n => context {
@@ -14,11 +14,19 @@
== ที่มาและความสำคัญของปัญหา
#i ความปลอดภัยนั้นเป็นเรื่องสำคัญสำหรับทุกคนแต่องค์กรแต่ละองค์กรและคนแต่ละคนมักมีความต้องการด้านความปลอดภัยไม่เหมือนกัน แต่ในบางครั้ง เมื่อมีบุคคลหรือองค์กรที่ต้องการเทคโนโลยีด้านความปลอดภัยเหล่านี้ เทคโนโลยีความปลอดภัยนั้นอาจมีราคาสูงเกินกว่าจะเอื้อมถึงได้ ส่งผลให้อาจมีการลดระดับความปลอดภัยลงมา เพิ่มความเสี่ยงของชีวิต ทรัพย์สิน เอกสาร และข้อมูลต่าง ขององค์กรหรือบุคคลนั้น
#i
ความปลอดภัยนั้นเป็นเรื่องสำคัญสำหรับทุกคนแต่องค์กรแต่ละองค์กรและคนแต่ละคนมักมีความต้องการด้านความปลอดภัยไม่เหมือนกัน
แต่ในบางครั้ง เมื่อมีบุคคลหรือองค์กรที่ต้องการเทคโนโลยีด้านความปลอดภัยเหล่านี้
เทคโนโลยีความปลอดภัยนั้นอาจมีราคาสูงเกินกว่าจะเอื้อมถึงได้ ส่งผลให้อาจมีการลดระดับความปลอดภัยลงมา
เพิ่มความเสี่ยงของชีวิต ทรัพย์สิน เอกสาร และข้อมูลต่าง ขององค์กรหรือบุคคลนั้น
#i ในโลกปัจจุบัน อินเทอร์เน็ตนั้นก็เป็นสิ่งที่สำคัญมากเช่นกัน และสถานที่ส่วนใหญ่มักจะมีอินเทอร์เน็ต จึงก่อให้เกิดการที่มีอุปกรณ์อินเทอร์เน็ตรอบตัวเพิ่มขึ้นทุกวัน และได้มีสิ่งที่เรียกว่า Internet of Things (IoT) เกิดขึ้น ซึ่งคืออุปกรณ์ที่ถูกปรับปรุงให้ใช้งานได้ดีขึ้นด้วยเทคโนโลยีไร้สายต่าง เช่น Wi-Fi, Bluetooth, Zigbee, และ Thread
#i ในโลกปัจจุบัน อินเทอร์เน็ตนั้นก็เป็นสิ่งที่สำคัญมากเช่นกัน และสถานที่ส่วนใหญ่มักจะมีอินเทอร์เน็ต
จึงก่อให้เกิดการที่มีอุปกรณ์อินเทอร์เน็ตรอบตัวเพิ่มขึ้นทุกวัน และได้มีสิ่งที่เรียกว่า Internet of Things
(IoT) เกิดขึ้น ซึ่งคืออุปกรณ์ที่ถูกปรับปรุงให้ใช้งานได้ดีขึ้นด้วยเทคโนโลยีไร้สายต่าง เช่น#jb Wi-Fi,
Bluetooth, Zigbee, และ Thread
#i โครงงานนี้จึงมีเป้าหมายที่จะแก้ไขปัญหาที่กล่าวไปข้างต้น พร้อมศึกษาและเรียนรู้เกี่ยวกับเทคโนโลยีไร้สาย Wi-Fi และ NFC เพื่อสร้างอุปกรณ์ยืนยันตัวตนที่ต้นทุนไม่สูงมากและให้ราคาเข้าถึงได้ง่ายขึ้น
#i โครงงานนี้จึงมีเป้าหมายที่จะแก้ไขปัญหาที่กล่าวไปข้างต้น พร้อมศึกษาและเรียนรู้เกี่ยวกับเทคโนโลยีไร้สาย
Wi-Fi และ NFC เพื่อสร้างอุปกรณ์ยืนยันตัวตนที่ต้นทุนไม่สูงมากและให้ราคาเข้าถึงได้ง่ายขึ้น
== วัตถุประสงค์ของโครงงาน
@@ -40,9 +48,11 @@
== นิยามศัพท์เฉพาะ
#i เครื่องยืนยันตัวตนด้วย NFC คืออุปกรณ์ความปลอดภัยที่มีหน้าที่ในการยืนยันตัวตนบุคคลที่เข้าออกพื้นที่ โดยใช้เทคโนโลยี NFC เป็นระบบยืนยันตัวตนบุคคลและใช้เซนเซอร์ตรวจจับความเคลื่อนใหวในการตรวจสอบหากมีบุคคลเข้าไปโดยไม่ได้รับอนุญาต
#i เครื่องยืนยันตัวตนด้วย NFC คืออุปกรณ์ความปลอดภัยที่มีหน้าที่ในการยืนยันตัวตนบุคคลที่เข้าออกพื้นที่
โดยใช้เทคโนโลยี NFC
เป็นระบบยืนยันตัวตนบุคคลและใช้เซนเซอร์ตรวจจับความเคลื่อนไหวในการตรวจสอบหากมีบุคคลเข้าไปโดยไม่ได้รับอนุญาต
#pagebreak()
#show: page-theme
== ผลที่คาดว่าจะได้รับ
+15 -5
View File
@@ -1,20 +1,30 @@
#import "../PageTemplate.typ": i
#import "../PageTemplate.typ": *
= ลำโพงสัญญาณ (Buzzer)
#i Buzzer เป็นอุปกรณ์ส่งสัญญาณเสียงซึ่งอาจเป็น อุปกรณ์ เชิงกลเครื่องกลไฟฟ้าหรือเพียโซอิเล็กทริก (เรียกสั้น ว่าเพียโซ) การใช้งานทั่วไปของบัซเซอร์และบี๊บเปอร์ ได้แก่อุปกรณ์แจ้งเตือนตัวตั้งเวลาวงจรและการยืนยันการป้อนข้อมูลของผู้ใช้ เช่น การคลิกเมาส์หรือการกดแป้นพิมพ์
#i Buzzer เป็นอุปกรณ์ส่งสัญญาณเสียงซึ่งอาจเป็น อุปกรณ์ เชิงกลเครื่องกลไฟฟ้าหรือเพียโซอิเล็กทริก
(เรียกสั้น ว่าเพียโซ) การใช้งานทั่วไปของบัซเซอร์และบี๊บเปอร์
ได้แก่อุปกรณ์แจ้งเตือนตัวตั้งเวลาวงจรและการยืนยันการป้อนข้อมูลของผู้ใช้ เช่น
การคลิกเมาส์หรือการกดแป้นพิมพ์
ประเภทของ Buzzer มี 3 ชนิด คือ
== ไฟฟ้าเชิงกล (Electromechanical)
#i อุปกรณ์ในยุคแรกๆ ใช้ระบบไฟฟ้าเครื่องกลแบบเดียวกับกระดิ่งไฟฟ้าโดยไม่มีฆ้องโลหะ ในทำนองเดียวกันรีเลย์อาจเชื่อมต่อเพื่อตัดกระแสไฟฟ้า ที่ทำหน้าที่สั่งการตัวเอง ซึ่งทำให้หน้าสัมผัสส่งเสียงหึ่งๆ (หน้าสัมผัสจะส่งเสียงหึ่งๆ ที่ความถี่สายหากใช้ไฟฟ้ากระแสสลับ) บ่อยครั้งที่อุปกรณ์เหล่านี้ถูกยึดไว้กับผนังหรือเพดานเพื่อใช้เป็นแผงเก็บเสียง คำว่า "buzzer" มาจากเสียงแหบๆ ของ buzzer ระบบไฟฟ้าเครื่องกล
#iii อุปกรณ์ในยุคแรกๆ ใช้ระบบไฟฟ้าเครื่องกลแบบเดียวกับกระดิ่งไฟฟ้าโดยไม่มีฆ้องโลหะ
ในทำนองเดียวกันรีเลย์อาจเชื่อมต่อเพื่อตัดกระแสไฟฟ้า ที่ทำหน้าที่สั่งการตัวเอง
ซึ่งทำให้หน้าสัมผัสส่งเสียงหึ่งๆ (หน้าสัมผัสจะส่งเสียงหึ่งๆ ที่ความถี่สายหากใช้ไฟฟ้ากระแสสลับ)
บ่อยครั้งที่อุปกรณ์เหล่านี้ถูกยึดไว้กับผนังหรือเพดานเพื่อใช้เป็นแผงเก็บเสียง คำว่า "buzzer"
มาจากเสียงแหบๆ ของ buzzer ระบบไฟฟ้าเครื่องกล
== กลไก (Mechanical)
#i จอยบัซเซอร์เป็นตัวอย่างของบัซเซอร์แบบกลไกล้วนๆ และจำเป็นต้องมีไดรเวอร์ ตัวอย่างอื่นๆ ของบัซเซอร์ประเภทนี้คือกริ่งประตู
#iii จอยบัซเซอร์เป็นตัวอย่างของบัซเซอร์แบบกลไกล้วนๆ และจำเป็นต้องมีไดรเวอร์ ตัวอย่างอื่นๆ
ของบัซเซอร์ประเภทนี้คือกริ่งประตู
== เพียโซอิเล็กทริก (Piezoelectric)
#i องค์ประกอบเพียโซอิเล็กทริกอาจถูกขับเคลื่อนด้วย วงจรอิเล็กทรอนิกส์ แบบสั่นหรือ แหล่ง สัญญาณเสียง อื่นๆ ซึ่งขับเคลื่อนด้วยเครื่องขยายเสียงเพียโซอิเล็กทริกเสียงที่มักใช้เพื่อระบุว่ามีการกดปุ่ม ได้แก่ เสียงคลิก เสียงกริ่ง หรือเสียงบี๊บ
#iii องค์ประกอบเพียโซอิเล็กทริกอาจถูกขับเคลื่อนด้วย วงจรอิเล็กทรอนิกส์ แบบสั่นหรือ แหล่ง สัญญาณเสียง
อื่นๆ ซึ่งขับเคลื่อนด้วยเครื่องขยายเสียงเพียโซอิเล็กทริกเสียงที่มักใช้เพื่อระบุว่ามีการกดปุ่ม ได้แก่ เสียงคลิก
เสียงกริ่ง หรือเสียงบี๊บ
+399 -195
View File
@@ -3,145 +3,303 @@
= ภาษาซี (C Programming Language) <cprogramming>
#i ภาษาซีเป็นภาษาโปรแกรมสำหรับวัตถุประสงค์ทั่วไปสร้างขึ้นในช่วงทศวรรษ 1970 โดยเดนนิสริตชีและยังคงได้รับความนิยมและใช้งานอย่างกว้างขวางด้วยการออกแบบภาษาซีทำให้โปรแกรมเมอร์สามารถเข้าถึงคุณลักษณะต่างๆของสถาปัตยกรรมซีพียูทั่วไปได้โดยตรง ซึ่งปรับแต่งให้เหมาะกับชุดคำสั่ง เป้าหมาย ภาษาซี ถูกนำมาใช้และยังคงนำมาใช้ในการพัฒนาระบบปฏิบัติการไดรเวอร์อุปกรณ์และสแต็กโปรโตคอลแต่การใช้งานในซอฟต์แวร์แอปพลิเคชั่นกำลังลดลงภาษาซีถูกนำมาใช้ในคอมพิวเตอร์ตั้งแต่ซูเปอร์คอมพิวเตอร์ขนาดใหญ่ที่สุดไปจนถึงไมโครคอนโทรลเลอร์ขนาดเล็กที่สุดและระบบฝังตัว
#i ภาษาซีเป็นภาษาโปรแกรมสำหรับวัตถุประสงค์ทั่วไปสร้างขึ้นในช่วงทศวรรษ 1970
โดยเดนนิสริตชีและยังคงได้รับความนิยมและใช้งานอย่างกว้างขวางด้วยการออกแบบภาษาซีทำให้โปรแกรมเมอร์สามารถเข้าถึงคุณลักษณะต่างๆของสถาปัตยกรรมซีพียูทั่วไปได้โดยตรง
ซึ่งปรับแต่งให้เหมาะกับชุดคำสั่ง เป้าหมาย ภาษาซี
ถูกนำมาใช้และยังคงนำมาใช้ในการพัฒนาระบบปฏิบัติการไดรเวอร์อุปกรณ์และสแต็กโปรโตคอลแต่การใช้งานในซอฟต์แวร์แอปพลิเคชั่นกำลังลดลงภาษาซีถูกนำมาใช้ในคอมพิวเตอร์ตั้งแต่ซูเปอร์คอมพิวเตอร์ขนาดใหญ่ที่สุดไปจนถึงไมโครคอนโทรลเลอร์ขนาดเล็กที่สุดและระบบฝังตัว
#i
ภาษาซีเป็นภาษาเชิงกระบวนการที่จำเป็นรองรับการเขียนโปรแกรมแบบมีโครงสร้างขอบเขตตัวแปรเชิงศัพท์และการเรียกซ้ำด้วยระบบชนิดข้อมูลแบบคงที่ภาษาซีถูกออกแบบมาเพื่อการคอมไพล์เพื่อให้สามารถเข้าถึงหน่วยความจำ และโครงสร้างภาษา ในระดับต่ำซึ่งแมปกับคำสั่งเครื่องได้อย่างมีประสิทธิภาพ โดยทั้งหมดนี้รองรับรันไทม์ขั้นต่ำ แม้จะมีความสามารถในระดับต่ำ แต่ภาษาซีก็ถูกออกแบบมาเพื่อสนับสนุนการเขียนโปรแกรมข้ามแพลตฟอร์ม โปรแกรมซี ที่สอดคล้องกับมาตรฐานที่เขียนขึ้นโดยคำนึงถึงความสามารถในการพกพาสามารถคอมไพล์สำหรับแพลตฟอร์มคอมพิวเตอร์และระบบปฏิบัติการที่หลากหลาย โดยมีการเปลี่ยนแปลงซอร์สโคดเพียงเล็กน้อย
ภาษาซีเป็นภาษาเชิงกระบวนการที่จำเป็นรองรับการเขียนโปรแกรมแบบมีโครงสร้างขอบเขตตัวแปรเชิงศัพท์และการเรียกซ้ำด้วยระบบชนิดข้อมูลแบบคงที่ภาษาซีถูกออกแบบมาเพื่อการคอมไพล์เพื่อให้สามารถเข้าถึงหน่วยความจำ
และโครงสร้างภาษา ในระดับต่ำซึ่งแมปกับคำสั่งเครื่องได้อย่างมีประสิทธิภาพ โดยทั้งหมดนี้รองรับรันไทม์ขั้นต่ำ
แม้จะมีความสามารถในระดับต่ำ แต่ภาษาซีก็ถูกออกแบบมาเพื่อสนับสนุนการเขียนโปรแกรมข้ามแพลตฟอร์ม
โปรแกรมซี
ที่สอดคล้องกับมาตรฐานที่เขียนขึ้นโดยคำนึงถึงความสามารถในการพกพาสามารถคอมไพล์สำหรับแพลตฟอร์มคอมพิวเตอร์และระบบปฏิบัติการที่หลากหลาย
โดยมีการเปลี่ยนแปลงซอร์สโคดเพียงเล็กน้อย
#i แม้ว่าทั้งภาษาซีและไลบรารีมาตรฐานของภาษา ซีจะไม่ได้มีคุณสมบัติยอดนิยมบางอย่างที่พบในภาษาอื่น แต่ก็มีความยืดหยุ่นเพียงพอที่จะรองรับคุณสมบัติเหล่านั้นได้ ตัวอย่างเช่นการวางแนววัตถุและการเก็บขยะนั้นจัดทำโดยไลบรารีภายนอก GLib Object System และ Boehm garbage collector ตามลำดับ
#i แม้ว่าทั้งภาษาซีและไลบรารีมาตรฐานของภาษา ซีจะไม่ได้มีคุณสมบัติยอดนิยมบางอย่างที่พบในภาษาอื่น
แต่ก็มีความยืดหยุ่นเพียงพอที่จะรองรับคุณสมบัติเหล่านั้นได้
ตัวอย่างเช่นการวางแนววัตถุและการเก็บขยะนั้นจัดทำโดยไลบรารีภายนอก GLib Object System และ
Boehm garbage collector ตามลำดับ
#i ตั้งแต่ปี 2000 เป็นต้นมาภาษาซี ได้รับการจัดอันดับอย่างต่อเนื่องให้อยู่ในอันดับสี่ภาษาสูงสุดในดัชนี TIOBE ซึ่งเป็นการวัดความนิยมของภาษาการเขียนโปรแกรม
#i ตั้งแต่ปี 2000 เป็นต้นมาภาษาซี ได้รับการจัดอันดับอย่างต่อเนื่องให้อยู่ในอันดับสี่ภาษาสูงสุดในดัชนี TIOBE
ซึ่งเป็นการวัดความนิยมของภาษาการเขียนโปรแกรม
== ตัวอย่าง "hello, world"
== ประวัติ
#i โดยการเรียนภาษาเขียนโปรแกรมใหม่ ต้องเริ่มด้วยการเขียนโปรแกรมในภาษานั้น โดยโปรแกรมแรกที่จะเขียนนั้นเหมือน กันในทุกภาษา คือการพิมพ์ "hello, world"
=== การพัฒนาช่วงแรก
```c
#include <stdio.h>
#h(9.75em) ที่มาของภาษา C มีความเชื่อมโยงอย่างใกล้ชิดกับการพัฒนาระบบปฏิบัติการ#jb Unix
ซึ่งเดิมทีเขียนด้วยภาษาแอสเซมบลีบน PDP-7 โดย Dennis Ritchie และ Ken Thompson
โดยนำแนวคิดหลายอย่างจากเพื่อนร่วมงานมาใช้ ในที่สุดพวกเขาก็ตัดสินใจย้ายระบบปฏิบัติการไปยัง PDP-11
เวอร์ชัน Unix ดั้งเดิมบน PDP-11 ก็ได้รับการพัฒนาด้วยภาษาแอสเซมบลีเช่นกัน
int main()
{
printf("hello, world\n");
}
```
=== ภาษา B
#i คุณสามารถบันทึกไฟล์นี้เป็นไฟล์ที่มีส่วนขยายไฟล์ `.c` เช่น `hello.c` ได้เลย แต่การจะรันโปรแกรมนี้นั้นขึ้นอยู่กับระบบปฏิบัติการของคุณ ตัวอย่างเช่นบนระบบที่มีชุดคอมไพเลอร์ GCC (หรือ MinGW สำหรับเวอร์ชันบน Windows) ติดตั้งอยู่สามารถใช้คำสั่ง
#h(13.5em) ทอมป์สันต้องการภาษาโปรแกรมสำหรับการพัฒนายูทิลิตี้สำหรับแพลตฟอร์มใหม่
เขาพยายามเขียนคอมไพเลอร์ Fortran ก่อน
แต่ในไม่ช้าเขาก็ล้มเลิกความคิดนั้นและสร้างเวอร์ชันย่อของภาษาโปรแกรมระบบ ที่พัฒนาขึ้นใหม่ชื่อ BCPL แทน
คำอธิบายอย่างเป็นทางการของ BCPL ยังไม่พร้อมใช้งานในขณะนั้นและทอมป์สันได้แก้ไขไวยากรณ์ให้
"กระชับ" น้อยลงและคล้ายกับ ALGOL ที่เรียบง่ายกว่า ที่เรียกว่า SMALGOL เขาเรียกผลลัพธ์ นี้ว่า B
โดยอธิบายว่าเป็น#jb "ความหมายของ BCPL ที่มีไวยากรณ์ SMALGOL จำนวนมาก" เช่นเดียวกับ BCPL, B
มีคอมไพเลอร์ บูตสแตรปเพื่ออำนวยความสะดวกในการพอร์ตไปยังเครื่องใหม่ในที่สุด
มีการเขียนยูทิลิตี้เพียงไม่กี่ตัวใน B เพราะมันช้าเกินไปและไม่สามารถใช้ประโยชน์จากคุณสมบัติของ PDP-11
เช่นการเข้าถึงที่อยู่ไบต์ได้
```bash
cc hello.c
```
=== ภาษา B ใหม่และ C รุ่นแรก
เพื่อคอมไพล์ไฟล์ได้ หากคุณไม่ได้ทำอะไรผิดพลาดไป เช่นการพิมพ์ตกหรือการสะกดผิด การคอมไพล์จะดำเนินการไปอย่างเงียบ และสร้างไฟล์ไบนารีชื่อ `a.out` ออกมา คุณสามารถรันไฟล์นั้นบนเทอร์มินัลของคุณได้โดยการพิมพ์ `./a.out` แล้วจึงจะได้ข้อความดังต่อไปนี้ออกมา
#h(13.5em) ในปี พ.ศ. 2514 ริชชีเริ่มปรับปรุง B เพื่อใช้คุณสมบัติของ PDP-11 ที่ทรงพลังยิ่งขึ้น
การเพิ่มเติมที่สำคัญคือประเภทข้อมูลอักขระ เขาเรียกสิ่งนี้ว่า New B (NB) ทอมป์สันเริ่มใช้ NB เพื่อเขียน
เคอร์เนล Unix และข้อกำหนดของเขากำหนดทิศทางการพัฒนาภาษา
```
hello, world
```
จนถึงปี 1972 มีการเพิ่มประเภทข้อมูลที่หลากหลายมากขึ้นให้กับภาษา NB ภาษา NB มีอาร์เรย์ของ int และ
char และได้มีการเพิ่มพอยเตอร์ ความสามารถในการสร้างพอยเตอร์ไปยังประเภทอื่นๆ
อาร์เรย์ของทุกประเภท และประเภทที่จะส่งคืนจากฟังก์ชัน
อาร์เรย์ภายในนิพจน์ได้รับการปฏิบัติเสมือนเป็นพอยเตอร์ มีการเขียนคอมไพเลอร์ใหม่ และเปลี่ยนชื่อภาษาเป็น
C
#i โดยโปรแกรมภาษา C นั้น ไม่ว่าจะขนาดใด จะประกอบไปด้วยฟังก์ชันและตัวแปร โดยฟังก์ชันจะประกอบไปด้วยสเตตเมนต์ (statements) ที่ระบุสิ่งที่โปรแกรมจะต้องกระทำ และตัวแปรนั้นกำหนดค่าที่จะถูกใช้งานในการกระทำเหล่านั้น โดยในตัวอย่างมีฟังก์ชันชื่อ `main` ซึ่งปกติแล้วคุณมีอิสระในการตั้งชื่อฟังก์ชันว่าอะไรก็ได้ แต่ฟังก์ชัน `main` นั้นพิเศษ เพราะโปรแกรมของคุณนั้นมีจุดเริ่มต้นที่ `main` ดังนั้น โปรแกรมทุกโปรแกรมต้องมี `main` อยู่สักที่
คอมไพเลอร์ C และยูทิลิตี้บางส่วนที่สร้างขึ้นด้วยคอมไพเลอร์นี้ถูกรวมอยู่ใน Unix เวอร์ชัน 2
ซึ่งเรียกอีกอย่างว่า Research Unix
#i โดยปกติแล้วฟังก์ชัน `main` นั้นจะเรียกใช้ฟังก์ชันอื่น เพื่อทำงานให้มัน โดยอาจเป็นฟังก์ชันที่คุณเขียน หรือฟังก์ชันที่มาจากไลบรารีที่คุณใช้งาน ในบรรทัดแรกของโปรแกรมตัวอย่าง
=== โครงสร้างและการเขียน Unix kernel ใหม่
```c
#include <stdio.h>
```
#h(13.5em) ใน Unix เวอร์ชัน 4 ซึ่งวางจำหน่ายในเดือนพฤศจิกายน พ.ศ. 2516 เคอร์เนล ของ Unix
ได้รับการเขียนใหม่อย่างกว้างขวางด้วยภาษา C ในเวลานั้น ภาษา C
ได้รับคุณสมบัติที่ทรงพลังบางอย่างเช่นประเภท struct
มีหน้าที่ในการนำเข้าข้อมูลเกี่ยวกับไลบรารีอินพุต/เอาต์พุตมาตรฐาน โดยบรรทัดนี้นั้นอยู่ในไฟล์ ภาษา C หลายไฟล์ เนื่องจากการแสดงผลข้อมูลนั้นเป็นการกระทำที่ถูกกระทำบ่อย
ตัวประมวลผลล่วงหน้าได้รับการแนะนำประมาณปี 1973 ตามคำแนะนำของ Alan Snyder
และยังเป็นการยอมรับถึงประโยชน์ของกลไกการรวมไฟล์ที่มีอยู่ใน BCPL และPL/I
เวอร์ชันดั้งเดิมให้เฉพาะไฟล์ที่รวมไว้และการแทนที่สตริงแบบง่ายเท่านั้น `#include` รวม `#define`
ถึงมาโครที่ไม่มีพารามิเตอร์ หลังจากนั้นไม่นาน ก็มีการขยายเพิ่มเติม โดยส่วนใหญ่โดย Mike Lesk
และต่อมาโดย John Reiser เพื่อรวมมาโครที่มีอาร์กิวเมนต์และการคอมไพล์แบบมีเงื่อนไข
#i หนึ่งในวิธีการโอนถ่ายข้อมูลระหว่างฟังก์ชันคือการมอบรายการของข้อมูลที่ต้องการมอบให้แก่ฟังก์ชัน โดยค่าที่มอบให้ฟังก์ชันเหล่านั้นมีชื่อเรียกว่า อาร์กิวเมนต์ (arguments) ซึ่งวงเล็บที่ตามหลังชื่อฟังก์ชันนั้นคือวงเล็บที่จะครอบรายการอาร์กิวเมนต์ โดยในตัวอย่างฟังก์ชัน `main` นั้นไม่หวังค่าอาร์กิวเมนต์ใด สังเกตได้จาก `()` ที่เป็นรายการที่ว่างปล่าว
Unix เป็นหนึ่งในเคอร์เนลระบบปฏิบัติการแรกๆ
ที่เขียนด้วยภาษาอื่นที่ไม่ใช่ภาษาแอสเซมบลีตัวอย่างก่อนหน้านี้ได้แก่ ระบบ Multics (ซึ่งเขียนด้วยภาษา
PL/I ) และ Master Control Program (MCP) สำหรับ Burroughs B5000 (ซึ่งเขียนด้วยภาษา
ALGOL ) ในปี 1961 ในช่วงปี 1977 Ritchie และ Stephen C. Johnson
ได้ทำการเปลี่ยนแปลงเพิ่มเติมให้กับภาษาเพื่ออำนวยความสะดวกในการพกพาระบบปฏิบัติการUnix
คอมไพเลอร์ Portable C ของ Johnson เป็นพื้นฐานสำหรับการใช้งาน C บนแพลตฟอร์มใหม่ๆ
หลายแพลตฟอร์ม
#i สเตตเมนต์ที่อยู่ภายในฟังก์ชันนั้นจะถูกครอบด้วยวงเล็บปีกกา `{}` ซึ่งในฟังก์ชัน `main` มีแค่ 1 สเตตเมนต์ คือ
=== K&R C
```c
printf("hello, world\n");
```
#h(9.75em) ในปี พ.ศ. 2521 Brian KernighanและDennis Ritchie ได้ตีพิมพ์หนังสือ The C
Programming Language ฉบับพิมพ์ครั้งแรกหนังสือเล่มนี้รู้จักกันในชื่อย่อ K&R
ตามชื่อย่อของผู้เขียนและทำหน้าที่เป็นข้อกำหนดที่ไม่เป็นทางการ ของภาษาเป็นเวลาหลายปีเวอร์ชันของภาษา
C ที่อธิบายไว้ในหนังสือเล่มนี้มักเรียกกันว่า "K&R C" เนื่องจาก หนังสือเล่มนี้ได้รับการเผยแพร่ในปี พ.ศ.
2521 จึงเรียกอีกอย่างว่า C78 หนังสือฉบับพิมพ์ครั้งที่สองครอบคลุมมาตรฐาน ANSI C ในภายหลัง
ซึ่งจะกล่าวถึงต่อไป
#i โดยฟังก์ชันนั้นจะถูกเรียกใช้ได้โดยการเรียกชื่อมัน ตามด้วยรายการอาร์กิวเมนต์ที่ถูกครอบด้วยวงเล็บ ดังนั้น สเตตเมนต์นี้จึงมีการเรียกใช้ฟังก์ชัน `printf` ด้วยอาร์กิวเมนต์ `"hello, world\n"` โดยที่ `printf` เป็นฟังก์ชันจากไลบรารีที่ทำการพรินต์ข้อมูล (ซึ่งการพรินต์ในที่นี้คือการแสดงผลข้อความบนหน้าจอในเทอร์มินัล) และข้อมูลที่มันแสดงนั้นก็คือรายการอักขระที่ถูกครอบอยู่ด้วยเครื่องหมายอัญประกาศนั่นเอง
K&R ได้เพิ่มฟีเจอร์ด้านภาษาหลายอย่าง:
#i รายการอักขระที่ถูกครอบด้วยเครื่องหมายอัญประกาศ เช่น `"hello, world\n"` นั้นมีชื่อเรียกว่า character string หรือ string constant และในตัวอย่างนี้นั้น เราจะมีการใช้รายการอักขระนี้เป็นเพียงแค่อาร์กิวเมนต์ของ `printf` และฟังก์ชันอื่น
+ ไลบรารีอินพุต/เอาต์พุตมาตรฐาน
+ long int ประเภทข้อมูล
+ unsigned int ประเภทข้อมูล
+ ตัวดำเนินการกำหนดค่าแบบผสมในรูปแบบ =_op_ (เช่น `=-`) ถูกเปลี่ยนเป็นรูปแบบ _op_= (นั่นคือ
`-=`)#jb เพื่อขจัดความกำกวมทางความหมายที่เกิดจากโครงสร้างเช่น `i=-10` ซึ่งถูกตีความว่า
`i =- 10` (ลด `i` ลง 10) แทนที่จะเป็นความหมายที่ตั้งใจไว้ (ให้ `i` เป็น -10)
#i ลำดับตัวอักษร `\n` ในสตริงคือสัญกรณ์ภาษา C สำหรับ#emph[ตัวอักษรบรรทัดใหม่] ซึ่งเมื่อถูกพรินต์แล้วจะให้เอาต์พุตไปอยู่ทางด้านซ้ายของบรรทัดใหม่ โดยหากไม่ใส่ `\n` (ซึ่งคุณสามารถทดลองได้เลย) คุณจะพบว่าไม่มีการขึ้นบรรทัดใหม่ของข้อความ และคุณต้องใช้ `\n` ในการขึ้นบรรทัดใหม่ และหากคุณลองทำแบบนี้:
#h(9.75em) แม้หลังจากมีการเผยแพร่มาตรฐาน ANSI ปี 1989 แล้วก็ตาม เป็นเวลาหลายปีที่ K&R C
ยังคงถูกพิจารณาว่าเป็น "ตัวหารร่วมที่ต่ำที่สุด" ที่โปรแกรมเมอร์ภาษา C
ยึดถือเมื่อต้องการความสามารถในการพกพาได้สูงสุด
เนื่องจากคอมไพเลอร์รุ่นเก่าจำนวนมากยังคงถูกใช้งานอยู่และเนื่องจากโค้ด K&R C
ที่เขียนอย่างระมัดระวังก็สามารถเป็นไปตามมาตรฐาน C ได้เช่นกัน
```c
printf("Hello, world
");
```
แม้ว่า C เวอร์ชันต่อมาจะกำหนดให้ฟังก์ชันต้องมีการประกาศประเภทอย่างชัดเจนแต่ C เวอร์ชัน K&R
กำหนดให้ฟังก์ชันที่ส่งคืนค่าประเภทอื่นที่ไม่ใช่ประเภท ที่กำหนดไว้เท่านั้น int ที่จะต้องประกาศก่อนใช้งาน
ฟังก์ชันที่ใช้โดยไม่มีการประกาศล่วงหน้าจะถือว่าส่งคืนค่าประเภทที่กำหนด int ไว้
คอมไพเลอร์ภาษา C นั้นจะแสดงข้อความแสดงข้อผิดพลาดขึ้นมา
=== ANSI C และ ISO C
#i `printf` นั้นจะไม่มีทางใส่ตัวอักษรขึ้นบรรทัดใหม่ให้โดยอัตโนมัติ ดังนั้นคุณสามารถเรียกใช้ฟังก์ชันหลาย ครั้งเพื่อค่อย สร้างเอาต์พุตออกมาได้ โดยที่โปรแกรมแรกของเราจะสามารถเขียนแบบนี้ได้
#h(9.75em) ในช่วงปลายทศวรรษ 1970 และ 1980 ภาษา C เวอร์ชันต่างๆ ถูกนำไปใช้งานใน
คอมพิวเตอร์เมนเฟรมมินิคอมพิวเตอร์และไมโครคอมพิวเตอร์หลากหลายรุ่นรวมถึง IBM PC ด้วย
เนื่องจากความนิยมของคอมพิวเตอร์ประเภทนี้เพิ่มขึ้นอย่างมาก
```c
#include <stdio.h>
#h(9.75em) ในปี 1983 สถาบันมาตรฐานแห่งชาติอเมริกัน (ANSI) ได้จัดตั้งคณะกรรมการ#jb X3J11
เพื่อกำหนดมาตรฐานของภาษา C X3J11 ใช้มาตรฐาน C ที่อิงตามการใช้งานบนระบบ Unix เป็นพื้นฐาน
อย่างไรก็ตามส่วนที่ไม่สามารถพกพาได้ของไลบรารี C บน Unix ได้ถูกส่งต่อไปยังกลุ่มทำงาน IEEE 1003
เพื่อใช้เป็นพื้นฐานสำหรับ มาตรฐาน POSIX ในปี 1988 ในปี 1989 มาตรฐาน C ได้รับการรับรองเป็น
ANSI X3.159-1989 "ภาษาโปรแกรม C" เวอร์ชันนี้ของภาษามักถูกเรียกว่า ANSI C, Standard C
หรือบางครั้งเรียกว่า C89
int main()
{
printf("hello, ");
printf("world");
printf("\n");
}
```
#h(9.75em) ในปี 1990 มาตรฐาน ANSI C (พร้อมการเปลี่ยนแปลงรูปแบบ)
ได้รับการรับรองโดยองค์การมาตรฐานสากล (ISO) ในชื่อ ISO/IEC 9899:1990 ซึ่งบางครั้งเรียกว่า C90
ดังนั้น คำว่า "C89" และ "C90" จึงหมายถึงภาษาโปรแกรมเดียวกัน
แล้วข้อความที่แสดงออกมาจะยังคงเดิม
#h(9.75em) เช่นเดียวกับองค์กรมาตรฐานแห่งชาติอื่นๆ ANSI ไม่ได้พัฒนามาตรฐาน C ด้วยตนเองอีกต่อไป
แต่จะอ้างอิงถึงมาตรฐาน C สากล ซึ่งดูแลโดยคณะทำงาน ISO/IEC JTC1/SC22 /WG14
การนำมาตรฐานสากลฉบับปรับปรุงมาใช้ในระดับประเทศมักเกิดขึ้นภายในหนึ่งปีหลังจากที่ ISO
เผยแพร่มาตรฐานดังกล่าว
#i คุณสามารถสังเกตได้ว่า `\n` นั้นจะแทนตัวอักษรตัวเดียว โดยสัญกรณ์ _escape sequence_ เช่น `\n` คือรูปแบบในการเขียนตัวอักษรที่อาจพิมพ์ได้ยากหรือตัวอักษรล่องหน โดยสัญกรณ์อื่น ในประเภทเดียวกันมีตัวอย่างเช่น `\t` สำหรับตัวอักษรแท็บ, `\b` สำหรับ backspace, `\"` สำหรับการพิมพ์สัญลักษณ์อัญประกาศ (ไม่เช่นนั้นตัวอักษรอัญประกาศจะถูกถือว่าเป็นตัวอักษรในการเริ่มต้น/สิ้นสุดของสตริง), และ `\\` สำหรับการพิมพ์ตัวอักษร backslash เอง
#h(9.75em) หนึ่งในเป้าหมายของกระบวนการกำหนดมาตรฐานภาษา C คือการสร้างซูเปอร์เซ็ตของ K&R C
โดยรวมเอาคุณสมบัติที่ไม่เป็นทางการหลายอย่างที่ถูกนำมาใช้ในภายหลัง
คณะกรรมการมาตรฐานยังได้เพิ่มคุณสมบัติเพิ่มเติมอีกหลายอย่างเช่นต้นแบบฟังก์ชัน (ยืมมาจาก C++),
voidพอยเตอร์, การรองรับชุดอักขระและภาษาท้องถิ่นระหว่างประเทศ และการปรับปรุงพรีโปรเซสเซอร์
แม้ว่าไวยากรณ์สำหรับการประกาศพารามิเตอร์จะได้รับการปรับปรุงให้รวมรูปแบบที่ใช้ใน C++
แต่ก็ยังคงอนุญาตให้ใช้อินเทอร์เฟซ K&R เพื่อความเข้ากันได้กับซอร์สโค้ดที่มีอยู่
#h(9.75em) C89 ได้รับการสนับสนุนจากคอมไพเลอร์ C ในปัจจุบัน และโค้ด C สมัยใหม่ส่วนใหญ่ก็ใช้ C89
เป็นพื้นฐานโปรแกรมใดๆ ที่เขียนด้วยภาษา C มาตรฐานเท่านั้น และไม่มีข้อสมมติฐานใดๆ ที่ขึ้นอยู่กับฮาร์ดแวร์
จะทำงานได้อย่างถูกต้องบนแพลตฟอร์มใดๆ ที่มีการใช้งาน C ที่สอดคล้องกับมาตรฐาน
ภายในขีดจำกัดของทรัพยากร หากไม่ระมัดระวัง
โปรแกรมอาจคอมไพล์ได้เฉพาะบนแพลตฟอร์มใดแพลตฟอร์มหนึ่ง หรือด้วยคอมไพเลอร์เฉพาะเท่านั้น
ตัวอย่างเช่น เนื่องจากการใช้ไลบรารีที่ไม่เป็นมาตรฐาน เช่น ไลบรารี GUI
หรือการพึ่งพาคุณลักษณะเฉพาะของคอมไพเลอร์หรือแพลตฟอร์ม เช่น ขนาดที่แน่นอนของชนิดข้อมูลและลำดับไบต์
#h(9.75em)
ในกรณีที่โค้ดต้องสามารถคอมไพล์ได้ทั้งโดยคอมไพเลอร์ที่สอดคล้องกับมาตรฐานหรือคอมไพเลอร์ที่ใช้ C แบบ
K&R นั้น `__STDC__` สามารถใช้มาโครเพื่อแบ่งโค้ดออกเป็นส่วนมาตรฐานและส่วน K&R
เพื่อป้องกันการใช้คุณสมบัติที่มีเฉพาะใน C มาตรฐานบนคอมไพเลอร์ที่ใช้ C แบบ K&R
#h(9.75em) หลังจากกระบวนการกำหนดมาตรฐาน ANSI/ISO ข้อกำหนดภาษา C
ยังคงค่อนข้างคงที่เป็นเวลาหลายปี ในปี 1995 มีการเผยแพร่การแก้ไขมาตรฐานฉบับที่ 1 ของมาตรฐาน C ปี
1990 (ISO/IEC 9899/AMD1:1995 ซึ่งเรียกกันอย่างไม่เป็นทางการว่า C95)
เพื่อแก้ไขรายละเอียดบางประการและเพิ่มการสนับสนุนชุดอักขระสากลที่ครอบคลุมมากขึ้น
=== C99
#h(9.75em) มาตรฐาน C ได้รับการแก้ไขเพิ่มเติมในช่วงปลายทศวรรษ 1990 ส่งผลให้มีการตีพิมพ์
ISO/IEC 9899:1999 ในปี 1999 ซึ่งโดยทั่วไปเรียกว่า "C99" ต่อมาได้มีการแก้ไขเพิ่มเติมอีกสามครั้งโดย
Technical Corrigenda
#h(9.75em) C99 ได้นำเสนอคุณสมบัติใหม่หลายประการรวมถึงฟังก์ชันอินไลน์ชนิดข้อมูลใหม่หลายชนิด(รวมถึง
long long intชนิด ข้อมูล complex ที่ใช้แทนจำนวนเชิงซ้อน)
อาร์เรย์ที่มีความยาวแปรผันได้และสมาชิกอาร์เรย์ที่ยืดหยุ่นการสนับสนุนที่ดีขึ้นสำหรับเลขทศลอย IEEE 754
การสนับสนุนมาโครแบบแปรผัน (มาโครที่มีจำนวนอาร์กิวเมนต์ แปรผันได้)
และการสนับสนุนความคิดเห็นแบบบรรทัดเดียวที่ขึ้นต้นด้วย `@` `//` เช่นเดียวกับใน BCPL หรือ C++
คุณสมบัติเหล่านี้หลายอย่างได้ถูกนำไปใช้เป็นส่วนขยายในคอมไพเลอร์ C หลายตัวแล้ว
#h(9.75em) โดยส่วนใหญ่แล้ว C99 สามารถใช้งานร่วมกับ C90 ได้ แต่มีความเข้มงวดมากกว่าในบางด้าน
โดยเฉพาะอย่างยิ่ง การประกาศที่ไม่มีตัวระบุประเภทจะไม่ถือว่ามีintการกำหนดโดยปริยายอีกต่อไป
มีการกำหนดมาโครมาตรฐาน `__STDC_VERSION__` พร้อมค่า `199901L` เพื่อระบุว่ามีการสนับสนุน C99
คอม ไพเลอร์ C อื่นๆ เช่น GCC, Solaris Studio และคอมไพเลอร์ C อื่นๆ
ในปัจจุบันรองรับคุณสมบัติใหม่หลายอย่างหรือทั้งหมดของ C99 อย่างไรก็ตาม คอมไพเลอร์ C ใน Microsoft
Visual C++ ใช้มาตรฐาน C89 และส่วนต่างๆ ของ C99 ที่จำเป็นสำหรับการใช้งานร่วมกับ C++11
#h(9.75em) นอกจากนี้ มาตรฐาน C99 ยังกำหนดให้รองรับตัวระบุที่ใช้ Unicode
ในรูปแบบของอักขระพิเศษ (เช่น `\u0040` หรือ `\U0001f431`) และแนะนำให้รองรับชื่อ Unicode
ดิบด้วย
=== C11
#h(9.75em) งานปรับปรุงมาตรฐาน C ฉบับใหม่เริ่มขึ้นในปี 2550 โดยเรียกกันอย่างไม่เป็นทางการว่า
"C1X" จนกระทั่งมีการประกาศใช้มาตรฐาน ISO/IEC 9899:2011 อย่างเป็นทางการในวันที่ 8 ธันวาคม
2554 คณะกรรมการมาตรฐาน C ได้กำหนดแนวทางเพื่อจำกัดการนำคุณสมบัติใหม่ๆ
ที่ยังไม่ได้รับการทดสอบโดยระบบที่มีอยู่มาใช้
#h(9.75em) มาตรฐาน C11 เพิ่มคุณสมบัติใหม่มากมายให้กับภาษา C และไลบรารี
รวมถึงมาโครแบบเจเนริกชนิดโครงสร้างนิรนามการสนับสนุน Unicode ที่ดีขึ้น
การดำเนินการอะตอมิกการทำงานแบบมัลติเธรดและฟังก์ชันตรวจสอบขอบเขต
นอกจากนี้ยังทำให้บางส่วนของไลบรารี C99 ที่มีอยู่เป็นตัวเลือก และปรับปรุงความเข้ากันได้กับ C++
มาโครมาตรฐาน `__STDC_VERSION__` ถูกกำหนดไว้เพื่อ `201112L` ระบุว่ามีการสนับสนุน C11 แล้ว
=== C17
#h(9.75em) C17 เป็นชื่อเรียกอย่างไม่เป็นทางการของ ISO/IEC 9899:2018
ซึ่งเป็นมาตรฐานสำหรับภาษาโปรแกรม C ที่เผยแพร่ในเดือนมิถุนายน 2018
มาตรฐานนี้ไม่ได้เพิ่มคุณสมบัติใหม่ใดๆ ให้กับภาษา แต่เป็นการแก้ไขทางเทคนิคและการชี้แจงข้อบกพร่องใน
C11 เท่านั้น มาโครมาตรฐาน `__STDC_VERSION__` ถูกกำหนดขึ้นเพื่อ `201710L` ระบุว่ามีการรองรับ
C17 แล้ว
=== C23
#h(9.75em) C23 เป็นชื่อเรียกอย่างไม่เป็นทางการของการแก้ไขมาตรฐานภาษา C หลักในปัจจุบัน
ซึ่งในระหว่างการพัฒนาส่วนใหญ่เรียกว่า "C2X" โดยสร้างขึ้นจากเวอร์ชันก่อนหน้า และแนะนำคุณสมบัติใหม่
เช่น คำหลักใหม่ ความหมายเพิ่มเติมสำหรับเพื่อ `auto`
ให้มีการอนุมานประเภทเมื่อประกาศตัวแปรประเภทใหม่รวมถึง `nullptr_t` และ `_BitInt` (N)
และการขยายไลบรารีมาตรฐาน
C23 ได้รับการเผยแพร่ในเดือนตุลาคม 2024 ในชื่อ ISO/IEC 9899:2024 มาโครมาตรฐาน
`__STDC_VERSION__` ถูกกำหนดไว้ `202311L` เพื่อระบุว่ามีการสนับสนุน C23
=== C2Y
#h(9.75em) C2Y เป็นชื่อเรียกอย่างไม่เป็นทางการของการแก้ไขมาตรฐานภาษา C ครั้งใหญ่ถัดไป หลังจาก
C23 (C2X) ซึ่งคาดว่าจะออกในช่วงปลายทศวรรษ 2020 ดังนั้นจึงมีเลข '2' ใน "C2Y" ร่างฉบับแรกของ
C2Y ได้รับการเผยแพร่ในเดือนกุมภาพันธ์ 2024 ในชื่อ N3220 โดยกลุ่มทำงาน ISO/IEC JTC1/SC22
/WG14
=== Embedded C
#h(9.75em) ในอดีตการเขียนโปรแกรม C
สำหรับระบบฝังตัวจำเป็นต้องใช้ส่วนขยายที่ไม่เป็นมาตรฐานของภาษา C เพื่อรองรับคุณสมบัติพิเศษ
เช่นการคำนวณเลขทศนิยมคงที่
ธนาคารหน่วยความจำหลายชุดที่แตกต่างกันและการดำเนินการอินพุต/เอาต์พุตพื้นฐาน
#h(9.75em) ในปี 2551 คณะกรรมการมาตรฐาน C ได้เผยแพร่รายงานทางเทคนิคที่ขยายภาษา C
เพื่อแก้ไขปัญหาเหล่านี้โดยการจัดหามาตรฐานทั่วไปสำหรับการใช้งานทั้งหมดให้ปฏิบัติตาม
ซึ่งรวมถึงคุณสมบัติหลายอย่างที่ไม่มีในภาษา C ปกติ เช่น การคำนวณเลขทศนิยมคงที่
พื้นที่แอดเดรสแบบมีชื่อและการกำหนดแอดเดรสฮาร์ดแวร์ I/O พื้นฐาน
== ตัวแปร (Variables)
#i ตัวแปรในภาษา C เบื้องต้นแล้วประกอบไปด้วยประเภทของข้อมูล และชื่อตัวแปร โดยที่ชื่อตัวแปรนั้นสามารถเป็นรายการที่ถูกแบ่งด้วยเครื่องหมายจุลภาคได้ด้วยเช่นกัน ตัวอย่างคือ
#i ตัวแปรในภาษา C เบื้องต้นแล้วประกอบไปด้วยประเภทของข้อมูลและชื่อตัวแปร
โดยที่ชื่อตัวแปรนั้นสามารถเป็นรายการที่ถูกแบ่งด้วยเครื่องหมายจุลภาคได้ด้วยเช่นกัน ตัวอย่างคือ
```c
int data;
float a, b, c;
```
#afigure(
```c
int data;
float a, b, c;
```,
kind: image,
caption: [ตัวอย่างการประกาศตัวแปรในภาษา C],
)
== ประเภทข้อมูล (Data Types)
#i ข้อมูลที่เกี่ยวข้องกับตัวเลขมักมีประเภท *unsigned* และ *signed* โดยความแตกต่างหากอธิบายสั้น คือ
#h(6em) ข้อมูลที่เกี่ยวข้องกับตัวเลขมักมีประเภท unsigned และ signed โดยความแตกต่างหากอธิบายสั้น
คือ
- *Signed (มีเครื่องหมาย):* ตัวเลขที่สามารถติดลบได้ ระยะข้อมูลตัวอย่างคือ -128 ถึง 127
- *Unsigned (ไม่มีเครื่องหมาย):* ตัวเลขที่ไม่สามารถติดลบได้ ระยะข้อมูลตัวอย่างคือ 0 ถึง 255
#[
#set enum(indent: 6em)
+ Signed (มีเครื่องหมาย): ตัวเลขที่สามารถติดลบได้ ระยะข้อมูลตัวอย่างคือ -128 ถึง 127
+ Unsigned (ไม่มีเครื่องหมาย): ตัวเลขที่ไม่สามารถติดลบได้ ระยะข้อมูลตัวอย่างคือ 0 ถึง 255
]
#i จะสังเกตได้ว่า ข้อมูลประเภท unsigned นั้นสามารถเก็บตัวเลขบวกได้จำนวนมากกว่า คือสูงสุดที่ 255 แต่หากนำค่าสัมบูรณ์ (absolute value) ของระยะข้อมูลแบบ signed มาบวกกัน เช่น\ #math.equation($|-128| + |127|$, alt: "ค่าสัมบูรณ์ของ -128 บวกค่าสัมบูรณ์ของ 127") จะพบว่าได้ค่า 255 หมายความว่า จริง แล้วข้อมูลประเภท signed สามารถเก็บข้อมูลได้ 255 ตัวเลขเช่นกัน เพียงแต่ว่าครึ่งหนึ่งของตัวเลขที่สามารถเก็บได้เป็นตัวเลขติดลบ
#h(6em) จะสังเกตได้ว่า ข้อมูลประเภท unsigned นั้นสามารถเก็บตัวเลขบวกได้จำนวนมากกว่า คือสูงสุดที่
255 แต่หากนำค่าสัมบูรณ์ (absolute value) ของระยะข้อมูลแบบ signed มาบวกกัน เช่น\
#math.equation($|-128| + |127|$, alt: "ค่าสัมบูรณ์ของ -128 บวกค่าสัมบูรณ์ของ 127")
จะพบว่าได้ค่า 255 หมายความว่า จริง แล้วข้อมูลประเภท signed สามารถเก็บข้อมูลได้ 255
ตัวเลขเช่นกัน เพียงแต่ว่าครึ่งหนึ่งของตัวเลขที่สามารถเก็บได้เป็นตัวเลขติดลบ
*หมายเหตุ:* เลขคณิตจำนวนเต็มมีนิยามแตกต่างกันสำหรับชนิดจำนวนเต็มแบบ signed และ unsigned โปรดดูตัวดำเนินการเลขคณิต โดยเฉพาะอย่างยิ่งการโอเวอร์โฟลว์จำนวนเต็ม
#h(6em) ดังนั้นโปรดจำไว้ว่า เลขคณิตจำนวนเต็มมีนิยามแตกต่างกันสำหรับชนิดจำนวนเต็มแบบ signed และ
unsigned โปรดดูตัวดำเนินการเลขคณิต โดยเฉพาะอย่างยิ่งการโอเวอร์โฟลว์จำนวนเต็ม
=== ประเภทบูลีน (Boolean)
*หมายเหตุ:* ประเภทบูลีนนั้นถูกนำเสนอครั้งแรกในมาตรฐาน C99
ประเภทบูลีนนั้นถูกนำเสนอครั้งแรกในมาตรฐาน C99 โดยการกล่าวถึงประเภทข้อมูลบูลีนนั้น ในประวัติของภาษา C แล้วมีสองแบบ
โดยการกล่าวถึงประเภทข้อมูลบูลีนนั้น ในประวัติของภาษา C แล้วมีสองแบบ
- `_Bool` (และมีมาโคร `bool`): จนถึงมาตรฐาน C23
- `bool` (ที่ไม่ใช่แค่มาโคร): มีตั้งแต่มาตรฐาน C23
+ `_Bool` (และมีมาโคร `bool`): จนถึงมาตรฐาน C23
+ `bool` (ที่ไม่ใช่แค่มาโคร): มีตั้งแต่มาตรฐาน C23
=== ประเภทจำนวนเต็ม (Integer)
- `short int` (หรืออีกชื่อหนึ่งคือ `short` และสามารถใช้คีย์เวิร์ด `signed` ได้)
- `unsigned short int` (หรือ `unsigned short`)
- `int` (หรือ `signed int`) \
คือประเภทข้อมูลตัวเลขที่ปกติที่สุด และจะถูกการันตีว่าจะมีขนาดขั้นต่ำ 16 บิตเสมอ โดยระบบทั่วไปส่วนใหญ่ในปัจจุบันจะเป็น 32 บิต
- `unsigned int` (หรือเพียงแค่ `unsigned`): คือประเภท `int` ในแบบ `unsigned`, มี modulo arithmetic, และเหมาะสมสำหรับการเปลี่ยนแปลงบิต
- `long int` (หรือ `long`)
- `unsigned long int` (หรือ `unsigned long`)
+ `short int` (หรืออีกชื่อหนึ่งคือ `short` และสามารถใช้คีย์เวิร์ด `signed` ได้)
+ `unsigned short int` (หรือ `unsigned short`)
+ `int` (หรือ `signed int`) \
คือประเภทข้อมูลตัวเลขที่ปกติที่สุด และจะถูกการันตีว่าจะมีขนาดขั้นต่ำ 16 บิตเสมอ
โดยระบบทั่วไปส่วนใหญ่ในปัจจุบันจะเป็น 32 บิต
+ `unsigned int` (หรือเพียงแค่ `unsigned`): คือประเภท `int` ในแบบ `unsigned`, มี
modulo arithmetic, และเหมาะสมสำหรับการเปลี่ยนแปลงบิต
+ `long int` (หรือ `long`)
+ `unsigned long int` (หรือ `unsigned long`)
+ มีเพิ่มตั้งแต่ C99:
+ `long long int` (หรือ `long long`)
+ `unsigned long long int` (หรือ `unsigned long long`)
+ มีเพิ่มตั้งแต่ C23:
+ `_BitInt(n)` (หรือ `signed _BitInt(n)`): ประเภทข้อมูล signed แบบมีขนาดชัดเจน โดย
n แทนด้วยจำนวนบิต (รวมถึงบิตเครื่องหมาย และ n จะต้องไม่มากกว่า `BITINT_MAXWIDTH`
จากไฟล์ `<limits.h>`)
+ `unsigned _BitInt(n)`: เหมือนข้างต้น เพียงแค่เป็นประเภท unsigned
(และไม่มีบิตเครื่องหมาย)
#pagebreak()
- มีเพิ่มตั้งแต่ C99:
- `long long int` (หรือ `long long`)
- `unsigned long long int` (หรือ `unsigned long long`)
- มีเพิ่มตั้งแต่ C23:
- `_BitInt(n)` (หรือ `signed _BitInt(n)`): ประเภทข้อมูล signed แบบมีขนาดชัดเจน โดย n แทนด้วยจำนวนบิต (รวมถึงบิตเครื่องหมาย และ n จะต้องไม่มากกว่า `BITINT_MAXWIDTH` จากไฟล์ `<limits.h>`)
- `unsigned _BitInt(n)`: เหมือนข้างต้น เพียงแค่เป็นประเภท unsigned (และไม่มีบิตเครื่องหมาย)
และเหมือนประเภทข้อมูลอื่น คุณสามารถเรียงคีย์เวิร์ดแบบใดก็ได้ เช่น `unsigned long long int` และ `long int unsigned long` นั้นเหมือนกัน
และเหมือนประเภทข้อมูลอื่น คุณสามารถเรียงคีย์เวิร์ดแบบใดก็ได้ เช่น `unsigned long long int`
และ `long int unsigned long` นั้นเหมือนกัน
ตารางต่อไปนี้สรุปประเภทตัวเลขทั้งหมดและคุณสมบัติของมัน
#show table.cell.where(y: 1): strong
#show table.cell: set par(justify: false, leading: 0.5em)
#show figure: i-figured.show-figure.with(level: 4)
#figure(
table(
columns: 7,
@@ -245,110 +403,126 @@ float a, b, c;
caption: [ขนาดของข้อมูลเป็นบิต (ต่อ)],
)
และนอกจากค่าบิตขั้นต่ำ มาตรฐาน C นั้นการันตีว่า:
#i ```c 1``` == ```c sizeof(char)``` #sym.lt.eq ```c sizeof(short)``` #sym.lt.eq ```c sizeof(int)``` #sym.lt.eq ```c sizeof(long)``` #sym.lt.eq ```c sizeof(long long)```
*หมายเหตุ:* เงื่อนไขนี้อนุญาตกรณีสุดขีดที่ทุกประเภทมีขนาด 64 บิตและ `sizeof` คืนค่า `1` สำหรับทุกประเภท
==== รูปแบบข้อมูล (data model)
#i รูปแบบข้อมูล หรือ data model คือรูปแบบการเก็บข้อมูลของโปรแกรมซึ่งเป็นสิ่งที่กำหนดขนาดของตัวแปร โดยรูปแบบข้อมูลนั้นจะถูกกำหนดโดยแพลตฟอร์มเป้าหมาย ซึ่งมีหน่วยประมวลผลและระบบปฏิบัติการเป็นปัจจัยหลัก โดยตามตารางในหัวข้อก่อนหน้า หลัก แล้วมีรูปแบบข้อมูลอยู่ 4 รูปแบบ คือ LP32, ILP32, LLP64, และ LP64 ซึ่งหากต้องการหาความหาย L หมายถึง Long, P หมายถึง Pointer, และ I หมายถึง Integer (จำนวนเต็ม) แล้วตามด้วยเลขบิต ดังนั้น สรุปแล้วจึงจะมีความหมายดังนี้
ระบบ 32 บิต:
- LP32 หรือ 2/4/4: `long` และ Pointer มีขนาด 32 บิต
- Win16 API
- ILP32 หรือ 4/4/4: `int`, `long`, และ Pointer มีขนาด 32 บิต
- Win32 API
- ระบบ Unix และเสมือน Unix (Linux, Mac OS X)
ระบบ 64 บิต:
- LLP64 หรือ 4/4/8: `long long` และ Pointer มีขนาด 64 บิต
- Win64 API
- LP64 หรือ 4/8/8: `long` และ Pointer มีขนาด 64 บิต
- ระบบ Unix และเสมือน Unix (Linux, Mac OS X)
#i รูปแบบอื่น นั้นหาได้ยาก ตัวอย่างเช่น ILP64 (8/8/8: `int`, `long`, และ Pointer ขนาด 64 บิต) ที่มีการใช้งานแค่ในระบบ Unix 64 บิตช่วงเริ่มต้น (เช่น Unicos บน Cray)
และโปรดจำไว้ว่า ตัวเลขที่มีขนาดแน่นอนนั้นมีให้ใช้งานใน `<stdint.h>` ตั้งแต่ C99
#h(13.5em) รูปแบบข้อมูล หรือ data model
คือรูปแบบการเก็บข้อมูลของโปรแกรมซึ่งเป็นสิ่งที่กำหนดขนาดของตัวแปร
โดยรูปแบบข้อมูลนั้นจะถูกกำหนดโดยแพลตฟอร์มเป้าหมาย
ซึ่งมีหน่วยประมวลผลและระบบปฏิบัติการเป็นปัจจัยหลัก โดยตามตารางในหัวข้อก่อนหน้า หลัก
แล้วมีรูปแบบข้อมูลอยู่ 4 รูปแบบ คือ LP32, ILP32, LLP64, และ LP64 ซึ่งหากต้องการหาความหาย L
หมายถึง Long, P หมายถึง Pointer, และ I หมายถึง Integer (จำนวนเต็ม) แล้วตามด้วยเลขบิต
=== ประเภทจำนวนทศนิยมจริง (Real floating types)
ภาษา C นั้นมีประเภทข้อมูลสำหรับแทนตัวเลขทศนิยมจริง 3 (หรือ 6 ตั้งแต่ C23) ประเภท
#h(9.75em) ภาษา C นั้นมีประเภทข้อมูลสำหรับแทนตัวเลขทศนิยมจริง 3 (หรือ 6 ตั้งแต่ C23) ประเภท
- `float`: จำนวนทศนิยมความแม่นยำเดี่ยว ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary32 หากรองรับ
- `double`: จำนวนทศนิยมความแม่นยำสองเท่า ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary64 หากรองรับ
- `long double`: จำนวนทศนิยมความแม่นยำเพิ่มเติม ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary128 หากรองรับ มิฉะนั้นจะตรงกับ IEEE-754 binary64-extended หากรองรับ มิฉะนั้นจะตรงกับรูปแบบจำนวนทศนิยมที่ไม่ตรงกับมาตรฐาน IEEE-754 รูปแบบใดก็ได้ตราบใดที่มีความแม่นยำกว่า binary64 และระยะข้อมูลนั้นอย่างน้อยก็ต้องดีเท่า binary64 และหากไม่รองรับทั้งหมดนั้น จะตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary64
- รูปแบบ binary128 นั้นถูกใช้โดยระบบ HP-UX, SPARC, MIPS, ARM64, และ z/OS บางระบบ
- รูปแบ IEEE-754 binary64-extended ที่รู้จักกันอย่างแพร่หลายที่สุดคือรูปแบบความแม่นยำเพิ่มเติม 80 บิต x87 ซึ่งถูกใช้โดยสถาปัตยกรรม x86 และ x86-64 บางระบบ (การยกเว้นที่ควรพูดถึงคือ MSVC ที่กำหนดให้ `long double` อยู่ในรูปแบบเดียวกันกับ `double`, เช่น binary64)
+ `float`: จำนวนทศนิยมความแม่นยำเดี่ยว ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary32 หากรองรับ
+ `double`: จำนวนทศนิยมความแม่นยำสองเท่า ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary64
หากรองรับ
+ `long double`: จำนวนทศนิยมความแม่นยำเพิ่มเติม ตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary128
หากรองรับ มิฉะนั้นจะตรงกั IEEE-754 binary64-extended หากรองรับ
มิฉะนั้นจะตรงกับรูปแบบจำนวนทศนิยมที่ไม่ตรงกับมาตรฐาน IEEE-754
รูปแบบใดก็ได้ตราบใดที่มีความแม่นยำกว่า binary64 และระยะข้อมูลนั้นอย่างน้อยก็ต้องดีเท่า binary64
และหากไม่รองรับทั้งหมดนั้น จะตรงกับฟอร์แมตมาตรฐาน IEEE-754 binary64
+ รูปแบบ binary128 นั้นถูกใช้โดยระบบ HP-UX, SPARC, MIPS, ARM64, และ z/OS บางระบบ
+ รูปแบบ IEEE-754 binary64-extended ที่รู้จักกันอย่างแพร่หลายที่สุดคือรูปแบบความแม่นยำเพิ่มเติม
80 บิต x87 ซึ่งถูกใช้โดยสถาปัตยกรรม x86 และ x86-64 บางระบบ (การยกเว้นที่ควรพูดถึงคือ
MSVC ที่กำหนดให้ `long double` อยู่ในรูปแบบเดียวกันกับ `double`, เช่น binary64)
เมื่อใช้มาตรฐาน C ตั้งแต่ C23 เป็นต้นไปและหากแพลตฟอร์มของคุณใช้งานคอนแสตนต์มาโคร `__STDC_IEC_60559_DFP__` ข้อมูลประเภทตัวเลขทศนิยมดังต่อไปนี้จะถูกรองรับด้วย:
เมื่อใช้มาตรฐาน C ตั้งแต่ C23 เป็นต้นไปและหากแพลตฟอร์มของคุณใช้งานคอนแสตนต์มาโคร
`__STDC_IEC_60559_DFP__` ข้อมูลประเภทตัวเลขทศนิยมดังต่อไปนี้จะถูกรองรับด้วย:
- `_Decimal32`: แทนรูปแบบมาตรฐาน IEEE-754 decimal32
- `_Decimal64`: แทนรูปแบบมาตรฐาน IEEE-754 decimal64
- `_Decimal128`: แทนรูปแบบมาตรฐาน IEEE-754 decimal128
#[
#set enum(indent:9.75em)
+ `_Decimal32`: แทนรูปแบบมาตรฐาน IEEE-754 decimal32
+ `_Decimal64`: แทนรูปแบบมาตรฐาน IEEE-754 decimal64
+ `_Decimal128`: แทนรูปแบบมาตรฐาน IEEE-754 decimal128
]
มิฉะนั้น ประเภทตัวเลขทศนิยมเพิ่มเติมเหล่านี้จะไม่ถูกรองรับ
ข้อมูลประเภททศนิยมอาจรองรับค่าพิเศษเพิ่มเติมได้แก่
- อนันต์ (Infinity, ทั้งบวกและลบ)
- ศูนย์ติดลบ, `-0.0` โดยมีค่าเท่ากับศูยน์ที่ติดบวก แต่อาจมีความหมายในบางสมการ เช่น `1.0 / 0.0 == INFINITY` แต่ `1.0 / -0.0 == -INFINITY`
- ไม่ใช่ตัวเลข (not-a-number; NaN) ซึ่งไม่เท่ากับอะไรเลย (รวมถึงตัวมันเอง)
#[
#set enum(indent: 9.75em)
+ อนันต์ (Infinity, ทั้งบวกและลบ)
+ ศูนย์ติดลบ, `-0.0` โดยมีค่าเท่ากับศูยน์ที่ติดบวก แต่อาจมีความหมายในบางสมการ เช่น
`1.0 / 0.0 == INFINITY` แต่ `1.0 / -0.0 == -INFINITY`
+ ไม่ใช่ตัวเลข (not-a-number; NaN) ซึ่งไม่เท่ากับอะไรเลย (รวมถึงตัวมันเอง)
]
ทศนิยมจำนวนจริงสามารถถูกใช้กับตัวดำเนินการทางคณิตศาสตร์ได้ *+ - / \** และฟังก์ชันทางคณิตศาสตร์จาก `<math.h>` โดยทั้งตัวดำเนินการและฟังก์ชันจากไลบรารีนั้นสามารถก่อให้เกิดการแสดงข้อผิดพลาดของจำนวนทศนิยมได้และจะตั้งค่า `errno`
ทศนิยมจำนวนจริงสามารถถูกใช้กับตัวดำเนินการทางคณิตศาสตร์ได้ *+ - / \**
และฟังก์ชันทางคณิตศาสตร์จาก `<math.h>`
โดยทั้งตัวดำเนินการและฟังก์ชันจากไลบรารีนั้นสามารถก่อให้เกิดการแสดงข้อผิดพลาดของจำนวนทศนิยมได้และจะตั้งค่า
`errno`
=== ประเภทจำนวนทศนิยมซับซ้อน (Complex floating types)
#i ประเภทข้อมูลจำนวนทศนิยมซับซ้อนนั้นเป็นประเภทที่แทนตัวเลขเชิงซ้อน (complex number) นั้นคือ ตัวเลขที่สามารถถูกเขียนแทนเป็นผลรวมของจำนวนจริงและจำนวนจริงที่คูณด้วยจำนวนจินตภาพ: #math.equation($a + b i$, alt: "a บวก b i")
#h(9.75em) ประเภทข้อมูลจำนวนทศนิยมซับซ้อนนั้นเป็นประเภทที่แทนตัวเลขเชิงซ้อน (complex number)
นั้นคือ ตัวเลขที่สามารถถูกเขียนแทนเป็นผลรวมของจำนวนจริงและจำนวนจริงที่คูณด้วยจำนวนจินตภาพ (a +
bi) โดยประเภทจำนวนเชิงซ้อนมีอยู่สามประเภท ได้แก่
ประเภทจำนวนเชิงซ้อนมีอยู่สามประเภท ได้แก่
+ `float _Complex` (และสามารถใช้ `float complex` ได้เช่นกันหากนำเข้า `<complex.h>`)
+ `double _Complex` (และสามารถใช้ `double complex` ได้เช่นกันหากนำเข้า `<complex.h>`)
+ `long double _Complex` (และสามารถใช้ `long double complex` ได้เช่นกันหากนำเข้า
`<complex.h>`)
- ```c float _Complex``` (และสามารถใช้ ```c float complex``` ได้เช่นกันหากนำเข้า `<complex.h>`)
- ```c double _Complex``` (และสามารถใช้ ```c double complex``` ได้เช่นกันหากนำเข้า `<complex.h>`)
- ```c long double _Complex``` (และสามารถใช้ ```c long double complex``` ได้เช่นกันหากนำเข้า `<complex.h>`)
*หมายเหตุ:* เหมือนกับประเภทอื่น ๆ สามารถพิมพ์คีย์เวิร์ดในลำดับใดก็ได้ ```c long double complex```, ```c complex long double``` และแม้แต่ ```c double complex long``` นั้นคือประเภทข้อมูลเดียวกัน
=== ประเภทจำนวนทศนิยมจินตภาพ (Imaginary floating types)
#i ประเภทข้อมูลจำนวนทศนิยมจินตภาพนั้นเป็นประเภทที่แทนตัวเลขจินตภาพ (imaginary number) นั้นคือ ตัวเลขที่สามารถถูกเขียนแทนเป็นจำนวนจริงที่คูณด้วยจำนวนจินตภาพ: #math.equation($b i$, alt: "b i")
#i ประเภทข้อมูลจำนวนทศนิยมจินตภาพนั้นเป็นประเภทที่แทนตัวเลขจินตภาพ (imaginary number) นั้นคือ
ตัวเลขที่สามารถถูกเขียนแทนเป็นจำนวนจริงที่คูณด้วยจำนวนจินตภาพ: #math.equation(
$b i$,
alt: "b i",
)
ประเภทจำนวนเชิงซ้อนมีอยู่สามประเภท ได้แก่
- ```c float _Imaginary``` (และสามารถใช้ ```c float imaginary``` ได้เช่นกันหากนำเข้า `<complex.h>`)
- ```c double _Imaginary``` (และสามารถใช้ ```c double imaginary``` ได้เช่นกันหากนำเข้า `<complex.h>`)
- ```c long double _Imaginary``` (และสามารถใช้ ```c long double imaginary``` ได้เช่นกันหากนำเข้า `<complex.h>`)
+ `float _Imaginary` (และสามารถใช้ `float imaginary` ได้เช่นกันหากนำเข้า
`<complex.h>`)
+ `double _Imaginary` (และสามารถใช้ `double imaginary` ได้เช่นกันหากนำเข้า
`<complex.h>`)
+ `long double _Imaginary` (และสามารถใช้ `long double imaginary` ได้เช่นกันหากนำเข้า
`<complex.h>`)
*หมายเหตุ:* เหมือนกับประเภทอื่น ๆ สามารถพิมพ์คีย์เวิร์ดในลำดับใดก็ได้ ```c long double imaginary```, ```c imaginary long double``` และแม้แต่ ```c double imaginary long``` นั้นคือประเภทข้อมูลเดียวกัน
=== ประเภทตัวอักษร (Character)
- `signed char`: ประเภทสำหรับตัวอักษรแบบ signed
- `unsigned char`: ประเภทสำหรับตัวอักษรแบบ unsigned
- `char`: ประเภทสำหรับตัวอักษรแบบไม่ระบุระยะข้อมูล ซึ่งสามารถเท่ากับ `signed char` หรือ `unsigned char` ก็ได้ขึ้นอยู่กับแพลตฟอร์มและคอมไพเลอร์ แต่อย่างไรก็ตาม `char` นั้นไม่ใช่เพียงแค่มาโครที่ลิงก์ไปยังประเภทอื่น ๆ แต่ `char` คือประเภทของมันเอง
+ `signed char`: ประเภทสำหรับตัวอักษรแบบ signed
+ `unsigned char`: ประเภทสำหรับตัวอักษรแบบ unsigned
+ `char`: ประเภทสำหรับตัวอักษรแบบไม่ระบุระยะข้อมูล ซึ่งสามารถเท่ากับ `signed char` หรือ
`unsigned char` ก็ได้ขึ้นอยู่กับแพลตฟอร์มและคอมไพเลอร์ แต่อย่างไรก็ตาม `char`
นั้นไม่ใช่เพียงแค่มาโครที่ลิงก์ไปยังประเภทอื่น ๆ แต่ `char` คือประเภทของมันเอง
=== คีย์เวิร์ด
- `bool`, `true`, `false`, `char`, `int`, `short`, `long`, `signed`, `unsigned`, `float`, `double`.
- `_Bool`, `_BitInt`, `_Complex`, `_Imaginary`, `_Decimal32`, `_Decimal64`, `_Decimal128`.
+ `bool`, `true`, `false`, `char`, `int`, `short`, `long`, `signed`, `unsigned`,
`float`, `double`.
+ `_Bool`, `_BitInt`, `_Complex`, `_Imaginary`, `_Decimal32`, `_Decimal64`,
`_Decimal128`.
=== ระยะค่าที่เก็บได้
#i ตารางต่อไปนี้ให้ข้อมูลเกี่ยวกับขอบเขตของประเภทข้อมูลต่าง ๆ
#h(9.75em) ก่อนมาตรฐาน C23 มาตรฐาน C อนุญาตการแทนตัวเลขแบบใดก็ได้ และระยะขั้นต่ำของตัวเลข
N บิตคือ #math.equation($-(2^(N-1)-1)$, alt: "ลบ 2 ยกกำลัง N ลบ 1 ทั้งหมดลบ 1") ถึง
#math.equation($+2^(N-1)-1$, alt: "บวก 2 ยกกำลัง N ลบ 1 ทั้งหมดลบ 1") (เช่น -127 ถึง
127 สำหรับประเภทตัวเลข 8 บิต) ซึ่งตรงกับขอบเขตของส่วนเติมเต็มหนึ่ง (one's complement)
หรือการแทนจำนวนมีเครื่องหมาย (sign-and-magnitude)
#i ก่อนมาตรฐาน C23 มาตรฐาน C อนุญาตการแทนตัวเลขแบบใดก็ได้ และระยะขั้นต่ำของตัวเลข N บิตคือ #math.equation($-(2^(N-1)-1)$, alt: "ลบ 2 ยกกำลัง N ลบ 1 ทั้งหมดลบ 1") ถึง
#math.equation($+2^(N-1)-1$, alt: "บวก 2 ยกกำลัง N ลบ 1 ทั้งหมดลบ 1") (เช่น *-127* ถึง *127* สำหรับประเภทตัวเลข 8 บิต) ซึ่งตรงกับขอบเขตของส่วนเติมเต็มหนึ่ง (one's complement) หรือการแทนจำนวนมีเครื่องหมาย (sign-and-magnitude)
#h(9.75em) อย่างไรก็ตาม รูปแบบข้อมูลที่ใช้กันอย่างแพร่หลายทั้งหมด (รวมถึง ILP32, LP32, LP64,
และ LLP64) และคอมไพเลอร์ C เกือบทั้งหมดใช้การแทนตัวเลขแบบส่วนเติมเต็มสอง (two's
complement) (มีข้อยกเว้นที่ทราบแค่บางคอมไพเลอร์สำหรับระบบ UNISYS) และตั้งแต่มาตรฐาน C23
มันคือการแทนตัวเลขแบบเดียวที่ถูกอนุญาตให้ใช้โดยมาตรฐาน และมีขอบเขตที่แน่นอนระหว่าง
#math.equation($-2^(N-1)$, alt: "ลบ 2 ยกกำลัง N ลบ 1") ถึง #math.equation(
$+2^(N-1)-1$,
alt: "บวก 2 ยกกำลัง N ลบ 1 ทั้งหมดลบ 1",
) (เช่น -128 ถึง 127 สำหรับประเภทตัวเลข 8 บิต)
#i อย่างไรก็ตาม รูปแบบข้อมูลที่ใช้กันอย่างแพร่หลายทั้งหมด (รวมถึง ILP32, LP32, LP64, และ LLP64) และคอมไพเลอร์ C เกือบทั้งหมดใช้การแทนตัวเลขแบบส่วนเติมเต็มสอง (two's complement) (มีข้อยกเว้นที่ทราบแค่บางคอมไพเลอร์สำหรับระบบ UNISYS) และตั้งแต่มาตรฐาน C23 มันคือการแทนตัวเลขแบบเดียวที่ถูกอนุญาตให้ใช้โดยมาตรฐาน และมีขอบเขตที่แน่นอนระหว่าง
#math.equation($-2^(N-1)$, alt: "ลบ 2 ยกกำลัง N ลบ 1") ถึง
#math.equation($+2^(N-1)-1$, alt: "บวก 2 ยกกำลัง N ลบ 1 ทั้งหมดลบ 1") (เช่น *-128* ถึง *127* สำหรับประเภทตัวเลข 8 บิต)
(มีการเพิ่มจุลภาคในทศนิยมเพื่อเพิ่มความสะดวกในการอ่าน)
#h(9.75em) ตารางต่อไปนี้ให้ข้อมูลเกี่ยวกับขอบเขตของประเภทข้อมูลต่าง ๆ (มีการเพิ่มจุลภาคในทศนิยมเพื่อเพิ่มความสะดวกในการอ่าน)
#show table.cell.where(x: 0): strong
#show math.equation.where(block: true): set block(spacing: 0.6em)
#show math.equation: set text(font: "Noto Sans Math")
#set list(indent: 0em)
#figure(
@@ -415,22 +589,31 @@ float a, b, c;
[IEEE-754],
table.cell(
[
- min subnormal:
#math.equation($± 1.401,298,4 · 10^(-45)$, alt: "บวกลบ 1.4012984 คูณ 10 ยกกำลัง -45")
- min normal:
#math.equation($± 1.175,494,3 · 10^(-38)$, alt: "บวกลบ 1.1754943 คูณ 10 ยกกำลัง -38")
- max: \
#math.equation($± 3.402,823,4 · 10^(38)$, alt: "บวกลบ 3.4028234 คูณ 10 ยกกำลัง 38")
+ min subnormal:
#math.equation(
$± 1.401,298,4 · 10^(-45)$,
alt: "บวกลบ 1.4012984 คูณ 10 ยกกำลัง -45",
)
+ min normal:
#math.equation(
$± 1.175,494,3 · 10^(-38)$,
alt: "บวกลบ 1.1754943 คูณ 10 ยกกำลัง -38",
)
+ max: \
#math.equation(
$± 3.402,823,4 · 10^(38)$,
alt: "บวกลบ 3.4028234 คูณ 10 ยกกำลัง 38",
)
],
align: left,
),
table.cell(
[
- min subnormal:\
+ min subnormal:\
`±0x1p-149`
- min normal:\
+ min normal:\
`±0x1p-126`
- max:\
+ max:\
`±0x1.fffffep+127`
],
align: left,
@@ -440,19 +623,19 @@ float a, b, c;
[IEEE-754],
table.cell(
[
- min subnormal:
+ min subnormal:
#math.equation(
$± 4.940,656,458,412\ · 10^(-324)$,
alt: "บวกลบ 4.940656458412 คูณ 10 ยกกำลัง ลบ 324",
block: true,
)
- min normal:
+ min normal:
#math.equation(
$± 2.225,073,858,507,201,\ 4 · 10^(-308)$,
alt: "บวกลบ 2.2250738585072014 คูณ 10 ยกกำลัง ลบ 308",
block: true,
)
- max:
+ max:
#math.equation(
$± 1.797,693,134,862,315,\ 7 · 10^308$,
alt: "บวกลบ 1.7976931348623157 คูณ 10 ยกกำลัง 308",
@@ -463,12 +646,11 @@ float a, b, c;
),
table.cell(
[
- min subnormal:
+ min subnormal:
`±0x1p-1074`
- min normal:\
+ min normal:\
`±0x1p-1022`
- max:
`±0x1` \ `.fffffffffffffp+1023`
+ max: `±0x1` \ `.fffffffffffffp+1023`
],
align: left,
),
@@ -495,19 +677,19 @@ float a, b, c;
[x86],
table.cell(
[
- min subnormal:
+ min subnormal:
#math.equation(
$± 3.645,199,531,882,474,\ 602,528 · 10^(-4951)$,
alt: "บวกลบ 3.645199531882474602528 คูณ 10 ยกกำลัง ลบ 4951",
block: true,
)
- min normal:
+ min normal:
#math.equation(
$± 3.362,103,143,112,093,\ 506,263 · 10^(-4932)$,
alt: "บวกลบ 3.362103143112093506263 คูณ 10 ยกกำลัง ลบ 4932",
block: true,
)
- max:
+ max:
#math.equation(
$± 1.189,731,495,357,231,\ 765,021 · 10^(4932)$,
alt: "บวกลบ 1.189731495357231765021 คูณ 10 ยกกำลัง 4932",
@@ -518,12 +700,11 @@ float a, b, c;
),
table.cell(
[
- min subnormal:
+ min subnormal:
`±0x1p-16445`
- min normal:
+ min normal:
`±0x1p-16382`
- max:
`±0x1.ffffffff`\ `fffffffep+16383`
+ max: `±0x1.ffffffff`\ `fffffffep+16383`
],
align: left,
),
@@ -532,19 +713,19 @@ float a, b, c;
[IEEE-754],
table.cell(
[
- min subnormal:
+ min subnormal:
#math.equation(
$± 6.475,175,119,438,025,\ 110,924,438,958,227,\ 646,552,5 · 10^(-4966)$,
alt: "บวกลบ 6.4751751194380251109244389582276465525 คูณ 10 ยกกำลัง ลบ 4966",
block: true,
)
- min normal:
+ min normal:
#math.equation(
$± 3.362,103,143,112,093,\ 506,262,677,817,321,\ 752,602,6 · 10^(-4932)$,
alt: "บวกลบ 3.3621031431120935062626778173217526026 คูณ 10 ยกกำลัง ลบ 4932",
block: true,
)
- max:
+ max:
#math.equation(
$± 1.189,731,495,357,231,\ 765,085,759,326,628,\ 007,016,2 · 10^4932$,
alt: "บวกลบ 1.1897314953572317650857593266280070162 คูณ 10 ยกกำลัง 4932",
@@ -555,12 +736,11 @@ float a, b, c;
),
table.cell(
[
- min subnormal:
+ min subnormal:
`±0x1p-16494`
- min normal:
+ min normal:
`±0x1p-16382`
- max:
`±0x1.ffffffffffffff`\ `ffffffffffffffp+16383`
+ max: `±0x1.ffffffffffffff`\ `ffffffffffffffp+16383`
],
align: left,
),
@@ -571,12 +751,15 @@ float a, b, c;
[],
table.cell(
[
- min subnormal:\
+ min subnormal:\
#math.equation($± 1 · 10^(-101)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 101")
- min normal:\
+ min normal:\
#math.equation($± 1 · 10^(-95)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 95")
- max:\
#math.equation($± 9.999'999 · 10^96$, alt: "บวกลบ 9.999999 คูณ 10 ยกกำลัง 96")
+ max:\
#math.equation(
$± 9.999'999 · 10^96$,
alt: "บวกลบ 9.999999 คูณ 10 ยกกำลัง 96",
)
],
align: left,
),
@@ -586,11 +769,11 @@ float a, b, c;
[],
table.cell(
[
- min subnormal:\
+ min subnormal:\
#math.equation($± 1 · 10^(-398)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ -398")
- min normal:\
+ min normal:\
#math.equation($± 1 · 10^(-383)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 383")
- max:
+ max:
#math.equation(
$± 9.999'999'999'999'999\ · 10^384$,
alt: "บวกลบ 9.999999999999999 คูณ 10 ยกกำลัง 384",
@@ -605,11 +788,17 @@ float a, b, c;
[],
table.cell(
[
- min subnormal:\
#math.equation($± 1 · 10^(-6176)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 6176")
- min normal:\
#math.equation($± 1 · 10^(-6143)$, alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 6143")
- max:
+ min subnormal:\
#math.equation(
$± 1 · 10^(-6176)$,
alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 6176",
)
+ min normal:\
#math.equation(
$± 1 · 10^(-6143)$,
alt: "บวกลบ 1 คูณ 10 ยกกำลัง ลบ 6143",
)
+ max:
#math.equation(
$ ± 9.999'999'999'999'999'\ 999'999'999'999'999'999\ · 10^6144 $,
alt: "บวกลบ 9.999999999999999999999999999999999 คูณ 10 ยกกำลัง 6144",
@@ -626,10 +815,25 @@ float a, b, c;
== ชุดแปลโปรแกรมของกนู (GNU Compiler Collection; GCC)
#i ในกระบวนการการพัฒนาโครงงานนี้ ชุดแปลโปรแกรมของกนูนั้นถูกใช้เป็นหลักเนื่องจากเป็นชุดแปลโปรแกรม (คอมไพเลอร์; Compiler) ที่ใช้เป็นหลักในการพัฒนาโคดที่สร้างบนพื้นฐาน Arduino และบอร์ดต่าง ๆ รวมถึงบอร์ด ESP32
#h(6em) ในกระบวนการการพัฒนาโครงงานนี้
ชุดแปลโปรแกรมของกนูนั้นถูกใช้เป็นหลักเนื่องจากเป็นชุดแปลโปรแกรม (คอมไพเลอร์; Compiler)
ที่ใช้เป็นหลักในการพัฒนาโคดที่สร้างบนพื้นฐาน Arduino และบอร์ดต่าง ๆ รวมถึงบอร์ด ESP32
#i ชุดคอมไพเลอร์ GNU (GNU Compiler Collection; GCC) (เดิมชื่อ GNU C Compiler) คือชุดคอมไพเลอร์จากโครงการ GNU ที่รองรับภาษาโปรแกรม สถาปัตยกรรมฮาร์ดแวร์ และระบบปฏิบัติการต่าง ๆ มูลนิธิซอฟต์แวร์เสรี (FSF) เผยแพร่ GCC ในฐานะซอฟต์แวร์เสรีภายใต้สัญญาอนุญาตสถูกเรียกาธารณะทั่วไปของ GNU (GNU GPL) GCC เป็นองค์ประกอบสำคัญของชุดเครื่องมือ GNU ซึ่งใช้สำหรับโครงการส่วนใหญ่ที่เกี่ยวข้องกับ GNU และเคอร์เนล Linux ด้วยโคดประมาณ 15 ล้านบรรทัดในปี 2019 GCC จึงเป็นหนึ่งในโปรแกรมฟรีที่ใหญ่ที่สุดเท่าที่เคยมีมา GCC มีบทบาทสำคัญในการเติบโตของซอฟต์แวร์เสรี ทั้งในฐานะเครื่องมือและตัวอย่าง
#h(6em) ชุดคอมไพเลอร์ GNU (GNU Compiler Collection; GCC) (เดิมชื่อ GNU C Compiler)
คือชุดคอมไพเลอร์จากโครงการ GNU ที่รองรับภาษาโปรแกรม สถาปัตยกรรมฮาร์ดแวร์
และระบบปฏิบัติการต่าง ๆ มูลนิธิซอฟต์แวร์เสรี (FSF) เผยแพร่ GCC
ในฐานะซอฟต์แวร์เสรีภายใต้สัญญาอนุญาตสถูกเรียกาธารณะทั่วไปของ GNU (GNU GPL) GCC
เป็นองค์ประกอบสำคัญของชุดเครื่องมือ GNU ซึ่งใช้สำหรับโครงการส่วนใหญ่ที่เกี่ยวข้องกับ GNU และเคอร์เนล
Linux ด้วยโคดประมาณ 15 ล้านบรรทัดในปี 2019 GCC จึงเป็นหนึ่งในโปรแกรมฟรีที่ใหญ่ที่สุดเท่าที่เคยมีมา
GCC มีบทบาทสำคัญในการเติบโตของซอฟต์แวร์เสรี ทั้งในฐานะเครื่องมือและตัวอย่าง
#i นอกจากจะเป็นคอมไพเลอร์อย่างเป็นทางการของระบบปฏิบัติการ GNU แล้ว GCC ยังได้รับการยอมรับให้เป็นคอมไพเลอร์มาตรฐานโดยระบบปฏิบัติการคอมพิวเตอร์สมัยใหม่ที่คล้ายกับ Unix อื่นๆ อีกมากมาย รวมถึงระบบปฏิบัติการ Linux ส่วนใหญ่ ระบบปฏิบัติการตระกูล BSD ส่วนใหญ่ก็เปลี่ยนมาใช้ GCC ไม่นานหลังจากเปิดตัว แม้ว่าหลังจากนั้น FreeBSD และ Apple macOS ได้เปลี่ยนมาใช้คอมไพเลอร์ Clang ส่วนใหญ่เป็นเพราะเหตุผลด้านลิขสิทธิ์ GCC ยังสามารถคอมไพเลอร์โคดสำหรับระบบปฏิบัติการ Windows, Android, iOS, Solaris, HP-UX, AIX และ MS-DOS ได้อีกด้วย
#h(6em) นอกจากจะเป็นคอมไพเลอร์อย่างเป็นทางการของระบบปฏิบัติการ GNU แล้ว GCC
ยังได้รับการยอมรับให้เป็นคอมไพเลอร์มาตรฐานโดยระบบปฏิบัติการคอมพิวเตอร์สมัยใหม่ที่คล้ายกับ Unix อื่นๆ
อีกมากมาย รวมถึงระบบปฏิบัติการ Linux ส่วนใหญ่ ระบบปฏิบัติการตระกูล BSD ส่วนใหญ่ก็เปลี่ยนมาใช้ GCC
ไม่นานหลังจากเปิดตัว แม้ว่าหลังจากนั้น FreeBSD และ Apple macOS ได้เปลี่ยนมาใช้คอมไพเลอร์ Clang
ส่วนใหญ่เป็นเพราะเหตุผลด้านลิขสิทธิ์ GCC ยังสามารถคอมไพเลอร์โคดสำหรับระบบปฏิบัติการ Windows,
Android, iOS, Solaris, HP-UX, AIX และ MS-DOS ได้อีกด้วย
#i GCC ได้รับการพอร์ตไปยังแพลตฟอร์มและสถาปัตยกรรมชุดคำสั่งต่าง ๆ มากกว่าคอมไพเลอร์อื่น ๆ และถูกนำไปใช้งานอย่างกว้างขวางในฐานะเครื่องมือในการพัฒนาซอฟต์แวร์ทั้งแบบฟรีและแบบที่เป็นกรรมสิทธิ์ นอกจากนี้ GCC ยังพร้อมใช้งานสำหรับระบบฝังตัวมากมาย รวมถึงชิปที่ใช้ ARM และ Power ISA
#h(6em) GCC ได้รับการพอร์ตไปยังแพลตฟอร์มและสถาปัตยกรรมชุดคำสั่งต่าง ๆ มากกว่าคอมไพเลอร์อื่น ๆ
และถูกนำไปใช้งานอย่างกว้างขวางในฐานะเครื่องมือในการพัฒนาซอฟต์แวร์ทั้งแบบฟรีและแบบที่เป็นกรรมสิทธิ์
นอกจากนี้ GCC ยังพร้อมใช้งานสำหรับระบบฝังตัวมากมาย รวมถึงชิปที่ใช้ ARM และ Power ISA
+1 -4
View File
@@ -1,9 +1,6 @@
#import "../PageTemplate.typ": page-theme
#import "@preview/i-figured:0.2.4"
// #show: page-theme
#show heading: i-figured.reset-counters.with(level: 3)
#show figure: i-figured.show-figure.with(level: 3)
#set enum(numbering: "1)")
#set heading(numbering: "บทที่ 1")
#include "Intro.typ"
+181 -492
View File
@@ -2,6 +2,7 @@
#import "@preview/treet:1.0.0": *
#import "@preview/tiaoma:0.3.0"
#set heading(numbering: "1.1", offset: 1)
#set figure(kind: image)
= Flutter <flutter>
@@ -9,8 +10,8 @@
สามารถใช้พัฒนาแอปพลิเคชันข้ามแพลตฟอร์มจากฐานโคดเดียวสำหรับเว็บ Fuchsia, Android, iOS,
Linux, macOS และ Windows โดย Flutter ได้รับการพูดถึงครั้งแรกในปี 2015
และเปิดตัวในเดือนพฤษภาคม 2017 และ Flutter ถูกใช้งานภายในโดย Google ในแอปพลิเคชันต่างๆ
เช่น Google Pay และ Google Earth รวมถึงโดยนักพัฒนาซอฟต์แวร์รายอื่นๆ เช่น ByteDance
และ Alibaba
เช่น Google Pay และ Google Earth รวมถึงโดยนักพัฒนาซอฟต์แวร์รายอื่นๆ เช่น ByteDance และ
Alibaba
#i Flutter จะสร้างแอปพลิเคชันที่มีเอ็นจิ้นการเรนเดอร์ของตัวเอง ซึ่งส่งข้อมูลพิกเซลไปยังหน้าจอโดยตรง
ซึ่งแตกต่างจากเฟรมเวิร์ก UI อื่น อีกมากมายที่อาศัยแพลตฟอร์มเป้าหมายเพื่อจัดหาเอ็นจิ้นการเรนเดอร์
@@ -19,546 +20,234 @@ Linux, macOS และ Windows โดย Flutter ได้รับการพ
ช่วยลดความยุ่งยากในการรองรับหลายแพลตฟอร์ม เนื่องจากสามารถใช้โคด UI
ที่เหมือนกันได้กับทุกแพลตฟอร์มเป้าหมาย
#pagebreak()
== การติดตั้งโปรแกรมเขียนโคด
#i จริง แล้วนั้น Flutter สามารถทำงานกับโปรแกรมเขียนโคดใดก็ได้ แต่มีโปรแกรมเหล่านี้ที่อาจมีประสบการณ์การพัฒนาที่ดีกว่าโปรแกรมอื่น:
- Visual Studio Code (VS Code)
- Android Studio
- JetBrains IntelliJ
- Firebase Studio
#i โครงงานนี้ใช้โปรแกรมเขียนโคด Android Studio เป็นหลักเนื่องจากแอพลิเคชันโครงงานมี Android เป็นเป้าหมายหลัก และ Android SDK สามารถจัดการได้ง่ายกว่าใน Android Studio
=== Android Studio
#i Android Studio สามารถดาวน์โหลดได้ผ่าน https://developer.android.com/studio หรือสามารถถูกติดตั้งและจัดการผ่านแอพลิเคชัน JetBrains Toolbox ได้เช่นกัน (https://www.jetbrains.com/toolbox-app/)
== การติดตั้ง Flutter <flInstall>
#i การติดตั้ง Flutter สามารถทำได้สองวิธีด้วยกัน คือการติดตั้งผ่าน Visual Studio Code (VS Code) และการติดตั้งด้วยตนเอง โดยหากต้องการใช้ VS Code เป็นโปรแกรมเขียนโคดอยู่แล้ว สามารถติดตั้งผ่าน VS Code ได้เลย
#i แต่ก่อนอื่น ต้องทำการติดตั้งโปรแกรมและไลบรารีพื้นฐานที่จำเป็นสำหรับ Flutter ก่อน
=== การติดตั้งโปรแกรมและไลบรารีที่จำเป็น
==== Windows
#grid(
columns: 2,
column-gutter: 1em,
[#i ในการพัฒนาซอฟต์แวร์บน Windows ด้วย Flutter คุณจำเป็นต้องติดตั้ง Git สำหรับ Windows ซึ่งคุณสามารถดูขั้นตอนการติดตั้งได้โดยการสแกน QR code ด้านข้าง หรือที่ https://git-scm.com/install/windows หรือเพียงแค่ใช้ WinGet ในการติดตั้งโดยการใช้คำสั่งด้านล่าง],
tiaoma.qrcode("https://git-scm.com/install/windows", width: 1in, alt: "QR โคดสำหรับหน้าการติดตั้ง Git สำหรับ Windows"),
)
```sh
winget install --id Git.Git -e --source winget
```
==== Linux
#i Flutter ใช้ไลบรารีดังต่อไปนี้ในขั้นตอนการพัฒนาแอพลิเคชันบน Linux (development dependencies; ยังไม่รวมไลบรารีและโปรแกรมที่ต้องมีในการสร้างแอพลิเคชัน _สำหรับ_ Linux)
#grid(
columns: 2,
column-gutter: 2in,
[
- curl
- git
- unzip
],
[
- xz
- zip
- glu
],
)
หากต้องการคำสั่งในการติดตั้งแพคเกจเหล่านี้ โปรดดู@flLinuxDetails
==== macOS
#i จำเป็นต้องทำการติดตั้งเครื่องมือ command-line Xcode เพื่อเข้าถึงเครื่องมือที่ Flutter จำเป็นต้องใช้ รวมถึง Git
ในการดาวน์โหลดเครื่องมือ ใช้คำสั่งต่อไปนี้ในเทอร์มินัลที่คุณเลือก:
```sh
xcode-select --install
```
#i หากคุณไม่ได้ติดตั้งเครื่องมืออยู่แล้ว จะมีไดอะลอกเพื่อคอนเฟิร์มว่าคุณต้องการที่จะติดตั้งมัน กด *Install* และกด *Done* เมื่อทำการติดตั้งเสร็จสิ้นแล้ว
=== การติดตั้งผ่าน Visual Studio Code
1. เปิด VSCode
2. ติดตั้งส่วนขยาย Flutter \
อยู่ภายใต้ ID `Dart-Code.flutter` ทั้งบน Visual Studio Marketplace และ OpenVSX
3. ติดตั้ง Flutter ด้วย VS Code
+ เปิด Command Palette ด้วยเมนู *View* > *Command Palette* หรือกด Ctrl + Shift + P
+ ใน Command Palette พิมพ์ `flutter`.
+ เลือก *Flutter: New Project*
+ VS Code จะให้คุณเลือก Flutter SDK บนคอมพิวเตอร์ของคุณ เลือก *Download SDK*
+ เมือหน้าไดอะลอก *Select Folder for Flutter SDK* แสดงขึ้น เลือกสถานที่ที่คุณอยากติดตั้ง Flutter
+ คลิก *Clone Flutter* \
ในระหว่างการดาวน์โหลด VS Code จะแสดงการแจ้งเตือนนี้:
```
Downloading the Flutter SDK. This may take a few minutes.
```
การดาวน์โหลดนี้จะใช้เวลาสองสามนาที หากคุณเชื่อว่าการดาวน์โหลดหยุดชะงัก คุณสามารถคลิก *Cancel* แล้วเริ่มต้นการติดตั้งใหม่ได้
+ คลิก *Add SDK to PATH* \
เมื่อเสร็จสิ้น จะมีการแจ้งเตือน
```
The Flutter SDK was added to your PATH
```
+ VS Code อาจแสดงการแจ้งเตือนเกี่ยวกับการเก็บข้อมูลของ Google หากคุณยินยอม คลิก *OK*
+ เพื่อความแน่ใจ กรุณาปิดเทอร์มินัลทุกหน้าต่างหรือรีสตาร์ท VS Code เพื่อให้แน่ใจว่า Flutter จะสามารถใช้ผ่านเทอร์มินัลได้
4. เมื่อเสร็จสิ้น ใช้คำสั่ง `flutter doctor -v` ในเทอร์มินัลที่คุณเลือกเพื่อตรวจสอบการติดตั้ง Flutter ของคุณ \
หากคำสั่งไม่เจอหรือเกิดข้อผิดพลาดขึ้น ตรวจสอบ https://docs.flutter.dev/install/troubleshoot สำหรับข้อมูลเพิ่มเติม
#pagebreak()
=== การติดตั้งด้วยตนเอง
#i แนะนำให้ทำตาม https://docs.flutter.dev/install/manual#install-flutter เนื่องจากกระบวนการนี้ต้องใช้ข้อมูลที่ใหม่ล่าสุด
1. ดาวน์โหลด Flutter (สามารถหาปุ่มดาวน์โหลดได้จากลิงก์ด้านบน)
2. สร้างโฟลเดอร์สำหรับเก็บ Flutter SDK
3. ทำการแตกไฟล์ที่ดาวน์โหลดมา
4. เพิ่ม Flutter เข้าไปยัง PATH ของคุณ (วิธีการขึ้นอยู่กับระบบปฏิบัติการ)
5. ยืนยันความถูกต้องของการติดตั้งของคุณด้วยคำสั่ง `flutter doctor -v`
== Dart
#i Dart เป็นภาษาโปรแกรมที่ออกแบบโดย Lars Bak และ Kasper Lund และพัฒนาโดย
Google สามารถใช้พัฒนาแอปพลิเคชันบนเว็บ มือถือ เซิร์ฟเวอร์ และเดสก์ท็อปได้ และยังเป็นภาษาหลักที่ใช้ในการพัฒนาแอพลิเคชัน Flutter
#iii Dart เป็นภาษาโปรแกรมที่ออกแบบโดย Lars Bak และ Kasper Lund และพัฒนาโดย Google
สามารถใช้พัฒนาแอปพลิเคชันบนเว็บ มือถือ เซิร์ฟเวอร์ และเดสก์ท็อปได้
และยังเป็นภาษาหลักที่ใช้ในการพัฒนาแอปพลิเคชัน Flutter
#i Dart เป็นภาษาเชิงวัตถุ อิงคลาส และรวบรวมขยะ (garbage-collection) ด้วยไวยากรณ์แบบ C สามารถคอมไพล์เป็นโค้ดเครื่อง JavaScript หรือ WebAssembly ได้ รองรับอินเทอร์เฟซ มิกซ์อิน คลาสนามธรรม เจเนอริกแบบรีไฟด์ และการอนุมานชนิดข้อมูล
#iii Dart เป็นภาษาเชิงวัตถุ อิงคลาส และรวบรวมขยะ (garbage-collection) ด้วยไวยากรณ์แบบ C
สามารถคอมไพล์เป็นโค้ดเครื่อง JavaScript หรือ WebAssembly ได้ รองรับอินเทอร์เฟซ มิกซ์อิน
คลาสนามธรรม เจเนอริกแบบรีไฟด์ และการอนุมานชนิดข้อมูล
== การสร้างโปรเจกต์
== สถาปัตยกรรม
#i ตั้งแต่หัวข้อนี้เป็นต้นไป จะเป็นข้อมูลสำหรับการทำงานกับ Android Studio เป็นหลักเนื่องจากเป็นโปรแกรมหลักที่ถูกใช้งานในการพัฒนาแอพลิเคชันโครงงานนี
#i หากยังไม่ได้ติดตั้งปลั๊กอิน Flutter โปรดติดตั้งปลั๊กอินก่อน โดยหากอยู่ในหน้าต้อนรับ สามารถติดตั้งปลั๊กอินได้โดยการเข้าไปยังแท็บ *Plugins* หรือหากเปิดโปรเจกต์อื่นอยู่ สามารเข้าถึงหน้าปลั๊กอินได้โดยการกดที่ไอคอนฟันเฟืองในแถบเครื่องมือ แล้วกด *Plugins...* หลังจากนั้น ในแท็บ *Marketplace* ของหน้าปลั๊กอิน ค้นหา *Flutter* (ผู้ผลิตปลั๊กอินคือ Google) แล้วกด *Install*
#iii Flutter ถูกออกแบบมาให้เป็นระบบแบบเลเยอร์ที่ต่อขยายได
ประกอบด้วยไลบรารีอิสระหลายชุดที่แต่ละชุดพึ่งพาเลเยอร์ที่อยู่ด้านล่าง
ไม่มีเลเยอร์ใดที่มีสิทธิ์พิเศษในการเข้าถึงเลเยอร์ด้านล่าง
และทุกส่วนของเฟรมเวิร์กถูกออกแบบมาให้เป็นตัวเลือกและสามารถทดแทนได้
#afigure(
image("Flutter/homePage.png", width: 65%),
attr: "ส่วนหนึ่งของโครงงาน, ศตคุณ อุตมะ, ภายใต้ CC BY-SA 4.0",
alt: "หน้ายินดีต้อนรับในแท็บ Projects ที่กำลังแสดงรายการโปรเจกต์และปุ่มในการสร้างโปรเจกต์ใหม่",
caption: [หน้ายินดีต้อนรับใน Android Studio],
image("Flutter/archdiagram.png", width: 80%),
attr: [Flutter, ภายใต้ CC BY 4.0],
alt: "แผนผังสถาปัตยกรรม Flutter",
caption: [สถาปัตยกรรม Flutter],
)
#i เมื่อคลิก *New Flutter Project* จะมีหน้าถามสถานที่ติดตั้ง Flutter SDK หลังจากนั้น กด *Next* แล้วจะมีหน้าต่อไปนี้ขึ้นมาเพื่อให้คุณกรอกรายละเอียดโปรเจกต์
#iii สำหรับระบบปฏิบัติการที่อยู่ภายใต้ แอปพลิเคชัน Flutter
จะถูกบรรจุในลักษณะเดียวกับแอปพลิเคชันเนทีฟอื่น โดยตัวฝังตัว (Embedder)
เฉพาะแพลตฟอร์มจะทำหน้าที่เป็นจุดเริ่มต้น ประสานงานกับระบบปฏิบัติการที่อยู่ภายใต้เพื่อเข้าถึงบริการต่างๆ
เช่น พื้นผิวการแสดงผล การเข้าถึง และการป้อนข้อมูล และจัดการลูปเหตุการณ์ข้อความ
ตัวฝังตัวเขียนด้วยภาษาที่เหมาะสมกับแพลตฟอร์ม ปัจจุบันคือ Java และ C++ สำหรับ Android, Swift
และ Objective-C/Objective-C++ สำหรับ#jb iOS และ macOS และ C++ สำหรับ Windows และ
Linux การใช้ตัวฝังตัว โค้ด Flutter สามารถรวมเข้ากับแอปพลิเคชันที่มีอยู่แล้วในรูปแบบโมดูล
หรือโค้ดอาจเป็นเนื้อหาทั้งหมดของแอปพลิเคชันก็ได้ Flutter
มีตัวฝังตัวจำนวนมากสำหรับแพลตฟอร์มเป้าหมายทั่วไป แต่ก็ยังมีตัวฝังตัวอื่นๆ อีกด้วย
#afigure(
image("Flutter/newProjectPage.png", width: 80%),
attr: "ส่วนหนึ่งของโครงงาน, ศตคุณ อุตมะ, ภายใต้ CC BY-SA 4.0",
alt: "หน้ากรอกรายละเอียดโปรเจกต์ใหม่",
caption: [หน้าโปรเจกต์ใหม่],
)
#iii หัวใจหลักของ Flutter คือ Flutter engine ซึ่งส่วนใหญ่เขียนด้วยภาษา C++
และรองรับฟังก์ชันพื้นฐานที่จำเป็นต่อการทำงานของแอปพลิเคชัน Flutter ทั้งหมด
เอนจินนี้มีหน้าที่ในการแปลงฉากที่ประกอบขึ้นเป็นภาพแรสเตอร์ทุกครั้งที่จำเป็นต้องวาดเฟรมใหม่
มันมีหน้าที่ให้การใช้งานระดับต่ำของ API หลักของ Flutter รวมถึงการจัดวางข้อความกราฟิก
การรับส่งข้อมูลไฟล์และเครือข่าย รันไทม์ Dart และเครื่องมือคอมไพล์
รายละเอียดที่จำเป็นต้องกรอกในการสร้างโปรเจกต์ใหม่มีดังนี้:
- *Project name:* ชื่อโปรเจกต์
- *Project location:* โฟลเดอร์ที่ต้องการเก็บโปรเจกต์
- *Description:* รายละเอียดโปรเจกต์
- *Project type:* ประเภทโปรเจกต์ ในกรณีนี้เป็นค่า *Application* เนื่องจากเราต้องการสร้างแอพลิเคชัน
- *Organization:* โดเมนเนมย้อนหลังขององค์กรที่พัฒนา (Reverse domain name notation; Reverse-DNS)
- *Android language:* เลือกระหว่าง Java และ Kotlin เป็นภาษาหลักที่ใช้ในแอพลิเคชัน Android
- *Platforms:* แพลตฟอร์มที่โปรเจกต์จะรองรับ อย่างไรก็ตาม การสร้างไฟล์ไบนารีสำหรับแอพลิเคชันขึ้นอยู่กับแพลตฟอร์มที่พัฒนาแอพลิเคชันเช่นกัน หมายความว่า ถึงแม้ตามทฤษฎีแล้วแอพลิเคชันของคุณจะรองรับ iOS คุณต้องมีอุปกรณ์ Mac ในการสร้างไฟล์แอพลิเคชัน iOS ออกมา
เมื่อทำการใส่รายละเอียดทั้งหมดแล้ว สามารถกด Create เพื่อสร้างโปรเจกต์ได้เลย
== แอพลิเคชันตัวอย่าง
เมื่อกดรันแอพลิเคชันด้วยไอคอน #box(image("Flutter/vscode_play.svg", alt: "Play"), baseline: 15%) (หรือ Shift+F10 ใน Android Studio) จะได้แอพลิเคชันดังรูปด้านล่างออกมา
#afigure(
grid(
columns: 2,
align: horizon,
image(
"Flutter/mobileExampleApp.png",
height: 2.5in,
alt: "แอพลิเคชันมือถือ มีแถบสีม่วง ตัวเลขแสดงจำนวนครั้งที่กดปุ่มและปุ่มกดเพิ่มจำนวน",
),
image(
"Flutter/desktopExampleApp.png",
width: 90%,
alt: "โปรแกรมคอมพิวเตอร์ แถบหน้าต่างโปรแกรมสีดำ ในหน้าต่างประกอบด้วยส่วนประกอบคล้ายแอพลิเคชันบนโทรศัพท์",
),
),
attr: "ส่วนหนึ่งของโครงงาน, ศตคุณ อุตมะ, ภายใต้ CC BY-SA 4.0",
caption: [แอพลิเคชันตัวอย่างบน Android 15 และ Arch Linux],
)
#show raw.where(block: true): set block(below: 2em)
_*หมายเหตุ:* โคดในห้วข้อนี้ถูกนำ comment ออกเพื่อความรวบรัด_
ภายในโฟลเดอร์โปรเจกต์ใหม่ จะมีไฟล์ `lib/main.dart` พร้อมแอพลิเคชันตัวอย่าง
โดยในบรรทัดแรก จะมีการนำเข้า Material UI
```dart
import 'package:flutter/material.dart';
```
และถัดมา จะมีฟังก์ชันหลักชื่อ `main` ที่ทำหน้าที่ในการรันแอพลิเคชัน โดยมีการรับอาร์กิวเมนต์เป็นวิดเจ็ท ซึ่งในกรณีนี้เป็นการสร้างวัตถุจากคลาส `MyApp` ที่เป็นวิดเจ็ท
```dart
void main() {
runApp(const MyApp());
}
```
ถัดมาจะมีคลาส `MyApp` ที่สืบทอดมาจาก `StatelessWidget` ซึ่งคือคลาสสำหรับวิดเจ็ทที่ไร้สถานะ ("Stateless")
```dart
class MyApp extends StatelessWidget {
```
ซึ่งในคลาสจะมี constructor ที่สามารถรับค่าคีย์ได้:
```dart
const MyApp({super.key});
```
และจะมีฟังก์ชันในการสร้างวิดเจ็ท ซึ่งฟังก์ชันนี้เป็นการสืบทอดฟังก์ชันมา สังเกตได้จาก `@override`
```dart
@override
Widget build(BuildContext context) {
```
และในฟังก์ชันจะมีการสร้างวัตถุ MaterialApp ซึ่งมีหน้าที่ในการเก็บข้อมูลเกี่ยวกับแอพลิเคชัน Material UI รวมถึงข้อมูลเช่น ชื่อแอพลิเคชัน (`title`) และธีม (`theme`)
```dart
return MaterialApp(
title: 'Flutter Demo',
```
โดยข้อมูลธีมนั้นถูกเก็บด้วยการสร้างวัตถุ `ThemeData`
```dart
theme: ThemeData(
```
และมีการสร้างธีมสีจากสีหลักโดยการใช้เมธอด `ColorScheme.fromSeed` แต่ในโคดด้านล่างนี้
คลาส `ColorScheme` นั้นถูกอนุมานขึ้นมา โดยใน Dart 3.10 มีฟีเจอร์ "dot shorthands" ซึ่งเป็นทางลัดในการข้ามการเขียนชื่อคลาส ซึ่งชื่อคลาสสามารถถูกอนุมานขึ้นมาได้เนื่องจากอาร์กิวเมนต์ `colorScheme` นั้นคาดหวังค่าที่เป็นวัตถุจากคลาส `ColorScheme` อยู่แล้ว
```dart
colorScheme: .fromSeed(seedColor: Colors.deepPurple),
),
```
และต่อมา อาร์กิวเมนต์ `home` เป็นอาร์กิวเมนต์ที่รับค่าเป็นวิดเจ็ทซึ่งจะเป็นหน้าแรกของแอพลิเคชัน
```dart
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
```
ถัดมา มีการสร้างคลาส `MyHomePage` ที่ถูกใช้ด้านบน โดยคลาสเป็น `StatefulWidget` ซึ่งหมายความว่า เป็นคลาสที่มีสถานะ (State)
```dart
class MyHomePage extends StatefulWidget {
```
โดยใน constructor มีการรับค่าพารามีเตอร์ `title`
```dart
const MyHomePage({super.key, required this.title});
```
โดยคลาสนี้เป็นคลาสที่เก็บการตั้งค่าวิดเจ็ท และเป็นคลาสที่เก็บค่าพารามิเตอร์จากวิดเจ็ทที่เหนือกว่า และตัวแปรในคลาสย่อยของ `StatefulWidget` นั้นจะมีคีย์เวิร์ด `final` เสมอ ซึ่งหมายถึงว่า ตัวแปรนี้เปลี่ยนแปลงไม่ได้หลังจากสร้างวัตถุจากคลาสแล้ว
```dart
final String title;
```
ต่อมาจึงมีการสร้างวัตถุ State ซึ่งในฟังก์ชัน `createState` ที่ถูกสืบทอดมานั้น จะมีการสร้างวัตถุ State จากคลาส `_MyHomePageState` (โดยที่ `_` หมายถึงว่าคลาสนั้นเป็นส่วนตัวและไม่ควรถูกนำเข้าโดยไฟล์อื่น)
```dart
@override
State<MyHomePage> createState() => _MyHomePageState();
}
```
```dart
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
```
โดยในฟังก์ชัน `_incrementCounter` มีการเรียกใช้ฟังก์ชัน `setState` ซึ่งจะแจ้งเตือน Flutter ว่ามีการเปลี่ยนแปลงสถานะ ซึ่งจะก่อให้เกิดการเร็นเดอร์วิดเจ็ทใหม่ และในอาร์กิวเมนต์ของ `setState` คือฟังก์ชันไม่ระบุชื่อ (anonymous functions หรืออีกชื่อหนึ่งคือ lambda) ที่เปลี่ยนแปลงสถานะของวิดเจ็ท
```dart
setState(() {
_counter++;
});
}
```
โดยต่อมา มีฟังก์ชัน `build` เช่นเคยที่มีหน้าที่ในการสร้างวิดเจ็ท โดยฟังก์ชัน `build` ของวิดเจ็ทที่มีสถานะนั้นจะถูกรันใหม่ทุกครั้งที่มีการเปลี่ยนแปลงสถานะ
```dart
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
```
*การทดลอง:* ในระหว่างที่รันแอพลิเคชันอยู่ ลองเปลี่ยนสีพื้นหลังของวิดเจ็ท `AppBar` (เป็นค่าอื่นเช่น `Colors.amber`) แล้วทำการ hot reload โดยการกดไอคอน#box(image("Flutter/flutterHotReload.svg", alt: "สายฟ้า", width: 1.5em), baseline: 20%)เพื่อเห็นการเปลี่ยนแปลงของสีแถบแอพลิเคชันในระหว่างที่สีของวิดเจ็ทอื่น ยังคงเดิม
```dart
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
```
โดยในอาร์กิวเมนต์ `title` นี้มีการใช้ค่าที่รับมาจากวิดเจ็ทที่เหนือกว่า โดย `widget` ในที่นี้คือวัตถุของคลาส `MyHomePage` ที่ทำหน้าที่เก็บค่า `title` ของเรา แล้วเราจึงทำค่า `title` นั้นใส่ในวิดเจ็ทข้อความ (`Text`)
```dart
title: Text(widget.title),
),
```
`Center` เป็นวิดเจ็ทจัดเลย์เอาต์ โดยจะทำให้ลูก 1 วิดเจ็ทของมัน (`child`) อยู่ตรงกลาง
```dart
body: Center(
```
และ `Column` เป็นวิดเจ็ทจัดเลย์เอาต์เช่นกัน มันรับลูกหลายคน (`children`) แล้วจัดเรียงมันในแนวตั้ง โดยค่าเริ่มต้นแล้ว มันจะจัดให้ตัวเองกว้างเท่ากับลูก ของมัน และพยายามจัดให้ตัวเองสูงเท่าวิดเจ็ทที่สูงกว่า
วิดเจ็ทคอลัมน์มีหลายคุณสมบัติในการควบคุมขนาดของมันและการจัดวางลูก ของมัน โดยด้านล่างมีการใช้อาร์กิวเมนต์ `mainAxisAlignment` ในการจัดลูก ของมันให้อยู่ตรงกลางในแนวตั้ง โดย "main axis" หรือ แกนหลัก ในกรณีนี้คือแนวตั้ง เพราะคอลัมน์นั้นเป็นแนวตั้ง (และ "cross axis" หรือแกนไขว้ จะเป็นแนวนอน คือแนวตรงข้ามกับแนวหลัก)
```dart
child: Column(
mainAxisAlignment: .center,
children: [
const Text('You have pushed the button this many times:'),
Text(
'$_counter',
```
การเข้าถึงธีมของแอพลิเคชัน (```dart Theme.of(context)```) แล้วนำธีมข้อความ `headlineMedium` มาใช้:
```dart
style: Theme.of(context).textTheme.headlineMedium,
), // Text
],
), // Column
), // Center
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: const Icon(Icons.add),
),
);
}
}
```
#iii เอนจินนี้ถูกเปิดเผยสู่เฟรมเวิร์ก Flutter ผ่านทาง dart:ui ซึ่งห่อหุ้มโค้ด C++
ที่อยู่เบื้องหลังด้วยคลาส Dart ไลบรารีนี้เปิดเผยส่วนประกอบพื้นฐานระดับต่ำสุด เช่น
คลาสสำหรับควบคุมระบบย่อยการรับข้อมูล กราฟิก และการแสดงผลข้อความ
#pagebreak()
== โครงสร้างโปรเจกต์ Flutter <flStructure>
#iii โดยทั่วไป นักพัฒนาจะโต้ตอบกับ Flutter ผ่านเฟรมเวิร์ก Flutter
ซึ่งเป็นเฟรมเวิร์กที่ทันสมัยและตอบสนองต่อสิ่งรอบข้าง เขียนด้วยภาษา Dart
เฟรมเวิร์กนี้ประกอบด้วยชุดไลบรารี แพลตฟอร์ม#jb เลย์เอาต์ และพื้นฐานที่ครบครัน
ซึ่งประกอบด้วยเลเยอร์หลายชั้น เริ่มจากล่างขึ้นบน ได้แก่
ในโครงงานนี้ โปรเจกต์ Flutter มีโครงสร้างคร่าว ดังกล่าว
#[
#set enum(indent: 5.5em)
+ คลาสพื้นฐานและบริการส่วนประกอบต่างๆ เช่น แอนิเมชัน การวาดภาพ และท่าทางสัมผัส
ซึ่งนำเสนอนามธรรมที่ใช้กันทั่วไปเหนือพื้นฐานที่อยู่เบื้องหลัง
#tree-list[
- android
- app
- src
- main
- java: โคด Java
- kotlin: โคด Kotlin
- res: โฟลเอร์ทรัพยากร เช่น ไอคอนแอพลิเคชัน
- AndroidManifest.xml
- build.gradle.kts
- settings.gradle.kts
- assets
- certificates
- rootCA.crt: ใบรับรอง Root (ดู@x509 สำหรับรายละเอียด)
- build: โฟลเดอร์สำหรับเก็บไฟล์ไบนารี
- ios
- lib: ซอร์สโคดของแอพลิเคชัน
- linux
- macos
- test
- windows
- l10n.yaml: ไฟล์ตั้งค่าฟีเจอร์แปลภาษา
- pubspec.yaml: ไฟล์ข้อมูลโปรเจกต์ Flutter
+ เลเยอร์การเรนเดอร์ให้นามธรรมสำหรับการจัดการเลย์เอาต์ ด้วยเลเยอร์นี้
คุณสามารถสร้างโครงสร้างแบบต้นไม้ของวัตถุที่เรนเดอร์ได้ คุณสามารถจัดการวัตถุเหล่านี้แบบไดนามิก
โดยโครงสร้างแบบต้นไม้จะอัปเดตเลย์เอาต์โดยอัตโนมัติเพื่อสะท้อนการเปลี่ยนแปลงของคุณ
+ เลเยอร์วิดเจ็ตเป็นนามธรรมของการประกอบ
วัตถุเรนเดอร์แต่ละชิ้นในเลเยอร์การเรนเดอร์จะมีคลาสที่สอดคล้องกันในเลเยอร์วิดเจ็ต นอกจากนี้
เลเยอร์วิดเจ็ตยังช่วยให้คุณกำหนดการรวมกันของคลาสที่คุณสามารถนำกลับมาใช้ใหม่ได้
นี่คือเลเอร์ที่แนะนำโมเดลการเขียนโปรแกรมแบบตอบสนอง
+ ไลบรารี Material และ Cupertino
นำเสนอชุดควบคุมที่ครอบคลุมซึ่งใช้ส่วนประกอบพื้นฐานของเลเยอร์วิดเจ็ตเพื่อนำภาษาการออกแบบ
Material หรือ iOS ไปใช้
]
(รายการข้างต้นรวมถึงแค่ไฟล์ที่สำคัญที่จะถูกกล่าวถึงใน@flutter นี้)
#iii เฟรมเวิร์ก Flutter มีขนาดค่อนข้างเล็ก
ฟีเจอร์ระดับสูงหลายอย่างที่นักพัฒนาอาจใช้ถูกพัฒนาขึ้นมาในรูปแบบของแพ็กเกจ
รวมถึงปลั๊กอินของแต่ละแพลตฟอร์ม เช่น กล้องและเว็บวิว ตลอดจนฟีเจอร์ที่ไม่ขึ้นกับแพลตฟอร์ม เช่น
ตัวอักษร, HTTP และแอนิเมชัน ซึ่งสร้างขึ้นจากไลบรารีหลักของ Dart และ Flutter
แพ็กเกจบางส่วนมาจากระบบนิเวศที่กว้างกว่า ครอบคลุมบริการต่างๆ เช่น การชำระเงินภายในแอป
การตรวจสอบสิทธิ์ของ Apple และแอนิเมชัน
== การนำเข้าแพคเกจ
== โครงสร้างของแอปพลิเคชัน
#i ไฟล์ `pubspec.yaml` เป็นไฟล์ที่เก็บข้อมูลเกี่ยวกับโปรเจกต์ Flutter ของคุณ เช่น ชื่อ คำอธิบาย เวอร์ชัน และรวมถึงสิ่งที่จะกล่าวถึงในหัวข้อนี้ คือการติดตั้งและนำเข้าแพคเกจภายนอกมาใช้ในโปรเจกต์
#iii แผนภาพต่อไปนี้แสดงภาพรวมของส่วนประกอบต่างๆ ที่ประกอบกันเป็นแอป Flutter
ทั่วไปที่สร้างขึ้นโดยคำสั่ง `flutter create` แผนภาพนี้แสดงตำแหน่งของ Flutter Engine
ในโครงสร้างนี้ เน้นขอบเขตของ API และระบุที่เก็บโค้ด (repository) ที่ส่วนประกอบแต่ละส่วนอยู่
คำอธิบายด้านล่างจะอธิบายคำศัพท์บางคำที่ใช้กันทั่วไปในการอธิบายส่วนประกอบของแอป Flutter
#i โดยหากไม่รวมรายละเอียดโปรเจกต์เบื้องต้นเช่นชื่อและคำอธิบายแล้ว ไฟล์ `pubspec.yaml` จะมีรายละเอียดดังนี้
#afigure(
image("Flutter/app-anatomy.svg", width: 2.5in),
attr: [Flutter, ภายใต้ CC BY 4.0],
alt: "เลเยอร์ต่าง ๆ ของแอพลิเคชัน Flutter ที่ถูกสร้างโดย flutter create",
caption: [เลเยอร์ต่าง ของแอพลิเคชัน Flutter],
)
`environment` นั้นจะกล่าวถึงสิ่งแวดล้อม ซึ่งในกรณีนี้มีเพียง `sdk` ที่ระบุเวอร์ชันของ Flutter SDK ในการคอมไพล์โปรเจกต์
#[
#set enum(indent: 9.25em)
=== แอปพลิเคชัน Dart (Dart app)
+ ประกอบวิดเจ็ตเข้าด้วยกันเพื่อสร้าง UI ที่ต้องการ
+ ดำเนินการตามตรรกะทางธุรกิจ
+ นักพัฒนาแอปเป็นเจ้าของ
```yaml
environment:
sdk: ^3.10.1
```
=== เฟรมเวิร์ก (Framework)
+ ให้ API ระดับสูงสำหรับการสร้างแอปคุณภาพสูง (ตัวอย่างเช่น วิดเจ็ต การทดสอบการกด
การตรวจจับท่าทาง การเข้าถึงได้ และการอินพุต ข้อความ)
+ ประกอบต้นวิดเจ็ตของแอปพลิเคชันเป็นฉาก
`dependencies` จะกล่าวถึงไลบรารีที่โปรเจกต์พึ่งพา ซึ่งโดยค่าเริ่มต้นแล้ว ในโปรเจกต์ตัวอย่างจะมีการติดตั้งเซ็ทไอคอน Cupertino มาให้ (`cupertino_icons`; หรือเรียกอย่างง่ายว่า ไอคอน iOS) ซึ่งแน่นอนว่าหากคุณไม่ใช้ สามารถลบทิ้งได้
=== เอนจิน (Engine)
+ มีหน้าที่แปลงฉากเป็นรูปแบบแรสเตอร์
+ ให้การทำงานระดับต่ำของแกนกลางของ Flutter API (เช่น กราฟิก การจัดข้อความ และรันไทม์
Dart)
+ เปิดเผยฟังก์ชันระดับนี้ให้แก่เฟรมเวิร์กผ่าน API `dart:ui`
+ บูรณาการกับแพลตฟอร์มต่าง ด้วย API ตัวฝังตัว
```yaml
dependencies:
flutter:
sdk: flutter
=== ตัวฝังตัว (Embedder)
+ ประสานงานกับระบบปฏิบัติการภายใต้สำหรับการเข้าถึงบริการต่าง เช่น พื้นผิวการเรนเดอร์
การเข้าถึง และการป้อนข้อมูล
+ จัดการลูปอิเวนต์
+ เปิดเผย API เฉพาะแพลตฟอร์มเพื่อบูรณาการตัวฝังตัวเข้าไปยังแอป
cupertino_icons: ^1.0.8
```
`dev_dependencies` กล่าวถึงไลบรารีที่โปรเจกต์พึ่งพา#emph([ในการพัฒนา]) หมายความว่า ไลบรารีเหล่านี้จะไม่ถูกใส่เข้าไปยังแอพลิเคชันของคุณโดยตรง โดยตามค่าเริ่มต้นแล้ว จะมีแพคเกจ `flutter_test` ที่ถูกดึงมาจาก Flutter SDK โดยตรง และมี `flutter_lints` สำหรับการตรวจข้อผิดพลาดในโคด
```yaml
dev_dependencies:
flutter_test:
sdk: flutter
flutter_lints: ^6.0.0
```
`flutter` เป็นการตั้งค่าเกี่ยวกับ Flutter โดยที่ตามค่าเริ่มต้นแล้วจะมีค่า `uses-material-design` มาให้เป็น `true` ซึ่งจะเป็นการบอกกับ Flutter ว่าแอพลิเคชันนั้นใช้ Material design
```yaml
flutter:
uses-material-design: true
```
และนอกจากนั้นแล้ว ในส่วนของ `flutter` นี้จะเป็นส่วนที่ลิสต์รายการไฟล์เพิ่มเติมที่ต้องการใส่เข้าไปในแอพลิเคชันด้วยเช่นกัน ตัวอย่างเช่น โครงงานนี้มีการเพิ่มเติมในส่วน `flutter` ดังนี้:
```yaml
assets:
- assets/certificates/rootCA.crt
```
โดยจะเป็นการเพิ่มไฟล์ใบรับรอง `rootCA.crt` เข้าไปกับแอพลิเคชันเพื่อใช้ในการส่งคำขอ HTTPS ไปยังอุปกรณ์ของโครงงาน
#pagebreak()
=== ตัวรัน (Runner)
+ ประกอบชิ้นส่วนที่ถูกเปิดเผยโดยตัวฝังตัวเข้าเป็นแพคเกจแอปพลิเคชันที่สามารถใช้งานได้บนแพลตฟอร์มเป้าหมาย
+ บางส่วนถูกสร้างขึ้นโดย `flutter create` และมีเจ้าของเป็นผู้พัฒนาแอป
]
== ระบบการดีไซน์
โดยใน Flutter แล้วนั้น ไม่รวมแพคเกจบุคคลที่สาม จะมีระบบการดีไซน์อยู่สองแบบคือ:
#iii โดยใน Flutter แล้วนั้น ไม่รวมแพคเกจบุคคลที่สาม จะมีระบบการดีไซน์อยู่สองแบบคือ:
+ Material Design: การดีไซน์ของ Google สำหรับ Android
+ Cupertino Design: การดีไซน์ของ Apple สำหรับ iOS
#[
#set enum(indent: 5.5em)
+ Material Design คือการดีไซน์ของ Google สำหรับ Android
+ Cupertino Design คือการดีไซน์ของ Apple สำหรับ iOS
]
*หมายเหตุ:* Cupertino Design ถูกแทนที่โดย Liquid Glass แล้ว โดยในปัจจุบันทีม Flutter กำลังทำการตรวจสอบและแก้ไขโครงสร้างระบบดีไซน์ ดังนั้น หากมีผู้พัฒนาต้องการใช้เอฟเฟกต์ Liquid Glass ในแอพลิเคชัน Flutter จึงจำเป็นต้องพึงพาแพคเกจบุคคลที่สามก่อนในขณะนี้ (Flutter เวอร์ชัน 3.38.3 เวลาที่พิมพ์)
#iii อย่างไรก็ตาม Cupertino Design ถูกแทนที่โดย Liquid Glass แล้ว โดยในปัจจุบันทีม Flutter
กำลังทำการตรวจสอบและแก้ไขโครงสร้างระบบดีไซน์ ดังนั้น หากมีผู้พัฒนาต้องการใช้เอฟเฟกต์#jb Liquid
Glass ในแอปพลิเคชัน Flutter จึงจำเป็นต้องพึงพาแพคเกจบุคคลที่สามก่อนในขณะนี้ (Flutter เวอร์ชัน
3.38.5 เวลาที่พิมพ์)
#i แอพลิเคชันในโครงงานนี้ใช้ Material Design เนื่องจากมีเป้าหมายหลักเป็นแพลตฟอร์ม Android โดย Material Design คือภาษาการดีไซน์ที่ถูกพัฒนาโดย Google และถูกเปิดตัวครั้งแรก 25 มิถุนายน 2014 และมีเวอร์ชันหลัก 3 เวอร์ชันด้วยกัน โดยที่เวอร์ชันที่ 3 ถูกเปิดตัวในงาน Google I/O 2021 และมีชื่อว่า "Material You" (แต่ชื่อธรรมดา "Material Design 3" ก็ยังถูกใช้งานกันอย่างปกติ) และในงาน Google I/O 2025 มีการเปิดตัว "Material 3 Expressive" ซึ่งเป็นการปรับปรุงต่อจาก Material You เดิมสำหรับ Android 16 และ Wear OS 6 และสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับ Material 3 ได้ที่ https://m3.material.io/
#iii Material Design คือภาษาการดีไซน์ที่ถูกพัฒนาโดย Google และถูกเปิดตัวครั้งแรก 25 มิถุนายน
2014 และมีเวอร์ชันหลัก 3 เวอร์ชันด้วยกัน โดยที่เวอร์ชันที่ 3 ถูกเปิดตัวในงาน Google I/O 2021
และมีชื่อว่า "Material You" (แต่ชื่อธรรมดา "Material Design 3" ก็ยังถูกใช้งานกันอย่างปกติ)#jb
และในงาน Google I/O 2025 มีการเปิดตัว "Material 3 Expressive"
ซึ่งเป็นการปรับปรุงต่อจาก#jb Material You เดิมสำหรับ Android 16 และ Wear OS 6
และสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับ Material 3 ได้ที่ https://m3.material.io/
== ข้อมูลเกี่ยวกับแพลตฟอร์ม
== ส่วนติดต่อผู้ใช้ที่มีปฏิกิริยา
=== Android <flAndroid>
#iii บนพื้นผิว Flutter เป็นเฟรมเวิร์ก UI แบบ reactive และ declarative
ซึ่งนักพัฒนาเป็นผู้จัดเตรียมการแมปจากสถานะแอปพลิเคชันไปยังสถานะอินเทอร์เฟซ
และเฟรมเวิร์กจะทำหน้าที่อัปเดตอินเทอร์เฟซขณะรันไทม์เมื่อสถานะของแอปพลิเคชันเปลี่ยนแปลง
โมเดลนี้ได้รับแรงบันดาลใจจากงานที่มาจาก Facebook สำหรับเฟรมเวิร์ก React ของพวกเขา
ซึ่งรวมถึงการทบทวนหลักการออกแบบแบบดั้งเดิมหลายประการ
#i ในการพัฒนาแอพลิเคชัน Android โดยใช้เฟรมเวิร์ก Flutter จำเป็นต้องใช้ส่วนประกอบเครื่องมือพัฒนา Android ดังนี้
#iii ในเฟรมเวิร์ก UI แบบดั้งเดิมส่วนใหญ่ สถานะเริ่มต้นของอินเทอร์เฟซผู้ใช้จะถูกอธิบายเพียงครั้งเดียว
จากนั้นจึงอัปเดตแยกกันด้วยโคดผู้ใช้ รันไทม์ เพื่อตอบสนองต่อเหตุการณ์
ความท้าทายประการหนึ่งของแนวทางนี้คือ เมื่อแอปพลิเคชันมีความซับซ้อนมากขึ้น
นักพัฒนาจำเป็นต้องทราบว่าสถานะเปลี่ยนแปลงไปอย่างไรตลอดทั้ง UI ตัวอย่างเช่น พิจารณา UI ต่อไปนี้:
- Android SDK (API Level 36 เวลาที่พิมพ์)
- Android SDK Build-Tools
- Android SDK Command-line Tools
- Android SDK Platform-Tools
- Android Emulator (ไม่บังคับ)
และแนะนำให้จัดการและติดตั้งเครื่องมือเหล่านี้ผ่าน Android Studio
#i ในการติดตั้ง Android SDK ควรติดตั้ง Android SDK ล่าสุดถึงแม้ว่าอุปกรณ์ของคุณจะใช้เวอร์ชันที่เก่ากว่านั้น เพื่อความมั่นใจว่าแอพลิเคชันจะสามารถใช้กับอุปกรณ์ที่ใหม่ล่าสุดได้
#i แอพลิเคชัน Android จะมี SDK/API level เป้าหมาย (Target SDK/API level) และ SDK/API level ขั้นต่ำ (Minimum SDK/API level) โครงงานนี้ เวลาที่พิมพ์ ใช้ API level เป้าหมาย 36 (Android 16) และ API level ขั้นต่ำ 24 (Android 7) ซึ่งรวมกันแล้ว แอพลิเคชัน Android จะสามารถติดตั้งได้บนระบบตั้งแต่ API level ขั้นต่ำจนถึง API level เป้าหมาย หรือก็คือ แอพลิเคชันในโครงงานนี้สามารถติดตั้งได้ตั้งแต่บนระบบ Android 7 ถึง Android 16 นั่นเอง
==== Java/Kotlin
#i Java และ Kotlin เป็นภาษาสำคัญสำหรับการพัฒนาแอพลิเคชัน Android ถึงอย่างไรก็ตาม แอพลิเคชัน Flutter นั้นถูกเขียนด้วยภาษา Dart แต่ยังจำเป็นต้องมีโคด Java และ Kotlin เล็กน้อยเพื่อเริ่มต้นแอพลิเคชัน Flutter
#i โดยปกติแล้ว Flutter จะสร้างโคดพื้นฐานขึ้นมาให้สำหรับการเริ่มแอพลิเคชันแบบพื้นฐาน (อยู่ภายในโฟลเดอร์ `java` และ `kotlin` ตามที่ถูกกล่าวถึงใน@flStructure) ดังนั้นจึงไม่จำเป็นต้องมีการเขียนโคด Java หรือ Kotlin เอง แต่ในบางกรณี อาจต้องเขียนโคดเพิ่มเองหากมีความต้องการเข้าถึงฟีเจอร์พื้นฐานระบบที่ Flutter ไม่มี API เพื่อให้เข้าถึงได้และไม่มีแพคเกจเพื่อรองรับฟีเจอร์ที่ต้องการ
#i โครงการนี้ใช้ Java 21 (JetBrains Runtime/Azul Zulu OpenJDK) เป็นหลักในการทำงานกับ Gradle แต่แอพลิเคชัน Android ที่ผลิตออกมานั้น เพื่อให้เข้ากับเวอร์ชันที่เก่ากว่าของระบบปฏิบัติการได้ ใช้ Java 11
==== Gradle
#i Gradle เป็นเครื่องมือสร้างระบบอัตโนมัติสำหรับการพัฒนาซอฟต์แวร์หลายภาษา จัดการงานต่าง เช่น การคอมไพล์ การแพ็คเกจ การทดสอบ การปรับใช้ และการเผยแพร่ ภาษาที่รองรับ ได้แก่ Java (รวมถึงภาษา Kotlin, Groovy, Scala ที่ใช้ JDK), C/C++ และ JavaScript Gradle พัฒนาต่อยอดจากแนวคิดของ Apache Ant และ Apache Maven และนำเสนอภาษาเฉพาะโดเมนที่ใช้ Groovy และ Kotlin ซึ่งต่างจากการกำหนดค่าโครงการที่ใช้ XML ที่ Maven ใช้ Gradle ใช้กราฟแบบอะไซคลิกกำกับทิศทางเพื่อจัดการการอ้างอิง กราฟนี้ใช้เพื่อกำหนดลำดับของงานที่ควรดำเนินการ Gradle ทำงานบน Java Virtual Machine
#i Gradle คือเครื่องมือหลักที่ใช้ในการจัดการโปรเจกต์ Java ส่วนใหญ่ รวมถึงโปรเจกต์ Android โดยในโครงการนี้ จะใช้ Gradle เวอร์ชัน 8.14.3 เป็นหลัก
#i โดยปกติแล้ว ผู้พัฒนานั้นไม่มีความจำเป็นที่จะต้องแตะต้อง Gradle ด้วยตนเอง และ Flutter จะทำการจัดการเอง แต่หากมีความจำเป็นต้องใช้คำสั่ง Gradle ด้วยตนเอง จะมีสคริปต์ `gradlew` (หรือ `gradlew.bat` สำหรับผู้ใช้ Windows) ภายในโฟลเดอร์ `android` ของโปรเจกต์ Flutter เสมอเพื่อเรียกใช้ Gradle ที่ถูกดาวน์โหลดมาสำหรับโปรเจกต์นั้น
=== Linux <flLinuxDetails>
#i เช่นเดียวกับ Android ที่กล่าวไปข้างต้น Flutter มีการสร้างโคดสำหรับการเปิดแอพลิเคชันแบบพื้นฐาน แต่สำหรับ Linux แล้วนั้น Flutter ใช้โคด C++ และเฟรมเวิร์ก CMake ในการสร้างรากฐานของแอพลิเคชัน
#i ในการพัฒนาแอพลิเคชันสำหรับ Linux ต้องติดตั้งโปรแกรมเพิ่มเติม (build dependencies) ขยายความคือ ด้านบนคือสิ่งที่จำเป็นหากมีระบบอื่นเป็นเป้าหมาย แต่หากต้องการพัฒนาแอพลิเคชัน Linux ต้องติดตั้งโปรแกรมในรายการด้านล่างเพิ่ม
#grid(
columns: 2,
column-gutter: 1in,
[
- GTK 3 (ไลบรารีสำหรับการพัฒนา)
- pkg-config
- ไลบรารี GNU Standard C++ v3
],
[
- Clang
- CMake
- Ninja
],
#afigure(
image("Flutter/color-picker.png", width: 70%),
alt: "หน้าต่างเลือกสี",
caption: [หน้าต่างเลือกสี],
)
#i การติดตั้งไลบรารีและโปรแกรมที่กล่าวไปข้างต้นจะแตกต่างกันไปแต่ละการแจกจ่าย Linux และ Flutter ใช้ไลบรารีพื้นฐานดังกล่าวในการทำงานของแอพลิเคชัน (runtime dependencies)
#iii มีหลายที่ที่สามารถเปลี่ยนสถานะได้: กล่องสี, แถบเลื่อนเฉดสี, ​ปุ่มตัวเลือก เมื่อผู้ใช้โต้ตอบกับ UI
การเปลี่ยนแปลงจะต้องสะท้อนให้เห็นในทุกที่ ที่เลวร้ายยิ่งกว่านั้น เว้นแต่จะได้รับการดูแล
การเปลี่ยนแปลงเล็กน้อยในส่วนใดส่วนหนึ่งของอินเทอร์เฟซผู้ใช้อาจทำให้เกิดเอฟเฟกต์คลื่นส่งผลกระทบกับโค้ดที่ดูเหมือนจะไม่เกี่ยวข้องกัน
- GTK 3
- blkid
- LZMA
#iii วิธีแก้ปัญหาอย่างหนึ่งคือแนวทางเช่น MVC
โดยที่คุณส่งข้อมูลการเปลี่ยนแปลงไปยังโมเดลผ่านคอนโทรลเลอร์
จากนั้นโมเดลจะพุชสถานะใหม่ไปยังมุมมองผ่านคอนโทรลเลอร์ อย่างไรก็ตาม#jb สิ่งนี้ก็เป็นปัญหาเช่นกัน
เนื่องจากการสร้างและการอัปเดตองค์ประกอบ UI
เป็นขั้นตอนสองขั้นตอนที่แยกจากกันซึ่งอาจไม่ซิงค์กันได้อย่างง่ายดาย
แต่โดยทั่วไปแล้ว ไลบรารีเหล่านี้ควรถูกติดตั้งมาอยู่แล้วหากคุณใช้ graphical desktop ทั่วไป
#iii Flutter พร้อมด้วยเฟรมเวิร์กเชิงโต้ตอบอื่น ใช้แนวทางอื่นในการแก้ไขปัญหานี้
โดยแยกอินเทอร์เฟซผู้ใช้ออกจากสถานะพื้นฐานอย่างชัดเจน ด้วย API สไตล์ React
คุณจะสร้างเฉพาะคำอธิบาย UI เท่านั้น
และเฟรมเวิร์กจะดูแลการใช้การกำหนดค่านั้นเพื่อสร้างหรืออัปเดตอินเทอร์เฟซผู้ใช้ตามความเหมาะสม
==== Debian
#iii ใน Flutter วิดเจ็ต (คล้ายกับส่วนประกอบใน React)
จะแสดงด้วยคลาสที่ไม่เปลี่ยนรูปซึ่งใช้ในการกำหนดค่าแผนผังของวัตถุ
วิดเจ็ตเหล่านี้ถูกใช้เพื่อจัดการแผนผังวัตถุที่แยกจากกันสำหรับโครงร่าง
ซึ่งจากนั้นจะใช้ในการจัดการแผนผังวัตถุที่แยกจากกันสำหรับการประกอบ หัวใจหลักของ Flutter
คือชุดของกลไกในการอัพเดทส่วนที่ดัดแปลงของแผนผังวิดเจ็ตอย่างมีประสิทธิภาพ
การแปลงแผนผังหลายแผนผังของวัตถุให้เป็นแผนผังระดับล่างของวัตถุ
และการแพร่กระจายการเปลี่ยนแปลงไปยังแผนผังวิดเจ็ตเหล่านี้
```sh
# Development dependencies:
sudo apt install curl git unzip xz-utils zip libglu1-mesa
#pagebreak()
# Linux build dependencies:
sudo apt install clang cmake ninja-build pkg-config libgtk-3-dev libstdc++-12-dev
#iii วิดเจ็ตประกาศส่วนติดต่อผู้ใช้โดยการเขียนทับเมธอด `build()` ซึ่งเป็นฟังก์ชันที่แปลงสถานะเป็น
UI:
# Runtime dependencies:
sudo apt install libgtk-3-0 libblkid1 liblzma5
```
#afigure(
```
UI = f(state)
```,
kind: image,
caption: [สูตรแสดงการทำงานอย่างคร่าว],
)
==== Fedora Linux
#iii เมธอด `build()` นั้นตามการออกแบบแล้วเป็นเมธอดที่เร็วและควรที่จะไม่มีผลข้างเคียง
ทำให้เมธอดนั้นสามารถถูกเรียกใช้โดยเฟรมเวิร์กเมื่อไหร่ก็ได้ที่จำเป็น
(เป็นไปได้ที่จะบ่อยมากและมีการเรียกใช้หนึ่งครั้งต่อหนึ่งเฟรม)
```sh
# Development dependencies:
sudo dnf install curl git unzip xz zip mesa-libglu
#iii วิธีนี้พึ่งพาลักษณะเฉพาะรันไทม์ภาษา (หากเจาะจงคือการสร้างและทำลายวัตถุอย่างรวดเร็ว) ซึ่ง
Dart นั้นเหมาะสำหรับงานนี้เป็นพิเศษ
# Linux build dependencies:
sudo dnf install clang cmake ninja-build pkgconf gtk3
== ประวัติ
# Runtime dependencies:
sudo dnf install gtk3 libblkid xz
```
#iii Flutter เวอร์ชันแรกรู้จักกันในชื่อ "Sky" และทำงานบนระบบปฏิบัติการ Android
มีการเปิดเผยในการประชุมสุดยอดนักพัฒนา Dart ประจำปี 2015
โดยมีจุดประสงค์ที่ระบุไว้คือสามารถแสดงผลได้อย่างสม่ำเสมอที่ 120 เฟรมต่อวินาที เมื่อวันที่ 4 ธันวาคม
2018 Flutter 1.0 เปิดตัวในการประชุม Flutter ที่ลอนดอน
==== Arch Linux
#iii ในวันที่ 6 พฤษภาคม 2020 ชุดพัฒนาซอฟต์แวร์ (SDK) Dart เวอร์ชัน 2.8 และ Flutter 1.17.0
ได้รับการเผยแพร่ โดยเพิ่มการรองรับ Metal API
```sh
# Development dependencies:
sudo pacman -S --needed curl git unzip xz zip glu
#iii เมื่อวันที่ 3 มีนาคม 2021 Google ได้เปิดตัว Flutter 2 ระหว่างกิจกรรม Flutter Engage
ออนไลน์ ได้เพิ่มตัวเรนเดอร์ที่ใช้ Canvas สำหรับเว็บ นอกเหนือจากตัวเรนเดอร์ที่ใช้ HTML
และการสนับสนุนแอปพลิเคชันเดสก์ท็อปแบบทดลองสำหรับ Windows, macOS, และ Linux
นอกจากนี้ยังมาพร้อมกับ Dart 2.0 ซึ่งรวมถึงการสนับสนุนด้านความปลอดภัยแบบ null (null-safety)
ความปลอดภัยแบบ null เป็นทางเลือกในตอนแรกเนื่องจากเป็นการเปลี่ยนแปลงครั้งใหญ่และบังคับใช้ใน
Dart 3 ที่เปิดตัวในปี 2023
# Linux build dependencies:
sudo pacman -S --needed clang cmake ninja pkgconf gtk3
#iii ในวันที่ 12 พฤษภาคม 2022 Flutter 3 และ Dart 2.17
ได้รับการเผยแพร่โดยมีการรองรับแพลตฟอร์มเดสก์ท็อปทั้งหมดอย่างเสถียร
# Runtime dependencies:
sudo pacman -S --needed util-linux-libs xz gtk3
```
#iii เมื่อวันที่ 27 ตุลาคม 2024 นักพัฒนาชุมชน Flutter จำนวนหนึ่งได้ประกาศเปิดตัว Flock
ซึ่งเป็นเวอร์ชันแยกของ Flutter ที่มีจุดประสงค์เพื่อให้ง่ายต่อการร่วมพัฒนา
ในขณะเดียวกันก็ยังคงรักษาความสอดคล้องกับทุกการเปลี่ยนแปลงที่เกิดขึ้นในโค้ดต้นทาง
=== macOS/iOS
#i การพัฒนาแอพลิเคชันสำหรับ macOS และ iOS นั้นต้องทำบน macOS เท่านั้นและจำเป็นต้องพึ่งพาเครื่องมือ Xcode แต่เนื่องจากในโครงงานนี้ไม่มีผู้ใช้ macOS จึงไม่สามารถสร้างไบนารีสำหรับ macOS และ iOS ออกมาได้ และไม่ใช่เป้าหมายของโครงงานนี้เช่นกัน
#iii ในปี 2025 Google ยังคงพัฒนา Flutter ต่อไปด้วยสถาปัตยกรรมแบบโมดูลาร์ที่ได้รับการปรับปรุง
การรองรับอุปกรณ์พับได้ และการเพิ่มประสิทธิภาพ ARM IoT ตามที่ระบุไว้ในแผนงานฉบับปรับปรุง
File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

+8 -8
View File
@@ -2,14 +2,14 @@
= Git
#i Git เป็นระบบซอฟต์แวร์ควบคุมเวอร์ชันแบบกระจาย ที่สามารถจัดการเวอร์ชันของซอร์สโคดหรือข้อมูลได้ มักใช้เพื่อควบคุมซอร์สโคดโดยโปรแกรมเมอร์ที่พัฒนาซอฟต์แวร์ร่วมกัน
#i Git เป็นระบบซอฟต์แวร์ควบคุมเวอร์ชันแบบกระจาย ที่สามารถจัดการเวอร์ชันของซอร์สโคดหรือข้อมูลได้
มักใช้เพื่อควบคุมซอร์สโคดโดยโปรแกรมเมอร์ที่พัฒนาซอฟต์แวร์ร่วมกัน
== Gitea
#i Gitea เป็นชุดซอฟต์แวร์ forge สำหรับการโฮสต์ระบบควบคุมเวอร์ชันการพัฒนาซอฟต์แวร์โดยใช้ Git รวมถึงฟีเจอร์การทำงานร่วมกันอื่น เช่น การติดตามบั๊ก การตรวจสอบโคด การผสานรวมอย่างต่อเนื่อง (Continuous Integration; CI) กระดาน Kanban ระบบรายงานปัญหา และวิกิ รองรับการโฮสต์ด้วยตนเอง และยังมีอินสแตนซ์สาธารณะของบุคคลที่หนึ่งให้ใช้งานฟรีอีกด้วย Gitea เป็นส่วนหนึ่งของ Gogs และเขียนด้วยภาษา Go Gitea สามารถโฮสต์ได้บนทุกแพลตฟอร์มที่รองรับ Go รวมถึง FreeBSD, Linux, macOS และ Windows โครงการนี้ได้รับทุนสนับสนุนจาก Open Collective
#i โครงงานนี้ใช้ Gitea (self-hosted) ในการโฮสต์โคดของโครงงาน โดยมี repository หลัก ดังนี้
- https://gitskette.dailitation.xyz/linesofcodes/liteauth-firmware32 - เฟิร์มแวร์ ESP32
- https://gitskette.dailitation.xyz/linesofcodes/liteauthconfig - แอพลิเคชัน Flutter ตั้งค่าอุปกรณ์
- https://gitskette.dailitation.xyz/linesofcodes/liteauthdocs - เอกสารโครงงานเล่มนี้
#iii Gitea เป็นชุดซอฟต์แวร์ forge สำหรับการโฮสต์ระบบควบคุมเวอร์ชันการพัฒนาซอฟต์แวร์โดยใช้ Git
รวมถึงฟีเจอร์การทำงานร่วมกันอื่น เช่น การติดตามบั๊ก การตรวจสอบโคด การผสานรวมอย่างต่อเนื่อง
(Continuous Integration; CI) กระดาน Kanban ระบบรายงานปัญหา และวิกิ
รองรับการโฮสต์ด้วยตนเอง และยังมีอินสแตนซ์สาธารณะของบุคคลที่หนึ่งให้ใช้งานฟรีอีกด้วย Gitea
เป็นส่วนหนึ่งของ Gogs และเขียนด้วยภาษา Go Gitea สามารถโฮสต์ได้บนทุกแพลตฟอร์มที่รองรับ Go
รวมถึง FreeBSD, Linux, macOS และ Windows โครงการนี้ได้รับทุนสนับสนุนจาก Open Collective
+190 -35
View File
@@ -2,87 +2,242 @@
= เกณฑ์วิธีขนส่งข้อความหลายมิติแบบมั่นคง (Hypertext Transfer Protocol Secure; HTTPS)
#i เกณฑ์วิธีขนส่งข้อความหลายมิติแบบมั่นคง (Hypertext Transfer Protocol Secure; HTTPS) คือส่วนต่อขยายของโปรโตคอลเกณฑ์วิธีขนส่งข้อความหลายมิติ (Hypertext Transfer Protocol; HTTP) ซึ่งใช้การเข้ารหัสเพื่อการสื่อสารที่ปลอดภัยผ่านเครือข่ายคอมพิวเตอร์ และถูกใช้อย่างแพร่หลายบนอินเทอร์เน็ต โดยโปรโตคอลเครือข่าย HTTPS จะถูกเข้ารหัสด้วยเกณฑ์วิธีความมั่นคงของชั้นขนส่ง (Transport Layer Security; TLS) หรือก่อนหน้านี้คือเกณฑ์วิธีชั้นซ็อกเก็ตปลอดภัย (Secure Sockets Layer; SSL) ด้วยเหตุนั้น โปรโตคอลนี้สามารถเรียกด้วยชื่อ HTTP over TLS หรือ HTTP over SSL ได้เช่นกัน
#i เกณฑ์วิธีขนส่งข้อความหลายมิติแบบมั่นคง (Hypertext Transfer Protocol Secure; HTTPS)
คือส่วนต่อขยายของโปรโตคอลเกณฑ์วิธีขนส่งข้อความหลายมิติ (Hypertext Transfer Protocol; HTTP)
ซึ่งใช้การเข้ารหัสเพื่อการสื่อสารที่ปลอดภัยผ่านเครือข่ายคอมพิวเตอร์ และถูกใช้อย่างแพร่หลายบนอินเทอร์เน็ต
โดยโปรโตคอลเครือข่าย HTTPS จะถูกเข้ารหัสด้วยเกณฑ์วิธีความมั่นคงของชั้นขนส่ง (Transport Layer
Security; TLS) หรือก่อนหน้านี้คือเกณฑ์วิธีชั้นซ็อกเก็ตปลอดภัย (Secure Sockets Layer; SSL)
ด้วยเหตุนั้น โปรโตคอลนี้สามารถเรียกด้วยชื่อ HTTP over TLS หรือ HTTP over SSL ได้เช่นกัน
#i แรงจูงใจหลักของ HTTPS คือการยืนยันตัวตนของเว็บไซต์ที่เข้าถึง และการปกป้องความเป็นส่วนตัวและความสมบูรณ์ของข้อมูลที่แลกเปลี่ยนระหว่างการรับส่งข้อมูล HTTPS ป้องกันการโจมตีแบบ man-in-the-middle และการเข้ารหัสบล็อกไซเฟอร์แบบสองทิศทางในการสื่อสารระหว่างไคลเอนต์และเซิร์ฟเวอร์ ช่วยป้องกันการสื่อสารจากการดักฟังและการปลอมแปลง ประเด็นการพิสูจน์ตัวตนของ HTTPS จำเป็นต้องมีบุคคลที่สามที่เชื่อถือได้ลงนามในใบรับรองดิจิทัลฝั่งเซิร์ฟเวอร์ เดิมทีการดำเนินการนี้มีค่าใช้จ่ายสูง ซึ่งหมายความว่าการเชื่อมต่อ HTTPS ที่ผ่านการรับรองความถูกต้องอย่างสมบูรณ์มักจะพบได้เฉพาะในบริการธุรกรรมการชำระเงินที่ปลอดภัยและระบบสารสนเทศขององค์กรที่ปลอดภัยอื่นๆ บนเวิลด์ไวด์เว็บเท่านั้น ในปี 2016 แคมเปญโดยมูลนิธิพรมแดนอิเล็กทรอนิกส์ (Electronic Frontier Foundation; EFF) ด้วยการสนับสนุนจากนักพัฒนาเว็บเบราว์เซอร์ ทำให้โปรโตคอลนี้แพร่หลายมากขึ้น นับตั้งแต่ปี 2018 เป็นต้นมา HTTPS ถูกใช้โดยผู้ใช้เว็บบ่อยกว่า HTTP ดั้งเดิมที่ไม่ปลอดภัย โดยส่วนใหญ่เพื่อปกป้องความถูกต้องของหน้าเว็บบนเว็บไซต์ทุกประเภท รักษาความปลอดภัยบัญชี และรักษาความเป็นส่วนตัวของการสื่อสาร การระบุตัวตน และการท่องเว็บของผู้ใช้
#i แรงจูงใจหลักของ HTTPS คือการยืนยันตัวตนของเว็บไซต์ที่เข้าถึง
และการปกป้องความเป็นส่วนตัวและความสมบูรณ์ของข้อมูลที่แลกเปลี่ยนระหว่างการรับส่งข้อมูล HTTPS
ป้องกันการโจมตีแบบ man-in-the-middle
และการเข้ารหัสบล็อกไซเฟอร์แบบสองทิศทางในการสื่อสารระหว่างไคลเอนต์และเซิร์ฟเวอร์
ช่วยป้องกันการสื่อสารจากการดักฟังและการปลอมแปลง ประเด็นการพิสูจน์ตัวตนของ HTTPS
จำเป็นต้องมีบุคคลที่สามที่เชื่อถือได้ลงนามในใบรับรองดิจิทัลฝั่งเซิร์ฟเวอร์ เดิมทีการดำเนินการนี้มีค่าใช้จ่ายสูง
ซึ่งหมายความว่าการเชื่อมต่อ HTTPS
ที่ผ่านการรับรองความถูกต้องอย่างสมบูรณ์มักจะพบได้เฉพาะในบริการธุรกรรมการชำระเงินที่ปลอดภัยและระบบสารสนเทศขององค์กรที่ปลอดภัยอื่นๆ
บนเวิลด์ไวด์เว็บเท่านั้น ในปี 2016 แคมเปญโดยมูลนิธิพรมแดนอิเล็กทรอนิกส์ (Electronic Frontier
Foundation; EFF) ด้วยการสนับสนุนจากนักพัฒนาเว็บเบราว์เซอร์ ทำให้โปรโตคอลนี้แพร่หลายมากขึ้น
นับตั้งแต่ปี 2018 เป็นต้นมา HTTPS ถูกใช้โดยผู้ใช้เว็บบ่อยกว่า HTTP ดั้งเดิมที่ไม่ปลอดภัย
โดยส่วนใหญ่เพื่อปกป้องความถูกต้องของหน้าเว็บบนเว็บไซต์ทุกประเภท รักษาความปลอดภัยบัญชี
และรักษาความเป็นส่วนตัวของการสื่อสาร การระบุตัวตน และการท่องเว็บของผู้ใช้
== โดยรวม
#i รูปแบบ Uniform Resource Identifier (URI) ของ HTTPS มีรูปแบบการใช้งานที่เหมือนกันกับรูปแบบ HTTP อย่างไรก็ตาม HTTPS จะส่งสัญญาณให้เบราว์เซอร์ใช้ชั้นการเข้ารหัสเพิ่มเติมของ SSL/TLS เพื่อปกป้องการรับส่งข้อมูลซึ่ง SSL/TLS เหมาะอย่างยิ่งสำหรับ HTTP เนื่องจากสามารถให้การป้องกันได้แม้ว่าจะมีการตรวจสอบความถูกต้องเพียงด้านเดียวของการสื่อสาร ในกรณีนี้คือธุรกรรม HTTP บนอินเทอร์เน็ต ซึ่งโดยทั่วไปมีเพียงเซิร์ฟเวอร์เท่านั้นที่ได้รับการรับรองความถูกต้อง (โดยไคลเอนต์ตรวจสอบใบรับรองของเซิร์ฟเวอร์)
#iii รูปแบบ Uniform Resource Identifier (URI) ของ HTTPS
มีรูปแบบการใช้งานที่เหมือนกันกับรูปแบบ HTTP อย่างไรก็ตาม HTTPS
จะส่งสัญญาณให้เบราว์เซอร์ใช้ชั้นการเข้ารหัสเพิ่มเติมของ SSL/TLS เพื่อปกป้องการรับส่งข้อมูลซึ่ง SSL/TLS
เหมาะอย่างยิ่งสำหรับ HTTP
เนื่องจากสามารถให้การป้องกันได้แม้ว่าจะมีการตรวจสอบความถูกต้องเพียงด้านเดียวของการสื่อสาร
ในกรณีนี้คือธุรกรรม HTTP บนอินเทอร์เน็ต
ซึ่งโดยทั่วไปมีเพียงเซิร์ฟเวอร์เท่านั้นที่ได้รับการรับรองความถูกต้อง
(โดยไคลเอนต์ตรวจสอบใบรับรองของเซิร์ฟเวอร์)
#i HTTPS สร้างช่องทางที่ปลอดภัยบนเครือข่ายที่ไม่ปลอดภัย วิธีนี้ช่วยให้มั่นใจได้ถึงการป้องกันที่เหมาะสมจากผู้ดักฟังและการโจมตีแบบ man-in-the-middle โดยมีเงื่อนไขว่ามีการใช้ชุดการเข้ารหัสที่เหมาะสม และใบรับรองเซิร์ฟเวอร์ได้รับการตรวจสอบและเชื่อถือได้
#iii HTTPS สร้างช่องทางที่ปลอดภัยบนเครือข่ายที่ไม่ปลอดภัย
วิธีนี้ช่วยให้มั่นใจได้ถึงการป้องกันที่เหมาะสมจากผู้ดักฟังและการโจมตีแบบ man-in-the-middle
โดยมีเงื่อนไขว่ามีการใช้ชุดการเข้ารหัสที่เหมาะสม และใบรับรองเซิร์ฟเวอร์ได้รับการตรวจสอบและเชื่อถือได้
#i เนื่องจาก HTTPS เชื่อมโยง HTTP ทั้งหมดเข้ากับ TLS โดยตรงจึงสามารถเข้ารหัสโปรโตคอล HTTP พื้นฐานทั้งหมดได้ ซึ่งรวมถึง URL ของคำขอ พารามิเตอร์การค้นหา ส่วนหัว และคุกกี้ (ซึ่งมักจะมีข้อมูลระบุตัวตนของผู้ใช้) อย่างไรก็ตาม เนื่องจากที่อยู่เว็บไซต์และหมายเลขพอร์ตเป็นส่วนหนึ่งของโปรโตคอล TCP/IP พื้นฐาน HTTPS จึงไม่สามารถปกป้องการเปิดเผยข้อมูลเหล่านี้ได้ ในทางปฏิบัติ หมายความว่าแม้แต่บนเว็บเซิร์ฟเวอร์ที่กำหนดค่าอย่างถูกต้อง ผู้ดักฟังก็สามารถอนุมานที่อยู่ IP และหมายเลขพอร์ตของเว็บเซิร์ฟเวอร์ และบางครั้งอาจรวมถึงชื่อโดเมน (เช่น www.example.org แต่ไม่สามารถอนุมานส่วนที่เหลือของ URL) ที่ผู้ใช้กำลังสื่อสารด้วย รวมถึงปริมาณข้อมูลที่ถ่ายโอนและระยะเวลาของการสื่อสาร แต่อย่างไรก็ตามไม่รวมถึงเนื้อหาของการสื่อสาร
#iii เนื่องจาก HTTPS เชื่อมโยง HTTP ทั้งหมดเข้ากับ TLS โดยตรงจึงสามารถเข้ารหัสโปรโตคอล HTTP
พื้นฐานทั้งหมดได้ ซึ่งรวมถึง URL ของคำขอ พารามิเตอร์การค้นหา ส่วนหัว และคุกกี้
(ซึ่งมักจะมีข้อมูลระบุตัวตนของผู้ใช้) อย่างไรก็ตาม
เนื่องจากที่อยู่เว็บไซต์และหมายเลขพอร์ตเป็นส่วนหนึ่งของโปรโตคอล TCP/IP พื้นฐาน HTTPS
จึงไม่สามารถปกป้องการเปิดเผยข้อมูลเหล่านี้ได้ ในทางปฏิบัติ
หมายความว่าแม้แต่บนเว็บเซิร์ฟเวอร์ที่กำหนดค่าอย่างถูกต้อง ผู้ดักฟังก็สามารถอนุมานที่อยู่ IP
และหมายเลขพอร์ตของเว็บเซิร์ฟเวอร์ และบางครั้งอาจรวมถึงชื่อโดเมน (เช่น www.example.org
แต่ไม่สามารถอนุมานส่วนที่เหลือของ URL) ที่ผู้ใช้กำลังสื่อสารด้วย
รวมถึงปริมาณข้อมูลที่ถ่ายโอนและระยะเวลาของการสื่อสาร แต่อย่างไรก็ตามไม่รวมถึงเนื้อหาของการสื่อสาร
#i เว็บเบราว์เซอร์รู้วิธีเชื่อถือเว็บไซต์ HTTPS โดยอ้างอิงจากผู้ให้บริการออกใบรับรอง (Certificate Authority) ที่ติดตั้งไว้ล่วงหน้าในซอฟต์แวร์ ผู้สร้างเว็บเบราว์เซอร์จึงไว้วางใจผู้ให้บริการออกใบรับรองในการออกใบรับรองที่ถูกต้อง ดังนั้น ผู้ใช้ควรเชื่อถือการเชื่อมต่อ HTTPS ไปยังเว็บไซต์ก็ต่อเมื่อเป็นไปตามเงื่อนไขทั้งหมดต่อไปนี้:
#iii เว็บเบราว์เซอร์รู้วิธีเชื่อถือเว็บไซต์ HTTPS โดยอ้างอิงจากผู้ให้บริการออกใบรับรอง#jb
(Certificate Authority) ที่ติดตั้งไว้ล่วงหน้าในซอฟต์แวร์
ผู้สร้างเว็บเบราว์เซอร์จึงไว้วางใจผู้ให้บริการออกใบรับรองในการออกใบรับรองที่ถูกต้อง ดังนั้น
ผู้ใช้ควรเชื่อถือการเชื่อมต่อ HTTPS ไปยังเว็บไซต์ก็ต่อเมื่อเป็นไปตามเงื่อนไขทั้งหมดต่อไปนี้:
- ผู้ใช้เชื่อมั่นว่าอุปกรณ์ของตน โฮสต์เบราว์เซอร์ และวิธีการเข้าถึงเบราว์เซอร์นั้นไม่ถูกบุกรุก (กล่าวคือ ไม่มีการโจมตีซัพพลายเชน)
- ผู้ใช้เชื่อมั่นว่าซอฟต์แวร์เบราว์เซอร์ใช้งาน HTTPS ได้อย่างถูกต้องพร้อมกับผู้ให้บริการออกใบรับรองที่ติดตั้งไว้ล่วงหน้าอย่างถูกต้อง
- ผู้ใช้เชื่อมั่นว่าผู้ให้บริการออกใบรับรองจะรับรองเฉพาะเว็บไซต์ที่ถูกต้องตามกฎหมายเท่านั้น (กล่าวคือ ผู้ให้บริการออกใบรับรองจะไม่ถูกบุกรุกและไม่มีการออกใบรับรองที่ผิดพลาด)
- เว็บไซต์มีใบรับรองที่ถูกต้อง ซึ่งหมายความว่าได้รับการลงนามโดยผู้ให้บริการที่เชื่อถือได้
- ใบรับรองระบุเว็บไซต์ได้อย่างถูกต้อง (เช่น เมื่อเบราว์เซอร์เข้าชม https://example.com ใบรับรองที่ได้รับนั้นถูกต้องสำหรับ example.com และไม่ใช่ของหน่วยงานอื่น)
- ผู้ใช้เชื่อมั่นว่าเลเยอร์การเข้ารหัสของโปรโตคอล (SSL/TLS) มีความปลอดภัยเพียงพอจากการดักฟั
#[
#set enum(indent: 6em)
+ ผู้ใช้เชื่อมั่นว่าอุปกรณ์ของตน โฮสต์เบราว์เซอร์ และวิธีการเข้าถึงเบราว์เซอร์นั้นไม่ถูกบุกรุก (กล่าวคือ
ไม่มีการโจมตีซัพพลายเชน)
+ ผู้ใช้เชื่อมั่นว่าซอฟต์แวร์เบราว์เซอร์ใช้งาน HTTPS
ได้อย่างถูกต้องพร้อมกับผู้ให้บริการออกใบรับรองที่ติดตั้งไว้ล่วงหน้าอย่างถูกต้อ
+ ผู้ใช้เชื่อมั่นว่าผู้ให้บริการออกใบรับรองจะรับรองเฉพาะเว็บไซต์ที่ถูกต้องตามกฎหมายเท่านั้น (กล่าวคือ
ผู้ให้บริการออกใบรับรองจะไม่ถูกบุกรุกและไม่มีการออกใบรับรองที่ผิดพลาด)
+ เว็บไซต์มีใบรับรองที่ถูกต้อง ซึ่งหมายความว่าได้รับการลงนามโดยผู้ให้บริการที่เชื่อถือได้
+ ใบรับรองระบุเว็บไซต์ได้อย่างถูกต้อง (เช่น เมื่อเบราว์เซอร์เข้าชม https://example.com
ใบรับรองที่ได้รับนั้นถูกต้องสำหรับ example.com และไม่ใช่ของหน่วยงานอื่น)
+ ผู้ใช้เชื่อมั่นว่าเลเยอร์การเข้ารหัสของโปรโตคอล (SSL/TLS) มีความปลอดภัยเพียงพอจากการดักฟัง
]
#i HTTPS มีความสำคัญอย่างยิ่งต่อเครือข่ายที่ไม่ปลอดภัยและเครือข่ายที่อาจถูกแทรกแซง เครือข่ายที่ไม่ปลอดภัย เช่น จุดเชื่อมต่อ Wi-Fi สาธารณะ ซึ่งเปิดโอกาสให้ทุกคนในเครือข่ายท้องถิ่นเดียวกันสามารถดักจับแพ็กเก็ตและค้นพบข้อมูลสำคัญที่ไม่ได้รับการป้องกันโดย HTTPS นอกจากนี้ ยังพบว่าเครือข่าย WLAN ทั้งแบบฟรีและแบบเสียเงินบางเครือข่ายได้แทรกแซงหน้าเว็บโดยการแทรกแพ็กเก็ตเพื่อแสดงโฆษณาของตนเองบนเว็บไซต์อื่น การกระทำเช่นนี้สามารถถูกนำไปใช้ในทางที่ผิดได้หลายวิธี เช่น การฉีดมัลแวร์ลงในหน้าเว็บและการขโมยข้อมูลส่วนบุคคลของผู้ใช้
#iii HTTPS มีความสำคัญอย่างยิ่งต่อเครือข่ายที่ไม่ปลอดภัยและเครือข่ายที่อาจถูกแทรกแซง
เครือข่ายที่ไม่ปลอดภัย เช่น จุดเชื่อมต่อ Wi-Fi สาธารณะ
ซึ่งเปิดโอกาสให้ทุกคนในเครือข่ายท้องถิ่นเดียวกันสามารถดักจับแพ็กเก็ตและค้นพบข้อมูลสำคัญที่ไม่ได้รับการป้องกันโดย
HTTPS นอกจากนี้ ยังพบว่าเครือข่าย WLAN
ทั้งแบบฟรีและแบบเสียเงินบางเครือข่ายได้แทรกแซงหน้าเว็บโดยการแทรกแพ็กเก็ตเพื่อแสดงโฆษณาของตนเองบนเว็บไซต์อื่น
การกระทำเช่นนี้สามารถถูกนำไปใช้ในทางที่ผิดได้หลายวิธี เช่น
การฉีดมัลแวร์ลงในหน้าเว็บและการขโมยข้อมูลส่วนบุคคลของผู้ใช้
#i เมื่อมีข้อมูลมากขึ้นเกี่ยวกับการเฝ้าระวังมวลชนทั่วโลกและการขโมยข้อมูลส่วนบุคคลของอาชญากร การใช้ระบบรักษาความปลอดภัย HTTPS บนเว็บไซต์ทั้งหมดจึงมีความสำคัญเพิ่มมากขึ้นเรื่อยๆ โดยไม่คำนึงถึงประเภทของการเชื่อมต่ออินเทอร์เน็ตที่ใช้งาน แม้ว่าข้อมูลเมตาเกี่ยวกับหน้าเว็บแต่ละหน้าที่ผู้ใช้เข้าชมอาจไม่ถือว่ามีความละเอียดอ่อน แต่เมื่อนำมารวมกันแล้ว ข้อมูลเมตาเหล่านี้อาจเปิดเผยข้อมูลเกี่ยวกับผู้ใช้ได้มาก และกระทบต่อความเป็นส่วนตัวของผู้ใช้
#iii เมื่อมีข้อมูลมากขึ้นเกี่ยวกับการเฝ้าระวังมวลชนทั่วโลกและการขโมยข้อมูลส่วนบุคคลของอาชญากร
การใช้ระบบรักษาความปลอดภัย HTTPS บนเว็บไซต์ทั้งหมดจึงมีความสำคัญเพิ่มมากขึ้นเรื่อยๆ
โดยไม่คำนึงถึงประเภทของการเชื่อมต่ออินเทอร์เน็ตที่ใช้งาน
แม้ว่าข้อมูลเมตาเกี่ยวกับหน้าเว็บแต่ละหน้าที่ผู้ใช้เข้าชมอาจไม่ถือว่ามีความละเอียดอ่อน
แต่เมื่อนำมารวมกันแล้ว ข้อมูลเมตาเหล่านี้อาจเปิดเผยข้อมูลเกี่ยวกับผู้ใช้ได้มาก
และกระทบต่อความเป็นส่วนตัวของผู้ใช้
#i การปรับใช้ HTTPS ยังอนุญาตให้ใช้ HTTP/2 และ HTTP/3 (และรุ่นก่อนหน้าอย่าง SPDY และ QUIC) ซึ่งเป็น HTTP เวอร์ชันใหม่ที่ออกแบบมาเพื่อลดเวลา ขนาด และความหน่วงในการโหลดหน้าเว็บ
#i และมีการแนะนำให้ใช้ HTTP Strict Transport Security (HSTS) ร่วมกับ HTTPS เพื่อป้องกันผู้ใช้จากการโจมตีแบบ man-in-the-middle โดยเฉพาะอย่างยิ่ง SSL stripping
#iii การปรับใช้ HTTPS ยังอนุญาตให้ใช้ HTTP/2 และ HTTP/3 (และรุ่นก่อนหน้าอย่าง SPDY และ
QUIC) ซึ่งเป็น HTTP เวอร์ชันใหม่ที่ออกแบบมาเพื่อลดเวลา ขนาด และความหน่วงในการโหลดหน้าเว็บ
และมีการแนะนำให้ใช้ HTTP Strict Transport Security (HSTS) ร่วมกับ HTTPS
เพื่อป้องกันผู้ใช้จากการโจมตีแบบ man-in-the-middle โดยเฉพาะอย่างยิ่ง SSL stripping
== ความปลอดภัย
#i ความปลอดภัยของ HTTPS อยู่ที่ TLS พื้นฐาน ซึ่งโดยทั่วไปจะใช้คีย์สาธารณะและคีย์ส่วนตัวระยะยาวเพื่อสร้างคีย์เซสชันระยะสั้น ซึ่งจะถูกนำไปใช้ในการเข้ารหัสการไหลของข้อมูลระหว่างไคลเอนต์และเซิร์ฟเวอร์ ใบรับรอง X.509 ถูกใช้เพื่อยืนยันตัวตนของเซิร์ฟเวอร์ (และบางครั้งรวมถึงไคลเอนต์ด้วย) ด้วยเหตุนี้ ผู้ให้บริการออกใบรับรองและใบรับรองคีย์สาธารณะจึงจำเป็นต่อการตรวจสอบความสัมพันธ์ระหว่างใบรับรองและเจ้าของ รวมถึงการสร้าง ลงนาม และดูแลความถูกต้องของใบรับรอง แม้ว่าวิธีนี้อาจมีประโยชน์มากกว่าการตรวจสอบตัวตนผ่านเครือข่ายที่เชื่อถือได้ แต่การเปิดเผยข้อมูลการเฝ้าระวังข้อมูลจำนวนมากในปี 2013 ได้ชี้ให้เห็นถึงผู้ให้บริการออกใบรับรองว่าเป็นจุดอ่อนที่อาจนำไปสู่การโจมตีแบบ man-in-the-middle คุณสมบัติที่สำคัญในบริบทนี้คือความลับแบบส่งต่อ (Forward Secrecy) ซึ่งรับประกันว่าการสื่อสารที่เข้ารหัสที่บันทึกไว้ในอดีตจะไม่สามารถดึงข้อมูลและถอดรหัสได้ หากคีย์ลับหรือรหัสผ่านระยะยาวถูกบุกรุกในอนาคต ไม่ใช่ทุกเว็บเซิร์ฟเวอร์ที่จะมีระบบความลับแบบส่งต่อ
#iii ความปลอดภัยของ HTTPS อยู่ที่ TLS พื้นฐาน
ซึ่งโดยทั่วไปจะใช้คีย์สาธารณะและคีย์ส่วนตัวระยะยาวเพื่อสร้างคีย์เซสชันระยะสั้น
ซึ่งจะถูกนำไปใช้ในการเข้ารหัสการไหลของข้อมูลระหว่างไคลเอนต์และเซิร์ฟเวอร์ ใบรับรอง X.509
ถูกใช้เพื่อยืนยันตัวตนของเซิร์ฟเวอร์ (และบางครั้งรวมถึงไคลเอนต์ด้วย) ด้วยเหตุนี้
ผู้ให้บริการออกใบรับรองและใบรับรองคีย์สาธารณะจึงจำเป็นต่อการตรวจสอบความสัมพันธ์ระหว่างใบรับรองและเจ้าของ
รวมถึงการสร้าง ลงนาม และดูแลความถูกต้องของใบรับรอง
แม้ว่าวิธีนี้อาจมีประโยชน์มากกว่าการตรวจสอบตัวตนผ่านเครือข่ายที่เชื่อถือได้
แต่การเปิดเผยข้อมูลการเฝ้าระวังข้อมูลจำนวนมากในปี 2013
ได้ชี้ให้เห็นถึงผู้ให้บริการออกใบรับรองว่าเป็นจุดอ่อนที่อาจนำไปสู่การโจมตีแบบ man-in-the-middle
คุณสมบัติที่สำคัญในบริบทนี้คือความลับแบบส่งต่อ (Forward Secrecy)
ซึ่งรับประกันว่าการสื่อสารที่เข้ารหัสที่บันทึกไว้ในอดีตจะไม่สามารถดึงข้อมูลและถอดรหัสได้
หากคีย์ลับหรือรหัสผ่านระยะยาวถูกบุกรุกในอนาคต ไม่ใช่ทุกเว็บเซิร์ฟเวอร์ที่จะมีระบบความลับแบบส่งต่อ
#i เพื่อให้ HTTPS มีประสิทธิภาพ เว็บไซต์จะต้องโฮสต์ผ่าน HTTPS ทั้งหมด หากเนื้อหาบางส่วนของเว็บไซต์ถูกโหลดผ่าน HTTP (เช่น สคริปต์หรือรูปภาพ) หรือหากโหลดเฉพาะหน้าที่มีข้อมูลละเอียดอ่อน เช่น หน้าเข้าสู่ระบบ ผ่าน HTTPS ขณะที่ส่วนอื่นๆ ของเว็บไซต์ผ่าน HTTP ธรรมดา ผู้ใช้จะเสี่ยงต่อการถูกโจมตีและการเฝ้าระวัง นอกจากนี้ คุกกี้บนเว็บไซต์ที่รันผ่าน HTTPS จะต้องเปิดใช้งานแอตทริบิวต์ secure ในเว็บไซต์ที่มีข้อมูลละเอียดอ่อน ผู้ใช้และเซสชันจะถูกเปิดเผยทุกครั้งที่เข้าถึงเว็บไซต์นั้นด้วย HTTP แทนที่จะเป็น HTTPS
#iii เพื่อให้ HTTPS มีประสิทธิภาพ เว็บไซต์จะต้องโฮสต์ผ่าน HTTPS ทั้งหมด
หากเนื้อหาบางส่วนของเว็บไซต์ถูกโหลดผ่าน HTTP (เช่น สคริปต์หรือรูปภาพ)
หรือหากโหลดเฉพาะหน้าที่มีข้อมูลละเอียดอ่อน เช่น หน้าเข้าสู่ระบบ ผ่าน HTTPS ขณะที่ส่วนอื่น
ของเว็บไซต์ผ่าน HTTP ธรรมดา#jb ผู้ใช้จะเสี่ยงต่อการถูกโจมตีและการเฝ้าระวัง นอกจากนี้
คุกกี้บนเว็บไซต์ที่รันผ่าน HTTPS จะต้องเปิดใช้งานแอตทริบิวต์ secure ในเว็บไซต์ที่มีข้อมูลละเอียดอ่อน
ผู้ใช้และเซสชันจะถูกเปิดเผยทุกครั้งที่เข้าถึงเว็บไซต์นั้นด้วย HTTP แทนที่จะเป็น HTTPS
#v(1em)
== รายละเอียดทางเทคนิค
#v(1em)
=== ความแตกต่างจาก HTTP
#i URL แบบ HTTPS เริ่มต้นด้วย "https://" และใช้พอร์ต 443 ตามค่าเริ่มต้น ในขณะที่ URL แบบ HTTP เริ่มต้นด้วย "http://" และใช้พอร์ต 80 ตามค่าเริ่มต้น
#iiii URL แบบ HTTPS เริ่มต้นด้วย "https://" และใช้พอร์ต 443 ตามค่าเริ่มต้น ในขณะที่ URL แบบ
HTTP เริ่มต้นด้วย "http://" และใช้พอร์ต 80 ตามค่าเริ่มต้น
#i HTTP ไม่ได้เข้ารหัส จึงมีความเสี่ยงต่อการโจมตีแบบ man-in-the-middle และการดักฟังซึ่งอาจทำให้ผู้โจมตีสามารถเข้าถึงบัญชีเว็บไซต์และข้อมูลสำคัญ และแก้ไขหน้าเว็บเพื่อแทรกมัลแวร์หรือโฆษณาได้ HTTPS ได้รับการออกแบบมาให้ทนทานต่อการโจมตีประเภทนี้ และถือว่าปลอดภัย (ยกเว้นการใช้งาน HTTPS ที่ใช้ SSL เวอร์ชันที่ล้าสมัย)
#iiii HTTP ไม่ได้เข้ารหัส จึงมีความเสี่ยงต่อการโจมตีแบบ man-in-the-middle
และการดักฟังซึ่งอาจทำให้ผู้โจมตีสามารถเข้าถึงบัญชีเว็บไซต์และข้อมูลสำคัญ
และแก้ไขหน้าเว็บเพื่อแทรกมัลแวร์หรือโฆษณาได้ HTTPS ได้รับการออกแบบมาให้ทนทานต่อการโจมตีประเภทนี้
และถือว่าปลอดภัย (ยกเว้นการใช้งาน HTTPS ที่ใช้ SSL เวอร์ชันที่ล้าสมัย)
=== ชั้นเครือข่าย
#i HTTP ทำงานที่เลเยอร์สูงสุดของโมเดล TCP/IP นั่นคือเลเยอร์แอปพลิเคชัน เช่นเดียวกับโปรโตคอลความปลอดภัย TLS (ซึ่งทำงานเป็นเลเยอร์ย่อยที่ต่ำกว่าของเลเยอร์เดียวกัน) ซึ่งเข้ารหัสข้อความ HTTP ก่อนส่ง และถอดรหัสเมื่อข้อความมาถึง โดยเคร่งครัดแล้ว HTTPS ไม่ใช่โปรโตคอลใหม่ที่แยกจากกัน แต่หมายถึงการใช้ HTTP ทั่วไปบนการเชื่อมต่อ SSL/TLS ที่เข้ารหัส (เป็นส่วนต่อขยายจาก HTTP อย่างที่กล่าวไปข้างต้น)
#iiii HTTP ทำงานที่เลเยอร์สูงสุดของโมเดล TCP/IP นั่นคือเลเยอร์แอปพลิเคชัน#jb
เช่นเดียวกับโปรโตคอลความปลอดภัย TLS (ซึ่งทำงานเป็นเลเยอร์ย่อยที่ต่ำกว่าของเลเยอร์เดียวกัน)#jb
ซึ่งเข้ารหัสข้อความ HTTP ก่อนส่ง และถอดรหัสเมื่อข้อความมาถึง โดยเคร่งครัดแล้ว HTTPS
ไม่ใช่โปรโตคอลใหม่ที่แยกจากกัน แต่หมายถึงการใช้ HTTP ทั่วไปบนการเชื่อมต่อ SSL/TLS ที่เข้ารหัส
(เป็นส่วนต่อขยายจาก HTTP อย่างที่กล่าวไปข้างต้น)
#i HTTPS เข้ารหัสเนื้อหาข้อความทั้งหมด รวมถึงส่วนหัว HTTP และข้อมูลคำขอ/การตอบกลับ ยกเว้นการโจมตีด้วยการเข้ารหัส CCA ที่อาจเกิดขึ้นตามที่อธิบายไว้ในส่วนข้อจำกัดด้านล่าง ผู้โจมตีควรจะสามารถตรวจพบการเชื่อมต่อระหว่างสองฝ่ายได้มากที่สุด รวมถึงชื่อโดเมนและที่อยู่ IP ของฝ่ายนั้นด้วย
#iiii HTTPS เข้ารหัสเนื้อหาข้อความทั้งหมด รวมถึงส่วนหัว HTTP และข้อมูลคำขอ/การตอบกลับ
ยกเว้นการโจมตีด้วยการเข้ารหัส CCA ที่อาจเกิดขึ้นตามที่อธิบายไว้ในส่วนข้อจำกัดด้านล่าง
ผู้โจมตีควรจะสามารถตรวจพบการเชื่อมต่อระหว่างสองฝ่ายได้มากที่สุด รวมถึงชื่อโดเมนและที่อยู่ IP
ของฝ่ายนั้นด้วย
=== การตั้งค่าเซิร์ฟเวอร์
เพื่อเตรียมเว็บเซิร์ฟเวอร์ให้ยอมรับการเชื่อมต่อ HTTPS ผู้ดูแลระบบต้องสร้างใบรับรองคีย์สาธารณะสำหรับเว็บเซิร์ฟเวอร์ ใบรับรองนี้ต้องได้รับการลงนามโดยผู้ออกใบรับรองที่เชื่อถือได้เพื่อให้เว็บเบราว์เซอร์ยอมรับโดยไม่มีการแจ้งเตือน ผู้ออกใบรับรองจะรับรองว่าผู้ถือใบรับรองคือผู้ดำเนินการของเว็บเซิร์ฟเวอร์ที่นำเสนอใบรับรองนั้น โดยทั่วไปเว็บเบราว์เซอร์จะเผยแพร่รายชื่อใบรับรองการลงนามของผู้ออกใบรับรองหลักๆ เพื่อให้สามารถตรวจสอบใบรับรองที่ลงนามโดยผู้ออกใบรับรองเหล่านั้นได้
#iiii เพื่อเตรียมเว็บเซิร์ฟเวอร์ให้ยอมรับการเชื่อมต่อ HTTPS
ผู้ดูแลระบบต้องสร้างใบรับรองคีย์สาธารณะสำหรับเว็บเซิร์ฟเวอร์
ใบรับรองนี้ต้องได้รับการลงนามโดยผู้ออกใบรับรองที่เชื่อถือได้เพื่อให้เว็บเบราว์เซอร์ยอมรับโดยไม่มีการแจ้งเตือน
ผู้ออกใบรับรองจะรับรองว่าผู้ถือใบรับรองคือผู้ดำเนินการของเว็บเซิร์ฟเวอร์ที่นำเสนอใบรับรองนั้น
โดยทั่วไปเว็บเบราว์เซอร์จะเผยแพร่รายชื่อใบรับรองการลงนามของผู้ออกใบรับรองหลักๆ
เพื่อให้สามารถตรวจสอบใบรับรองที่ลงนามโดยผู้ออกใบรับรองเหล่านั้นได้
==== การขอใบรับรอง
#i มีผู้ให้บริการออกใบรับรองเชิงพาณิชย์จำนวนหนึ่งที่เสนอใบรับรอง SSL/TLS แบบชำระเงินหลายประเภท รวมถึงใบรับรองการตรวจสอบขยาย
#iiiii มีผู้ให้บริการออกใบรับรองเชิงพาณิชย์จำนวนหนึ่งที่เสนอใบรับรอง SSL/TLS
แบบชำระเงินหลายประเภท รวมถึงใบรับรองการตรวจสอบขยาย
#i Let's Encrypt เปิดตัวในเดือนเมษายน 2559 ให้บริการใบรับรอง SSL/TLS พื้นฐานแบบอัตโนมัติฟรีแก่เว็บไซต์ มูลนิธิ Electronic Frontier Foundation ระบุว่า Let's Encrypt จะทำให้การเปลี่ยนจาก HTTP เป็น HTTPS "ง่ายดายเพียงแค่ออกคำสั่งหรือคลิกปุ่ม" ปัจจุบันผู้ให้บริการเว็บโฮสต์และผู้ให้บริการคลาวด์ส่วนใหญ่ใช้ประโยชน์จาก Let's Encrypt เพื่อมอบใบรับรองฟรีให้กับลูกค้า
#iiiii Let's Encrypt เปิดตัวในเดือนเมษายน 2559 ให้บริการใบรับรอง SSL/TLS
พื้นฐานแบบอัตโนมัติฟรีแก่เว็บไซต์ มูลนิธิ Electronic Frontier Foundation ระบุว่า Let's Encrypt
จะทำให้การเปลี่ยนจาก HTTP เป็น HTTPS "ง่ายดายเพียงแค่ออกคำสั่งหรือคลิกปุ่ม"
ปัจจุบันผู้ให้บริการเว็บโฮสต์และผู้ให้บริการคลาวด์ส่วนใหญ่ใช้ประโยชน์จาก Let's Encrypt
เพื่อมอบใบรับรองฟรีให้กับลูกค้า
==== ใช้เป็นการควบคุมการเข้าถึง
#i ระบบนี้ยังสามารถใช้สำหรับการตรวจสอบสิทธิ์ไคลเอ็นต์เพื่อจำกัดการเข้าถึงเว็บเซิร์ฟเวอร์เฉพาะผู้ใช้ที่ได้รับอนุญาตเท่านั้น ในการดำเนินการนี้ ผู้ดูแลระบบเว็บไซต์มักจะสร้างใบรับรองสำหรับผู้ใช้แต่ละราย ซึ่งผู้ใช้จะโหลดใบรับรองลงในเบราว์เซอร์ โดยปกติใบรับรองจะมีชื่อและที่อยู่อีเมลของผู้ใช้ที่ได้รับอนุญาต และจะถูกตรวจสอบโดยเซิร์ฟเวอร์โดยอัตโนมัติในแต่ละการเชื่อมต่อเพื่อยืนยันตัวตนของผู้ใช้ ซึ่งอาจไม่จำเป็นต้องใช้รหัสผ่านด้วยซ้ำ
#iiiii
ระบบนี้ยังสามารถใช้สำหรับการตรวจสอบสิทธิ์ไคลเอ็นต์เพื่อจำกัดการเข้าถึงเว็บเซิร์ฟเวอร์เฉพาะผู้ใช้ที่ได้รับอนุญาตเท่านั้น
ในการดำเนินการนี้ ผู้ดูแลระบบเว็บไซต์มักจะสร้างใบรับรองสำหรับผู้ใช้แต่ละราย
ซึ่งผู้ใช้จะโหลดใบรับรองลงในเบราว์เซอร์ โดยปกติใบรับรองจะมีชื่อและที่อยู่อีเมลของผู้ใช้ที่ได้รับอนุญาต
และจะถูกตรวจสอบโดยเซิร์ฟเวอร์โดยอัตโนมัติในแต่ละการเชื่อมต่อเพื่อยืนยันตัวตนของผู้ใช้
ซึ่งอาจไม่จำเป็นต้องใช้รหัสผ่านด้วยซ้ำ
==== ในกรณีที่คีย์ลับถูกบุกรุก
#i คุณสมบัติที่สำคัญในบริบทนี้คือการเข้ารหัสแบบส่งต่อที่สมบูรณ์แบบ (PFS) การมีคีย์ลับแบบอสมมาตรระยะยาวตัวใดตัวหนึ่งที่ใช้สร้างเซสชัน HTTPS ไม่น่าจะทำให้การได้มาซึ่งคีย์เซสชันระยะสั้นเพื่อถอดรหัสการสนทนาทำได้ง่ายขึ้น แม้ในภายหลังก็ตาม ในปี 2013 มีเพียงการแลกเปลี่ยนคีย์ DiffieHellman (DHE) และการแลกเปลี่ยนคีย์ DiffieHellman แบบเส้นโค้งวงรี (ECDHE) เท่านั้นที่ทราบว่ามีคุณสมบัตินี้ ในปี 2013 มีเพียง 30% ของเซสชัน Firefox, Opera และ Chromium Browser เท่านั้นที่ใช้คุณสมบัตินี้ และเกือบ 0% ของเซสชัน Safari และ Microsoft Internet Explorer ของ Apple ที่ใช้คุณสมบัตินี้ TLS 1.3 ซึ่งเผยแพร่ในเดือนสิงหาคม 2018 ได้ยกเลิกการสนับสนุนการเข้ารหัสแบบไม่มีการเข้ารหัสแบบส่งต่อ เดือนกุมภาพันธ์ พ.ศ. 2562 เว็บเซิร์ฟเวอร์ที่สำรวจ 96.6% รองรับการรักษาความลับแบบ Forward ในรูปแบบใดรูปแบบหนึ่ง และ 52.1% จะใช้การรักษาความลับแบบ Forward กับเบราว์เซอร์ส่วนใหญ่ เดือนกรกฎาคม พ.ศ. 2566 เว็บเซิร์ฟเวอร์ที่สำรวจ 99.6% รองรับการรักษาความลับแบบ Forward ในรูปแบบใดรูปแบบหนึ่ง และ 75.2% จะใช้การรักษาความลับแบบ Forward กับเบราว์เซอร์ส่วนใหญ่
#iiiii คุณสมบัติที่สำคัญในบริบทนี้คือการเข้ารหัสแบบส่งต่อที่สมบูรณ์แบบ (PFS)
การมีคีย์ลับแบบอสมมาตรระยะยาวตัวใดตัวหนึ่งที่ใช้สร้างเซสชัน HTTPS
ไม่น่าจะทำให้การได้มาซึ่งคีย์เซสชันระยะสั้นเพื่อถอดรหัสการสนทนาทำได้ง่ายขึ้น แม้ในภายหลังก็ตาม ในปี
2013 มีเพียงการแลกเปลี่ยนคีย์ Diffie--Hellman (DHE) และการแลกเปลี่ยนคีย์ Diffie--Hellman
แบบเส้นโค้งวงรี (ECDHE) เท่านั้นที่ทราบว่ามีคุณสมบัตินี้ ในปี 2013 มีเพียง 30% ของเซสชัน Firefox,
Opera และ Chromium Browser เท่านั้นที่ใช้คุณสมบัตินี้ และเกือบ 0% ของเซสชัน Safari และ
Microsoft Internet Explorer ของ Apple ที่ใช้คุณสมบัตินี้ TLS 1.3 ซึ่งเผยแพร่ในเดือนสิงหาคม
2018 ได้ยกเลิกการสนับสนุนการเข้ารหัสแบบไม่มีการเข้ารหัสแบบส่งต่อ เดือนกุมภาพันธ์ พ.ศ. 2562
เว็บเซิร์ฟเวอร์ที่สำรวจ 96.6% รองรับการรักษาความลับแบบ Forward ในรูปแบบใดรูปแบบหนึ่ง และ
52.1% จะใช้การรักษาความลับแบบ Forward กับเบราว์เซอร์ส่วนใหญ่ เดือนกรกฎาคม พ.ศ. 2566
เว็บเซิร์ฟเวอร์ที่สำรวจ 99.6% รองรับการรักษาความลับแบบ Forward ในรูปแบบใดรูปแบบหนึ่ง และ
75.2% จะใช้การรักษาความลับแบบ Forward กับเบราว์เซอร์ส่วนใหญ่
===== การเพิกถอนใบรับรอง
ใบรับรองอาจถูกเพิกถอนก่อนหมดอายุได้ เช่น เนื่องจากความลับของคีย์ส่วนตัวถูกละเมิด เบราว์เซอร์ยอดนิยมเวอร์ชันที่ใหม่พอเช่น Firefox Opera และ Internet Explorer บน Windows Vista จะใช้ Online Certificate Status Protocol (OCSP) เพื่อตรวจสอบว่าไม่เป็นเช่นนั้น เบราว์เซอร์จะส่งหมายเลขซีเรียลของใบรับรองไปยังผู้ออกใบรับรองหรือผู้แทนผ่าน OCSP และผู้ออกใบรับรองจะตอบกลับ โดยแจ้งให้เบราว์เซอร์ทราบว่าใบรับรองยังคงใช้ได้อยู่หรือไม่ นอกจากนี้ CA อาจออกรายการเพิกถอนใบรับรอง (Certificate Revocation List; CRL) เพื่อแจ้งให้ผู้ใช้ทราบว่าใบรับรองเหล่านี้ถูกเพิกถอนแล้ว อย่างไรก็ตาม CRL ไม่จำเป็นสำหรับฟอรัม CA/Browser (“ฟอรัม CA/Browser” ดังกล่าวคือองค์กร) อีกต่อไป อย่างไรก็ตาม CA ยังคงใช้ CRL กันอย่างแพร่หลาย สถานะการเพิกถอนส่วนใหญ่บนอินเทอร์เน็ตจะหายไปในไม่ช้าหลังจากใบรับรองหมดอายุ
#iiiiii ใบรับรองอาจถูกเพิกถอนก่อนหมดอายุได้ เช่น เนื่องจากความลับของคีย์ส่วนตัวถูกละเมิด
เบราว์เซอร์ยอดนิยมเวอร์ชันที่ใหม่พอเช่น Firefox Opera และ#jb Internet Explorer บน Windows
Vista จะใช้ Online Certificate Status Protocol (OCSP) เพื่อตรวจสอบว่าไม่เป็นเช่นนั้น
เบราว์เซอร์จะส่งหมายเลขซีเรียลของใบรับรองไปยังผู้ออกใบรับรองหรือผู้แทนผ่าน OCSP
และผู้ออกใบรับรองจะตอบกลับ โดยแจ้งให้เบราว์เซอร์ทราบว่าใบรับรองยังคงใช้ได้อยู่หรือไม่ นอกจากนี้ CA
อาจออกรายการเพิกถอนใบรับรอง (Certificate Revocation List; CRL)
เพื่อแจ้งให้ผู้ใช้ทราบว่าใบรับรองเหล่านี้ถูกเพิกถอนแล้ว อย่างไรก็ตาม CRL ไม่จำเป็นสำหรับฟอรัม
CA/Browser (“ฟอรัม CA/Browser” ดังกล่าวคือองค์กร) อีกต่อไป อย่างไรก็ตาม CA ยังคงใช้ CRL
กันอย่างแพร่หลาย สถานะการเพิกถอนส่วนใหญ่บนอินเทอร์เน็ตจะหายไปในไม่ช้าหลังจากใบรับรองหมดอายุ
=== ข้อจำกัด
#i การเข้ารหัส SSL (Secure Sockets Layer) และ TLS (Transport Layer Security) สามารถกำหนดค่าได้สองโหมด ได้แก่ โหมดธรรมดาและโหมด Mutual ในโหมดธรรมดา การตรวจสอบสิทธิ์จะดำเนินการโดยเซิร์ฟเวอร์เท่านั้น โหมด Mutual กำหนดให้ผู้ใช้ต้องติดตั้งใบรับรองไคลเอ็นต์ส่วนบุคคลในเว็บเบราว์เซอร์เพื่อการตรวจสอบสิทธิ์ผู้ใช้ ไม่ว่าในกรณีใด ระดับการป้องกันจะขึ้นอยู่กับความถูกต้องของการใช้งานซอฟต์แวร์และอัลกอริทึมการเข้ารหัสที่ใช้
#iiii การเข้ารหัส SSL (Secure Sockets Layer) และ TLS (Transport Layer Security)
สามารถกำหนดค่าได้สองโหมด ได้แก่ โหมดธรรมดาและโหมด Mutual ในโหมดธรรมดา
การตรวจสอบสิทธิ์จะดำเนินการโดยเซิร์ฟเวอร์เท่านั้น โหมด Mutual
กำหนดให้ผู้ใช้ต้องติดตั้งใบรับรองไคลเอ็นต์ส่วนบุคคลในเว็บเบราว์เซอร์เพื่อการตรวจสอบสิทธิ์ผู้ใช้
ไม่ว่าในกรณีใด
ระดับการป้องกันจะขึ้นอยู่กับความถูกต้องของการใช้งานซอฟต์แวร์และอัลกอริทึมการเข้ารหัสที่ใช้
#i SSL/TLS ไม่ป้องกันการจัดทำดัชนีของเว็บไซต์โดยเว็บครอว์เลอร์ และในบางกรณี URI ของทรัพยากรที่เข้ารหัสสามารถอนุมานได้โดยการทราบขนาดคำขอ/การตอบสนองที่ถูกสกัดกั้นเท่านั้น วิธีนี้ช่วยให้ผู้โจมตีสามารถเข้าถึงข้อความธรรมดา (เนื้อหาคงที่ที่เปิดเผยต่อสาธารณะ) และข้อความที่เข้ารหัส (เนื้อหาคงที่เวอร์ชันเข้ารหัส) ทำให้สามารถโจมตีด้วยการเข้ารหัสได้
#iiii SSL/TLS ไม่ป้องกันการจัดทำดัชนีของเว็บไซต์โดยเว็บครอว์เลอร์ และในบางกรณี URI
ของทรัพยากรที่เข้ารหัสสามารถอนุมานได้โดยการทราบขนาดคำขอ/การตอบสนองที่ถูกสกัดกั้นเท่านั้น
วิธีนี้ช่วยให้ผู้โจมตีสามารถเข้าถึงข้อความธรรมดา (เนื้อหาคงที่ที่เปิดเผยต่อสาธารณะ) และข้อความที่เข้ารหัส
(เนื้อหาคงที่เวอร์ชันเข้ารหัส) ทำให้สามารถโจมตีด้วยการเข้ารหัสได้
#i เนื่องจาก TLS ทำงานที่ระดับโปรโตคอลที่ต่ำกว่า HTTP และไม่มีความรู้เกี่ยวกับโปรโตคอลระดับสูงกว่า เซิร์ฟเวอร์ TLS จึงสามารถแสดงใบรับรองได้เพียงใบเดียวสำหรับที่อยู่และพอร์ตที่กำหนดเท่านั้น ในอดีต นั่นหมายความว่าไม่สามารถใช้การโฮสต์เสมือนแบบอิงชื่อกับ HTTPS ได้ มีโซลูชันที่เรียกว่า Server Name Indication (SNI) ซึ่งส่งชื่อโฮสต์ไปยังเซิร์ฟเวอร์ก่อนเข้ารหัสการเชื่อมต่อ แม้ว่าเบราว์เซอร์รุ่นเก่าจะไม่รองรับส่วนขยายนี้ก็ตาม การรองรับ SNI มีให้ใช้งานตั้งแต่ Firefox 2, Opera 8, Apple Safari 2.1, Google Chrome 6 และ Internet Explorer 7 บน Windows Vista
#iiii เนื่องจาก TLS ทำงานที่ระดับโปรโตคอลที่ต่ำกว่า HTTP
และไม่มีความรู้เกี่ยวกับโปรโตคอลระดับสูงกว่า เซิร์ฟเวอร์ TLS
จึงสามารถแสดงใบรับรองได้เพียงใบเดียวสำหรับที่อยู่และพอร์ตที่กำหนดเท่านั้น ในอดีต
นั่นหมายความว่าไม่สามารถใช้การโฮสต์เสมือนแบบอิงชื่อกับ HTTPS ได้ มีโซลูชันที่เรียกว่า Server Name
Indication (SNI) ซึ่งส่งชื่อโฮสต์ไปยังเซิร์ฟเวอร์ก่อนเข้ารหัสการเชื่อมต่อ
แม้ว่าเบราว์เซอร์รุ่นเก่าจะไม่รองรับส่วนขยายนี้ก็ตาม การรองรับ SNI มีให้ใช้งานตั้งแต่ Firefox 2,
Opera 8, Apple Safari 2.1, Google Chrome 6 และ Internet Explorer 7 บน Windows
Vista
#i การโจมตีแบบ man-in-the-middle ที่ซับซ้อนประเภทหนึ่งที่เรียกว่า SSL stripping ถูกนำเสนอในงานประชุม Blackhat Conference ปี 2009 การโจมตีประเภทนี้ทำลายความปลอดภัยของ HTTPS โดยการเปลี่ยนลิงก์ https: ให้เป็นลิงก์ http: โดยใช้ประโยชน์จากข้อเท็จจริงที่ว่าผู้ใช้อินเทอร์เน็ตเพียงไม่กี่คนเท่านั้นที่พิมพ์ "https" ลงในอินเทอร์เฟซเบราว์เซอร์ พวกเขาจึงเข้าสู่เว็บไซต์ที่ปลอดภัยได้โดยการคลิกลิงก์ และถูกหลอกให้คิดว่ากำลังใช้ HTTPS ในขณะที่จริงๆ แล้วกำลังใช้ HTTP ผู้โจมตีจึงสื่อสารกับไคลเอ็นต์อย่างชัดเจน สิ่งนี้กระตุ้นให้เกิดการพัฒนามาตรการรับมือใน HTTP ที่เรียกว่า HTTP Strict Transport Security
#iiii การโจมตีแบบ man-in-the-middle ที่ซับซ้อนประเภทหนึ่งที่เรียกว่า SSL stripping
ถูกนำเสนอในงานประชุม Blackhat Conference ปี 2009 การโจมตีประเภทนี้ทำลายความปลอดภัยของ
HTTPS โดยการเปลี่ยนลิงก์ https: ให้เป็นลิงก์ http:
โดยใช้ประโยชน์จากข้อเท็จจริงที่ว่าผู้ใช้อินเทอร์เน็ตเพียงไม่กี่คนเท่านั้นที่พิมพ์ "https"
ลงในอินเทอร์เฟซเบราว์เซอร์ พวกเขาจึงเข้าสู่เว็บไซต์ที่ปลอดภัยได้โดยการคลิกลิงก์
และถูกหลอกให้คิดว่ากำลังใช้ HTTPS ในขณะที่จริงๆ แล้วกำลังใช้ HTTP
ผู้โจมตีจึงสื่อสารกับไคลเอ็นต์อย่างชัดเจน สิ่งนี้กระตุ้นให้เกิดการพัฒนามาตรการรับมือใน HTTP ที่เรียกว่า
HTTP Strict Transport Security
#i HTTPS ได้รับการพิสูจน์แล้วว่ามีความเสี่ยงต่อการโจมตีวิเคราะห์ทราฟฟิกหลากหลายรูปแบบ การโจมตีวิเคราะห์ทราฟฟิกเป็นการโจมตีแบบ Side-Channel ประเภทหนึ่งที่อาศัยการเปลี่ยนแปลงเวลาและขนาดของทราฟฟิกเพื่ออนุมานคุณสมบัติของทราฟฟิกที่เข้ารหัส การวิเคราะห์ทราฟฟิกเป็นไปได้เนื่องจากการเข้ารหัส SSL/TLS เปลี่ยนแปลงเนื้อหาของทราฟฟิก แต่มีผลกระทบน้อยมากต่อขนาดและระยะเวลาของทราฟฟิก ในเดือนพฤษภาคม 2553 งานวิจัยโดยนักวิจัยจาก Microsoft Research และ Indiana University ค้นพบว่าข้อมูลผู้ใช้ที่ละเอียดอ่อนโดยละเอียดสามารถอนุมานได้จากช่องทางด้านข้าง เช่น ขนาดแพ็กเก็ต นักวิจัยพบว่าแม้จะมีการป้องกัน HTTPS ในแอปพลิเคชันเว็บชั้นนำที่มีชื่อเสียงหลายตัวในด้านการดูแลสุขภาพ ภาษี การลงทุน และการค้นหาเว็บ แต่ผู้แอบฟังสามารถอนุมานโรค/ยา/การผ่าตัดของผู้ใช้ รายได้ของครอบครัว และความลับในการลงทุนได้
#iiii HTTPS ได้รับการพิสูจน์แล้วว่ามีความเสี่ยงต่อการโจมตีวิเคราะห์ทราฟฟิกหลากหลายรูปแบบ
การโจมตีวิเคราะห์ทราฟฟิกเป็นการโจมตีแบบ Side-Channel
ประเภทหนึ่งที่อาศัยการเปลี่ยนแปลงเวลาและขนาดของทราฟฟิกเพื่ออนุมานคุณสมบัติของทราฟฟิกที่เข้ารหัส
การวิเคราะห์ทราฟฟิกเป็นไปได้เนื่องจากการเข้ารหัส SSL/TLS เปลี่ยนแปลงเนื้อหาของทราฟฟิก
แต่มีผลกระทบน้อยมากต่อขนาดและระยะเวลาของทราฟฟิก ในเดือนพฤษภาคม 2553 งานวิจัยโดยนักวิจัยจาก
Microsoft Research และ Indiana University
ค้นพบว่าข้อมูลผู้ใช้ที่ละเอียดอ่อนโดยละเอียดสามารถอนุมานได้จากช่องทางด้านข้าง เช่น ขนาดแพ็กเก็ต
นักวิจัยพบว่าแม้จะมีการป้องกัน HTTPS ในแอปพลิเคชันเว็บชั้นนำที่มีชื่อเสียงหลายตัวในด้านการดูแลสุขภาพ
ภาษี การลงทุน และการค้นหาเว็บ แต่ผู้แอบฟังสามารถอนุมานโรค/ยา/การผ่าตัดของผู้ใช้
รายได้ของครอบครัว และความลับในการลงทุนได้
#i ความจริงที่ว่าเว็บไซต์สมัยใหม่ส่วนใหญ่ รวมถึง Google, Yahoo! และ Amazon ใช้ HTTPS ทำให้เกิดปัญหาสำหรับผู้ใช้จำนวนมากที่พยายามเข้าถึงจุดเชื่อมต่อ Wi-Fi สาธารณะ เนื่องจากหน้าเข้าสู่ระบบจุดเชื่อมต่อ Wi-Fi ของพอร์ทัลแบบแคปทีฟไม่สามารถโหลดได้หากผู้ใช้พยายามเปิดทรัพยากร HTTPS และเว็บไซต์หลายแห่ง เช่น NeverSSL รับประกันว่าเว็บไซต์เหล่านั้นจะสามารถเข้าถึงได้ผ่าน HTTP เสมอ
#iiii ความจริงที่ว่าเว็บไซต์สมัยใหม่ส่วนใหญ่ รวมถึง Google, Yahoo! และ Amazon ใช้ HTTPS
ทำให้เกิดปัญหาสำหรับผู้ใช้จำนวนมากที่พยายามเข้าถึงจุดเชื่อมต่อ Wi-Fi สาธารณะ
เนื่องจากหน้าเข้าสู่ระบบจุดเชื่อมต่อ Wi-Fi
ของพอร์ทัลแบบแคปทีฟไม่สามารถโหลดได้หากผู้ใช้พยายามเปิดทรัพยากร HTTPS และเว็บไซต์หลายแห่ง เช่น
NeverSSL รับประกันว่าเว็บไซต์เหล่านั้นจะสามารถเข้าถึงได้ผ่าน HTTP เสมอ
+36 -28
View File
@@ -1,41 +1,49 @@
#import "../PageTemplate.typ": chapter-page, i, jb
#show: chapter-page
#set enum(indent: 3em, numbering: n => "2." + str(n))
#heading([#linebreak()ทฤษฎีและเอกสารที่เกี่ยวข้อง])
#i ผู้จัดทำโครงงาน#h(1em)เครื่องยืนยันตัวตนด้วย NFC#h(1em)ได้ศึกษาทฤษฎีที่เกี่ยวข้องต่าง และ\
#i ผู้จัดทำโครงงาน เครื่องยืนยันตัวตนด้วย NFC ได้ศึกษาทฤษฎีที่เกี่ยวข้องต่าง และ#jb
รวบรวมแนวทางและหลักการต่าง จากเอกสารงานวิจัยที่เกี่ยวข้องดังต่อไปนี้
+ ไมโครคอนโทรเลอร์ (Microcontroller)
+ เซ็นเซอร์ (Sensors)
+ ลำโพงสัญญาณ (Buzzer)
+ เกณฑ์วิธีขนส่งข้อความหลายมิติ (HyperText Transfer Protocol; HTTP)
+ เกณฑ์วิธีขนส่งข้อความหลายมิติแบบมั่นคง (Hypertext Transfer Protocol Secure; HTTPS)
+ เกณฑ์วิธีความมั่นคงของชั้นขนส่ง (Transport Layer Security; TLS)
+ การสื่อสารสนามใกล้ (Near-field communication; NFC)
+ Flutter
+ Git
+ ภาษาซี (C Programming Language)
#block(inset: (left: 3em))[
2.1 ไมโครคอนโทรเลอร์ (Microcontroller)\
2.2 เซ็นเซอร์ (Sensors)\
2.3 ลำโพงสัญญาณ (Buzzer)\
2.4 เกณฑ์วิธีขนส่งข้อความหลายมิติ (HyperText Transfer Protocol; HTTP)\
2.5 เกณฑ์วิธีขนส่งข้อความหลายมิติแบบมั่นคง (Hypertext Transfer Protocol Secure; HTTPS)\
2.6 เกณฑ์วิธีความมั่นคงของชั้นขนส่ง (Transport Layer Security; TLS)\
2.7 การสื่อสารสนามใกล้ (Near-field communication; NFC)\
2.8 Flutter\
2.9 Git\
2.10 ภาษาซี (C Programming Language)
]
#set heading(numbering: "1.1")
#counter(heading).update((2, 0))
== ไมโครคอนโทรเลอร์ (Microcontroller)
#i ความรู้เกี่ยวกับไมโครคอนโทรลเลอร์เบื้องต้น ไมโครคอนโทรลเลอร์ (มักย่อว่า uC หรือ MCU) คือ
อุปกรณ์ควบคุมขนาดเล็ก ซึ่งบรรจุความสามารถที่คล้ายคลึงกับระบบคอมพิวเตอร์ โดยใน
ไมโครคอนโทรลเลอร์ได้รวม เอาซีพียูหน่วยความจำและพอร์ต ซึ่งเป็นส่วนประกอบหลักสำคัญของ
ระบบคอมพิวเตอร์เข้าไว้ด้วยกัน โดยทำการบรรจุเข้าไว้ในตัวถังเดียวกัน ไมโครคอนโทรลเลอร์ถ้าแปล
ความหมายแบบตรงตัวก็คือ ระบบคอนโทรลขนาดเล็กเรียกอีกอย่างหนึ่งคือเป็นระบบคอมพิวเตอร์ ขนาดเล็ก
ที่สามารถนำมาประยุกต์ใช้งานได้หลากหลาย โดยผ่านการออกแบบวงจรให้เหมาะกับงาน ต่างๆ
และยังสามารถเขียนโปรแกรมคำสั่งเพื่อควบคุมขา Input/Output เพื่อสั่งงานให้ไป ควบคุม อุปกรณ์ต่างๆ
ด้อีกด้วย ซึ่งก็นับว่าเป็นระบบที่สามารถนำมาประยุกต์ใช้งานได้หลากหลาย ทั้ง ทางด้าน Digital และ
Analog ยกตัวอย่างเช่น ระบบสัญญาณตอบรับอัตโนมัติ, ระบบบัตรคิว, ระบบ ตอกบัตรพนักงาน และอื่นๆ
ยิ่งระบบไมโครคอนโทรลเลอร์ในยุคปัจจุบันนั้นสามารถทำการเชื่อต่อกับ ระบบ Network
ของคอมพิวเตอร์ทั่วไปได้อีกด้วย ดังนั้นการสั่งงานจึงไม่ใช่แค่หน้าแผงวงจร แต่ อาจจะเป็นการสั่งงานอยู่คนละ
ซีกโลกผ่านเครือข่ายอินเตอร์เน็ตก็ได้โครงสร้างโดยทั่วไปของไมโครคอนโทรลเลอร์นั้น
สามารถแบ่งออกมาได้เป็น 5 ส่วนใหญ่ ได้แก่ หน่วประมวลผลกลาง หรือ ซีพียู, หน่วยความจำ,
ส่วนติดต่อกับอุปกรณ์ภายนอก หรือพอร์ต, ช่องทางเดินของสัญญาณ หรือบัส และ วงจรกำเนิดสัญญาณนาฬิกา#jb
น่วยความจำนั้น สามารถแบ่งออกเป็น 2 ส่วนคือ หน่วยความจำที่มีไว้สำหรับเก็บ โปรแกรมหลัก
เปรียบเสมือนฮาร์ดดิสก์และหน่วยความจำข้อมูล ใช้เป็นเหมือนกับ กระดาษทดในการ คำนวณของ#jb
#i ไมโครคอนโทรลเลอร์ (Microcontroller, MC, uC, หรือ #(sym.mu)C)
หรือหน่วยไมโครคอนโทรลเลอร์ (Microcontroller Unit; MCU)
เป็นคอมพิวเตอร์ขนาดเล็กบนวงจรรวมเดียว (Integrated Circuit; IC)
โดยไมโครคอนโทรลเลอร์ประกอบด้วยแกนประมวลผลหนึ่งแกนหรือมากกว่า
พร้อมด้วยหน่วยความจำและอุปกรณ์ต่อพ่วงอินพุต/เอาต์พุตที่ตั้งโปรแกรมได้
หน่วยความจำโปรแกรมในรูปแบบของ NOR flash, OTP ROM, หรือ ferroelectric RAM
มักจะถูกรวมไว้ในชิปด้วยเช่นกัน รวมถึง RAM จำนวนเล็กน้อย
มโครคอนโทรลเลอร์ได้รับการออกแบบมาสำหรับการใช้งานแบบฝังตัว
ซึ่งแตกต่างจากไมโครโปรเซสเซอร์ที่ใช้ในคอมพิวเตอร์ส่วนบุคคลหรือแอปพลิเคชันทั่วไปอื่น
ที่ประกอบด้วยชิปแยกชิ้นต่าง
#i ในศัพท์สมัยใหม่ ไมโครคอนโทรลเลอร์นั้นคล้ายคลึงกับระบบบนชิป (System on a chip; SoC)
แต่มีความซับซ้อนน้อยกว่า SoC อาจมีไมโครคอนโทรลเลอร์เป็นส่วประกอบหนึ่ง
แต่โดยทั่วไปแล้วจะรวมเข้ากับอุปกรณ์ต่อพ่วงขั้นสูง ช่ หน่วยประมวลผลกราฟิก (GPU) โมดูล Wi-Fi
รือตัวประมวลผลร่วม (coprocessor) อย่างน้อยหนึ่งตัว
#i ไมโครคอนโทรลเลอร์ถูกนำไปใช้ในผลิตภัณฑ์และอุปกรณ์ควบคุมอัตโนมัติ เช่น
ระบบควบคุมเครื่องยนต์รถยนต์ อุปกรณ์ทางการแพทย์ที่ฝังในร่างกาย รีโมทคอนโทรล เครื่องใช้สำนักงาน
เครื่องใช้ไฟฟ้า เครื่องมือไฟฟ้า ของเล่น และระบบฝังตัวอื่น
การลดขนาดและต้นทุนเมื่อเทียบกับการออกแบบที่ใช้ไมโครโปรเซสเซอร์ หน่วยความจำ
และอุปกรณ์อินพุต/เอาต์พุตแยกต่างหาก ทำให้การควบคุมแบบดิจิทัลสำหรับอุปกรณ์และกระบวนการต่าง
เป็นไปได้มากขึ้น ไมโครคอนโทรลเลอร์แบบผสมสัญญาณเป็นที่นิยม
โดยจะรวมส่วนประกอบอนาล็อกที่จำเป็นในการควบคุมระบบอิเล็กทรอนิกส์ที่ไม่ใช่ดิจิทัล#jb
+345 -136
View File
@@ -1,172 +1,381 @@
#import "../PageTemplate.typ": i, jb
#import "../PageTemplate.typ": *
ซีพียู โดย ESP32 เป็นไมโครคอนโทรลเลอร์แบบ System-on-a-Chip (SoC)
ที่มีการรวมส่วนประกอบทั้งหมดที่จำเป็นสำหรับการประมวลผลและการสื่อสารไร้สายไว้ในชิปเดียว
ที่มีคุณสมบัติเด่นด้านการเชื่อมต่อ Wi-Fi และ Bluetooth ในตัว เป็นชิปไมโครคอนโทรลเลอร์แบบ 32 บิต
ที่มีความสามารถสูง พัฒนาและผลิตโดย บริษัท Espressif Systems จากประเทศจีน
ส่วนประกอบหลักของบอร์ด ESP32
ในบริบทของ Internet of Things (IoT) ไมโครคอนโทรลเลอร์เป็นวิธีการรวบรวมข้อมูล การตรวจจับ
และการกระตุ้นโลกทางกายภาพในฐานะอุปกรณ์ปลายทางที่มีราคาประหยัดและเป็นที่นิยม
#i ESP32 คือ ไมโครคอนโทรลเลอร์ราคาประหยัดและประหยัดพลังงานที่ผสานรวมความสามารถทั้ง Wi-Fi
และ Bluetooth ชิปเหล่านี้มีตัวเลือกการประมวลผลที่หลากหลาย รวมถึง ไมโครโปรเซสเซอร์#jb
Tensilica Xtensa LX6 ที่มีทั้งแบบดูอัลคอร์และแบบซิงเกิลคอร์ โปรเซสเซอร์ดูอัลคอร์ Xtensa LX7 หรือ
ไมโครโปรเซสเซอร์ RISC-V แบบซิงเกิลคอร์ นอกจากนี้ ESP32
ยังมีส่วนประกอบที่จำเป็นสำหรับการสื่อสารข้อมูลไร้สาย เช่น สวิตช์เสาอากาศในตัว บาลัน RF
เครื่องขยายสัญญาณ ตัวรับสัญญาณเสียงรบกวนต่ำ ตัวกรอง และโมดูลจัดการพลังงาน
#i ไมโครคอนโทรลเลอร์บางตัวอาจใช้คำแบบสี่บิตและทำงานที่ความถี่ต่ำถึง 4 kHz เพื่อการใช้พลังงานต่ำ
(มิลลิวัตต์หรือไมโครวัตต์หลักเดียว) โดยทั่วไปแล้ว
ไมโครคอนโทรลเลอร์เหล่านี้สามารถคงการทำงานไว้ได้ในขณะที่รอเหตุการณ์ เช่น
การกดปุ่มหรือการขัดจังหวะอื่นๆ การใช้พลังงานขณะอยู่ในโหมดสลีป (โดยที่นาฬิกา CPU
และอุปกรณ์ต่อพ่วงส่วนใหญ่ปิดอยู่) อาจอยู่ที่ระดับนาโนวัตต์เท่านั้น#jb
ทำให้หลายตัวเหมาะสำหรับแอปพลิเคชันที่ใช้แบตเตอรี่ได้นาน ส่วนไมโครคอนโทรลเลอร์อื่นๆ
อาจทำหน้าที่ในบทบาทที่สำคัญต่อประสิทธิภาพ ซึ่งอาจต้องทำงานคล้ายกับตัวประมวลผลสัญญาณดิจิทัล (Digital
Signal Processor; DSP) โดยมีความเร็วสัญญาณนาฬิกาและการใช้พลังงานที่สูงกว่า
#i โดยทั่วไป ESP32 จะถูกฝังอยู่บนแผงวงจรพิมพ์เฉพาะอุปกรณ์ หรือนำเสนอเป็นส่วนหนึ่งของชุดพัฒนาที่มี
พินและขั้วต่อ GPIO หลากหลายรูป แบบ โดยมีการกำหนดค่าแตกต่างกันไปตามรุ่นและผู้ผลิต ESP32
ออกแบบโดย Espressif Systems และผลิตโดย TSMC โดยใช้กระบวนการ 40
นาโนเมตรเป็นรุ่นต่อยอดจากไมโครคอนโทรลเลอร์ ESP8266
== ประวัติ
#i นับตั้งแต่เปิดตัว ESP32 รุ่นดั้งเดิม มีการเปิดตัวและประกาศรุ่นต่างๆ มากมาย
พวกมันรวมกันเป็นไมโครคอนโทรลเลอร์ตระกูล ESP32 ชิปเหล่านี้มี CPU และความสามารถที่แตกต่างกัน
แต่ทั้งหมดใช้ SDK เดียวกันและส่วนใหญ่เข้ากันได้กับโค้ด นอกจากนี้ ESP32 รุ่นดั้งเดิมยังได้รับการปรับปรุง
และส่วนประกอบหลักของบอร์ด ESP32 คือ ไมโครโปรเซสเซอร์ LX6 32 บิตแบบคอร์เดี่ยว/คู่ Xtensa
องรับหน่วยจุดลอยตัวความแม่นยำเดี่ยว (FPU) ไวไฟ: 802.11b/g/n บลูทูธ: v4.2 BR/EDR และ BLE
(แชร์วิทยุกับ Wi-Fi) GPIO จำนวน 34 ตัว ADC SAR #math.equation(
$2 times 12$,
alt: "2 คูณ 12",
) บิต สูงสุด 18 ช่องและ #math.equation($2 times 8$, alt: "2 คูณ 8") บิต DAC
#iii ไมโครโปรเซสเซอร์แบบหลายชิปตัวแรก ได้แก่ Four-Phase Systems AL1 ในปี 1969 และ#jb
Garrett AiResearch MP944 ในปี 1970 ซึ่งถูกพัฒนาขึ้นโดยใช้ชิป MOS LSI หลายตัว
ส่วนไมโครโปรเซสเซอร์แบบชิปเดียวตัวแรกคือ Intel 4004 ซึ่งวางจำหน่ายในปี 1971 โดยใช้ชิป MOS
LSI เพียงตัวเดียว พัฒนาโดย Federico Faggin โดยใช้เทคโนโลยี MOS แบบซิลิคอนเกต
่วมกับวิศวกรของ#jb Intel คือ Marcian Hoff และ Stan Mazor และวิศวกรของ Busicom คือ
Masatoshi Shima ต่อมาก็มี Intel 4040 แบบ 4 บิต, Intel 8008 แบบ 8 บิต, และ Intel 8080
แบบ 8 บิต โปรเซสเซอร์เหล่านี้ทั้งหมดต้องการชิปภายนอกหลายตัวเพื่อสร้างระบบที่ใช้งานได้
รวมถึงชิปหน่วยความจำและชิปอินเทอร์เฟซอุปกรณ์ต่อพ่วง
ส่งผลให้ต้นทุนของระบบโดยรวมสูงถึงหลายร้อยดอลลาร์สหรัฐ (ในทศวรรษ 1970)
ทำให้การนำคอมพิวเตอร์มาใช้กับเครื่องใช้ไฟฟ้าขนาดเล็กนั้นไม่คุ้มค่าทางเศรษฐกิจ
#iii บริษัท MOS Technology เปิดตัวไมโครโปรเซสเซอร์ราคาต่ำกว่า 100 ดอลลาร์ในปี 1975 ได้แก่รุ่น
6501 และ 6502 จุดประสงค์หลักคือการลดอุปสรรคด้านราคา
แต่ไมโครโปรเซสเซอร์เหล่านี้ยังคงต้องการการสนับสนุนจากภายนอก หน่วยความจำ และชิปอุปกรณ์ต่อพ่วง
ซึ่งทำให้ต้นทุนรวมของระบบยังคงอยู่ในระดับหลายร้อยดอลลาร์
=== การพัฒนา
#iiii หนังสือเล่มหนึ่งระบุว่า Gary Boone และ Michael Cochran วิศวกรของบริษัท TI
ประสบความสำเร็จในการสร้างไมโครคอนโทรลเลอร์ตัวแรกในปี 1971 ผลงานของพวกเขาคือ TMS 1000
ซึ่งวางจำหน่ายในเชิงพาณิชย์ในปี 1974 ไมโครคอนโทรลเลอร์นี้รวมหน่วยความจำแบบอ่านอย่างเดียว
หน่วยความจำแบบทั้งอ่านและเขียน โปรเซสเซอร์ และนาฬิกาไว้ในชิปเดียว และมุ่งเป้าไปที่ระบบฝังตัว
#iiii ในช่วงต้นถึงกลางทศวรรษ 1970
ผู้ผลิตอุปกรณ์อิเล็กทรอนิกส์ของญี่ปุ่นเริ่มผลิตไมโครคอนโทรลเลอร์สำหรับรถยนต์ ซึ่งรวมถึง MCU 4
บิตสำหรับระบบความบันเทิงในรถยนต์ ที่ปัดน้ำฝนอัตโนมัติ ระบบล็อคอิเล็กทรอนิกส์ และแผงหน้าปัด ตลอดจน
MCU 8 บิตสำหรับควบคุมเครื่องยนต์
#iiii ส่วนหนึ่งเพื่อตอบสนองต่อการมีอยู่ของชิป TMS 1000 แบบชิปเดี่ยว Intel
จึงพัฒนาชิปประมวลผลระบบคอมพิวเตอร์บนชิปที่ปรับให้เหมาะสมสำหรับการใช้งานด้านการควบคุม นั่นคือ#jb
Intel 8048 โดยเริ่มจัดส่งชิ้นส่วนเชิงพาณิชย์ครั้งแรกในปี 1977 ชิปนี้รวม RAM และ ROM
ไว้ในชิปเดียวกันกับไมโครโปรเซสเซอร์ ในบรรดาแอปพลิเคชันมากมาย
ชิปนี้ได้ถูกนำไปใช้ในแป้นพิมพ์พีซีมากกว่าหนึ่งพันล้านเครื่องในที่สุด ในเวลานั้น Luke J. Valenter
ประธานของ Intel
กล่าวว่าไมโครคอนโทรลเลอร์เป็นหนึ่งในผลิตภัณฑ์ที่ประสบความสำเร็จมากที่สุดในประวัติศาสตร์ของบริษัท
และเขาได้ขยายงบประมาณของแผนกไมโครคอนโทรลเลอร์เพิ่มขึ้นกว่า 25%
#iiii ไมโครคอนโทรลเลอร์ส่วนใหญ่ในเวลานั้นมีหลายรุ่นที่ใช้งานพร้อมกัน รุ่นหนึ่งใช้หน่วยความจำโปรแกรม
EPROM
โดยมีหน้าต่างควอตซ์โปร่งใสอยู่ที่ฝาปิดของตัวชิปเพื่อให้สามารถลบข้อมูลได้โดยการฉายแสงอัลตราไวโอเลต
ชิปที่ลบได้เหล่านี้มักใช้สำหรับการสร้างต้นแบบ อีกรุ่นหนึ่งคือ ROM ที่ตั้งโปรแกรมด้วยมาสก์ หรือ PROM
ที่ตั้งโปรแกรมได้เพียงครั้งเดียว สำหรับรุ่นหลัง บางครั้งจะใช้คำว่า#jb OTP ซึ่งย่อมาจาก "one-time
programmable" (ตั้งโปรแกรมได้ครั้งเดียว) ในไมโครคอนโทรลเลอร์#jb OTP นั้น PROM
มักจะเป็นชนิดเดียวกับ EPROM แต่ตัวชิปไม่มีหน้าต่างควอตซ์
เนื่องจากไม่มีวิธีใดที่จะฉายแสงอัลตราไวโอเลตไปยัง EPROM ได้ จึงไม่สามารถลบข้อมูลได้
เนื่องจากรุ่นที่ลบได้ต้องใช้ตัวชิปเซรามิกที่มีหน้าต่างควอตซ์ จึงมีราคาแพงกว่ารุ่น OTP อย่างมาก
ซึ่งสามารถผลิตได้ในตัวชิปพลาสติกทึบแสงที่มีราคาถูกกว่า สำหรับรุ่นที่สามารถลบได้นั้น
จำเป็นต้องใช้ควอตซ์แทนกระจกที่มีราคาถูกกว่า#jb เนื่องจากมีความโปร่งใสต่อแสงอัลตราไวโอเลต
ซึ่งกระจกส่วนใหญ่ทึบแสง แต่ปัจจัยหลักที่ทำให้ต้นทุนแตกต่างกันคือตัวบรรจุภัณฑ์เซรามิกเอง
นอกจากนี้ยังมีการใช้ไมโครคอนโทรลเลอร์แบบ Piggyback ด้วย
#afigure(
image("Microcontroller/PIC16CxxxWIN.jpg", height: 2.5in),
attr: [Camillo - Own work, CC BY 2.5,
https://commons.wikimedia.org/w/index.php?curid=569240],
alt: "ไมโครคอนโทรลเลอร์ 4 ชิ้นที่ขนาดต่างกัน แต่มีช่องให้เห็น EPROM ภายใน",
caption: "ไมโครคอนโทรลเลอร์ PIC ต่าง ๆ ที่มี EPROM ภายใน",
)
#v(1em)
#afigure(
image(
"Microcontroller/Microcomputer_with_EPROM_(piggyback).jpg",
height: 2in,
),
attr: [Medvedev - Own work, CC BY-SA 3.0,
https://commons.wikimedia.org/w/index.php?curid=33161178],
alt: "thing",
caption: [ไมโครคอนโทรลเลอร์ Piggyback จาก MOSTEK],
)
#iiii ในปี พ.ศ. 2536 การเปิดตัวหน่วยความจำ EEPROM ทำให้ไมโครคอนโทรลเลอร์ (เริ่มต้นด้วย
Microchip PIC16C84)
สามารถลบข้อมูลด้วยไฟฟ้าได้อย่างรวดเร็วโดยไม่ต้องใช้แพ็คเกจราคาแพงอย่างที่จำเป็นสำหรับ EPROM
ซึ่งช่วยให้สามารถสร้างต้นแบบได้อย่างรวดเร็วและตั้งโปรแกรมในระบบได้ (เทคโนโลยี EEPROM
มีมาก่อนหน้านี้ แต่ EEPROM รุ่นก่อนหน้านี้มีราคาแพงกว่าและทนทานน้อยกว่า
ทำให้ไม่เหมาะสำหรับไมโครคอนโทรลเลอร์ที่ผลิตจำนวนมากในราคาประหยัด) ในปีเดียวกันนั้น Atmel
ได้เปิดตัวไมโครคอนโทรลเลอร์ตัวแรกที่ใช้หน่วยความจำ Flash ซึ่งเป็น EEPROM ชนิดพิเศษ บริษัทอื่น
ก็ได้ดำเนินการตามมาอย่างรวดเร็ว โดยมีทั้งหน่วยความจำทั้งสองประเภท
#iiii ปัจจุบันไมโครคอนโทรลเลอร์มีราคาถูกและหาซื้อได้ง่ายสำหรับผู้ที่ชื่นชอบงานอดิเรก
โดยมีชุมชนออนไลน์ขนาดใหญ่ที่ให้ความสนใจกับโปรเซสเซอร์บางประเภท
=== ปริมาณและค่าใช้จ่าย
#iiii ในปี 2002 ประมาณ 55% ของ CPU
ทั้งหมดที่จำหน่ายในโลกเป็นไมโครคอนโทรลเลอร์และไมโครโปรเซสเซอร์ 8 บิต
#iiii มีการขายไมโครคอนโทรลเลอร์ 8 บิตมากกว่าสองพันล้านตัวในปี 1997 และจากข้อมูลของ Semico
พบว่าไมโครคอนโทรลเลอร์ 8 บิตมากกว่าสี่พันล้านถูกจำหน่ายในปี 2006 ล่าสุด Semico อ้างว่าตลาด MCU
เติบโตขึ้น 36.5% ในปี 2010 และ 12% ในปี 2011
#iiii บ้านทั่วไปในประเทศที่พัฒนาแล้วมีแนวโน้มที่จะมีไมโครโปรเซสเซอร์อเนกประสงค์เพียงสี่ตัว
แต่มีไมโครคอนโทรลเลอร์ประมาณสามโหล รถยนต์ระดับกลางทั่วไปมีไมโครคอนโทรลเลอร์ประมาณ 30 ตัว
นอกจากนี้ยังสามารถพบได้ในอุปกรณ์ไฟฟ้าหลายชนิด เช่น เครื่องซักผ้า เตาไมโครเวฟ และโทรศัพท์
#iiii ต้นทุนในการผลิตอาจต่ำกว่า 0.10 เหรียญสหรัฐต่อหน่วย
#iiii ค่าใช้จ่ายลดลงเมื่อเวลาผ่านไป โดยไมโครคอนโทรลเลอร์ 8 บิตที่ถูกที่สุดมีจำหน่ายในราคาต่ำกว่า
0.03 ดอลลาร์สหรัฐฯ ในปี 2018 และไมโครคอนโทรลเลอร์ 32 บิตบางรุ่นมีราคาประมาณ 1
ดอลลาร์สหรัฐฯ สำหรับปริมาณที่ใกล้เคียงกัน
#iiii ในปี 2012 หลังเกิดวิกฤติทั่วโลก ยอดขายลดลงและการฟื้นตัวต่อปีที่เลวร้ายที่สุดเท่าที่เคยมีมา
และราคาขายเฉลี่ยเมื่อเทียบเป็นรายปีลดลง 17% ซึ่งถือเป็นการลดลงครั้งใหญ่ที่สุดนับตั้งแต่ทศวรรษ 1980
ราคาเฉลี่ยสำหรับไมโครคอนโทรลเลอร์อยู่ที่ 0.88 เหรียญสหรัฐฯ (0.69 เหรียญสหรัฐฯ สำหรับ 4/8 บิต,
0.59 เหรียญสหรัฐฯ สำหรับ 16 บิต, 1.76 เหรียญสหรัฐฯ สำหรับ 32 บิต)
#iiii ในปี 2012 ยอดขายไมโครคอนโทรลเลอร์ 8 บิตทั่วโลกมีมูลค่าประมาณ 4 พันล้านดอลลาร์สหรัฐ
ในขณะที่ไมโครคอนโทรลเลอร์ 4 บิตก็มียอดขายที่สำคัญเช่นกัน
#iiii ในปี 2015 ไมโครคอนโทรลเลอร์ 8 บิตสามารถซื้อได้ในราคา 0.311 ดอลลาร์สหรัฐฯ#jb (1,000
หน่วย) 16 บิตราคา 0.385 ดอลลาร์สหรัฐฯ (1,000 หน่วย) และ 32 บิตในราคา 0.378 ดอลลาร์สหรัฐฯ
(1,000 หน่วย แต่อยู่ที่ 0.35 ดอลลาร์สหรัฐฯ สำหรับ 5,000)
#iiii ในปี 2018 ไมโครคอนโทรลเลอร์ 8 บิตสามารถซื้อได้ในราคา 0.03 ดอลลาร์สหรัฐฯ#jb 16
บิตในราคา 0.393 ดอลลาร์สหรัฐฯ (1,000 หน่วย แต่ราคา 0.563 ดอลลาร์สหรัฐฯ สำหรับ 100
หน่วยหรือ 0.349 ดอลลาร์สหรัฐฯ สำหรับม้วนเต็ม 2,000 หน่วย) และ 32 บิตในราคา 0.503
ดอลลาร์#jb สหรัฐฯ (1,000 หน่วย แต่ที่ 0.466 ดอลลาร์สหรัฐสำหรับ 5,000 หน่วย)
#iiii ในปี 2018 ไมโครคอนโทรลเลอร์ราคาถูกที่สูงกว่าปี 2015 ทั้งหมดมีราคาแพงกว่า
(โดยคำนวณอัตราเงินเฟ้อระหว่างราคาปี 2018 ถึง 2015 สำหรับหน่วยเฉพาะเหล่านั้น)
โดยไมโครคอนโทรลเลอร์ 8 บิตสามารถซื้อได้ในราคา 0.319 ดอลลาร์สหรัฐฯ (1,000 หน่วย) หรือสูงกว่า
2.6%
#iiii ไมโครคอนโทรลเลอร์ 16 บิตมีราคา 0.464 ดอลลาร์สหรัฐฯ (1,000 หน่วย) หรือ 21% สูงกว่า
#iiii แบบ 32 บิตในราคา 0.503 ดอลลาร์สหรัฐฯ (1,000 หน่วย แต่อยู่ที่ 0.466 ดอลลาร์สหรัฐฯ
สำหรับ 5,000) หรือสูงกว่า 33%
=== คอมพิวเตอร์ที่เล็กที่สุด
#iiii เมื่อวันที่ 21 มิถุนายน 2018 มหาวิทยาลัยมิชิแกนได้ประกาศ "คอมพิวเตอร์ที่เล็กที่สุดในโลก"
อุปกรณ์ดังกล่าวเป็น "ระบบเซ็นเซอร์ไร้สายและไร้แบตเตอรี่ขนาด 0.04 ลบ.มม. 16 nW
พร้อมด้วยโปรเซสเซอร์ Cortex-M0+ ในตัวและการสื่อสารแบบออปติกสำหรับการวัดอุณหภูมิของเซลล์"#jb
"วัดด้านข้างเพียง 0.3 มม. ประมาณขนาดเมล็ดข้าว [...] นอกเหนือจาก RAM
และเซลล์แสงอาทิตย์แล้ว#jb อุปกรณ์
คอมพิวเตอร์รุ่นใหม่ยังมีโปรเซสเซอร์และเครื่องส่งและตัวรับสัญญาณไร้สาย
เนื่องจากมีขนาดเล็กเกินไปที่จะมีเสาอากาศวิทยุแบบธรรมดา อุปกรณ์จึงรับและส่งข้อมูลด้วยแสงที่มองเห็นได้
สถานีฐานให้แสงสำหรับพลังงานและการเขียนโปรแกรม และรับข้อมูล" อุปกรณ์นี้มีขนาด 1/10 ของขนาดที่
IBM อ้างสิทธิ์ก่อนหน้านี้ คอมพิวเตอร์ที่มีขนาดเป็นสถิติโลกเมื่อหลายเดือนก่อนในเดือนมีนาคม 2018 ซึ่ง#jb
"เล็กกว่าเม็ดเกลือ" มีทรานซิสเตอร์หนึ่งล้านตัว ต้นทุนการผลิตน้อยกว่า 0.10 ดอลลาร์
และเมื่อรวมกับเทคโนโลยีบล็อกเชนแล้ว มีไว้สำหรับการขนส่งและ "จุดยึดเข้ารหัสลับ"
ซึ่งเป็นแอปพลิเคชันลายนิ้วมือดิจิทัล
== ประเภท
#iii ปี 2008 มีผู้ขายและสถาปัตยกรรมไมโครคอนโทรลเลอร์จำนวนมาก รวมไปถึง:#jb
#block(inset: (left: 5.5em))[
+ หน่วยประมวลผล ARM core โดยเฉพาะคอร์ประเภท ARM Cortex-M
+ Microchip Technology Atmel AVR (8 บิต), AVR32 (32 บิต), และ AT91SAM (32 บิต)
+ คอร์ M8C ของ Cypress Semiconductor's ที่ถูกใช้ใน Cypress PSoC ของพวกเขา
+ Freescale ColdFire (32 บิต) และ S08 (8 บิต)
+ Freescale 68HC11 (8 บิต) และอื่น ที่มีรากฐานมาจากครอบครัว Motorola 6800
+ Intel 8051, ซึ่งนอกจาก Intel ก็ถูกผลิตโดย NXP Semiconductors, Infineon, และอื่น
หลายรายการ
+ Infineon: 8 บิต XC800, 16 บิต XE166, 32 บิต XMC4000 (ARM based Cortex M4F), 32
บิต TriCore, และ 32 บิต Aurix Tricore Bit microcontrollers
+ Maxim Integrated MAX32600, MAX32620, MAX32625, MAX32630, MAX32650, MAX32640
+ MIPS
+ Microchip Technology PIC, (8 บิต PIC16, PIC18, 16 บิต dsPIC33 / PIC24), (32 บิต
PIC32)
+ NXP Semiconductors LPC1000, LPC2000, LPC3000, LPC4000 (32 บิต), LPC900,
LPC700 (8 บิต)
+ Parallax Propeller
+ PowerPC ISE
+ Rabbit 2000 (8 บิต)
+ Renesas Electronics: RL78 16 บิต MCU; RX 32 บิต MCU; SuperH; V850 32 บิต MCU;
H8; R8C 16 บิต MCU
+ Silicon Laboratories ไมโครคอนโทรลเลอร์ Pipelined 8 บิต 8051
และไมโครคอนโทรลเลอร์แบบ ARM-based 32 บิต สัญญาณผสม
+ STMicroelectronics STM8 (8 บิต), ST10 (16 บิต), STM32 (32 บิต), SPC5
(automotive 32 บิต)
+ Texas Instruments TI MSP430 (16 บิต), MSP432 (32 บิต), C2000 (32 บิต)
+ Toshiba TLCS-870 (8 บิต/16 บิต)
]
#iiii และยังมีอีกมากมาย โดยบางอย่างนั้นถูกใช้ในแอปพลิเคชันที่เจาะจงมาก
หรือเหมือนกับหน่วยประมวลผลเฉพาะแอปพลิเคชันมากกว่าไมโครคอนโทรลเลอร์
ตลาดไมโครคอนโทรลเลอร์นั้นกระจัดกระจายเป็นอย่างมาก และมีผู้ขาย เทคโนโลยี และตลาดมากมาย
และผู้ขายจำนวนมากขายหลายสถาปัตยกรรม
== ESP32
#iii ESP32 คือกลุ่มไมโครคอนโทรลเลอร์ราคาประหยัดและประหยัดพลังงานที่ผสานรวมความสามารถทั้ง
Wi-Fi และบลูทูธ ชิปเหล่านี้มีตัวเลือกการประมวลผลที่หลากหลาย รวมถึงไมโครโปรเซสเซอร์ Tensilica
Xtensa LX6 ที่มีให้เลือกทั้งแบบ dual-core และ single-core, โปรเซสเซอร์#jb Xtensa LX7
dual-core หรือไมโครโปรเซสเซอร์ RISC-V แบบ single-core นอกจากนี้ ESP32
ยังรวมส่วนประกอบที่จำเป็นสำหรับการสื่อสารข้อมูลไร้สาย เช่น สวิตช์เสาอากาศในตัว บาลัน RF
เครื่องขยายกำลัง เครื่องรับสัญญาณรบกวนต่ำ ตัวกรอง และโมดูลการจัดการพลังงาน
#[
// #set par(spacing: 0.75em)
#afigure(
image("Microcontroller/ESP32-C3_RISC-V_NodeMCU_board.jpg", width: 2in),
alt: "บอร์ดสีดำ มีพิน GPIO ด้านข้างและมีชิพอยู่บริเวณด้านบนบอร์ด",
attr: [Popolon, CC BY-SA 4.0,
https://commons.wikimedia.org/w/index.php?curid=112634884],
caption: [บอร์ด NodeMCU ที่มี ESP32-C3-32S],
)
#iii โดยทั่วไปแล้ว ESP32
จะถูกฝังอยู่บนแผงวงจรพิมพ์เฉพาะอุปกรณ์หรือนำเสนอเป็นส่วนหนึ่งของชุดการพัฒนาที่มีพินและตัวเชื่อมต่อ
GPIO ที่หลากหลาย โดยมีการกำหนดค่าที่แตกต่างกันไปตามรุ่นและผู้ผลิต ESP32 ได้รับการออกแบบโดย
Espressif Systems และผลิตโดย TSMC โดยใช้กระบวนการ 40 นาโนเมตร
มันเป็นผู้สืบทอดของไมโครคอนโทรลเลอร์ ESP8266
]
=== Espressif Systems
#iiii บริษัท Espressif Systems (Shanghai) จำกัด (เอสเพรสซิฟ)
เป็นบริษัทเซมิคอนดักเตอร์สัญชาติจีนที่จดทะเบียนในตลาดหลักทรัพย์ มีสำนักงานใหญ่ตั้งอยู่ที่เซี่ยงไฮ้
บริษัทมุ่งเน้นการพัฒนาและจำหน่ายชิปและโมดูลสื่อสารไมโครคอนโทรลเลอร์ไร้สายที่ใช้ใน Internet of
things (IoT)
#iiii ผลิตภัณฑ์เซมิคอนดักเตอร์ที่เป็นที่รู้จักมากที่สุดสองอย่างของ Espressif คือ ESP8266 และ ESP32
ซึ่งเป็นรุ่นต่อจาก ESP8266 ผลิตภัณฑ์เหล่านี้ถูกนำไปใช้ในผลิตภัณฑ์ต่างๆ เช่น เครื่องชงกาแฟและหลอดไฟ
รวมถึงผู้ให้บริการโซลูชันเมืองอัจฉริยะและระบบอัตโนมัติ นอกจากนี้ยังถูกใช้โดยผู้ที่ชื่นชอบงาน DIY
ด้านเทคโนโลยีอีกด้วย
== ตารางพาร์ทิชัน (Partition Table)
#i ตารางพาร์ทิชันคือสิ่งที่กำหนดการจัดการรูปแบบหน่วยความจำแฟลชและข้อมูลต่าง
#iii ตารางพาร์ทิชันคือสิ่งที่กำหนดการจัดการรูปแบบหน่วยความจำแฟลชและข้อมูลต่าง
จะถูกเก็บไว้ในแต่ละพาร์ทิชัน
โดยผู้พัฒนาสามารถใช้รูปแบบตารางพาร์ทิชันที่ถูกกำหนดมาไว้แล้วหรือสามารถกำหนดรูปแบบตารางพาร์ทิชันเองก็ได้
#i โดยตารางพาร์ทัชันที่ถูกใช้ในโครงงานนี้มีรูปแบบดังนี้
โดยตารางพาร์ทัชันที่ถูกใช้ในโครงงานนี้มีรูปแบบดังนี้
#let partition-table = csv("PartitionTable.csv")
#table(
columns: 6,
table.header([Name], [Type], [SubType], [Offset], [Size], [Flags]),
..partition-table.flatten().slice(6),
#figure(
table(
columns: 6,
align: left,
table.header([Name], [Type], [SubType], [Offset], [Size], [Flags]),
..partition-table.flatten().slice(6),
),
caption: [รายการพาร์ทิชัน],
)
ซึ่งคือตารางค่าเริ่มต้นของ ESP32 ใน Arduino platform
#iii ซึ่งคือตารางค่าเริ่มต้นของ ESP32 ใน Arduino platform
อย่างไรก็ตามมีการเปลี่ยนแปลงระบบเก็บไฟล์จาก SPIFFS เป็น LittleFS โดยที่:
+ *Name:* ชื่อของพาร์ทิชัน ห้ามซ้ำกัน ชื่อนั้นไม่สำคัญต่อระบบและต้องขนาดไม่เกิน 16 ตัวอักษร
#block(inset: (left: 6em))[
+ Name คือ ชื่อของพาร์ทิชัน ห้ามซ้ำกัน ชื่อนั้นไม่สำคัญต่อระบบและต้องขนาดไม่เกิน 16 ตัวอักษร
(ไม่มีอักขระพิเศษ)
+ *Type:* ประเภทของพาร์ทชัน สามารถเป็น `data` หรือ `app` ได้
- `app` คือพาร์ทิชันที่ใช้ในการเก็บแอพลิเคชัน
- `data` คือพาร์ทิชันที่ใช้ในการเก็บข้อมูลทั่วไป
+ *SubType:* ประเภทย่อย ระบุการใช้งานของพาร์ทิชัน `app` และ `data`
- `data`
- `ota`: พาร์ทัชันเก็บข้อมูล OTA (สำหรับการอัพเดททางอากาศ, Over-the-air update)
โดยหากไม่ใช้งาน OTA สามารถนำออกได้ โดยขนาดของพาร์ทิชันนี้ควรจะมีขนาดที่แน่นอนอยู่ที่ 8 KiB
(0x2000 ไบต์)
- `nvs`: พาร์ทิชันเก็บข้อมูลทั่วไปเช่น ข้อมูล Wi-Fi, ข้อมูลการสอบเทียบ PHY ของอุปกรณ์,
และข้อมูลอื่น ที่ต้องถูกเก็บบนหน่วยความจำถาวร (Non-volatile memory)
โดยพาร์ทิชันประเภทนี้เหมาะสมสำหรับการเก็บข้อมูลการตั้งค่าเล็กน้อย ใบรองรับคลาวด์ ฯลฯ
และการใช้งาน NVS อีกอย่างคือการเก็บข้อมูลที่ละเอียดอ่อน เนื่องจาก NVS รองรับการเข้ารหัส
และเป็นสิ่งที่แนะนำอย่างมากที่จะมีพาร์ทิชัน NVS ขนาดขั้นต่ำ 12 KiB (0x3000 ไบต์)
และหากจำเป็น คุณสามารถขยายขนาดเพิ่มได้ โดยขนาดที่แนะนำนั้นอยู่ระหว่าง 12 KiB และ 64
KiB ถึงแม้ว่าคุณจะสามารถขยายให้มันใหญ่กว่านี้ได้ การใช้งานระบบไฟล์เช่น FAT หรือ SPIFFS
นั้นจะเหมาะสมสำหรับข้อมูลที่ใหญ่กว่า
- `coredump`: ประเภทพาร์ทิชันย่อยนี้มีหน้าที่ในการเก็บข้อมูล core dump บนหน่วยความจำแฟลช
โดย core dump
นั้นคือข้อมูลที่ถูกใช้งานสำหรับการตรวจสอบข้อผิด-พลาดร้ายแรงเช่นการแครชและแพนิค
โดยฟังก์ชันนี้จะต้องถูกเปิดในการตั้งค่าโปรเจกต์และตั้งที่หมายในการแฟลช
และพาร์ทิชันนี้มีขนาดที่แนะนำอยู่ที่ 64 KiB (0x10000)
- `nvs_keys`: พาร์ทิชันที่เป็นประเภทย่อยนี้เก็บคีย์การเข้ารหัสของพาร์ทัชัน NVS
เมื่อการเข้ารหัสถูกใช้งาน โดยมีขนาดอยู่ที่ 4 KiB (0x1000)
- `fat`: กำหนดพาร์ทิชันสำหรับระบบไฟล์ FAT โดยที่จะเหมาะสมสำหรับข้อมูลใหญ่
และหากข้อมูลนั้นถูกเปลี่ยนแปลงบ่อย โดยระบบไฟล์ FAT สามารถใช้ฟีเจอร์ wear leveling
และการเข้ารหัสได้
- `spiffs`: กำหนดพาร์ทิชันสำหรับระบบไฟล์ SPIFFS เหมาะสำหรับไฟล์ใหญ่เช่นกันและรองรับ
wear leveling อย่างไรก็ตาม ระบบไฟล์นี้ไม่รองรับการเข้ารหัส
- `app`
- `factory`: พาร์ทิชันเก็บแอพลิเคชันเริ่มต้น
โปรแกรมบูตโหลดเดอร์จะเลือกพาร์ทิชันนี้เป็นแอพลิเคชันเริ่มต้นหากไม่มีพาร์ทิชัน OTA หรือพาร์ทิชัน
OTA นั้นว่างเปล่า หากมีการใช้พาร์ทิชัน OTA พาร์ทิชัน `ota_0`
สามารถถูกใช้เป็นแอพลิเคชันเริ่มต้นได้และพาร์ทิชัน `factory` สามารถถูกนำออกได้
- `ota_0` ถึง `ota_15`: พาร์ทิชัน ota_x นั้นถูกใช้สำหรับอัพเดท OTA โดยฟีเจอร์ OTA
นั้นจำเป็นต้องใช้พาร์ทิชัน OTA อย่างน้อย 2 พาร์ทิชัน (โดยปกติคือ ota_0 และ ota_1)
และจำเป็นต้องใช้พาร์ทิชัน ota ด้วยเช่นกันในการเก็บข้อมูลเกี่ยวกับ OTA โดยสามารถมีพาร์ทิชัน
OTA ได้สูงสุด 16 พาร์ทิชัน แต่ 2 พาร์ทิชันคือจำนวนขั้นต่ำที่ต้องใช้สำหรับฟีเจอร์ OTA แบบเบสิค
- `test`: ใช้สำหรับการทดสอบในโรงงาน
+ *Offset:* กำหนดพื้นที่ที่พาร์ทิชันนั้นเริ่มต้น โดย Offset นั้นถูกกำหนดโดยการรวมค่า Offset
และขนาดของพาร์ทิชันก่อนหน้า \
*หมายเหตุ:* Offset จะต้องเป็นทวีคูณของ 4 KiB (0x1000)
และพาร์ทิชันแอพจะต้องจัดตำแหน่งให้มีขนาด 64 KiB (0x10000) โดยหากปล่อยให้ว่าง ค่า Offset
จะถูกคำนวนโดยอัตโนมัติตามตำแหน่งท้ายของพาร์ทิชันก่อนหน้า รวมถึงการจัดตำแหน่งใด ๆ ที่จำเป็น
อย่างไรก็ตาม Offset ของพาร์ทิชันแรกนั้นจะต้องเป็น *0x9000* และ *0x10000*
สำหรับพาร์ทิชันแอพลิเคชันแรก
+ *Size:* ขนาดของพาร์ทิชัน โดยค่านี้สามารถเป็นเลขทศนิยม, ตัวเลข Hex (นำหน้าด้วย `0x`),
หรือใช้ตัวอักษรต่อท้ายเพื่อบ่งบอกหน่วย K (กิโล) หรือ M (เมกา) เช่น 4096 = 4K = 0x1000
+ *Flags:* ในปัจจุบันคอลัมน์นี้ใช้เพียงแค่เพื่อบ่งบอกว่าพาร์ทิชันนั้น ๆ ถูกเข้ารหัสหรือไม่
+ Type คือ ประเภทของพาร์ทชัน สามารถเป็น data หรือ app ได้
+ app คือพาร์ทิชันที่ใช้ในการเก็บแอพลิเคชัน
+ data คือพาร์ทิชันที่ใช้ในการเก็บข้อมูลทั่วไป
+ SubType คือ ประเภทย่อย ระบุการใช้งานของพาร์ทิชัน data และ app
+ data
+ ota คือ พาร์ทัชันเก็บข้อมูล OTA (สำหรับการอัพเดททางอากาศ, Over-the-air update)
โดยหากไม่ใช้งาน OTA สามารถนำออกได้ โดยขนาดของพาร์ทิชันนี้ควรจะมีขนาดที่แน่นอนอยู่ที่ 8
KiB (0x2000 ไบต์)
+ nvs คือ พาร์ทิชันเก็บข้อมูลทั่วไปเช่น ข้อมูล Wi-Fi, ข้อมูลการสอบเทียบ PHY ของอุปกรณ์,
และข้อมูลอื่น ที่ต้องถูกเก็บบนหน่วยความจำถาวร (Non-volatile memory)
โดยพาร์ทิชันประเภทนี้เหมาะสมสำหรับการเก็บข้อมูลการตั้งค่าเล็กน้อย ใบรองรับคลาวด์ ฯลฯ
และการใช้งาน NVS อีกอย่างคือการเก็บข้อมูลที่ละเอียดอ่อน เนื่องจาก NVS รองรับการเข้ารหัส
และเป็นสิ่งที่แนะนำอย่างมากที่จะมีพาร์ทิชัน NVS ขนาดขั้นต่ำ 12 KiB (0x3000 ไบต์)
และหากจำเป็น คุณสามารถขยายขนาดเพิ่มได้ โดยขนาดที่แนะนำนั้นอยู่ระหว่าง 12 KiB และ 64
KiB ถึงแม้ว่าคุณจะสามารถขยายให้มันใหญ่กว่านี้ได้ การใช้งานระบบไฟล์เช่น FAT หรือ SPIFFS
นั้นจะเหมาะสมสำหรับข้อมูลที่ใหญ่กว่า
+ coredump คือ ประเภทพาร์ทิชันย่อยนี้มีหน้าที่ในการเก็บข้อมูล core dump บนหน่วยความจำแฟลช
โดย core dump
นั้นคือข้อมูลที่ถูกใช้งานสำหรับการตรวจสอบข้อผิด-พลาดร้ายแรงเช่นการแครชและแพนิค
โดยฟังก์ชันนี้จะต้องถูกเปิดในการตั้งค่าโปรเจกต์และตั้งที่หมายในการแฟลช
และพาร์ทิชันนี้มีขนาดที่แนะนำอยู่ที่ 64 KiB (0x10000)
+ nvs_keys คือ พาร์ทิชันที่เป็นประเภทย่อยนี้เก็บคีย์การเข้ารหัสของพาร์ทัชัน NVS
เมื่อการเข้ารหัสถูกใช้งาน โดยมีขนาดอยู่ที่ 4 KiB (0x1000)
+ fat คือ กำหนดพาร์ทิชันสำหรับระบบไฟล์ FAT โดยที่จะเหมาะสมสำหรับข้อมูลใหญ่
และหากข้อมูลนั้นถูกเปลี่ยนแปลงบ่อย โดยระบบไฟล์ FAT สามารถใช้ฟีเจอร์ wear leveling
และการเข้ารหัสได้
+ spiffs คือ กำหนดพาร์ทิชันสำหรับระบบไฟล์ SPIFFS เหมาะสำหรับไฟล์ใหญ่เช่นกันและรองรับ
wear leveling อย่างไรก็ตาม ระบบไฟล์นี้ไม่รองรับการเข้ารหัส
+ app
+ factory คือ พาร์ทิชันเก็บแอพลิเคชันเริ่มต้น
โปรแกรมบูตโหลดเดอร์จะเลือกพาร์ทิชันนี้เป็นแอพลิเคชันเริ่มต้นหากไม่มีพาร์ทิชัน OTA
หรือพาร์ทิชัน OTA นั้นว่างเปล่า หากมีการใช้พาร์ทิชัน OTA พาร์ทิชัน ota_0
สามารถถูกใช้เป็นแอพลิเคชันเริ่มต้นได้และพาร์ทิชัน factory สามารถถูกนำออกได้
+ ota_0 ถึง ota_15 คือ พาร์ทิชัน ota_x นั้นถูกใช้สำหรับอัพเดท OTA โดยฟีเจอร์ OTA
นั้นจำเป็นต้องใช้พาร์ทิชัน OTA อย่างน้อย 2 พาร์ทิชัน (โดยปกติคือ ota_0 และ ota_1)
และจำเป็นต้องใช้พาร์ทิชัน ota ด้วยเช่นกันในการเก็บข้อมูลเกี่ยวกับ OTA โดยสามารถมีพาร์ทิชัน
OTA ได้สูงสุด 16 พาร์ทิชัน แต่ 2 พาร์ทิชันคือจำนวนขั้นต่ำที่ต้องใช้สำหรับฟีเจอร์ OTA แบบเบสิค
+ test คือ ใช้สำหรับการทดสอบในโรงงาน
+ Offset คือ กำหนดพื้นที่ที่พาร์ทิชันนั้น เริ่มต้น โดย Offset นั้นถูกกำหนดโดยการรวมค่า Offset
และขนาดของพาร์ทิชันก่อนหน้า 0 อย่างไรก็ตาม Offset จะต้องเป็นทวีคูณของ 4 KiB (0x1000)
และพาร์ทิชันแอพจะต้องจัดตำแหน่งให้มีขนาด 64 KiB (0x10000) โดยหากปล่อยให้ว่าง ค่า Offset
จะถูกคำนวนโดยอัตโนมัติตามตำแหน่งท้ายของพาร์ทิชันก่อนหน้า รวมถึงการจัดตำแหน่งใด ที่จำเป็น
อย่างไรก็ตาม Offset ของพาร์ทิชันแรกนั้นจะต้องเป็น 0x9000 และ 0x10000
สำหรับพาร์ทิชันแอปพลิเคชันแรก
+ Size คือ ขนาดของพาร์ทิชัน โดยค่านี้สามารถเป็นเลขทศนิยม, ตัวเลข Hex (นำหน้าด้วย 0x),
หรือใช้ตัวอักษรต่อท้ายเพื่อบ่งบอกหน่วย K (กิโล) หรือ M (เมกา) เช่น 4096 = 4K = 0x1000
+ Flags คือ ในปัจจุบันคอลัมน์นี้ใช้เพียงแค่เพื่อบ่งบอกว่าพาร์ทิชันนั้น ถูกเข้ารหัสหรือไม่
]
== LittleFS
#i LittleFS คือระบบไฟล์ขนาดเล็กที่ปลอดภัยต่อความล้มเหลวที่ออกแบบมาสำหรับ#jb
== littlefs
#iii littlefs คือระบบไฟล์ขนาดเล็กที่ปลอดภัยต่อความล้มเหลวที่ออกแบบมาสำหรับ#jb
ไมโครคอนโทรลเลอร์
#show raw: set par(leading: 0.5em)
```
| | | .---._____
.-----. | |
--|o |---| littlefs |
--| |---| |
'-----' '----------'
| | |
```
*ความยืดหยุ่นในการป้องกันการสูญเสียพลังงาน* littlefs ออกแบบมาเพื่อรับมือกับปัญหาไฟฟ้าดับแบบสุ่ม
#iii ความยืดหยุ่นในการป้องกันการสูญเสียพลังงาน littlefs ออกแบบมาเพื่อรับมือกับปัญหาไฟฟ้าดับแบบสุ่ม
การดำเนินการไฟล์ทั้งหมดมีการรับประกันการคัดลอกข้อมูลเมื่อเขียนข้อมูล (copy-on-write) ที่แข็งแกร่ง
และหากไฟฟ้าดับ ระบบไฟล์จะกลับสู่สถานะปกติล่าสุดที่ทราบ
*การปรับระดับการสึกหรอแบบไดนามิก* littlefs ออกแบบมาเพื่อแฟลชโดยเฉพาะ
#iii การปรับระดับการสึกหรอแบบไดนามิก littlefs ออกแบบมาเพื่อแฟลชโดยเฉพาะ
และมอบการปรับระดับการสึกหรอบนบล็อกแบบไดนามิก นอกจากนี้ littlefs
ยังสามารถตรวจจับบล็อกเสียและแก้ไขปัญหาได้
*RAM/ROM แบบมีขอบเขต* littlefs ออกแบบมาเพื่อทำงานกับหน่วยความจำขนาดเล็ก การใช้งาน#jb
RAM ถูกจำกัดอย่างเข้มงวด ซึ่งหมายความว่าการใช้ RAM จะไม่เปลี่ยนแปลงเมื่อระบบไฟล์เติบโตขึ้น#jb
#iii RAM/ROM แบบมีขอบเขต littlefs ออกแบบมาเพื่อทำงานกับหน่วยความจำขนาดเล็ก#jb การใช้งาน
RAM ถูกจำกัดอย่างเข้มงวด ซึ่งหมายความว่าการใช้ RAM จะไม่เปลี่ยนแปลงเมื่อระบบไฟล์เติบโตขึ้น
ระบบไฟล์ไม่มีการเรียกซ้ำแบบไม่มีขอบเขต
และหน่วยความจำแบบไดนามิกถูกจำกัดให้อยู่ในบัฟเฟอร์ที่กำหนดค่าได้ซึ่งสามารถจัดเตรียมแบบคงที่ได้
== ออกแบบ
#i ในระดับสูง littlefs
#iii ในระดับสูง littlefs
เป็นระบบไฟล์แบบบล็อกที่ใช้ไฟล์บันทึกขนาดเล็กในการจัดเก็บข้อมูลเมตาและโครงสร้าง copy-on-write
(COW) ขนาดใหญ่ในการจัดเก็บข้อมูลไฟล์
#i ใน littlefs ส่วนผสมเหล่านี้ก่อตัวเป็นเค้กสองชั้น โดยที่ท่อนไม้ขนาดเล็ก (เรียกว่าคู่เมตาเดตา)#jb
จะให้การอัปเดตเมตาเดตาอย่างรวดเร็วในทุกที่ในที่เก็บข้อมูล ในขณะที่โครงสร้าง COW
จะจัดเก็บข้อมูลไฟล์อย่างกะทัดรัดและไม่มีค่าใช้จ่ายในการขยายการสึกหรอใด
#iii ใน littlefs ส่วนผสมเหล่านี้ก่อตัวเป็นเค้กสองชั้น โดยที่ท่อนไม้ขนาดเล็ก
(เรียกว่าคู่เมตาเดตา)#jb จะให้การอัปเดตเมตาเดตาอย่างรวดเร็วในทุกที่ในที่เก็บข้อมูล
ในขณะที่โครงสร้าง COW จะจัดเก็บข้อมูลไฟล์อย่างกะทัดรัดและไม่มีค่าใช้จ่ายในการขยายการสึกหรอใด
#i โครงสร้างข้อมูลทั้งสองนี้สร้างขึ้นจากบล็อก ซึ่งถูกป้อนโดยตัวจัดสรรบล็อกร่วม
โดยการจำกัดจำนวนการลบข้อมูลที่อนุญาตบนบล็อกต่อการจัดสรรแต่ละครั้ง
ตัวจัดสรรจะปรับระดับการสึกหรอแบบไดนามิกทั่วทั้งระบบไฟล์
#iii โครงสร้างข้อมูลทั้งสองนี้สร้างขึ้นจากบล็อก ซึ่งถูกป้อนโดยตัวจัดสรรบล็อกร่วม
โดยการจำกัดจำนวนการลบข้อมูลที่อนุญาตบนบล็อกต่อการจัดสรรแต่ละครั้ง ตัวจัดสรรจะปรับระดับการ#jb
สึกหรอแบบไดนามิกทั่วทั้งระบบไฟล์
```
root
.--------.--------.
| A'| B'| |
| | |-> |
| | | |
'--------'--------'
.----' '--------------.
A v B v
.--------.--------. .--------.--------.
| C'| D'| | | E'|new| |
| | |-> | | | E'|-> |
| | | | | | | |
'--------'--------' '--------'--------'
.-' '--. | '------------------.
v v .-' v
.--------. .--------. v .--------.
| C | | D | .--------. write | new E |
| | | | | E | ==> | |
| | | | | | | |
'--------' '--------' | | '--------'
'--------' .-' |
.-' '-. .-------------|------'
v v v v
.--------. .--------. .--------.
| F | | G | | new F |
| | | | | |
| | | | | |
'--------' '--------' '--------'
```
#show raw: set par(leading: 0.35em)
#show raw: set text(size: 6pt)
#afigure(
```
root
.--------.--------.
| A'| B'| |
| | |-> |
| | | |
'--------'--------'
.----' '--------------.
A v B v
.--------.--------. .--------.--------.
| C'| D'| | | E'|new| |
| | |-> | | | E'|-> |
| | | | | | | |
'--------'--------' '--------'--------'
.-' '--. | '------------------.
v v .-' v
.--------. .--------. v .--------.
| C | | D | .--------. write | new E |
| | | | | E | ==> | |
| | | | | | | |
'--------' '--------' | | '--------'
'--------' .-' |
.-' '-. .-------------|------'
v v v v
.--------. .--------. .--------.
| F | | G | | new F |
| | | | | |
| | | | | |
'--------' '--------' '--------'
```,
kind: image,
attr: [เจ้าของ LittleFS (ภายใต้สัญญาอนุญาต BSD-3-Clause)],
supplement: "รูปที่",
caption: [แสดงการทำงานเบื้องต้นของ LittleFS],
)
Binary file not shown.

After

Width:  |  Height:  |  Size: 723 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

+80 -20
View File
@@ -2,37 +2,86 @@
= การสื่อสารสนามใกล้ (Near-field communication; NFC)
#i การสื่อสารแบบใกล้สนาม (NFC) คือชุดโปรโตคอลการสื่อสารที่ทำให้สามารถสื่อสารระหว่างอุปกรณ์อิเล็กทรอนิกส์สองเครื่องในระยะทาง 4 ซม. (#math.equation(alt: "1 เศษ 1 ส่วน 2", $1 1/2$) นิ้ว) หรือน้อยกว่า NFC นำเสนอการเชื่อมต่อความเร็วต่ำผ่านการตั้งค่าที่ง่ายดายซึ่งสามารถใช้สำหรับการบูตสแตรปของการเชื่อมต่อไร้สายที่สามารถใช้งานได้เช่นเดียวกับเทคโนโลยีการ์ดระยะใกล้อื่นๆ NFC มีพื้นฐานมาจากการเชื่อมต่อแบบเหนี่ยวนำ ระหว่างขดลวดแม่เหล็กไฟฟ้าสองอันบนอุปกรณ์ที่รองรับ NFC เช่นสมาร์ทโฟนการสื่อสาร NFC ในทิศทางเดียวหรือทั้งสองทิศทางใช้ความถี่ 13.56 MHz ในย่านความถี่วิทยุ ISM ที่ไม่มีใบอนุญาต ซึ่งใช้กันทั่วโลก สอดคล้องกับมาตรฐานอินเทอร์เฟซทางอากาศ ISO/IEC 18000-3 ที่อัตราข้อมูลตั้งแต่ 106 ถึง 848 กิโลบิต/วินาที
#i การสื่อสารแบบใกล้สนาม (NFC)
คือชุดโปรโตคอลการสื่อสารที่ทำให้สามารถสื่อสารระหว่างอุปกรณ์อิเล็กทรอนิกส์สองเครื่องในระยะทาง 4 ซม.
(#math.equation(alt: "1 เศษ 1 ส่วน 2", $1 1/2$) นิ้ว) หรือน้อยกว่า NFC
นำเสนอการเชื่อมต่อความเร็วต่ำผ่านการตั้งค่าที่ง่ายดายซึ่งสามารถใช้สำหรับการบูตสแตรปของการเชื่อมต่อไร้สายที่สามารถใช้งานได้เช่นเดียวกับเทคโนโลยีการ์ดระยะใกล้อื่นๆ
NFC มีพื้นฐานมาจากการเชื่อมต่อแบบเหนี่ยวนำ ระหว่างขดลวดแม่เหล็กไฟฟ้าสองอันบนอุปกรณ์ที่รองรับ NFC
เช่นสมาร์ทโฟนการสื่อสาร NFC ในทิศทางเดียวหรือทั้งสองทิศทางใช้ความถี่ 13.56 MHz ในย่านความถี่วิทยุ
ISM ที่ไม่มีใบอนุญาต ซึ่งใช้กันทั่วโลก สอดคล้องกับมาตรฐานอินเทอร์เฟซทางอากาศ ISO/IEC 18000-3
ที่อัตราข้อมูลตั้งแต่ 106 ถึง 848 กิโลบิต/วินาที
#i ฟอรัม NFC ได้ช่วยกำหนดและส่งเสริมเทคโนโลยีโดยกำหนดมาตรฐานสำหรับการรับรองการปฏิบัติตามข้อกำหนดของอุปกรณ์การสื่อสารที่ปลอดภัยสามารถทำได้โดยใช้ขั้นตอนวิธีการเข้ารหัสเช่นเดียวกับที่ใช้กับบัตรเครดิตและหากตรงตามเกณฑ์สำหรับการพิจารณาให้เป็นเครือข่ายพื้นที่ส่วนบุคคล
#i ฟอรัม NFC
ได้ช่วยกำหนดและส่งเสริมเทคโนโลยีโดยกำหนดมาตรฐานสำหรับการรับรองการปฏิบัติตามข้อกำหนดของอุปกรณ์การสื่อสารที่ปลอดภัยสามารถทำได้โดยใช้ขั้นตอนวิธีการเข้ารหัสเช่นเดียวกับที่ใช้กับบัตรเครดิตและหากตรงตามเกณฑ์สำหรับการพิจารณาให้เป็นเครือข่ายพื้นที่ส่วนบุคคล
== มาตราฐาน NFC
#i มาตรฐาน NFC ครอบคลุมโปรโตคอลการสื่อสารและรูปแบบการแลกเปลี่ยนข้อมูล และอิงตามมาตรฐานการระบุด้วยคลื่นความถี่วิทยุ (RFID) ที่มีอยู่ รวมถึง ISO/IEC 14443 และ FeliCa มาตรฐานเหล่านี้รวมถึง ISO/IEC 18092 และมาตรฐานที่กำหนดโดย NFC Forum นอกจาก NFC Forum แล้วกลุ่ม GSMA ยังได้กำหนดแพลตฟอร์มสำหรับการปรับใช้มาตรฐาน NFC ของ GSMA ภายในโทรศัพท์มือถือ ความพยายามของ GSMA ได้แก่ Trusted Services Manager, Single Wire Protocol, การทดสอบ/การรับรอง และองค์ประกอบความปลอดภัยอุปกรณ์พกพาที่เปิดใช้งาน NFC สามารถมาพร้อมกับซอฟต์แวร์แอปพลิเคชันเช่น เพื่ออ่านแท็กอิเล็กทรอนิกส์หรือชำระเงินเมื่อเชื่อมต่อกับระบบที่รองรับ NFC สิ่งเหล่านี้เป็นมาตรฐานของโปรโตคอล NFC แทนที่เทคโนโลยีที่เป็นกรรมสิทธิ์ที่ใช้ในระบบก่อนหน้านี้
#iii มาตรฐาน NFC ครอบคลุมโปรโตคอลการสื่อสารและรูปแบบการแลกเปลี่ยนข้อมูล
และอิงตามมาตรฐานการระบุด้วยคลื่นความถี่วิทยุ (RFID) ที่มีอยู่ รวมถึง ISO/IEC 14443 และ FeliCa
มาตรฐานเหล่านี้รวมถึง ISO/IEC 18092 และมาตรฐานที่กำหนดโดย NFC Forum นอกจาก NFC Forum
แล้วกลุ่ม GSMA ยังได้กำหนดแพลตฟอร์มสำหรับการปรับใช้มาตรฐาน NFC ของ GSMA ภายในโทรศัพท์มือถือ
ความพยายามของ GSMA ได้แก่ Trusted Services Manager, Single Wire Protocol,
การทดสอบ/การรับรอง และองค์ประกอบความปลอดภัยอุปกรณ์พกพาที่เปิดใช้งาน NFC
สามารถมาพร้อมกับซอฟต์แวร์แอปพลิเคชันเช่น
เพื่ออ่านแท็กอิเล็กทรอนิกส์หรือชำระเงินเมื่อเชื่อมต่อกับระบบที่รองรับ NFC
สิ่งเหล่านี้เป็นมาตรฐานของโปรโตคอล NFC แทนที่เทคโนโลยีที่เป็นกรรมสิทธิ์ที่ใช้ในระบบก่อนหน้านี้
#i โปรแกรมอนุญาตสิทธิ์สิทธิบัตรสำหรับ NFC กำลังอยู่ระหว่างการใช้งานโดย France Brevets ซึ่งเป็นกองทุนสิทธิบัตรที่จัดตั้งขึ้นในปี 2011 โปรแกรมนี้อยู่ระหว่างการพัฒนาโดย Via Licensing Corporation ซึ่งเป็นบริษัทสาขาอิสระของ Dolby Laboratories และยุติลงในเดือนพฤษภาคม 2012 ไลบรารี NFC แบบโอเพนซอร์สและอิสระต่อแพลตฟอร์ม libnfc มีให้บริการภายใต้ใบอนุญาตสาธารณะทั่วไปแบบผ่อนปรนของ GNU
#iii โปรแกรมอนุญาตสิทธิ์สิทธิบัตรสำหรับ NFC กำลังอยู่ระหว่างการใช้งานโดย France Brevets
ซึ่งเป็นกองทุนสิทธิบัตรที่จัดตั้งขึ้นในปี 2011 โปรแกรมนี้อยู่ระหว่างการพัฒนาโดย Via Licensing
Corporation ซึ่งเป็นบริษัทสาขาอิสระของ Dolby Laboratories และยุติลงในเดือน#jb พฤษภาคม
2012 ไลบรารี NFC แบบโอเพนซอร์สและอิสระต่อแพลตฟอร์ม libnfc มีให้บริการภายใต้ใบอนุญาต GNU
Lesser General Public License (LGPL)
#i แอปพลิเคชันปัจจุบันและที่คาดว่าจะมีในอนาคต ได้แก่ ธุรกรรมแบบไร้สัมผัส การแลกเปลี่ยนข้อมูล และการตั้งค่าการสื่อสารที่ซับซ้อนมากขึ้น เช่น Wi-Fi ที่ง่าย ขึ้นนอกจากนี้เมื่ออุปกรณ์ที่เชื่อมต่อเครื่องหนึ่งมีการเชื่อมต่ออินเทอร์เน็ตอีกเครื่องหนึ่งก็สามารถแลกเปลี่ยนข้อมูลกับบริการออนไลน์ได้
#iii แอปพลิเคชันปัจจุบันและที่คาดว่าจะมีในอนาคต ได้แก่ ธุรกรรมแบบไร้สัมผัส การแลกเปลี่ยนข้อมูล
และการตั้งค่าการสื่อสารที่ซับซ้อนมากขึ้น เช่น Wi-Fi ที่ง่าย
ขึ้นนอกจากนี้เมื่ออุปกรณ์ที่เชื่อมต่อเครื่องหนึ่งมีการเชื่อมต่ออินเทอร์เน็ตอีกเครื่องหนึ่งก็สามารถแลกเปลี่ยนข้อมูลกับบริการออนไลน์ได้
== ออกแบบ
#i NFC เป็นชุดเทคโนโลยีไร้สายระยะสั้น โดยทั่วไปต้องมีระยะห่าง 10 ซม. (#math.equation(alt: "3 เศษ 7 ส่วน 8", $3 7/8$) นิ้ว) หรือน้อยกว่า NFC ทำงานที่ความถี่ 13.56 MHz บนอินเทอร์เฟซทางอากาศ ISO/IEC 18000-3 และที่อัตราตั้งแต่ 106 กิโลบิต/วินาที ถึง 424 กิโลบิต/วินาที NFC มักประกอบด้วยตัวเริ่มต้นและเป้าหมาย ตัวเริ่มต้นจะสร้างสนาม RF ที่สามารถจ่ายพลังงานให้กับเป้าหมายแบบพาสซีฟได้ ซึ่งทำให้เป้าหมาย NFC มีรูปแบบที่เรียบง่ายมาก เช่น แท็ก สติกเกอร์ พวงกุญแจ หรือการ์ดที่ไม่ได้รับพลังงานการสื่อสารแบบเพียร์ทูเพียร์ของ NFC สามารถทำได้หากอุปกรณ์ทั้งสองมีพลังงาน
#iii NFC เป็นชุดเทคโนโลยีไร้สายระยะสั้น โดยทั่วไปต้องมีระยะห่าง 10 ซม. (#math.equation(
alt: "3 เศษ 7 ส่วน 8",
$3 7/8$,
) นิ้ว) หรือน้อยกว่า NFC ทำงานที่ความถี่ 13.56 MHz บนอินเทอร์เฟซทางอากาศ ISO/IEC 18000-3
และที่อัตราตั้งแต่ 106 กิโลบิต/วินาที ถึง 424 กิโลบิต/วินาที NFC มักประกอบด้วยตัวเริ่มต้นและเป้าหมาย
ตัวเริ่มต้นจะสร้างสนาม RF ที่สามารถจ่ายพลังงานให้กับเป้าหมายแบบพาสซีฟได้ ซึ่งทำให้เป้าหมาย NFC
มีรูปแบบที่เรียบง่ายมาก เช่น แท็ก สติกเกอร์ พวงกุญแจ
หรือการ์ดที่ไม่ได้รับพลังงานการสื่อสารแบบเพียร์ทูเพียร์ของ NFC สามารถทำได้หากอุปกรณ์ทั้งสองมีพลังงาน
#i แท็ก NFC มีข้อมูลและโดยทั่วไปเป็นแบบอ่านอย่างเดียว แต่อาจเขียนได้ ผู้ผลิตสามารถกำหนดรหัสเองได้ หรือใช้ข้อกำหนดของ NFC Forum แท็กสามารถจัดเก็บข้อมูลส่วนบุคคลอย่างปลอดภัย เช่น ข้อมูลบัตรเดบิตและบัตรเครดิต ข้อมูลโปรแกรมสะสมคะแนน รหัส PIN และรายชื่อผู้ติดต่อในเครือข่าย
รวมถึงข้อมูลอื่นๆ NFC Forum กำหนดแท็กห้าประเภทที่มีความเร็วและความสามารถในการสื่อสารที่แตกต่างกันในแง่ของความสามารถในการกำหนดค่าหน่วยความจำ ความปลอดภัยการเก็บข้อมูลและความทนทานต่อการเขียน
#iii แท็ก NFC มีข้อมูลและโดยทั่วไปเป็นแบบอ่านอย่างเดียว แต่อาจเขียนได้
ผู้ผลิตสามารถกำหนดรหัสเองได้ หรือใช้ข้อกำหนดของ NFC Forum
แท็กสามารถจัดเก็บข้อมูลส่วนบุคคลอย่างปลอดภัย เช่น ข้อมูลบัตรเดบิตและบัตรเครดิต
ข้อมูลโปรแกรมสะสมคะแนน รหัส PIN และรายชื่อผู้ติดต่อในเครือข่าย รวมถึงข้อมูลอื่นๆ NFC Forum
กำหนดแท็กห้าประเภทที่มีความเร็วและความสามารถในการสื่อสารที่แตกต่างกันในแง่ของความสามารถในการกำหนดค่าหน่วยความจำ
ความปลอดภัยการเก็บข้อมูลและความทนทานต่อการเขียน
#i เช่นเดียวกับ เทคโนโลยี การ์ดแบบ Proximity NFC ใช้การเชื่อมต่อแบบเหนี่ยวนำระหว่างเสาอากาศแบบวงสองต้นที่อยู่ใกล้เคียงกัน
ซึ่งก่อตัวเป็นหม้อแปลงแกนอากาศได้อย่างมีประสิทธิภาพเนื่องจากระยะทางที่เกี่ยวข้องนั้นน้อยมากเมื่อเทียบกับความยาวคลื่นของรังสีแม่เหล็กไฟฟ้า (คลื่นวิทยุ) ของความถี่นั้น (ประมาณ 22 เมตร) ปฏิสัมพันธ์นี้จึงถูกเรียกว่า สนามแม่เหล็กใกล้ (Near Field) สนามแม่เหล็กไฟฟ้าสลับเป็นปัจจัยการเชื่อมต่อหลัก และแทบไม่มีพลังงานแผ่ออกมาในรูปแบบของคลื่นวิทยุ (ซึ่งเป็นคลื่นแม่เหล็กไฟฟ้าที่เกี่ยวข้องกับสนามไฟฟ้าสั่นด้วย) ซึ่งช่วยลดการรบกวนระหว่างอุปกรณ์ดังกล่าวกับการสื่อสารทางวิทยุใดๆ ที่ความถี่เดียวกันหรือกับอุปกรณ์ NFC อื่นๆ ที่อยู่นอกเหนือขอบเขตที่ตั้งใจไว้ NFC ทำงานในย่านความถี่วิทยุ ISM ซึ่งใช้ทั่วโลกและไม่ได้รับอนุญาตที่ 13.56 MHz พลังงาน RF ส่วนใหญ่กระจุกตัวอยู่ในแบนด์วิดท์ ±7 kHz ที่จัดสรรให้กับย่านความถี่นั้น แต่ ความกว้างสเปกตรัมของการแผ่รังสีอาจกว้างได้ถึง 1.8 MHz เพื่อรองรับอัตราข้อมูลสูง
#iii เช่นเดียวกับ เทคโนโลยี การ์ดแบบ Proximity NFC
ใช้การเชื่อมต่อแบบเหนี่ยวนระหว่างเสาอากาศแบบวงสองต้นที่อยู่ใกล้เคียงกัน
ซึ่งก่อตัวเป็นหม้อแปลงแกนอากาศได้อย่างมีประสิทธิภาพเนื่องจากระยะทางที่เกี่ยวข้องนั้นน้อยมากเมื่อเทียบกับความยาวคลื่นของรังสีแม่เหล็กไฟฟ้า
(คลื่นวิทยุ) ของความถี่นั้น (ประมาณ 22 เมตร) ปฏิสัมพันธ์นี้จึงถูกเรียกว่า สนามแม่เหล็กใกล้ (Near
Field) สนามแม่เหล็กไฟฟ้าสลับเป็นปัจจัยการเชื่อมต่อหลัก
และแทบไม่มีพลังงานแผ่ออกมาในรูปแบบของคลื่นวิทยุ
(ซึ่งเป็นคลื่นแม่เหล็กไฟฟ้าที่เกี่ยวข้องกับสนามไฟฟ้าสั่นด้วย)
ซึ่งช่วยลดการรบกวนระหว่างอุปกรณ์ดังกล่าวกับการสื่อสารทางวิทยุใดๆ ที่ความถี่เดียวกันหรือกับอุปกรณ์ NFC
อื่นๆ ที่อยู่นอกเหนือขอบเขตที่ตั้งใจไว้ NFC ทำงานในย่านความถี่วิทยุ ISM ซึ่งใช้ทั่วโลกและไม่ได้รับอนุญาตที่
13.56 MHz พลังงาน RF ส่วนใหญ่กระจุกตัวอยู่ในแบนด์วิดท์ ±7 kHz ที่จัดสรรให้กับย่านความถี่นั้น แต่
ความกว้างสเปกตรัมของการแผ่รังสีอาจกว้างได้ถึง 1.8 MHz เพื่อรองรับอัตราข้อมูลสูง
#i ระยะการทำงานด้วยเสาอากาศมาตรฐานขนาดกะทัดรัดและระดับพลังงานที่สมจริงอาจสูงถึงประมาณ 20 ซม. (#math.equation(alt: "7 เศษ 7 ส่วน 8", $7 7/8$) นิ้ว) (แต่ในทางปฏิบัติ ระยะการทำงานไม่ควรเกิน 10 ซม. หรือ #math.equation(alt: "3 เศษ 7 ส่วน 8", $3 7/8$) นิ้ว) โปรดทราบว่าเนื่องจากเสาอากาศรับสัญญาณอาจถูกดับในกระแสวนโดยพื้นผิวโลหะที่อยู่ใกล้เคียง แท็กอาจต้องแยกออกจากพื้นผิวดังกล่าวอย่างน้อยที่สุด
#iii ระยะการทำงานด้วยเสาอากาศมาตรฐานขนาดกะทัดรัดและระดับพลังงานที่สมจริงอาจสูงถึงประมาณ 20
ซม. (#math.equation(alt: "7 เศษ 7 ส่วน 8", $7 7/8$) นิ้ว) (แต่ในทางปฏิบัติ
ระยะการทำงานไม่ควรเกิน 10 ซม. หรือ #math.equation(alt: "3 เศษ 7 ส่วน 8", $3 7/8$)
นิ้ว) โปรดทราบว่าเนื่องจากเสาอากาศรับสัญญาณอาจถูกดับในกระแสวนโดยพื้นผิวโลหะที่อยู่ใกล้เคียง
แท็กอาจต้องแยกออกจากพื้นผิวดังกล่าวอย่างน้อยที่สุด
มาตรฐาน ISO/IEC 18092 รองรับอัตราข้อมูล 106, 212 หรือ 424 กิโลบิต/วินาที
การสื่อสารเกิดขึ้นระหว่างอุปกรณ์ "ตัวเริ่มต้น" ที่ใช้งานอยู่และอุปกรณ์เป้าหมาย ซึ่งอาจเป็น:
การสื่อสารเกิดขึ้นระหว่างอุปกรณ์ "ตัวเริ่มต้น" ที่ใช้งานอยู่และอุปกรณ์เป้าหมาย ซึ่งอาจเป็น
/ พาสซีฟ: อุปกรณ์ตัวเริ่มต้นจะทำหน้าที่เป็นสนามแม่เหล็กพาหะ และอุปกรณ์เป้าหมายจะสื่อสารโดยการปรับสนามแม่เหล็กตกกระทบ ในโหมดนี้ อุปกรณ์เป้าหมายอาจดึงพลังงานจากสนามแม่เหล็กที่ตัวเริ่มต้นจัดหาให้
+ พาสซีฟ โดยอุปกรณ์ตัวเริ่มต้นจะทำหน้าที่เป็นสนามแม่เหล็กพาหะ
และอุปกรณ์เป้าหมายจะสื่อสารโดยการปรับสนามแม่เหล็กตกกระทบ ในโหมดนี้
อุปกรณ์เป้าหมายอาจดึงพลังงานจากสนามแม่เหล็กที่ตัวเริ่มต้นจัดหาให้
/ คล่องแคล่ว: ทั้งอุปกรณ์เริ่มต้นและอุปกรณ์เป้าหมายสื่อสารกันโดยการสร้างฟิลด์ของตัวเองสลับกัน อุปกรณ์จะหยุดส่งสัญญาณเพื่อรับข้อมูลจากอีกอุปกรณ์หนึ่ง โหมดนี้กำหนดให้อุปกรณ์ทั้งสองต้องมีแหล่งจ่ายไฟ
+ คล่องแคล่ว โดยทั้งอุปกรณ์เริ่มต้นและอุปกรณ์เป้าหมายสื่อสารกันโดยการสร้างฟิลด์ของตัวเองสลับกัน
อุปกรณ์จะหยุดส่งสัญญาณเพื่อรับข้อมูลจากอีกอุปกรณ์หนึ่ง โหมดนี้กำหนดให้อุปกรณ์ทั้งสองต้องมีแหล่งจ่ายไฟ
#figure(
table(
@@ -45,12 +94,23 @@
caption: [การเทียบความเร็วและวิธีการสื่อสารที่ใช้],
)
#i NFC ใช้การเข้ารหัสสองแบบที่แตกต่างกันในการถ่ายโอนข้อมูล หากอุปกรณ์ที่ใช้งานอยู่ถ่ายโอนข้อมูลที่ความเร็ว 106 กิโลบิต/วินาที จะใช้การเข้ารหัสแบบมิลเลอร์ที่ปรับเปลี่ยนแล้วพร้อมการมอดูเลต 100 เปอร์เซ็นต์ในกรณีอื่นๆทั้งหมดจะใช้การเข้ารหัสแบบแมนเชสเตอร์โดยมีอัตราการมอดูเลต 10 เปอร์เซ็นต์
#iii NFC ใช้การเข้ารหัสสองแบบที่แตกต่างกันในการถ่ายโอนข้อมูล
หากอุปกรณ์ที่ใช้งานอยู่ถ่ายโอนข้อมูลที่ความเร็ว 106 กิโลบิต/วินาที
จะใช้การเข้ารหัสแบบมิลเลอร์ที่ปรับเปลี่ยนแล้วพร้อมการมอดูเลต 100
เปอร์เซ็นต์ในกรณีอื่นๆทั้งหมดจะใช้การเข้ารหัสแบบแมนเชสเตอร์โดยมีอัตราการมอดูเลต 10 เปอร์เซ็นต์
อุปกรณ์ NFC ที่ใช้งานอยู่ทุกเครื่องสามารถทำงานในโหมดใดโหมดหนึ่งหรือหลายโหมดได้:
#iii อุปกรณ์ NFC ที่ใช้งานอยู่ทุกเครื่องสามารถทำงานในโหมดใดโหมดหนึ่งหรือหลายโหมดได้
/ การจำลองการ์ด NFC: ช่วยให้อุปกรณ์ที่รองรับ NFC เช่น สมาร์ทโฟน ทำหน้าที่เหมือนสมาร์ทการ์ด ช่วยให้ผู้ใช้ทำธุรกรรมต่างๆ เช่น การชำระเงินหรือการออกตั๋วได้ ดูการจำลองการ์ดโฮสต์
/ เครื่องอ่าน/เขียน NFC: ช่วยให้อุปกรณ์ที่เปิดใช้งาน NFC สามารถอ่านข้อมูลที่จัดเก็บไว้ในแท็ก NFC ราคาไม่แพงที่ฝังอยู่ในฉลากหรือโปสเตอร์อัจฉริยะได้
/ NFC เพียร์ทูเพียร์: ช่วยให้อุปกรณ์ที่เปิดใช้งาน NFC องเครื่องสามารถสื่อสารกันเพื่อแลกเปลี่ยนข้อมูลในลักษณะ เฉพาะกิจ
+ การจำลองการ์ด NFC ช่วยให้อุปกรณ์ที่รองรับ NFC เช่น สมาร์ทโฟน ทำหน้าที่เหมือนสมาร์ทการ์ด
ช่วยให้ผู้ใช้ทำธุรกรรมต่างๆ เช่น การชำระเงินหรือการออกตั๋วได้ ดูการจำลองการ์ดโฮสต์
+ เครื่องอ่าน/เขียน NFC ช่วยให้อุปกรณ์ที่เปิดใช้งาน NFC ามารถอ่านข้อมูลที่จัดเก็บไว้ในแท็ก NFC
ราคาไม่แพงที่ฝังอยู่ในฉลากหรือโปสเตอร์อัจฉริยะได้
+ NFC เพียร์ทูเพียร์ ช่วยให้อุปกรณ์ที่เปิดใช้งาน NFC
สองเครื่องสามารถสื่อสารกันเพื่อแลกเปลี่ยนข้อมูลในลักษณะ เฉพาะกิจ
แท็ก NFC คือหน่วยเก็บข้อมูลแบบพาสซีฟที่อุปกรณ์ NFC สามารถอ่านและเขียนข้อมูลได้ในบางกรณี โดยทั่วไปจะมีข้อมูล (ณ ปี 2015 มีขนาดระหว่าง 96 ถึง 8,192 ไบต์) และเป็นแบบอ่านอย่างเดียวในการใช้งานปกติ แต่อาจเขียนซ้ำได้ การใช้งานรวมถึงการจัดเก็บข้อมูลส่วนบุคคลที่ปลอดภัย (เช่นข้อมูล บัตร เดบิตหรือบัตรเครดิตข้อมูลโปรแกรมสะสมคะแนน หมายเลขประจำตัว (PIN) และรายชื่อผู้ติดต่อ)\ แท็ก NFC สามารถเข้ารหัสแบบกำหนดเองโดยผู้ผลิต หรือใช้ข้อกำหนดเฉพาะของอุตสาหกรรม
แท็ก NFC คือหน่วยเก็บข้อมูลแบบพาสซีฟที่อุปกรณ์ NFC สามารถอ่านและเขียนข้อมูลได้ในบางกรณี#jb
โดยทั่วไปจะมีข้อมูล (ณ ปี 2015 มีขนาดระหว่าง 96 ถึง 8,192 ไบต์)
และเป็นแบบอ่านอย่างเดียวในการใช้งานปกติ แต่อาจเขียนซ้ำได้
การใช้งานรวมถึงการจัดเก็บข้อมูลส่วนบุคคลที่ปลอดภัย (เช่นข้อมูล บัตร
เดบิตหรือบัตรเครดิตข้อมูลโปรแกรมสะสมคะแนน หมายเลขประจำตัว (PIN) และรายชื่อผู้ติดต่อ)\ แท็ก NFC
สามารถเข้ารหัสแบบกำหนดเองโดยผู้ผลิต หรือใช้ข้อกำหนดเฉพาะของอุตสาหกรรม
+20 -13
View File
@@ -1,25 +1,32 @@
#import "../PageTemplate.typ": i
#import "../PageTemplate.typ": *
#set heading(numbering: "1.1", offset: 2)
= OpenSSL
#i OpenSSL คือไลบรารีซอฟต์แวร์สำหรับแอปพลิเคชันที่ให้การสื่อสารที่ปลอดภัยผ่านเครือข่ายคอมพิวเตอร์ป้องกันการดักฟังและระบุตัวบุคคลที่อยู่ปลายทาง OpenSSL ถูกใช้อย่างแพร่หลายในเซิร์ฟเวอร์อินเทอร์เน็ตรวมถึงเว็บไซต์ HTTPS ส่วนใหญ่
OpenSSL ประกอบด้วยการนำโปรโตคอล SSL และ TLS ไปใช้งานแบบโอเพนซอร์สไลบรารีหลักที่เขียนด้วยภาษา C ทำหน้าที่เข้ารหัสข้อมูลพื้นฐานและมีฟังก์ชันยูทิลิตี้ต่างๆมากมาย มีแรปเปอร์ (Wrapper) ที่ช่วยให้สามารถใช้ไลบรารี OpenSSL ในภาษาคอมพิวเตอร์ได้หลากหลายภาษา
#iii OpenSSL
คือไลบรารีซอฟต์แวร์สำหรับแอปพลิเคชันที่ให้การสื่อสารที่ปลอดภัยผ่านเครือข่ายคอมพิวเตอร์ป้องกันการดักฟังและระบุตัวบุคคลที่อยู่ปลายทาง
OpenSSL ถูกใช้อย่างแพร่หลายในเซิร์ฟเวอร์อินเทอร์เน็ตรวมถึงเว็บไซต์ HTTPS ส่วนใหญ่ OpenSSL
ประกอบด้วยการนำโปรโตคอล SSL และ TLS ไปใช้งานแบบโอเพนซอร์สไลบรารีหลักที่เขียนด้วยภาษา C
ทำหน้าที่เข้ารหัสข้อมูลพื้นฐานและมีฟังก์ชันยูทิลิตี้ต่างๆมากมาย มีแรปเปอร์ (Wrapper)
ที่ช่วยให้สามารถใช้ไลบรารี OpenSSL ในภาษาคอมพิวเตอร์ได้หลากหลายภาษา
#i มูลนิธิซอฟต์แวร์ OpenSSL (OSF) เป็นตัวแทนของโครงการ OpenSSL ในขอบเขตทางกฎหมายส่วนใหญ่ ซึ่งรวมถึงข้อตกลงสิทธิ์การใช้งานสำหรับผู้สนับสนุนการจัดการการบริจาค และอื่นๆบริการซอฟต์แวร์ OpenSSL (OSS) ยังเป็นตัวแทนของโครงการ OpenSSL สำหรับสัญญาสนับสนุนอีกด้วย
#iii มูลนิธิซอฟต์แวร์ OpenSSL (OSF) เป็นตัวแทนของโครงการ OpenSSL
ในขอบเขตทางกฎหมายส่วนใหญ่ ซึ่งรวมถึงข้อตกลงสิทธิ์การใช้งานสำหรับผู้สนับสนุนการจัดการการบริจาค
และอื่นๆบริการซอฟต์แวร์ OpenSSL (OSS) ยังเป็นตัวแทนของโครงการ OpenSSL
สำหรับสัญญาสนับสนุนอีกด้วย
#i OpenSSL พร้อมใช้งานสำหรับระบบปฏิบัติการประเภท Unix ส่วนใหญ่ (รวมถึง Linux , macOS และ BSD ), Microsoft Windows และ OpenVMS
#iii OpenSSL พร้อมใช้งานสำหรับระบบปฏิบัติการประเภท Unix ส่วนใหญ่ (รวมถึง Linux , macOS
และ BSD ), Microsoft Windows และ OpenVMS
#i OpenSSL รองรับอัลกอริทึมการเข้ารหัสที่แตกต่างกันจำนวนหนึ่ง:
#iii OpenSSL รองรับอัลกอริทึมการเข้ารหัสที่แตกต่างกันจำนวนหนึ่ง โดยฟังก์ชันการเข้ารหัสได้แก่ AES,
Blowfish, Camellia, ChaCha20, Poly1305, SEED, CAST-128, DES, IDEA, RC2, RC4,
RC5, Triple DES, GOST 28147-89, SM4
*รหัส:*
AES, Blowfish, Camellia, ChaCha20, Poly1305, SEED, CAST-128, DES, IDEA, RC2, RC4, RC5, Triple DES, GOST 28147-89, SM4
#iii ฟังก์ชันแฮชการเข้ารหัสได้แก่ MD5, MD4, MD2, SHA-1, SHA-2, SHA-3, RIPEMD-160,
MDC-2, GOST R 34.11-94, BLAKE2, วังวน, SM3
*ฟังก์ชันแฮชการเข้ารหัส:*
MD5, MD4, MD2, SHA-1, SHA-2, SHA-3, RIPEMD-160, MDC-2, GOST R 34.11-94, BLAKE2, วังวน, SM3
*การเข้ารหัสด้วยคีย์สาธารณะ:*
RSA, DSA, การแลกเปลี่ยนคีย์ Diffie--Hellman, เส้นโค้งวงรี, X25519, Ed25519, X448, Ed448, GOST R 34.10-2001, SM2
#iii ฟังก์ชันการเข้ารหัสด้วยคีย์สาธารณะได้แก่ RSA, DSA, การแลกเปลี่ยนคีย์ Diffie--Hellman,
เส้นโค้งวงรี, X25519, Ed25519, X448, Ed448, GOST R 34.10-2001, SM2
(การปกปิดแบบสมบูรณ์แบบได้รับการสนับสนุนโดยใช้เส้นโค้งวงรี Diffie--Hellman ตั้งแต่เวอร์ชัน 1.0)
+184 -50
View File
@@ -5,79 +5,149 @@
= เซ็นเซอร์อินฟราเรดแบบพาสซีฟ (PIR sensor)
#i เซ็นเซอร์อินฟราเรดแบบพาสซีฟ (PIR sensor) คือ เซ็นเซอร์อิเล็กทรอนิกส์ที่วัดแสงอินฟราเรด (IR) ที่แผ่ออกมาจากวัตถุในระยะการมองเห็น เซ็นเซอร์ชนิดนี้มักใช้ในเครื่องตรวจจับความเคลื่อนไหว แบบ PIR เซ็นเซอร์ PIR มักใช้ในสัญญาณเตือนภัยและระบบไฟส่องสว่างอัตโนมัติ
#iii เซ็นเซอร์อินฟราเรดแบบพาสซีฟ (PIR sensor) คือ เซ็นเซอร์อิเล็กทรอนิกส์ที่วัดแสงอินฟราเรด
(IR) ที่แผ่ออกมาจากวัตถุในระยะการมองเห็น เซ็นเซอร์ชนิดนี้มักใช้ในเครื่องตรวจจับความเคลื่อนไหว แบบ
PIR เซ็นเซอร์ PIR มักใช้ในสัญญาณเตือนภัยและระบบไฟส่องสว่างอัตโนมัติ
#v(1em)
#afigure(
image("PIR/Front-Fresnel_type.jpg", height: image-height),
attr: [Jack LaRosa, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4479143],
attr: [Jack LaRosa, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=4479143],
alt: "เซนเซอร์ตรวจจับการเคลื่อนไหวทรงสี่เหลี่ยมผืนผ้าแนวตั้ง",
caption: [เครื่องตรวจจับการเคลื่อนไหวแบบ PIR ทั่วไปสำหรับที่พักอาศัย/เชิงพาณิชย์],
)
#i เซ็นเซอร์ PIR ตรวจจับการเคลื่อนไหวทั่วไป แต่ไม่ได้ให้ข้อมูลว่าใครหรือสิ่งใดเคลื่อนไหว ดังนั้น จึงจำเป็นต้องใช้ เซ็นเซอร์ IR แบบสร้างภาพ เซ็นเซอร์ PIR มักเรียกสั้นๆ ว่า "PIR" หรือบางครั้งเรียกว่า "PID" ซึ่งย่อมาจาก "เครื่องตรวจจับอินฟราเรดแบบพาสซีฟ" เซ็นเซอร์ PIR ตรวจจับการเคลื่อนไหวทั่วไป แต่ไม่ได้ให้ข้อมูลว่าใครหรือสิ่งใดเคลื่อนไหว ดังนั้น จึงจำเป็นต้องใช้ เซ็นเซอร์ IR แบบสร้างภาพ เซ็นเซอร์ PIR มักเรียกสั้นๆ ว่า "PIR" หรือบางครั้งเรียกว่า "PID" ซึ่งย่อมาจาก "เครื่องตรวจจับอินฟราเรดแบบพาสซีฟ" คำว่าพาสซีฟหมายถึงข้อเท็จจริงที่ว่าอุปกรณ์ PIR ไม่ได้แผ่พลังงานเพื่อจุดประสงค์ในการตรวจจับ แต่ทำงานโดยการตรวจจับรังสีอินฟราเรด (ความร้อนจากการแผ่รังสี) ที่แผ่ออกมาจากหรือสะท้อนจากวัตถุ เท่านั้นซีฟ" คำว่าพาสซีฟหมายถึงข้อเท็จจริงที่ว่าอุปกรณ์ PIR ไม่ได้แผ่พลังงานเพื่อจุดประสงค์ในการตรวจจับ แต่ทำงานโดยการตรวจจับรังสีอินฟราเรด (ความร้อนจากการแผ่รังสี) ที่แผ่ออกมาจากหรือสะท้อนจากวัตถุ เท่านั้น
#iii เซ็นเซอร์ PIR ตรวจจับการเคลื่อนไหวทั่วไป แต่ไม่ได้ให้ข้อมูลว่าใครหรือสิ่งใดเคลื่อนไหว#jb ดังนั้น
จึงจำเป็นต้องใช้ เซ็นเซอร์ IR แบบสร้างภาพ เซ็นเซอร์ PIR มักเรียกสั้นๆ ว่า "PIR"
หรือบางครั้งเรียกว่า "PID" ซึ่งย่อมาจาก "เครื่องตรวจจับอินฟราเรดแบบพาสซีฟ" เซ็นเซอร์ PIR
ตรวจจับการเคลื่อนไหวทั่วไป แต่ไม่ได้ให้ข้อมูลว่าใครหรือสิ่งใดเคลื่อนไหว ดังนั้น จึงจำเป็นต้องใช้ เซ็นเซอร์
IR แบบสร้างภาพ เซ็นเซอร์ PIR มักเรียกสั้นๆ ว่า "PIR" หรือบางครั้งเรียกว่า "PID" ซึ่งย่อมาจาก
"เครื่องตรวจจับอินฟราเรดแบบพาสซีฟ" คำว่าพาสซีฟหมายถึงข้อเท็จจริงที่ว่าอุปกรณ์ PIR
ไม่ได้แผ่พลังงานเพื่อจุดประสงค์ในการตรวจจับ แต่ทำงานโดยการตรวจจับรังสีอินฟราเรด
(ความร้อนจากการแผ่รังสี) ที่แผ่ออกมาจากหรือสะท้อนจากวัตถุ เท่านั้นซีฟ"
คำว่าพาสซีฟหมายถึงข้อเท็จจริงที่ว่าอุปกรณ์ PIR ไม่ได้แผ่พลังงานเพื่อจุดประสงค์ในการตรวจจับ
แต่ทำงานโดยการตรวจจับรังสีอินฟราเรด (ความร้อนจากการแผ่รังสี) ที่แผ่ออกมาจากหรือสะท้อนจากวัตถุ
เท่านั้น
== หลักการทำงาน
#i วัตถุทุกชนิดที่มีอุณหภูมิสูงกว่าศูนย์องศาสัมบูรณ์จะปล่อยพลังงานความร้อนออกมาในรูปของรังสีแม่เหล็กไฟฟ้า โดยปกติแล้วรังสีนี้มองไม่เห็นด้วยตาเปล่าเนื่องจากแผ่รังสีในช่วงความยาวคลื่นอินฟราเรด แต่อุปกรณ์อิเล็กทรอนิกส์ที่ออกแบบมาเพื่อจุดประสงค์นี้ สามารถตรวจจับได้
#iiii
วัตถุทุกชนิดที่มีอุณหภูมิสูงกว่าศูนย์องศาสัมบูรณ์จะปล่อยพลังงานความร้อนออกมาในรูปของรังสีแม่เหล็กไฟฟ้า
โดยปกติแล้วรังสีนี้มองไม่เห็นด้วยตาเปล่าเนื่องจากแผ่รังสีในช่วงความยาวคลื่นอินฟราเรด
แต่อุปกรณ์อิเล็กทรอนิกส์ที่ออกแบบมาเพื่อจุดประสงค์นี้ สามารถตรวจจับได้
#v(1em)
== เครื่องตรวจจับการเคลื่อนไหวแบบ PIR
\
#afigure(
image("PIR/Motion_detector.jpg", height: image-height),
alt: "เครื่องตรวจจับความเคลื่อนไหว ติดตั้งบนเพดาน",
attr: [CHG, Public Domain, https://commons.wikimedia.org/w/index.php?curid=6087132],
caption: [เครื่องตรวจจับความเคลื่อนไหว PIR
ใช้สำหรับควบคุมไฟภายนอกอาคารแบบอัตโนมัติ],
attr: [CHG, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=6087132],
caption: [เครื่องตรวจจับความเคลื่อนไหว PIR ใช้สำหรับควบคุมไฟภายนอกอาคารแบบอัตโนมัติ],
)
#afigure(
image("PIR/Camera_trap,_fotopułapka,_kamera_leśna,_kamera_obserwacyjna.jpg"),
attr: [Dariusz Kowalczyk, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=96211951],
attr: [Dariusz Kowalczyk, CC BY-SA 4.0,
https://commons.wikimedia.org/w/index.php?curid=96211951],
alt: "กล้องดักถ่ายที่ถูกพันรอบต้นไม้",
caption: [กล้องดักถ่ายพร้อมระบบตรวจจับความเคลื่อนไหวแบบ PIR],
)
#afigure(
image("PIR/Light_switch_with_passive_infrared_sensor.jpg", height: image-height),
image(
"PIR/Light_switch_with_passive_infrared_sensor.jpg",
height: image-height,
),
alt: "สวิตช์ไฟทรงสี่เหลี่ยมผืนผ้าแนวตั้งที่ติดตั้งเซนเซอร์ตรวจจับคน",
attr: [Z22, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=35183184],
attr: [Z22, CC BY-SA 4.0,
https://commons.wikimedia.org/w/index.php?curid=35183184],
caption: [สวิตช์ไฟภายในอาคารที่ติดตั้งเซนเซอรตรวจจับการครอบครองแบบ PIR],
)
#i เครื่องตรวจจับความเคลื่อนไหวแบบ PIR ใช้เพื่อตรวจจับการเคลื่อนไหวของคน สัตว์ หรือวัตถุอื่นๆ มักใช้กับสัญญาณกันขโมยและระบบไฟส่องสว่างแบบอัตโนมัติ
#iiii เครื่องตรวจจับความเคลื่อนไหวแบบ PIR ใช้เพื่อตรวจจับการเคลื่อนไหวของคน สัตว์ หรือวัตถุอื่นๆ
มักใช้กับสัญญาณกันขโมยและระบบไฟส่องสว่างแบบอัตโนมัติ
== การดำเนินการ
#i เซ็นเซอร์ PIR สามารถตรวจจับการเปลี่ยนแปลงของปริมาณรังสีอินฟราเรดที่กระทบกับวัตถุ ซึ่งจะแตกต่างกันไปขึ้นอยู่กับอุณหภูมิและลักษณะพื้นผิวของวัตถุที่อยู่ด้านหน้าเซ็นเซอร์เมื่อวัตถุ เช่น บุคคล ผ่านด้านหน้าพื้นหลัง เช่น กำแพง อุณหภูมิ จุดนั้นในมุมมองของเซ็นเซอร์จะเพิ่มขึ้นจากอุณหภูมิห้องเป็นอุณหภูมิร่างกายแล้วกลับมาอีกครั้ง เซ็นเซอร์จะแปลงการเปลี่ยนแปลงที่เกิดขึ้นของรังสีอินฟราเรดที่เข้ามาเป็นการเปลี่ยนแปลงของแรงดันไฟฟ้าขาออก และสิ่งนี้จะกระตุ้นการตรวจจับ วัตถุที่มีอุณหภูมิใกล้เคียงกันแต่มีลักษณะพื้นผิวต่างกันอาจมีรูปแบบการปล่อยรังสีอินฟราเรดที่แตกต่างกัน ดังนั้นการเคลื่อนย้ายวัตถุเทียบกับพื้นหลังอาจกระตุ้นเครื่องตรวจจับได้เช่นกัน
#iiii เซ็นเซอร์ PIR สามารถตรวจจับการเปลี่ยนแปลงของปริมาณรังสีอินฟราเรดที่กระทบกับวัตถุ
ซึ่งจะแตกต่างกันไปขึ้นอยู่กับอุณหภูมิและลักษณะพื้นผิวของวัตถุที่อยู่ด้านหน้าเซ็นเซอร์เมื่อวัตถุ เช่น บุคคล
ผ่านด้านหน้าพื้นหลัง เช่น กำแพง อุณหภูมิ
จุดนั้นในมุมมองของเซ็นเซอร์จะเพิ่มขึ้นจากอุณหภูมิห้องเป็นอุณหภูมิร่างกายแล้วกลับมาอีกครั้ง
เซ็นเซอร์จะแปลงการเปลี่ยนแปลงที่เกิดขึ้นของรังสีอินฟราเรดที่เข้ามาเป็นการเปลี่ยนแปลงของแรงดันไฟฟ้าขาออก
และสิ่งนี้จะกระตุ้นการตรวจจับ
วัตถุที่มีอุณหภูมิใกล้เคียงกันแต่มีลักษณะพื้นผิวต่างกันอาจมีรูปแบบการปล่อยรังสีอินฟราเรดที่แตกต่างกัน
ดังนั้นการเคลื่อนย้ายวัตถุเทียบกับพื้นหลังอาจกระตุ้นเครื่องตรวจจับได้เช่นกัน
#i PIR มีหลายรูปแบบการใช้งานที่หลากหลาย รุ่นที่นิยมใช้กันมากที่สุดมีเลนส์เฟรสเนลหรือส่วนกระจกจำนวนมาก ระยะการทำงานประมาณ 10 เมตร (30 ฟุต) และมุมมองภาพน้อยกว่า 180° มีรุ่นที่มีมุมมองภาพกว้างกว่า รวมถึง 360° ซึ่งโดยทั่วไปออกแบบมาเพื่อติดตั้งบนเพดาน PIR ขนาดใหญ่บางรุ่นผลิตด้วยกระจกส่วนเดียวและสามารถตรวจจับการเปลี่ยนแปลงของพลังงานอินฟราเรดได้ในระยะ 30 เมตร (100 ฟุต) จาก PIR นอกจากนี้ยังมี PIR ที่ออกแบบด้วยกระจกแบบปรับทิศทางได้ ซึ่งสามารถครอบคลุมพื้นที่ได้กว้าง (110°) หรือครอบคลุมพื้นที่แคบมากแบบ "ม่าน" หรือสามารถเลือกส่วนกระจกแยกแต่ละส่วนเพื่อ "ปรับแต่ง" พื้นที่ครอบคลุมได้
#iiii PIR มีหลายรูปแบบการใช้งานที่หลากหลาย
รุ่นที่นิยมใช้กันมากที่สุดมีเลนส์เฟรสเนลหรือส่วนกระจกจำนวนมาก ระยะการทำงานประมาณ 10 เมตร (30
ฟุต) และมุมมองภาพน้อยกว่า 180° มีรุ่นที่มีมุมมองภาพกว้างกว่า รวมถึง 360°
ซึ่งโดยทั่วไปออกแบบมาเพื่อติดตั้งบนเพดาน PIR
ขนาดใหญ่บางรุ่นผลิตด้วยกระจกส่วนเดียวและสามารถตรวจจับการเปลี่ยนแปลงของพลังงานอินฟราเรดได้ในระยะ
30 เมตร (100 ฟุต) จาก PIR นอกจากนี้ยังมี PIR ที่ออกแบบด้วยกระจกแบบปรับทิศทางได้
ซึ่งสามารถครอบคลุมพื้นที่ได้กว้าง (110°) หรือครอบคลุมพื้นที่แคบมากแบบ "ม่าน"
หรือสามารถเลือกส่วนกระจกแยกแต่ละส่วนเพื่อ "ปรับแต่ง" พื้นที่ครอบคลุมได้
== การตรวจจับความแตกต่าง
#i เซ็นเซอร์หลายตัวอาจเชื่อมต่อเป็นอินพุตตรงข้ามกับเครื่องขยายสัญญาณดิฟเฟอเรนเชียล ในรูปแบบนี้ การวัดค่า PIR จะหักล้างกันเอง ทำให้อุณหภูมิเฉลี่ยของระยะการมองเห็นถูกตัดออกจากสัญญาณไฟฟ้า การเพิ่มขึ้นของพลังงานอินฟราเรดทั่วทั้งเซ็นเซอร์จะหักล้างตัวเองและจะไม่กระตุ้นอุปกรณ์ วิธีนี้ช่วยให้อุปกรณ์ต้านทานการเปลี่ยนแปลงที่ผิดพลาดในกรณีที่ได้รับแสงแฟลชสั้นๆ หรือแสงที่ส่องสว่างทั่วทั้งสนาม (การได้รับพลังงานสูงอย่างต่อเนื่องอาจทำให้วัสดุเซ็นเซอร์อิ่มตัวและทำให้เซ็นเซอร์ไม่สามารถบันทึกข้อมูลเพิ่มเติมได้) ในขณะเดียวกัน การจัดเรียงแบบดิฟเฟอเรนเชียลนี้ยังช่วยลดสัญญาณรบกวนโหมดทั่วไปทำให้อุปกรณ์ต้านทานการกระตุ้นเนื่องจากสนามไฟฟ้าใกล้เคียง อย่างไรก็ตาม เซ็นเซอร์แบบดิฟเฟอเรนเชียลคู่ไม่สามารถวัดอุณหภูมิได้ในรูปแบบนี้ ดังนั้นจึงมีประโยชน์เฉพาะสำหรับการตรวจจับการเคลื่อนไหวเท่านั้น
#iiii เซ็นเซอร์หลายตัวอาจเชื่อมต่อเป็นอินพุตตรงข้ามกับเครื่องขยายสัญญาณดิฟเฟอเรนเชียล ในรูปแบบนี้
การวัดค่า PIR จะหักล้างกันเอง ทำให้อุณหภูมิเฉลี่ยของระยะการมองเห็นถูกตัดออกจากสัญญาณไฟฟ้า
การเพิ่มขึ้นของพลังงานอินฟราเรดทั่วทั้งเซ็นเซอร์จะหักล้างตัวเองและจะไม่กระตุ้นอุปกรณ์
วิธีนี้ช่วยให้อุปกรณ์ต้านทานการเปลี่ยนแปลงที่ผิดพลาดในกรณีที่ได้รับแสงแฟลชสั้นๆ
หรือแสงที่ส่องสว่างทั่วทั้งสนาม
(การได้รับพลังงานสูงอย่างต่อเนื่องอาจทำให้วัสดุเซ็นเซอร์อิ่มตัวและทำให้เซ็นเซอร์ไม่สามารถบันทึกข้อมูลเพิ่มเติมได้)
ในขณะเดียวกัน
การจัดเรียงแบบดิฟเฟอเรนเชียลนี้ยังช่วยลดสัญญาณรบกวนโหมดทั่วไปทำให้อุปกรณ์ต้านทานการกระตุ้นเนื่องจากสนามไฟฟ้าใกล้เคียง
อย่างไรก็ตาม เซ็นเซอร์แบบดิฟเฟอเรนเชียลคู่ไม่สามารถวัดอุณหภูมิได้ในรูปแบบนี้
ดังนั้นจึงมีประโยชน์เฉพาะสำหรับการตรวจจับการเคลื่อนไหวเท่านั้น
== การปฏิบัติจริง
#i เมื่อเซ็นเซอร์ PIR ถูกกำหนดค่าในโหมดดิฟเฟอเรนเชียล เซ็นเซอร์จะสามารถใช้งานได้เฉพาะในฐานะอุปกรณ์ตรวจจับการเคลื่อนไหว ในโหมดนี้ เมื่อตรวจจับการเคลื่อนไหวภายใน "แนวสายตา" ของเซ็นเซอร์ พัลส์เสริมคู่หนึ่งจะถูกประมวลผลที่ขาเอาต์พุตของเซ็นเซอร์ เพื่อนำสัญญาณเอาต์พุตนี้ไปใช้งานจริงในการกระตุ้นโหลด เช่น รีเลย์หรือเครื่องบันทึกข้อมูลหรือสัญญาณเตือนสัญญาณดิฟเฟอเรน-เชียลจะถูกแก้ไขโดยใช้วงจรเรียงกระแสแบบบริดจ์และป้อนเข้าสู่วงจรขับรีเลย์แบบทรานซิสเตอร์ หน้าสัมผัสของรีเลย์นี้จะปิดและเปิดเพื่อตอบสนองต่อสัญญาณจาก PIR โดยกระตุ้นโหลดที่เชื่อมต่ออยู่ผ่านหน้าสัมผัสของมัน รับรู้ถึงการตรวจจับบุคคลภายในพื้นที่จำกัดที่กำหนดไว้ล่วงหน้า
#iiii เมื่อเซ็นเซอร์ PIR ถูกกำหนดค่าในโหมดดิฟเฟอเรนเชียล
เซ็นเซอร์จะสามารถใช้งานได้เฉพาะในฐานะอุปกรณ์ตรวจจับการเคลื่อนไหว ในโหมดนี้
เมื่อตรวจจับการเคลื่อนไหวภายใน "แนวสายตา" ของเซ็นเซอร์
พัลส์เสริมคู่หนึ่งจะถูกประมวลผลที่ขาเอาต์พุตของเซ็นเซอร์
เพื่อนำสัญญาณเอาต์พุตนี้ไปใช้งานจริงในการกระตุ้นโหลด เช่น
รีเลย์หรือเครื่องบันทึกข้อมูลหรือสัญญาณเตือนสัญญาณดิฟเฟอเรน-เชียลจะถูกแก้ไขโดยใช้วงจรเรียงกระแสแบบบริดจ์และป้อนเข้าสู่วงจรขับรีเลย์แบบทรานซิสเตอร์
หน้าสัมผัสของรีเลย์นี้จะปิดและเปิดเพื่อตอบสนองต่อสัญญาณจาก PIR
โดยกระตุ้นโหลดที่เชื่อมต่ออยู่ผ่านหน้าสัมผัสของมัน
รับรู้ถึงการตรวจจับบุคคลภายในพื้นที่จำกัดที่กำหนดไว้ล่วงหน้า
== การออกแบบผลิตภัณฑ์
#afigure(
image("PIR/PIR_Motion_Sensor-Sensinova_(SN-PR11).png", height: image-height),
attr: [Versatile Techno - http://www.sensinova.in/pir-motion-sensor/SNPR11.php, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=48377787],
attr: [Versatile Techno -
http://www.sensinova.in/pir-motion-sensor/SNPR11.php, CC BY-SA 4.0,
https://commons.wikimedia.org/w/index.php?curid=48377787],
alt: "ผลิตภัณฑ์เซนเซอร์สีขาว มีเครื่องหมายแบรนด์ Sensinova",
caption: [การออกแบบเซ็นเซอร์ตรวจจับการเคลื่อนไหว PIR],
)
#i โดยทั่วไปเซ็นเซอร์ PIR จะติดตั้งอยู่บนแผงวงจรพิมพ์ซึ่งมีอุปกรณ์อิเล็กทรอนิกส์ที่จำเป็นสำหรับการตีความสัญญาณจากตัวเซ็นเซอร์เอง โดยทั่วไปแล้วชุดประกอบทั้งหมดจะบรรจุอยู่ภายในตัวเรือน ซึ่งติดตั้งในตำแหน่งที่เซ็นเซอร์สามารถครอบคลุมพื้นที่ที่ต้องการตรวจสอบได้ ตัวเรือนมักจะมี "หน้าต่าง" พลาสติกที่พลังงานอินฟราเรดสามารถผ่านเข้ามาได้ แม้ว่ามักจะโปร่งแสงต่อแสงที่มองเห็น แต่พลังงานอินฟราเรดสามารถผ่านเข้ามายังเซ็นเซอร์ได้ผ่านหน้าต่าง เนื่องจากพลาสติกที่ใช้นั้นโปร่งใสต่อรังสีอินฟราเรด หน้าต่างพลาสติกช่วยลดโอกาสที่วัตถุแปลกปลอม (ฝุ่น แมลง ฝน ฯลฯ) จะบดบังมุมมองของเซ็นเซอร์ ทำให้กลไกเสียหาย และอาจทำให้เกิดสัญญาณเตือนที่ผิดพลาด หน้าต่างนี้สามารถใช้เป็นตัวกรองเพื่อจำกัดความยาวคลื่นให้อยู่ที่ 8-14 ไมโครเมตร ซึ่งใกล้เคียงกับรังสีอินฟราเรดที่มนุษย์ปล่อยออกมามากที่สุด นอกจากนี้ยังสามารถใช้เป็นกลไกโฟกัสได้อีกด้วย (ดูด้านล่าง)
#iiii โดยทั่วไปเซ็นเซอร์ PIR
จะติดตั้งอยู่บนแผงวงจรพิมพ์ซึ่งมีอุปกรณ์อิเล็กทรอนิกส์ที่จำเป็นสำหรับการตีความสัญญาณจากตัวเซ็นเซอร์เอง
โดยทั่วไปแล้วชุดประกอบทั้งหมดจะบรรจุอยู่ภายในตัวเรือน
ซึ่งติดตั้งในตำแหน่งที่เซ็นเซอร์สามารถครอบคลุมพื้นที่ที่ต้องการตรวจสอบได้ ตัวเรือนมักจะมี "หน้าต่าง"
พลาสติกที่พลังงานอินฟราเรดสามารถผ่านเข้ามาได้ แม้ว่ามักจะโปร่งแสงต่อแสงที่มองเห็น
แต่พลังงานอินฟราเรดสามารถผ่านเข้ามายังเซ็นเซอร์ได้ผ่านหน้าต่าง
เนื่องจากพลาสติกที่ใช้นั้นโปร่งใสต่อรังสีอินฟราเรด หน้าต่างพลาสติกช่วยลดโอกาสที่วัตถุแปลกปลอม (ฝุ่น
แมลง ฝน ฯลฯ)#jb จะบดบังมุมมองของเซ็นเซอร์ ทำให้กลไกเสียหาย
และอาจทำให้เกิดสัญญาณเตือนที่ผิดพลาด หน้าต่างนี้สามารถใช้เป็นตัวกรองเพื่อจำกัดความยาวคลื่นให้อยู่ที่
8-14 ไมโครเมตร ซึ่งใกล้เคียงกับรังสีอินฟราเรดที่มนุษย์ปล่อยออกมามากที่สุด
นอกจากนี้ยังสามารถใช้เป็นกลไกโฟกัสได้อีกด้วย (ดูด้านล่าง)
== การโฟกัส
#i สามารถใช้กลไกที่แตกต่างกันเพื่อโฟกัสพลังงานอินฟราเรดระยะไกลลงบนพื้นผิวเซ็นเซอร์ได้
#iiii สามารถใช้กลไกที่แตกต่างกันเพื่อโฟกัสพลังงานอินฟราเรดระยะไกลลงบนพื้นผิวเซ็นเซอร์ได้
== เลนส์
#i ม่านพลาสติกอาจหล่อขึ้นรูปหลายเหลี่ยมเพื่อรวมพลังงานอินฟราเรดไปยังเซ็นเซอร์ แต่ละเหลี่ยมคือเลนส์เฟรสเนล
#iiii ม่านพลาสติกอาจหล่อขึ้นรูปหลายเหลี่ยมเพื่อรวมพลังงานอินฟราเรดไปยังเซ็นเซอร์
แต่ละเหลี่ยมคือเลนส์เฟรสเนล
=== เลนส์มัลติเฟรสเนลของ PIR
@@ -85,103 +155,167 @@
image("PIR/FacetLensOfMotionDetector_animation2.gif", height: 2in),
attr: [CC BY-SA 3.0, https://en.wikipedia.org/w/index.php?curid=14193664],
alt: "เครื่องตรวจจับความเคลื่อนไหวทรงกระบอก",
caption: [ตัวเรือนเครื่องตรวจจับความเคลื่อนไหว PIR พร้อมช่องหน้าต่างทรงกระบอกเหลี่ยมโดยแต่ละเหลี่ยมเป็นเลนส์เฟรสเนล โฟกัสแสงไปที่ชิ้นส่วนเซ็นเซอร์ไพโรอิเล็กทริกที่อยู่ด้านล่าง],
caption: [ตัวเรือนเครื่องตรวจจับความเคลื่อนไหว PIR
พร้อมช่องหน้าต่างทรงกระบอกเหลี่ยมโดยแต่ละเหลี่ยมเป็นเลนส์เฟรสเนล
โฟกัสแสงไปที่ชิ้นส่วนเซ็นเซอร์ไพโรอิเล็กทริกที่อยู่ด้านล่าง],
)
#v(3em)
#afigure(
image("PIR/Fresnel_only.jpg", height: 2in),
attr: [Jack LaRosa, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4463018],
attr: [Jack LaRosa, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=4463018],
alt: "ฝาครอบของเซนเซอร์ตรวจจับความเคลื่อนไหว",
caption: [ฝาครอบด้านหน้า PIR เท่านั้น (ถอดอุปกรณ์อิเล็กทรอนิกส์ออก) โดยมีแหล่งกำเนิดแสงจุดอยู่ด้านหลัง เพื่อแสดงเลนส์แต่ละตัว],
caption: [ฝาครอบด้านหน้า PIR เท่านั้น (ถอดอุปกรณ์อิเล็กทรอนิกส์ออก)
โดยมีแหล่งกำเนิดแสงจุดอยู่ด้านหลัง เพื่อแสดงเลนส์แต่ละตัว],
)
#v(3em)
#afigure(
image("PIR/Circuit_board_revealed.jpg", height: 2in),
attr: [Jack LaRosa, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4478366],
attr: [Jack LaRosa, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=4478366],
alt: "แผงวงจร PIR ลูกศรสีเขียวชี้ไปยังเซนเซอร์ภายในบอร์ด",
caption: [PIR ที่ถอดฝาครอบด้านหน้าออก แสดงตำแหน่งของ
เซ็นเซอร์ไพโรอิเล็กทริก (ลูกศรสีเขียว)],
caption: [PIR ที่ถอดฝาครอบด้านหน้าออก แสดงตำแหน่งของ เซ็นเซอร์ไพโรอิเล็กทริก
(ลูกศรสีเขียว)],
)
== กระจก PIR
#i บางรุ่นผลิตขึ้นโดยใช้กระจกพาราโบลา แบบแบ่งส่วนภายใน เพื่อรวมพลังงานอินฟราเรด ในกรณีที่ใช้กระจก ฝาครอบกระจกพลาสติกโดยทั่วไปจะไม่มีเลนส์เฟรสเนลหล่อขึ้นรูป
#iiii บางรุ่นผลิตขึ้นโดยใช้กระจกพาราโบลา แบบแบ่งส่วนภายใน เพื่อรวมพลังงานอินฟราเรด
ในกรณีที่ใช้กระจก ฝาครอบกระจกพลาสติกโดยทั่วไปจะไม่มีเลนส์เฟรสเนลหล่อขึ้นรูป
=== PIR ชนิดกระจกแบ่งส่วน
#afigure(
image("PIR/Front-(mirror_type).jpg", height: 2in),
attr: [Jack LaRosa, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4501665],
attr: [Jack LaRosa, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=4501665],
alt: "เซนเซอร์ทรงคล้ายทรงกลม",
caption: [PID ทั่วไปสำหรับที่พักอาศัย/เชิงพาณิชย์ที่
ใช้กระจกแบ่งส่วนภายในเพื่อการโฟกัส],
caption: [PID ทั่วไปสำหรับที่พักอาศัย/เชิงพาณิชย์ที่ ใช้กระจกแบ่งส่วนภายในเพื่อการโฟกัส],
)
#v(1em)
#afigure(
image("PIR/Mirror_type_opened.jpg", height: 2in),
attr: [Deuxdad, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4501724],
attr: [Deuxdad, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=4501724],
alt: "เซนเซอร์ก่อนหน้าเมื่อถูกถอดฝาครอบออก",
caption: [ถอดฝาครอบออกแล้ว กระจกแบ่งส่วน
ด้านล่างมีแผงวงจรพิมพ์ (PC) อยู่ด้านบน],
caption: [ถอดฝาครอบออกแล้ว กระจกแบ่งส่วน ด้านล่างมีแผงวงจรพิมพ์ (PC) อยู่ด้านบน],
)
#v(1em)
#afigure(
image("PIR/Mirror_in_place.jpg", height: 2in),
attr: [Jack LaRosa, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4502198],
attr: [Jack LaRosa, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=4502198],
alt: "เซนเซอร์ก่อนหน้าเมื่อถอดแผงวงจรให้เห็นกระจกแบ่งส่วนด้านใน",
caption: [แผงวงจรพิมพ์ถูกถอดออกเพื่อแสดงกระจกแบบแบ่งส่วน],
)
#afigure(
image("PIR/Segmented-parabolic_mirror.jpg", height: 2in),
attr: [Deuxdad, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4502224],
attr: [Deuxdad, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=4502224],
alt: "กระจกแบ่งส่วนที่ถูกถอดออก",
caption: [กระจกพาราโบลาแบบแบ่งส่วนถอดออกจากตัวเครื่อง],
)
#v(1em)
#afigure(
image("PIR/Rear_of_circuit_board2.jpg", height: 2in),
attr: [Jack LaRosa, Public Domain, https://commons.wikimedia.org/w/index.php?curid=4508036],
attr: [Jack LaRosa, Public Domain,
https://commons.wikimedia.org/w/index.php?curid=4508036],
alt: "ด้านหลังของแผงวงจรก่อนหน้า ลูกศรสีเขียวชี้ไปยังเซนเซอร์",
caption: [ด้านหลังของแผงวงจรที่หันเข้าหากระจกเมื่อติดตั้ง
เซ็นเซอร์ไพโรอิเล็กทริกแสดงด้วยลูกศรสีเขียว],
)
#v(2em)
== รูปแบบลำแสง
#afigure(
image("PIR/Motion_Detector_with_Beam_Pattern.jpg", height: 2in),
attr: [AndreasCT, CC BY-SA 4.0, https://commons.wikimedia.org/w/index.php?curid=84066723],
attr: [AndreasCT, CC BY-SA 4.0,
https://commons.wikimedia.org/w/index.php?curid=84066723],
alt: "กราฟิกแสดงลำแสงจำลองการทำงานของเครื่องตรวจจับความเคลื่อนไหว",
caption: [เครื่องตรวจจับความเคลื่อนไหวที่มีรูปแบบลำแสงซ้อนทับ ความยาวของลำแสงเป็นตัวชี้วัดความไวของเครื่องตรวจจับในทิศทางนั้น],
caption: [เครื่องตรวจจับความเคลื่อนไหวที่มีรูปแบบลำแสงซ้อนทับ
ความยาวของลำแสงเป็นตัวชี้วัดความไวของเครื่องตรวจจับในทิศทางนั้น],
)
#i จากการโฟกัส ทำให้มุมมองของเครื่องตรวจจับกลายเป็นรูปแบบลำแสง ภายใต้มุมบางมุม (โซน)\ เซ็นเซอร์ PIR แทบจะไม่ได้รับพลังงานรังสีใด และภายใต้มุมอื่น PIR จะได้รับพลังงานอินฟราเรดในปริมาณที่เข้มข้น การแยกนี้ช่วยให้เครื่องตรวจจับความเคลื่อนไหวสามารถแยกแยะระหว่างแสงสว่างที่กว้างและวัตถุที่กำลังเคลื่อนที่ได้
#v(2em)
#i เมื่อบุคคลเดินจากมุมหนึ่ง (ลำแสง) ไปยังอีกมุมหนึ่ง เครื่องตรวจจับจะมองเห็นบุคคลที่กำลังเคลื่อนไหวเป็นระยะ เท่านั้น ส่งผลให้สัญญาณเซ็นเซอร์เปลี่ยนแปลงอย่างรวดเร็ว ซึ่งระบบอิเล็กทรอนิกส์จะใช้เพื่อส่งสัญญาณเตือนภัยหรือเปิดไฟ ระบบอิเล็กทรอนิกส์จะไม่สนใจสัญญาณที่เปลี่ยนแปลงช้า
#h(9.75em) จากการโฟกัส ทำให้มุมมองของเครื่องตรวจจับกลายเป็นรูปแบบลำแสง ภายใต้มุมบางมุม
(โซน) เซ็นเซอร์ PIR แทบจะไม่ได้รับพลังงานรังสีใด และภายใต้มุมอื่น PIR
จะได้รับพลังงานอินฟราเรดในปริมาณที่เข้มข้น
การแยกนี้ช่วยให้เครื่องตรวจจับความเคลื่อนไหวสามารถแยกแยะระหว่างแสงสว่างที่กว้างและวัตถุที่กำลังเคลื่อนที่ได้
#i จำนวน รูปร่าง การกระจาย และความไวของโซนเหล่านี้ถูกกำหนดโดยเลนส์และกระจก ผู้ผลิตพยายามอย่างเต็มที่เพื่อสร้างรูปแบบลำแสงความไวที่เหมาะสมที่สุดสำหรับการใช้งานแต่ละประเภท
#h(9.75em) เมื่อบุคคลเดินจากมุมหนึ่ง (ลำแสง) ไปยังอีกมุมหนึ่ง
เครื่องตรวจจับจะมองเห็นบุคคลที่กำลังเคลื่อนไหวเป็นระยะ เท่านั้น
ส่งผลให้สัญญาณเซ็นเซอร์เปลี่ยนแปลงอย่างรวดเร็ว
ซึ่งระบบอิเล็กทรอนิกส์จะใช้เพื่อส่งสัญญาณเตือนภัยหรือเปิดไฟ
ระบบอิเล็กทรอนิกส์จะไม่สนใจสัญญาณที่เปลี่ยนแปลงช้า
#h(9.75em) จำนวน รูปร่าง การกระจาย และความไวของโซนเหล่านี้ถูกกำหนดโดยเลนส์และกระจก
ผู้ผลิตพยายามอย่างเต็มที่เพื่อสร้างรูปแบบลำแสงความไวที่เหมาะสมที่สุดสำหรับการใช้งานแต่ละประเภท
== การใช้งานระบบไฟอัตโนมัติ
#i เมื่อใช้เป็นส่วนหนึ่งของระบบไฟส่องสว่าง ระบบอิเล็กทรอนิกส์ใน PIR มักจะควบคุมรีเลย์ในตัวที่สามารถสลับแรงดันไฟฟ้าหลักได้ ซึ่งหมายความว่า PIR สามารถตั้งค่าให้เปิดไฟที่เชื่อมต่อกับ PIR เมื่อตรวจพบการเคลื่อนไหวได้ วิธีนี้มักใช้ในสถานการณ์กลางแจ้ง ทั้งเพื่อป้องกันอาชญากร (ไฟรักษาความปลอดภัย) หรือเพื่อการใช้งานจริง เช่น การเปิดไฟประตูหน้าบ้านเพื่อให้คุณหากุญแจเจอในความมืด\ การใช้งานเพิ่มเติมสามารถทำได้ในห้องน้ำสาธารณะ ห้องเตรียมอาหารแบบวอล์กอิน ทางเดิน หรือบริเวณใดก็ตามที่สามารถควบคุมไฟอัตโนมัติได้ วิธีนี้ช่วยประหยัดพลังงานได้ เพราะไฟจะเปิดเฉพาะเมื่อจำเป็นเท่านั้น และผู้ใช้ไม่จำเป็นต้องปิดไฟเมื่อออกจากพื้นที่
#h(9.75em) เมื่อใช้เป็นส่วนหนึ่งของระบบไฟส่องสว่าง ระบบอิเล็กทรอนิกส์ใน PIR
มักจะควบคุมรีเลย์ในตัวที่สามารถสลับแรงดันไฟฟ้าหลักได้ ซึ่งหมายความว่า PIR
สามารถตั้งค่าให้เปิดไฟที่เชื่อมต่อกับ PIR เมื่อตรวจพบการเคลื่อนไหวได้ วิธีนี้มักใช้ในสถานการณ์กลางแจ้ง
ทั้งเพื่อป้องกันอาชญากร (ไฟรักษาความปลอดภัย) หรือเพื่อการใช้งานจริง เช่น
การเปิดไฟประตูหน้าบ้านเพื่อให้คุณหากุญแจเจอในความมืด
การใช้งานเพิ่มเติมสามารถทำได้ในห้องน้ำสาธารณะ ห้องเตรียมอาหารแบบวอล์กอิน ทางเดิน
หรือบริเวณใดก็ตามที่สามารถควบคุมไฟอัตโนมัติได้ วิธีนี้ช่วยประหยัดพลังงานได้
เพราะไฟจะเปิดเฉพาะเมื่อจำเป็นเท่านั้น และผู้ใช้ไม่จำเป็นต้องปิดไฟเมื่อออกจากพื้นที่
== แอปพลิเคชั่นด้านความปลอดภัย
#i เมื่อใช้เป็นส่วนหนึ่งของระบบรักษาความปลอดภัย วงจรอิเล็กทรอนิกส์ใน PIR มักจะควบคุมรีเลย์ ขนาดเล็ก รีเลย์นี้จะทำหน้าที่เชื่อมต่อวงจรไฟฟ้าผ่านหน้า สัมผัสไฟฟ้าคู่หนึ่งที่เชื่อมต่อกับโซนอินพุตตรวจจับของแผงควบคุมสัญญาณกันขโมยโดยทั่วไประบบจะออกแบบให้หากไม่มีการเคลื่อนไหว หน้าสัมผัสรีเลย์จะปิดอยู่ ซึ่งเรียกว่ารีเลย์แบบ 'ปกติปิด' (NC) หากตรวจพบการเคลื่อนไหว รีเลย์จะเปิดวงจรเพื่อส่งสัญญาณเตือนภัย หรือหากสายไฟถูกตัดการเชื่อมต่อ สัญญาณเตือนภัยก็จะทำงานเช่นกัน
#h(9.75em) เมื่อใช้เป็นส่วนหนึ่งของระบบรักษาความปลอดภัย วงจรอิเล็กทรอนิกส์ใน PIR
มักจะควบคุมรีเลย์ ขนาดเล็ก รีเลย์นี้จะทำหน้าที่เชื่อมต่อวงจรไฟฟ้าผ่านหน้า
สัมผัสไฟฟ้าคู่หนึ่งที่เชื่อมต่อกับโซนอินพุตตรวจจับของแผงควบคุมสัญญาณกันขโมยโดยทั่วไประบบจะออกแบบให้หากไม่มีการเคลื่อนไหว
หน้าสัมผัสรีเลย์จะปิดอยู่ ซึ่งเรียกว่ารีเลย์แบบ 'ปกติปิด' (NC) หากตรวจพบการเคลื่อนไหว
รีเลย์จะเปิดวงจรเพื่อส่งสัญญาณเตือนภัย หรือหากสายไฟถูกตัดการเชื่อมต่อ สัญญาณเตือนภัยก็จะทำงานเช่นกัน
== การจัดวาง
#i ผู้ผลิตแนะนำให้วางผลิตภัณฑ์อย่างระมัดระวังเพื่อป้องกันการแจ้งเตือนที่ผิดพลาด (เช่น การตรวจจับใดๆ ที่ไม่ได้เกิดจากผู้บุกรุก)
#h(9.75em) ผู้ผลิตแนะนำให้วางผลิตภัณฑ์อย่างระมัดระวังเพื่อป้องกันการแจ้งเตือนที่ผิดพลาด (เช่น
การตรวจจับใดๆ ที่ไม่ได้เกิดจากผู้บุกรุก)
#i พวกเขาแนะนำให้ติดตั้ง PIR ในลักษณะที่ PIR ไม่สามารถ "มองเห็น" ออกจากหน้าต่างได้ แม้ว่าความยาวคลื่นของรังสีอินฟราเรดที่ชิปมีความไวต่อแสงจะทะลุผ่านกระจกได้ไม่ดีนัก แต่แหล่งกำเนิดแสงอินฟราเรดที่แรง (เช่น จากไฟหน้ารถยนต์หรือแสงแดด) อาจทำให้เซ็นเซอร์รับภาพเกินพิกัดและทำให้เกิดสัญญาณเตือนภัยผิดพลาดได้ บุคคลที่เคลื่อนไหวอยู่อีกฝั่งของกระจกจะไม่ถูก PID "มองเห็น" ซึ่งอาจเป็นผลดีสำหรับหน้าต่างที่หันหน้าไปทางทางเท้าสาธารณะ หรือเป็นผลเสียสำหรับหน้าต่างในฉากกั้นภายใน
#h(9.75em) พวกเขาแนะนำให้ติดตั้ง PIR ในลักษณะที่ PIR ไม่สามารถ "มองเห็น" ออกจากหน้าต่างได้
แม้ว่าความยาวคลื่นของรังสีอินฟราเรดที่ชิปมีความไวต่อแสงจะทะลุผ่านกระจกได้ไม่ดีนัก
แต่แหล่งกำเนิดแสงอินฟราเรดที่แรง (เช่น จากไฟหน้ารถยนต์หรือแสงแดด)
อาจทำให้เซ็นเซอร์รับภาพเกินพิกัดและทำให้เกิดสัญญาณเตือนภัยผิดพลาดได้
บุคคลที่เคลื่อนไหวอยู่อีกฝั่งของกระจกจะไม่ถูก PID "มองเห็น"
ซึ่งอาจเป็นผลดีสำหรับหน้าต่างที่หันหน้าไปทางทางเท้าสาธารณะ
หรือเป็นผลเสียสำหรับหน้าต่างในฉากกั้นภายใน
#i ขอแนะนำว่าไม่ควรติดตั้ง PIR ในตำแหน่งที่ ช่องระบายอากาศ HVAC จะเป่าลมร้อนหรือเย็นลงบนพื้นผิวพลาสติกที่ปิดหน้าต่างของตัวบ้าน แม้ว่าอากาศจะมีค่าการแผ่รังสี ต่ำมาก (ปล่อยพลังงานอินฟราเรดในปริมาณน้อยมาก) แต่ลมที่พัดผ่านฝาครอบหน้าต่างพลาสติกอาจทำให้อุณหภูมิของพลาสติกเปลี่ยนแปลงจนทำให้เกิดสัญญาณเตือนที่ผิดพลาดได้
#h(9.75em) ขอแนะนำว่าไม่ควรติดตั้ง PIR ในตำแหน่งที่ ช่องระบายอากาศ HVAC
จะเป่าลมร้อนหรือเย็นลงบนพื้นผิวพลาสติกที่ปิดหน้าต่างของตัวบ้าน แม้ว่าอากาศจะมีค่าการแผ่รังสี ต่ำมาก#jb
(ปล่อยพลังงานอินฟราเรดในปริมาณน้อยมาก)
แต่ลมที่พัดผ่านฝาครอบหน้าต่างพลาสติกอาจทำให้อุณหภูมิของพลาสติกเปลี่ยนแปลงจนทำให้เกิดสัญญาณเตือนที่ผิดพลาดได้
#i เซ็นเซอร์มักได้รับการออกแบบมาให้ "เพิกเฉย" สัตว์เลี้ยงในบ้าน เช่น สุนัขหรือแมว โดยการตั้งค่าความไวให้สูงขึ้น หรือทำให้แน่ใจว่าพื้นห้องจะไม่อยู่ในโฟกัส
#h(9.75em) เซ็นเซอร์มักได้รับการออกแบบมาให้ "เพิกเฉย" สัตว์เลี้ยงในบ้าน เช่น สุนัขหรือแมว
โดยการตั้งค่าความไวให้สูงขึ้น หรือทำให้แน่ใจว่าพื้นห้องจะไม่อยู่ในโฟกัส
#i เนื่องจากเซ็นเซอร์ PIR มีระยะการทำงานสูงสุด 10 เมตร (30 ฟุต) ดังนั้นการติดตั้งเครื่องตรวจจับเพียงตัวเดียวใกล้ทางเข้าจึงเพียงพอสำหรับห้องที่มีทางเข้าเพียงทางเดียว ระบบรักษาความปลอดภัยที่ใช้ PIR ยังใช้งานได้ดีกับระบบรักษาความปลอดภัยภายนอกอาคารและระบบไฟที่ไวต่อการเคลื่อนไหว ข้อดีอย่างหนึ่งคือใช้พลังงานต่ำ ซึ่งทำให้สามารถใช้พลังงานแสงอาทิตย์ได้
#h(9.75em) เนื่องจากเซ็นเซอร์ PIR มีระยะการทำงานสูงสุด 10 เมตร (30 ฟุต)
ดังนั้นการติดตั้งเครื่องตรวจจับเพียงตัวเดียวใกล้ทางเข้าจึงเพียงพอสำหรับห้องที่มีทางเข้าเพียงทางเดียว
ระบบรักษาความปลอดภัยที่ใช้ PIR
ยังใช้งานได้ดีกับระบบรักษาความปลอดภัยภายนอกอาคารและระบบไฟที่ไวต่อการเคลื่อนไหว
ข้อดีอย่างหนึ่งคือใช้พลังงานต่ำ ซึ่งทำให้สามารถใช้พลังงานแสงอาทิตย์ได้
== เทอร์โมมิเตอร์แบบควบคุมระยะไกลด้วย PIR
#i มีการออกแบบวงจร PIR ที่ใช้วัดอุณหภูมิของวัตถุที่อยู่ห่างไกลในวงจรดังกล่าว จะใช้เอาต์พุต PIR แบบไม่มีค่าความแตกต่าง สัญญาณเอาต์พุตจะถูกประเมินตามการสอบเทียบสเปกตรัม IR ของสสารชนิดเฉพาะที่ต้องการตรวจวัด ด้วยวิธีนี้ การวัดอุณหภูมิจากระยะไกลจึงค่อนข้างแม่นยำและแม่นยำ หากไม่มีการสอบเทียบกับชนิดของวัสดุที่ตรวจวัด อุปกรณ์เทอร์โมมิเตอร์ PIR จะสามารถวัดการเปลี่ยนแปลงของการแผ่รังสี IR ซึ่งสอดคล้องกับการเปลี่ยนแปลงของอุณหภูมิโดยตรง แต่ไม่สามารถคำนวณค่าอุณหภูมิที่แท้จริงได้
#h(9.75em) มีการออกแบบวงจร PIR ที่ใช้วัดอุณหภูมิของวัตถุที่อยู่ห่างไกลในวงจรดังกล่าว#jb
จะใช้เอาต์พุต PIR แบบไม่มีค่าความแตกต่าง สัญญาณเอาต์พุตจะถูกประเมินตามการสอบเทียบ#jb สเปกตรัม
IR ของสสารชนิดเฉพาะที่ต้องการตรวจวัด ด้วยวิธีนี้ การวัดอุณหภูมิจากระยะไกลจึงค่อนข้างแม่นยำและแม่นยำ
หากไม่มีการสอบเทียบกับชนิดของวัสดุที่ตรวจวัด อุปกรณ์เทอร์โมมิเตอร์ PIR
จะสามารถวัดการเปลี่ยนแปลงของการแผ่รังสี IR ซึ่งสอดคล้องกับการเปลี่ยนแปลงของอุณหภูมิโดยตรง
แต่ไม่สามารถคำนวณค่าอุณหภูมิที่แท้จริงได้
+32 -6
View File
@@ -3,16 +3,42 @@
= เซนเซอร์ (Sensors)
#i โดยทั่วไปแล้ว เซนเซอร์จะถูกนิยามว่าเป็นอุปกรณ์ที่รับและตอบสนองต่อสัญญาณหรือสิ่งเร้าสิ่งเร้าคือปริมาณ คุณสมบัติ หรือสภาวะที่ถูกตรวจจับและแปลงเป็นสัญญาณไฟฟ้า
#i โดยทั่วไปแล้ว เซนเซอร์จะถูกนิยามว่าเป็นอุปกรณ์ที่รับและตอบสนองต่อสัญญาณหรือสิ่งเร้าสิ่งเร้าคือปริมาณ
คุณสมบัติ หรือสภาวะที่ถูกตรวจจับและแปลงเป็นสัญญาณไฟฟ้า
#i ในความหมายกว้างที่สุด เซนเซอร์คืออุปกรณ์ โมดูล เครื่องจักร หรือระบบย่อยที่ตรวจจับเหตุการณ์หรือการเปลี่ยนแปลงในสภาพแวดล้อม และส่งข้อมูลไปยังอุปกรณ์อิเล็กทรอนิกส์อื่นๆ ซึ่งส่วนใหญ่มักจะเป็นหน่วยประมวลผลของคอมพิวเตอร์
#i ในความหมายกว้างที่สุด เซนเซอร์คืออุปกรณ์ โมดูล เครื่องจักร
หรือระบบย่อยที่ตรวจจับเหตุการณ์หรือการเปลี่ยนแปลงในสภาพแวดล้อม
และส่งข้อมูลไปยังอุปกรณ์อิเล็กทรอนิกส์อื่นๆ ซึ่งส่วนใหญ่มักจะเป็นหน่วยประมวลผลของคอมพิวเตอร์
#i เซ็นเซอร์ถูกนำมาใช้ในสิ่งของในชีวิตประจำวัน เช่น ปุ่มลิฟต์แบบสัมผัส (เซ็นเซอร์สัมผัส) และโคมไฟที่หรี่หรือสว่างขึ้นโดยการสัมผัสที่ฐาน และในแอปพลิเคชันมากมายนับไม่ถ้วนซึ่งคนส่วนใหญ่ไม่เคยตระหนักถึง ด้วยความก้าวหน้าในด้านไมโครแมชชีนเนอรี่ และแพลตฟอร์ม ไมโครคอนโทรลเลอร์ที่ใช้งานง่ายการใช้งานเซ็นเซอร์จึงขยายออกไปนอกเหนือจากสาขาแบบดั้งเดิมของการวัดอุณหภูมิ ความดัน และการไหลตัวอย่างเช่น ไปสู่เซ็นเซอร์ MARG
#i เซ็นเซอร์ถูกนำมาใช้ในสิ่งของในชีวิตประจำวัน เช่น ปุ่มลิฟต์แบบสัมผัส (เซ็นเซอร์สัมผัส)
และโคมไฟที่หรี่หรือสว่างขึ้นโดยการสัมผัสที่ฐาน
และในแอปพลิเคชันมากมายนับไม่ถ้วนซึ่งคนส่วนใหญ่ไม่เคยตระหนักถึง
ด้วยความก้าวหน้าในด้านไมโครแมชชีนเนอรี่ และแพลตฟอร์ม
ไมโครคอนโทรลเลอร์ที่ใช้งานง่ายการใช้งานเซ็นเซอร์จึงขยายออกไปนอกเหนือจากสาขาแบบดั้งเดิมของการวัดอุณหภูมิ
ความดัน และการไหลตัวอย่างเช่น ไปสู่เซ็นเซอร์ MARG
#i เซ็นเซอร์แบบอนาล็อก เช่นโพเทนชิโอมิเตอร์และตัวต้านทานรับแรงยังคงมีการใช้งานอย่างแพร่หลาย การใช้งานของเซ็นเซอร์เหล่านี้รวมถึงการผลิตและเครื่องจักร เครื่องบินและอวกาศ รถยนต์ การแพทย์ หุ่นยนต์และอีกหลายแง่มุมในชีวิตประจำวันของเรา นอกจากนี้ยังมีเซ็นเซอร์อื่นๆ อีกมากมายที่ใช้วัดคุณสมบัติทางเคมีและกายภาพของวัสดุ รวมถึงเซ็นเซอร์แบบออปติคอลสำหรับการวัดดัชนีหักเห เซ็นเซอร์แบบสั่นสะเทือนสำหรับการวัดความหนืดของของเหลว และเซ็นเซอร์ทางเคมีไฟฟ้าสำหรับการตรวจสอบค่า pH ของของเหลว
#i เซ็นเซอร์แบบอนาล็อก เช่นโพเทนชิโอมิเตอร์และตัวต้านทานรับแรงยังคงมีการใช้งานอย่างแพร่หลาย
การใช้งานของเซ็นเซอร์เหล่านี้รวมถึงการผลิตและเครื่องจักร เครื่องบินและอวกาศ รถยนต์ การแพทย์
หุ่นยนต์และอีกหลายแง่มุมในชีวิตประจำวันของเรา นอกจากนี้ยังมีเซ็นเซอร์อื่นๆ
อีกมากมายที่ใช้วัดคุณสมบัติทางเคมีและกายภาพของวัสดุ รวมถึงเซ็นเซอร์แบบออปติคอลสำหรับการวัดดัชนีหักเห
เซ็นเซอร์แบบสั่นสะเทือนสำหรับการวัดความหนืดของของเหลว
และเซ็นเซอร์ทางเคมีไฟฟ้าสำหรับการตรวจสอบค่า pH ของของเหลว
#i ความไวของเซนเซอร์บ่งชี้ว่าเอาต์พุตเปลี่ยนแปลงไปมากน้อยเพียงใดเมื่อปริมาณอินพุตที่วัดเปลี่ยนแปลง ตัวอย่างเช่น หากปรอทในเทอร์โมมิเตอร์เคลื่อนที่ 1 ซม. เมื่ออุณหภูมิเปลี่ยนแปลง 1 °C ความไวของมันคือ 1 ซม./°C (โดยพื้นฐานแล้วคือความชัน dy/dx โดยสมมติว่ามีลักษณะเชิงเส้น) เซนเซอร์บางชนิดอาจส่งผลต่อสิ่งที่วัดได้เช่นกัน ตัวอย่างเช่น เทอร์โมมิเตอร์วัดอุณหภูมิห้องที่เสียบลงในถ้วยของเหลวร้อนจะทำให้ของเหลวเย็นลงในขณะที่ของเหลวทำให้เทอร์โมมิเตอร์ร้อนขึ้น โดยทั่วไปเซนเซอร์ได้รับการออกแบบให้มีผลกระทบต่อสิ่งที่วัดน้อยที่สุด การทำให้เซนเซอร์มีขนาดเล็กลงมักจะช่วยปรับปรุงสิ่งนี้และอาจนำมาซึ่งข้อดีอื่นๆ
#i ความไวของเซนเซอร์บ่งชี้ว่าเอาต์พุตเปลี่ยนแปลงไปมากน้อยเพียงใดเมื่อปริมาณอินพุตที่วัดเปลี่ยนแปลง
ตัวอย่างเช่น หากปรอทในเทอร์โมมิเตอร์เคลื่อนที่ 1 ซม. เมื่ออุณหภูมิเปลี่ยนแปลง#jb 1 °C
ความไวของมันคือ 1 ซม./°C (โดยพื้นฐานแล้วคือความชัน dy/dx โดยสมมติว่ามีลักษณะเชิงเส้น)#jb
เซนเซอร์บางชนิดอาจส่งผลต่อสิ่งที่วัดได้เช่นกัน ตัวอย่างเช่น
เทอร์โมมิเตอร์วัดอุณหภูมิห้องที่เสียบลงในถ้วยของเหลวร้อนจะทำให้ของเหลวเย็นลงในขณะที่ของเหลวทำให้เทอร์โมมิเตอร์ร้อนขึ้น
โดยทั่วไปเซนเซอร์ได้รับการออกแบบให้มีผลกระทบต่อสิ่งที่วัดน้อยที่สุด
การทำให้เซนเซอร์มีขนาดเล็กลงมักจะช่วยปรับปรุงสิ่งนี้และอาจนำมาซึ่งข้อดีอื่นๆ
#i ความก้าวหน้าทางเทคโนโลยีทำให้สามารถผลิตเซ็นเซอร์ได้มากขึ้นเรื่อย ในระดับจุลภาคเช่ ไมโครเซ็นเซอร์โดยใช้ เทคโนโลยี MEMSในกรณีส่วนใหญ่ ไมโครเซ็นเซอร์สามารถวัดได้เร็วกว่าและมีความไวสูงกว่าเมื่อเทียบกับวิธีการแบบมหภาคเนื่องจากความต้องการข้อมูลที่รวดเร็ว ราคาไม่แพง และเชื่อถือได้เพิ่มมากขึ้นในโลกปัจจุบัน เซ็นเซอร์แบบใช้แล้วทิ้ง ซึ่งเป็นอุปกรณ์ราคาถูกและใช้งานง่ายสำหรับการตรวจสอบระยะสั้นหรือการวัดแบบครั้งเดียว จึงได้รับความสำคัญเพิ่มมากขึ้น การใช้เซ็นเซอร์ประเภทนี้ทำให้ทุกคนสามารถรับข้อมูลการวิเคราะห์ที่สำคัญได้ทุกที่ ทุกเวลา โดยไม่จำเป็นต้องปรับเทียบใหม่และไม่ต้องกังวลเรื่องการปนเปื้อ
#i ความก้าวหน้าทางเทคโนโลยีทำให้สามารถผลิตเซ็นเซอร์ได้มากขึ้นเรื่อย ในระดับจุลภาคเช่น
ไมโครเซ็นเซอร์โดยใช้เทคโนโลยี MEMS ในกรณีส่วนใหญ่
ไมโครเซ็นเซอร์สามารถวัดได้เร็วกว่าและมีความไวสูงกว่าเมื่อเทียบกับวิธีการแบบมหภาคเนื่องจากความต้องการข้อมูลที่รวดเร็ว
ราคาไม่แพง#jb และเชื่อถือได้เพิ่มมากขึ้นในโลกปัจจุบัน เซ็นเซอร์แบบใช้แล้วทิ้ง
ซึ่งเป็นอุปกรณ์ราคาถูกและใช้งานง่ายสำหรับการตรวจสอบระยะสั้นหรือการวัดแบบครั้งเดียว
จึงได้รับความสำคัญเพิ่มมากขึ้น
การใช้เซ็นเซอร์ประเภทนี้ทำให้ทุกคนสามารถรับข้อมูลการวิเคราะห์ที่สำคัญได้ทุกที่ ทุกเวลา
โดยไม่จำเป็นต้องปรับเทียบใหม่และไม่ต้องกังวลเรื่องการปนเปื้อน
#include "PIR.typ"
+109 -28
View File
@@ -1,53 +1,134 @@
#import "../PageTemplate.typ": i
#import "../PageTemplate.typ": *
#set list(marker: ([], [], []))
= เกณฑ์วิธีความมั่นคงของชั้นขนส่ง (Transport Layer Security; TLS)
#i
เกณฑ์วิธีความมั่นคงของชั้นขนส่ง (Transport Layer Security; TLS) เป็นโปรโตคอลการเข้ารหัสที่ออกแบบมาเพื่อรักษาความปลอดภัยการสื่อสารบนเครือข่ายคอมพิวเตอร์เช่นอินเทอร์เน็ตโปรโตคอลนี้ถูกใช้อย่างแพร่หลายในแอปพลิเคชันต่างๆเช่นอีเมลการส่งข้อความโต้ตอบแบบทันทีและบริการเสียงผ่าน IP แต่การใช้งานเพื่อรักษาความปลอดภัย HTTPS ยังคงเป็นที่เปิดเผยต่อสาธารณะมากที่สุด
เกณฑ์วิธีความมั่นคงของชั้นขนส่ง (Transport Layer Security; TLS)
เป็นโปรโตคอลการเข้ารหัสที่ออกแบบมาเพื่อรักษาความปลอดภัยการสื่อสารบนเครือข่ายคอมพิวเตอร์เช่นอินเทอร์เน็ตโปรโตคอลนี้ถูกใช้อย่างแพร่หลายในแอปพลิเคชันต่างๆเช่นอีเมลการส่งข้อความโต้ตอบแบบทันทีและบริการเสียงผ่าน
IP แต่การใช้งานเพื่อรักษาความปลอดภัย HTTPS ยังคงเป็นที่เปิดเผยต่อสาธารณะมากที่สุด
#i โปรโตคอล TLS มีวัตถุประสงค์หลักเพื่อรักษาความปลอดภัย รวมถึงความเป็นส่วนตัว (ความลับ) ความสมบูรณ์ และความถูกต้อง ผ่านการใช้การเข้ารหัสเช่น การใช้ใบรับรองระหว่างแอปพลิเคชันคอมพิวเตอร์ที่สื่อสารกันตั้งแต่สองแอปพลิเคชันขึ้นไป โปรโตคอลนี้ทำงานในเลเยอร์การนำเสนอและประกอบด้วยสองชั้น ได้แก่ ระเบียน TLS และโปรโตคอล TLS handshake
#i โปรโตคอล TLS มีวัตถุประสงค์หลักเพื่อรักษาความปลอดภัย รวมถึงความเป็นส่วนตัว (ความลับ)
ความสมบูรณ์ และความถูกต้อง ผ่านการใช้การเข้ารหัสเช่น
การใช้ใบรับรองระหว่างแอปพลิเคชันคอมพิวเตอร์ที่สื่อสารกันตั้งแต่สองแอปพลิเคชันขึ้นไป
โปรโตคอลนี้ทำงานในเลเยอร์การนำเสนอและประกอบด้วยสองชั้น ได้แก่ ระเบียน TLS และโปรโตคอล TLS
handshake
#i Datagram Transport Layer Security (DTLS) ซึ่งเป็นโปรโตคอลการสื่อสารที่เกี่ยวข้องอย่างใกล้ชิดมอบความปลอดภัยให้กับ แอปพลิเคชันที่ใช้ ดาต้าแกรมในงานเขียนทางเทคนิค มักพบการอ้างอิงถึง "(D)TLS" เมื่อใช้กับทั้งสองเวอร์ชัน
#i Datagram Transport Layer Security (DTLS)
ซึ่งเป็นโปรโตคอลการสื่อสารที่เกี่ยวข้องอย่างใกล้ชิดมอบความปลอดภัยให้กับ แอปพลิเคชันที่ใช้
ดาต้าแกรมในงานเขียนทางเทคนิค มักพบการอ้างอิงถึง "(D)TLS" เมื่อใช้กับทั้งสองเวอร์ชัน
#i TLS เป็นมาตรฐานที่ได้รับการเสนอโดย Internet Engineering Task Force (IETF) ซึ่งกำหนดขึ้นครั้งแรกในปี 1999 และเวอร์ชันปัจจุบันคือ TLS 1.3 ซึ่งกำหนดขึ้นในเดือนสิงหาคม 2018 TLS สร้างขึ้นจาก ข้อกำหนด SSL (Secure Sockets Layer) ที่ไม่รองรับอีกต่อไป (1994, 1995, 1996) ซึ่งพัฒนาโดย Netscape Communications เพื่อเพิ่มโปรโตคอล HTTPS ลงในเว็บเบราว์เซอร์ Netscape Navigator
#i TLS เป็นมาตรฐานที่ได้รับการเสนอโดย Internet Engineering Task Force (IETF)
ซึ่งกำหนดขึ้นครั้งแรกในปี 1999 และเวอร์ชันปัจจุบันคือ TLS 1.3 ซึ่งกำหนดขึ้นในเดือนสิงหาคม 2018 TLS
สร้างขึ้นจาก ข้อกำหนด SSL (Secure Sockets Layer) ที่ไม่รองรับอีกต่อไป (1994, 1995, 1996)
ซึ่งพัฒนาโดย Netscape Communications เพื่อเพิ่มโปรโตคอล HTTPS ลงในเว็บเบราว์เซอร์ Netscape
Navigator
== คำอธิบาย
#i
เนื่องจากแอปพลิเคชันสามารถสื่อสารได้ทั้งแบบมีหรือไม่มี TLS (หรือ SSL) จึงจำเป็นที่ไคลเอนต์จะต้องร้องขอให้เซิร์ฟเวอร์ตั้งค่าการเชื่อมต่อ TLS หนึ่งในวิธีหลักในการทำเช่นนี้คือการใช้หมายเลขพอร์ต อื่น สำหรับการเชื่อมต่อ TLS โดยทั่วไปแล้ว พอร์ต 80 จะใช้สำหรับ การรับส่งข้อมูล HTTP ที่ไม่ได้เข้ารหัส ในขณะที่พอร์ต 443 เป็นพอร์ตทั่วไปที่ใช้สำหรับ การรับส่งข้อมูล HTTPS ที่เข้ารหัส อีกกลไกหนึ่งคือการสร้างคำขอ STARTTLS เฉพาะโปรโตคอลไปยังเซิร์ฟเวอร์เพื่อสลับการเชื่อมต่อกับ TLS ตัวอย่างเช่น เมื่อใช้โปรโตคอลอีเมลและข่าวสารบางอย่าง
#iii
เนื่องจากแอปพลิเคชันสามารถสื่อสารได้ทั้งแบบมีหรือไม่มี TLS (หรือ SSL)
จึงจำเป็นที่ไคลเอนต์จะต้องร้องขอให้เซิร์ฟเวอร์ตั้งค่าการเชื่อมต่อ TLS
หนึ่งในวิธีหลักในการทำเช่นนี้คือการใช้หมายเลขพอร์ต อื่น สำหรับการเชื่อมต่อ TLS โดยทั่วไปแล้ว พอร์ต 80
จะใช้สำหรับ การรับส่งข้อมูล HTTP ที่ไม่ได้เข้ารหัส ในขณะที่พอร์ต 443 เป็นพอร์ตทั่วไปที่ใช้สำหรับ
การรับส่งข้อมูล HTTPS ที่เข้ารหัส อีกกลไกหนึ่งคือการสร้างคำขอ STARTTLS
เฉพาะโปรโตคอลไปยังเซิร์ฟเวอร์เพื่อสลับการเชื่อมต่อกับ TLS ตัวอย่างเช่น
เมื่อใช้โปรโตคอลอีเมลและข่าวสารบางอย่าง
#i เมื่อไคลเอนต์และเซิร์ฟเวอร์ตกลงที่จะใช้ TLS แล้ว พวกเขาจะเจรจา การเชื่อมต่อ แบบมีสถานะโดยใช้ขั้นตอนการจับมือ (ดูการจับมือ TLS) โปรโตคอลใช้การจับมือกับรหัสแบบอสมมาตรเพื่อกำหนดค่าการเข้ารหัสไม่เพียงเท่านั้น แต่ยังรวมถึงคีย์ที่ใช้ร่วมกันเฉพาะเซสชัน ซึ่งการสื่อสารต่อไปจะถูกเข้ารหัสโดยใช้รหัสแบบสมมาตรในระหว่างการจับมือนี้ ไคลเอนต์และเซิร์ฟเวอร์จะตกลงกันเกี่ยวกับพารามิเตอร์ต่างๆ ที่ใช้สร้างความปลอดภัยของการเชื่อมต่อ:
#iii เมื่อไคลเอนต์และเซิร์ฟเวอร์ตกลงที่จะใช้ TLS แล้ว พวกเขาจะเจรจา การเชื่อมต่อ
แบบมีสถานะโดยใช้ขั้นตอนการจับมือ (ดูการจับมือ TLS)
โปรโตคอลใช้การจับมือกับรหัสแบบอสมมาตรเพื่อกำหนดค่าการเข้ารหัสไม่เพียงเท่านั้น
แต่ยังรวมถึงคีย์ที่ใช้ร่วมกันเฉพาะเซสชัน
ซึ่งการสื่อสารต่อไปจะถูกเข้ารหัสโดยใช้รหัสแบบสมมาตรในระหว่างการจับมือนี้
ไคลเอนต์และเซิร์ฟเวอร์จะตกลงกันเกี่ยวกับพารามิเตอร์ต่างๆ ที่ใช้สร้างความปลอดภัยของการเชื่อมต่อ
- การจับมือเริ่มต้นเมื่อไคลเอนต์เชื่อมต่อกับเซิร์ฟเวอร์ที่เปิดใช้งาน TLS เพื่อขอการเชื่อมต่อที่ปลอดภัยและไคลเอนต์แสดงรายการชุดรหัสที่รองรับ (รหัสและฟังก์ชันแฮช)
- จากรายการนี้ เซิร์ฟเวอร์จะเลือกฟังก์ชันรหัสและแฮชที่รองรับ และแจ้งให้ไคลเอนต์ทราบถึงการตัดสินใจ
- โดยปกติแล้วเซิร์ฟเวอร์จะระบุตัวตนในรูปแบบของใบรับรองดิจิทัลใบรับรองประกอบด้วยชื่อเซิร์ฟเวอร์ผู้ให้บริการออกใบรับรอง (CA) ที่เชื่อถือได้ซึ่งรับรองความถูกต้องของใบรับรอง และคีย์การเข้ารหัสสาธารณะของเซิร์ฟเวอร์
- ลูกค้าต้องยืนยันความถูกต้องของใบรับรองก่อนดำเนินการต่อ
- ในการสร้างคีย์เซสชันที่ใช้สำหรับการเชื่อมต่อที่ปลอดภัย ไคลเอนต์จะต้องทำดังนี้:
- เข้ารหัสตัวเลขสุ่ม (PreMasterSecret) ด้วยคีย์สาธารณะของเซิร์ฟเวอร์และส่งผลลัพธ์ไปยังเซิร์ฟเวอร์ (ซึ่งเฉพาะเซิร์ฟเวอร์เท่านั้นที่จะสามารถถอดรหัสด้วยคีย์ส่วนตัว) จากนั้นทั้งสองฝ่ายใช้ตัวเลขสุ่มเพื่อสร้างคีย์เซสชันเฉพาะสำหรับการเข้ารหัสและถอดรหัสข้อมูลในระหว่างเซสชันในภายหลังหรือ
- ใช้การแลกเปลี่ยนคีย์ DiffieHellman (หรือรูปแบบ DH ที่เป็นเส้นโค้งวงรี) เพื่อสร้างคีย์เซสชันแบบสุ่มและไม่ซ้ำกันอย่างปลอดภัยสำหรับการเข้ารหัสและถอดรหัส ซึ่งมีคุณสมบัติเพิ่มเติมของการปกปิดแบบส่งต่อ : หากคีย์ส่วนตัวของเซิร์ฟเวอร์ถูกเปิดเผยในอนาคต จะไม่สามารถใช้คีย์นั้นเพื่อถอดรหัสเซสชันปัจจุบันได้ แม้ว่าเซสชันนั้นจะถูกดักจับและบันทึกโดยบุคคลที่สามก็ตาม
#block(inset: (left: 6em))[
+ การจับมือเริ่มต้นเมื่อไคลเอนต์เชื่อมต่อกับเซิร์ฟเวอร์ที่เปิดใช้งาน TLS
เพื่อขอการเชื่อมต่อที่ปลอดภัยและไคลเอนต์แสดงรายการชุดรหัสที่รองรับ (รหัสและฟังก์ชันแฮช)
+ จากรายการนี้ เซิร์ฟเวอร์จะเลือกฟังก์ชันรหัสและแฮชที่รองรับ และแจ้งให้ไคลเอนต์ทราบถึงการตัดสินใจ
+ โดยปกติแล้วเซิร์ฟเวอร์จะระบุตัวตนในรูปแบบของใบรับรองดิจิทัลใบรับรองประกอบด้วยชื่อเซิร์ฟเวอร์ผู้ให้บริการออกใบรับรอง
(CA) ที่เชื่อถือได้ซึ่งรับรองความถูกต้องของใบรับรอง และคีย์การเข้ารหัสสาธารณะของเซิร์ฟเวอร์
+ ลูกค้าต้องยืนยันความถูกต้องของใบรับรองก่อนดำเนินการต่อ
+ ในการสร้างคีย์เซสชันที่ใช้สำหรับการเชื่อมต่อที่ปลอดภัย ไคลเอนต์จะต้องทำดังนี้:
+ เข้ารหัสตัวเลขสุ่ม (PreMasterSecret)
ด้วยคีย์สาธารณะของเซิร์ฟเวอร์และส่งผลลัพธ์ไปยังเซิร์ฟเวอร์
(ซึ่งเฉพาะเซิร์ฟเวอร์เท่านั้นที่จะสามารถถอดรหัสด้วยคีย์ส่วนตัว)
จากนั้นทั้งสองฝ่ายใช้ตัวเลขสุ่มเพื่อสร้างคีย์เซสชันเฉพาะสำหรับการเข้ารหัสและถอดรหัสข้อมูลในระหว่างเซสชันในภายหลังหรือ
+ ใช้การแลกเปลี่ยนคีย์ Diffie--Hellman (หรือรูปแบบ DH ที่เป็นเส้นโค้งวงรี)
เพื่อสร้างคีย์เซสชันแบบสุ่มและไม่ซ้ำกันอย่างปลอดภัยสำหรับการเข้ารหัสและถอดรหัส
ซึ่งมีคุณสมบัติเพิ่มเติมของการปกปิดแบบส่งต่อ : หากคีย์ส่วนตัวของเซิร์ฟเวอร์ถูกเปิดเผยในอนาคต
จะไม่สามารถใช้คีย์นั้นเพื่อถอดรหัสเซสชันปัจจุบันได้
แม้ว่าเซสชันนั้นจะถูกดักจับและบันทึกโดยบุคคลที่สามก็ตาม
]
#i การดำเนินการนี้จะสิ้นสุดการจับมือและเริ่มการเชื่อมต่อที่ปลอดภัยซึ่งจะถูกเข้ารหัสและถอดรหัสด้วยคีย์เซสชันจนกว่าการเชื่อมต่อจะสิ้นสุดลงหากขั้นตอนใดขั้นตอนหนึ่งข้างต้นล้มเหลวการจับมือ TLS จะล้มเหลวและการเชื่อมต่อจะไม่ถูกสร้างขึ้น
#iii
การดำเนินการนี้จะสิ้นสุดการจับมือและเริ่มการเชื่อมต่อที่ปลอดภัยซึ่งจะถูกเข้ารหัสและถอดรหัสด้วยคีย์เซสชันจนกว่าการเชื่อมต่อจะสิ้นสุดลงหากขั้นตอนใดขั้นตอนหนึ่งข้างต้นล้มเหลวการจับมือ
TLS จะล้มเหลวและการเชื่อมต่อจะไม่ถูกสร้างขึ้น
#i TLS และ SSL ไม่สามารถจัดวางได้อย่างลงตัวในเลเยอร์ใดเลเยอร์หนึ่งของแบบจำลอง OSI หรือแบบจำลอง TCP/IP TLS ทำงาน "บนโปรโตคอลการขนส่งที่เชื่อถือได้ (เช่น TCP)" ซึ่งหมายความว่ามันอยู่เหนือเลเยอร์การขนส่งมันทำหน้าที่เข้ารหัสให้กับเลเยอร์ที่สูงกว่า ซึ่งโดยปกติแล้วเป็นหน้าที่ของเลเยอร์การนำเสนออย่างไรก็ตาม โดยทั่วไปแอปพลิเคชันจะใช้ TLS เหมือนกับเป็นเลเยอร์การขนส่งแม้ว่าแอปพลิเคชันที่ใช้ TLS จะต้องควบคุมการเริ่มต้นการจับมือ TLS และการจัดการใบรับรองการตรวจสอบสิทธิ์ที่แลกเปลี่ยนกัน
#iii TLS และ SSL ไม่สามารถจัดวางได้อย่างลงตัวในเลเยอร์ใดเลเยอร์หนึ่งของแบบจำลอง OSI
หรือแบบจำลอง TCP/IP TLS ทำงาน "บนโปรโตคอลการขนส่งที่เชื่อถือได้ (เช่น TCP)"
ซึ่งหมายความว่ามันอยู่เหนือเลเยอร์การขนส่งมันทำหน้าที่เข้ารหัสให้กับเลเยอร์ที่สูงกว่า
ซึ่งโดยปกติแล้วเป็นหน้าที่ของเลเยอร์การนำเสนออย่างไรก็ตาม โดยทั่วไปแอปพลิเคชันจะใช้ TLS
เหมือนกับเป็นเลเยอร์การขนส่งแม้ว่าแอปพลิเคชันที่ใช้ TLS จะต้องควบคุมการเริ่มต้นการจับมือ TLS
และการจัดการใบรับรองการตรวจสอบสิทธิ์ที่แลกเปลี่ยนกัน
#i เมื่อได้รับการรักษาความปลอดภัยโดย TLS การเชื่อมต่อระหว่างไคลเอนต์ (เช่น เว็บเบราว์เซอร์)\ และเซิร์ฟเวอร์ (เช่น wikipedia.org) จะมีคุณสมบัติทั้งหมดดังต่อไปนี้
#iii เมื่อได้รับการรักษาความปลอดภัยโดย TLS การเชื่อมต่อระหว่างไคลเอนต์ (เช่น เว็บเบราว์เซอร์)
และเซิร์ฟเวอร์ (เช่น wikipedia.org) จะมีคุณสมบัติทั้งหมดดังต่อไปนี้
- การเชื่อมต่อเป็นแบบส่วนตัว (หรือมีความลับ) เนื่องจาก มีการใช้ อัลกอริทึมคีย์แบบสมมาตรในการเข้ารหัสข้อมูลที่ส่ง คีย์สำหรับการเข้ารหัสแบบสมมาตรนี้จะถูกสร้างขึ้นอย่างเฉพาะเจาะจงสำหรับแต่ละการเชื่อมต่อ และอิงจากความลับร่วมที่เจรจากันไว้เมื่อเริ่มต้นเซสชัน เซิร์ฟเวอร์และไคลเอ็นต์จะเจรจารายละเอียดเกี่ยวกับอัลกอริทึมการเข้ารหัสและคีย์การเข้ารหัสที่จะใช้ก่อนที่จะส่งข้อมูลไบต์แรก (ดูด้านล่าง) การเจรจาความลับร่วมนั้นทั้งปลอดภัย (ความลับที่เจรจากันไว้จะไม่สามารถเข้าถึงได้โดยผู้ดักฟังและไม่สามารถได้รับ แม้แต่โดยผู้โจมตีที่วางตัวเองอยู่ตรงกลางการเชื่อมต่อ) และเชื่อถือได้ (ไม่มีผู้โจมตีคนใดสามารถแก้ไขการสื่อสารระหว่างการเจรจาโดยไม่ถูกตรวจพบ)
- การยืนยันตัวตนของฝ่ายที่สื่อสารสามารถยืนยันได้โดยใช้การเข้ารหัสด้วยคีย์สาธารณะการยืนยันตัวตนนี้จำเป็นสำหรับเซิร์ฟเวอร์และเป็นทางเลือกสำหรับไคลเอนต์
- การเชื่อมต่อมีความน่าเชื่อถือ (หรือมีความสมบูรณ์) เนื่องจากข้อความแต่ละข้อความที่ส่งออกจะมีการตรวจสอบความสมบูรณ์ของข้อความโดยใช้รหัสยืนยันข้อความเพื่อป้องกันการสูญหายหรือการเปลี่ยนแปลงข้อมูลที่ไม่ถูกตรวจพบระหว่างการส่งข้อมูล
#[
#set enum(indent: 6em)
+ การเชื่อมต่อเป็นแบบส่วนตัว (หรือมีความลับ) เนื่องจาก มีการใช้
อัลกอริทึมคีย์แบบสมมาตรในการเข้ารหัสข้อมูลที่ส่ง
คีย์สำหรับการเข้ารหัสแบบสมมาตรนี้จะถูกสร้างขึ้นอย่างเฉพาะเจาะจงสำหรับแต่ละการเชื่อมต่อ
และอิงจากความลับร่วมที่เจรจากันไว้เมื่อเริ่มต้นเซสชัน
เซิร์ฟเวอร์และไคลเอ็นต์จะเจรจารายละเอียดเกี่ยวกับอัลกอริทึมการเข้ารหัสและคีย์การเข้ารหัสที่จะใช้ก่อนที่จะส่งข้อมูลไบต์แรก
(ดูด้านล่าง) การเจรจาความลับร่วมนั้นทั้งปลอดภัย
(ความลับที่เจรจากันไว้จะไม่สามารถเข้าถึงได้โดยผู้ดักฟังและไม่สามารถได้รับ
แม้แต่โดยผู้โจมตีที่วางตัวเองอยู่ตรงกลางการเชื่อมต่อ) และเชื่อถือได้
(ไม่มีผู้โจมตีคนใดสามารถแก้ไขการสื่อสารระหว่างการเจรจาโดยไม่ถูกตรวจพบ)
+ การยืนยันตัวตนของฝ่ายที่สื่อสารสามารถยืนยันได้โดยใช้การเข้ารหัสด้วยคีย์สาธารณะการยืนยันตัวตนนี้จำเป็นสำหรับเซิร์ฟเวอร์และเป็นทางเลือกสำหรับไคลเอนต์
+ การเชื่อมต่อมีความน่าเชื่อถือ (หรือมีความสมบูรณ์)
เนื่องจากข้อความแต่ละข้อความที่ส่งออกจะมีการตรวจสอบความสมบูรณ์ของข้อความโดยใช้รหัสยืนยันข้อความเพื่อป้องกันการสูญหายหรือการเปลี่ยนแปลงข้อมูลที่ไม่ถูกตรวจพบระหว่างการส่งข้อมูล
]
#i TLS รองรับวิธีการที่หลากหลายสำหรับการแลกเปลี่ยนคีย์ การเข้ารหัสข้อมูล และการตรวจสอบความถูกต้องของข้อความ ดังนั้น การกำหนดค่า TLS อย่างปลอดภัยจึงเกี่ยวข้องกับพารามิเตอร์ที่กำหนดค่าได้มากมาย และตัวเลือกทั้งหมดไม่ได้มีคุณสมบัติที่เกี่ยวข้องกับความเป็นส่วนตัวทั้งหมดที่อธิบายไว้ในรายการด้านบน (ดูตารางด้านล่าง การแลกเปลี่ยนคีย์ ความปลอดภัยของการเข้ารหัสและความสมบูรณ์ของข้อมูล)
#iii TLS รองรับวิธีการที่หลากหลายสำหรับการแลกเปลี่ยนคีย์ การเข้ารหัสข้อมูล
และการตรวจสอบความถูกต้องของข้อความ ดังนั้น การกำหนดค่า TLS
อย่างปลอดภัยจึงเกี่ยวข้องกับพารามิเตอร์ที่กำหนดค่าได้มากมาย
และตัวเลือกทั้งหมดไม่ได้มีคุณสมบัติที่เกี่ยวข้องกับความเป็นส่วนตัวทั้งหมดที่อธิบายไว้ในรายการด้านบน
(ดูตารางด้านล่าง การแลกเปลี่ยนคีย์ ความปลอดภัยของการเข้ารหัสและความสมบูรณ์ของข้อมูล)
#i มีการพยายามบ่อนทำลายแง่มุมด้านความปลอดภัยในการสื่อสารที่ TLS มุ่งหวังจะมอบให้ และโปรโตคอลนี้ได้รับการแก้ไขหลายครั้งเพื่อจัดการกับภัยคุกคามด้านความปลอดภัยเหล่านี้ นักพัฒนาเว็บเบราว์เซอร์ได้ปรับปรุงผลิตภัณฑ์ของตนซ้ำแล้วซ้ำเล่าเพื่อป้องกันจุดอ่อนด้านความปลอดภัยที่อาจเกิดขึ้นหลังจากค้นพบจุดอ่อนเหล่านี้ (ดูประวัติการสนับสนุน TLS/SSL ของเว็บเบราว์เซอร์)
ความปลอดภัยของเลเยอร์การขนส่งดาต้าแกรม
#iii มีการพยายามบ่อนทำลายแง่มุมด้านความปลอดภัยในการสื่อสารที่ TLS มุ่งหวังจะมอบให้
และโปรโตคอลนี้ได้รับการแก้ไขหลายครั้งเพื่อจัดการกับภัยคุกคามด้านความปลอดภัยเหล่านี้
นักพัฒนาเว็บเบราว์เซอร์ได้ปรับปรุงผลิตภัณฑ์ของตนซ้ำแล้วซ้ำเล่าเพื่อป้องกันจุดอ่อนด้านความปลอดภัยที่อาจเกิดขึ้นหลังจากค้นพบจุดอ่อนเหล่านี้
(ดูประวัติการสนับสนุน TLS/SSL ของเว็บเบราว์เซอร์) ความปลอดภัยของเลเยอร์การขนส่งดาต้าแกรม
#i Datagram Transport Layer Security หรือเรียกย่อๆ ว่า DTLS เป็นโปรโตคอลการสื่อสาร ที่เกี่ยวข้องซึ่งให้ความปลอดภัยแก่ แอปพลิเคชันที่ใช้ Datagram โดยอนุญาตให้แอปพลิเคชันสื่อสารในลักษณะที่ออกแบบมาเพื่อป้องกันการดักฟัง การปลอมแปลงหรือการปลอมแปลงข้อความโปรโตคอล DTLS ใช้ โปรโตคอล Transport Layer Security (TLS) ที่เน้น การสตรีมและมีจุดประสงค์เพื่อให้การรับประกันความปลอดภัยที่คล้ายคลึงกัน อย่างไรก็ตาม โปรโตคอลนี้แตกต่างจาก TLS ตรงที่สามารถใช้งานร่วมกับโปรโตคอลที่เน้น Datagram ส่วนใหญ่ ได้แก่ User Datagram Protocol (UDP), Datagram Congestion Control Protocol (DCCP), Control And Provisioning of Wireless Access Points (CAPWAP), Stream Control Transmission Protocol (SCTP) encapsulation และ Secure Real-time Transport Protocol (SRTP)
#iii Datagram Transport Layer Security หรือเรียกย่อๆ ว่า DTLS เป็นโปรโตคอลการสื่อสาร
ที่เกี่ยวข้องซึ่งให้ความปลอดภัยแก่ แอปพลิเคชันที่ใช้ Datagram
โดยอนุญาตให้แอปพลิเคชันสื่อสารในลักษณะที่ออกแบบมาเพื่อป้องกันการดักฟัง
การปลอมแปลงหรือการปลอมแปลงข้อความโปรโตคอล DTLS ใช้ โปรโตคอล Transport Layer
Security (TLS) ที่เน้น การสตรีมและมีจุดประสงค์เพื่อให้การรับประกันความปลอดภัยที่คล้ายคลึงกัน
อย่างไรก็ตาม โปรโตคอลนี้แตกต่างจาก TLS ตรงที่สามารถใช้งานร่วมกับโปรโตคอลที่เน้น Datagram
ส่วนใหญ่ ได้แก่ User Datagram Protocol (UDP), Datagram Congestion Control Protocol
(DCCP), Control And Provisioning of Wireless Access Points (CAPWAP), Stream
Control Transmission Protocol (SCTP) encapsulation และ Secure Real-time
Transport Protocol (SRTP)
#i เนื่องจากเดตาแกรมของโปรโตคอล DTLS รักษาความหมายของการขนส่งพื้นฐานไว้ แอปพลิเคชันจึงไม่ประสบปัญหาความล่าช้าที่เกี่ยวข้องกับโปรโตคอลสตรีม อย่างไรก็ตาม แอปพลิเคชันต้องจัดการกับการเรียงลำดับแพ็กเก็ตใหม่ การสูญหายของเดตาแกรม และข้อมูลที่มีขนาดใหญ่กว่าขนาดของแพ็กเก็ตเครือข่าย เดตาแกรม เนื่องจาก DTLS ใช้ UDP หรือ SCTP แทน TCP จึงหลีกเลี่ยงปัญหา TCP ล่มเมื่อนำไปใช้สร้างอุโมงค์ VPN
#iii เนื่องจากเดตาแกรมของโปรโตคอล DTLS รักษาความหมายของการขนส่งพื้นฐานไว้
แอปพลิเคชันจึงไม่ประสบปัญหาความล่าช้าที่เกี่ยวข้องกับโปรโตคอลสตรีม อย่างไรก็ตาม
แอปพลิเคชันต้องจัดการกับการเรียงลำดับแพ็กเก็ตใหม่ การสูญหายของเดตาแกรม
และข้อมูลที่มีขนาดใหญ่กว่าขนาดของแพ็กเก็ตเครือข่าย เดตาแกรม เนื่องจาก DTLS ใช้ UDP หรือ SCTP
แทน TCP จึงหลีกเลี่ยงปัญหา TCP ล่มเมื่อนำไปใช้สร้างอุโมงค์ VPN
#i DTLS เวอร์ชัน 1.0 ฉบับดั้งเดิมในปี 2006 ไม่ใช่เอกสารแบบสแตนด์อโลน แต่ได้รับการกำหนดให้เป็นชุดเดลต้าของ TLS 1.1 ทำนองเดียวกัน DTLS เวอร์ชัน 2012 ที่ตามมาก็ถูกกำหนดให้เป็นเดลต้าของ TLS 1.2 โดยได้รับหมายเลขเวอร์ชันของ DTLS 1.2 เพื่อให้ตรงกับเวอร์ชัน TLS สุดท้าย DTLS 1.3 ปี 2022 ก็ถูกกำหนดให้เป็นเดลต้าของ TLS 1.3 เช่นเดียวกับสองเวอร์ชันก่อนหน้า DTLS 1.3 มีวัตถุประสงค์เพื่อให้ "การรับประกันความปลอดภัยที่เทียบเท่า [กับ TLS 1.3] ยกเว้นการป้องกันคำสั่ง/การไม่สามารถเล่นซ้ำได้"
#iii DTLS เวอร์ชัน 1.0 ฉบับดั้งเดิมในปี 2006 ไม่ใช่เอกสารแบบสแตนด์อโลน
แต่ได้รับการกำหนดให้เป็นชุดเดลต้าของ TLS 1.1 ทำนองเดียวกัน DTLS เวอร์ชัน 2012
ที่ตามมาก็ถูกกำหนดให้เป็นเดลต้าของ TLS 1.2 โดยได้รับหมายเลขเวอร์ชันของ DTLS 1.2
เพื่อให้ตรงกับเวอร์ชัน TLS สุดท้าย DTLS 1.3 ปี 2022 ก็ถูกกำหนดให้เป็นเดลต้าของ TLS 1.3
เช่นเดียวกับสองเวอร์ชันก่อนหน้า DTLS 1.3 มีวัตถุประสงค์เพื่อให้ "การรับประกันความปลอดภัยที่เทียบเท่า
[กับ TLS 1.3] ยกเว้นการป้องกันคำสั่ง/การไม่สามารถเล่นซ้ำได้"
#i ไคลเอนต์ VPN จำนวนมากรวมถึง Cisco AnyConnect & InterCloud Fabric, OpenConnect, อุโมงค์ ZScaler, F5 Networks Edge VPN Client และ Citrix Systems NetScaler ใช้ DTLS เพื่อรักษาความปลอดภัยการรับส่งข้อมูล UDP นอกจากนี้ เว็บเบราว์เซอร์สมัยใหม่ทั้งหมดยังรองรับ DTLS-SRTP สำหรับ WebRTC
#iii ไคลเอนต์ VPN จำนวนมากรวมถึง Cisco AnyConnect & InterCloud Fabric,
OpenConnect, อุโมงค์ ZScaler, F5 Networks Edge VPN Client และ Citrix Systems
NetScaler ใช้ DTLS เพื่อรักษาความปลอดภัยการรับส่งข้อมูล UDP นอกจากนี้
เว็บเบราว์เซอร์สมัยใหม่ทั้งหมดยังรองรับ DTLS-SRTP สำหรับ WebRTC
#include "X509.typ"
#include "x690.typ"
+92 -43
View File
@@ -2,62 +2,111 @@
== X.509 (รูปแบบใบรับรอง TLS/SSL) <x509>
#i ในการเข้ารหัส X.509 เป็นมาตรฐานของสหภาพโทรคมนาคมระหว่างประเทศ (ITU) ที่กำหนดรูปแบบของใบรับรองคีย์สาธารณะใบรับรอง X.509 ถูกใช้ในโปรโตคอลอินเทอร์เน็ตมากมายรวมถึง TLS/SSL ซึ่งเป็นพื้นฐานของ HTTPS โปรโตคอลที่ปลอดภัยสำหรับการท่องเว็บ นอกจากนี้ยังใช้ในแอปพลิเคชันออฟไลน์เช่น ลาย เซ็นอิเล็กทรอนิกส์
ใบรับรอง X.509 เชื่อมโยงข้อมูลประจำตัวกับคีย์สาธารณะโดยใช้ลายเซ็นดิจิทัล ใบรับรองประกอบด้วยข้อมูลประจำตัว (ชื่อโฮสต์องค์กร หรือบุคคล) และคีย์สาธารณะ (RSA, DSA, ECDSA, ed25519 เป็นต้น) ซึ่งลงนามโดยผู้ออกใบรับรองหรือลงนามด้วยตนเอง เมื่อใบรับรองได้รับการลงนามโดยผู้ออกใบรับรองที่เชื่อถือได้หรือผ่านการตรวจสอบความถูกต้องด้วยวิธีอื่น ผู้ถือใบรับรองนั้นสามารถใช้คีย์สาธารณะที่มีอยู่เพื่อสร้างการสื่อสารที่ปลอดภัยกับบุคคลอื่น หรือตรวจสอบความถูกต้องของเอกสารที่ลงนามดิจิทัลด้วย คีย์ส่วนตัวที่เกี่ยวข้องได้
#iii ในการเข้ารหัส X.509 เป็นมาตรฐานของสหภาพโทรคมนาคมระหว่างประเทศ (ITU)
ที่กำหนดรูปแบบของใบรับรองคีย์สาธารณะใบรับรอง X.509 ถูกใช้ในโปรโตคอลอินเทอร์เน็ตมากมายรวมถึง
TLS/SSL ซึ่งเป็นพื้นฐานของ HTTPS โปรโตคอลที่ปลอดภัยสำหรับการท่องเว็บ
นอกจากนี้ยังใช้ในแอปพลิเคชันออฟไลน์เช่น ลาย เซ็นอิเล็กทรอนิกส์ ใบรับรอง X.509
เชื่อมโยงข้อมูลประจำตัวกับคีย์สาธารณะโดยใช้ลายเซ็นดิจิทัล ใบรับรองประกอบด้วยข้อมูลประจำตัว
(ชื่อโฮสต์องค์กร หรือบุคคล) และคีย์สาธารณะ (RSA, DSA, ECDSA, ed25519 เป็นต้น)
ซึ่งลงนามโดยผู้ออกใบรับรองหรือลงนามด้วยตนเอง
เมื่อใบรับรองได้รับการลงนามโดยผู้ออกใบรับรองที่เชื่อถือได้หรือผ่านการตรวจสอบความถูกต้องด้วยวิธีอื่น
ผู้ถือใบรับรองนั้นสามารถใช้คีย์สาธารณะที่มีอยู่เพื่อสร้างการสื่อสารที่ปลอดภัยกับบุคคลอื่น
หรือตรวจสอบความถูกต้องของเอกสารที่ลงนามดิจิทัลด้วย คีย์ส่วนตัวที่เกี่ยวข้องได้
#i X.509 ยังกำหนดรายการเพิกถอนใบรับรองซึ่งเป็นวิธีการแจกจ่ายข้อมูลเกี่ยวกับใบรับรองที่ถือว่าไม่ถูกต้องโดยผู้มีอำนาจลงนาม ตลอดจนอัลกอริทึมการตรวจสอบเส้นทางการรับรองซึ่งช่วยให้ใบรับรองได้รับการลงนามโดยใบรับรอง CA ตัวกลาง ซึ่งใบรับรองเหล่านี้จะได้รับการลงนามโดยใบรับรองอื่นๆ ต่อไปจนไปถึงจุดยึดที่เชื่อถือได้ในที่สุด
#iii X.509
ยังกำหนดรายการเพิกถอนใบรับรองซึ่งเป็นวิธีการแจกจ่ายข้อมูลเกี่ยวกับใบรับรองที่ถือว่าไม่ถูกต้องโดยผู้มีอำนาจลงนาม
ตลอดจนอัลกอริทึมการตรวจสอบเส้นทางการรับรองซึ่งช่วยให้ใบรับรองได้รับการลงนามโดยใบรับรอง CA
ตัวกลาง ซึ่งใบรับรองเหล่านี้จะได้รับการลงนามโดยใบรับรองอื่นๆ ต่อไปจนไปถึงจุดยึดที่เชื่อถือได้ในที่สุด
#i X.509 ถูกกำหนดโดย "Standardization Sector" ของ ITU (SG17 ของ ITU-T) ใน ITU-T Study Group 17 และมีพื้นฐานมาจาก Abstract Syntax Notation One (ASN.1) ซึ่งเป็นมาตรฐานอีกประการหนึ่งของ ITU-T
#iii X.509 ถูกกำหนดโดย "Standardization Sector" ของ ITU (SG17 ของ ITU-T) ใน ITU-T
Study Group 17 และมีพื้นฐานมาจาก Abstract Syntax Notation One (ASN.1)
ซึ่งเป็นมาตรฐานอีกประการหนึ่งของ ITU-T
=== โครงสร้างของใบรับรอง
#i โครงสร้างที่กำหนดไว้โดยมาตรฐานจะแสดงอยู่ในภาษาทางการที่เรียกว่า Abstract Syntax Notation One (ASN.1)
#iiii โครงสร้างที่กำหนดไว้โดยมาตรฐานจะแสดงอยู่ในภาษาทางการที่เรียกว่า Abstract Syntax
Notation One (ASN.1)
โครงสร้างของใบรับรองดิจิทัล X.509 v3 มีดังนี้:
#iiii โครงสร้างของใบรับรองดิจิทัล X.509 v3 มีดังนี้
- ใบรับรอง
- หมายเลขเวอร์ชัน
- หมายเลขซีเรียล
- รหัสอัลกอริทึมลายเซ็น
- ชื่อผู้ออก
- ระยะเวลาใช้งาน
- ไม่ก่อ
- ไม่หลังจากนั้น
- ชื่อเรื่อง
- ข้อมูลคีย์สาธารณะของเรื่อง
- อัลกอริทึมคีย์สาธารณะ
- คีย์สาธารณะของเรื่อง
รหัสประจำตัวผู้ออก (ทางเลือก)
รหัสประจำตัวเฉพาะเรื่อง (ทางเลือก)
ส่วนขยาย (ทางเลือก)
+ ใบรับรอง
+ หมายเลขเวอร์ชัน
+ หมายเลขซีเรียล
+ รหัสอัลกอริทึมลายเซ็น
+ ชื่อผู้ออก
+ ระยะเวลาใช้งานไม่ก่อนหรือไม่หลังจากนั้น
+ ชื่อเรื่อ
+ ข้อมูลคีย์สาธารณะของเรื่องได้แก่อัลกอริทึมคีย์สาธารณะ
คีย์สาธารณะของเรื่องเช่นรหัสประจำตัวผู้ออก (ไม่จำเป็น)
รหัสประจำตัวเฉพาะเรื่อง (ไม่จำเป็น) ส่วนขยาย (ไม่จำเป็น)
+ อัลกอริทึมลายเซ็นใบรับรอง
+ ลายเซ็นใบรับรอง
- อัลกอริทึมลายเซ็นใบรับรอง
- ลายเซ็นใบรับรอง
#iiii ฟิลด์ส่วนขยาย (ถ้ามี) จะเป็นลำดับของส่วนขยายใบรับรองอย่างน้อยหนึ่งรายการ
แต่ละส่วนขยายมีรหัสประจำตัวเฉพาะของตัวเอง ซึ่งแสดงเป็นตัวระบุวัตถุ (OID)
ซึ่งเป็นชุดค่าพร้อมกับข้อบ่งชี้ที่สำคัญหรือไม่สำคัญ
ระบบที่ใช้ใบรับรองต้องปฏิเสธใบรับรองหากพบส่วนขยายที่สำคัญที่ไม่รู้จักหรือส่วนขยายที่สำคัญซึ่งมีข้อมูลที่ไม่สามารถประมวลผลได้
ส่วนขยายที่ไม่สำคัญอาจถูกละเว้นหากไม่รู้จัก แต่จะต้องได้รับการประมวลผลหากรู้จักส่วนขยายใบรับรอง
#i ฟิลด์ส่วนขยาย (ถ้ามี) จะเป็นลำดับของส่วนขยายใบรับรองอย่างน้อยหนึ่งรายการ แต่ละส่วนขยายมีรหัสประจำตัวเฉพาะของตัวเอง ซึ่งแสดงเป็นตัวระบุวัตถุ (OID) ซึ่งเป็นชุดค่าพร้อมกับข้อบ่งชี้ที่สำคัญหรือไม่สำคัญ ระบบที่ใช้ใบรับรองต้องปฏิเสธใบรับรองหากพบส่วนขยายที่สำคัญที่ไม่รู้จักหรือส่วนขยายที่สำคัญซึ่งมีข้อมูลที่ไม่สามารถประมวลผลได้ ส่วนขยายที่ไม่สำคัญอาจถูกละเว้นหากไม่รู้จัก แต่จะต้องได้รับการประมวลผลหากรู้จักส่วนขยายใบรับรอง
#iiii โครงสร้างของเวอร์ชัน 1 มีอยู่ ใน RFC 1422
#i โครงสร้างของเวอร์ชัน 1 มีอยู่ ใน RFC 1422
#iiii รูปแบบภายในของตัวระบุเฉพาะของผู้เผยแพร่และเรื่องที่ระบุไว้ใน X.520 ไดเร็กทอรี:คำแนะนำ
ประเภทแอตทริบิวต์ที่เลือก
#i รูปแบบภายในของตัวระบุเฉพาะของผู้เผยแพร่และเรื่องที่ระบุไว้ใน X.520 ไดเร็กทอรี:คำแนะนำ ประเภทแอตทริบิวต์ที่เลือก
#iiii ITU-T ได้นำตัวระบุเฉพาะของผู้ออกหลักทรัพย์และบุคคลมาใช้ในเวอร์ชัน 2
เพื่ออนุญาตให้นำชื่อผู้ออกหลักทรัพย์หรือบุคคลมาใช้ซ้ำได้หลังจากระยะเวลาหนึ่ง
ตัวอย่างหนึ่งของการนำกลับมาใช้ซ้ำคือเมื่อ CA ล้มละลายและชื่อถูกลบออกจากรายชื่อสาธารณะของประเทศ
หลังจากนั้น CA อื่นที่มีชื่อเดียวกันอาจลงทะเบียนตัวเองได้ แม้ว่าจะไม่เกี่ยวข้องกับ CA แรกก็ตาม
อย่างไรก็ตาม IETF แนะนำว่าไม่ควรนำชื่อผู้ออกหลักทรัพย์และบุคคลมาใช้ซ้ำ ดังนั้นเวอร์ชัน 2
จึงยังไม่แพร่หลายในอินเทอร์เน็ต
#i ITU-T ได้นำตัวระบุเฉพาะของผู้ออกหลักทรัพย์และบุคคลมาใช้ในเวอร์ชัน 2 เพื่ออนุญาตให้นำชื่อผู้ออกหลักทรัพย์หรือบุคคลมาใช้ซ้ำได้หลังจากระยะเวลาหนึ่ง ตัวอย่างหนึ่งของการนำกลับมาใช้ซ้ำคือเมื่อ CA ล้มละลายและชื่อถูกลบออกจากรายชื่อสาธารณะของประเทศ หลังจากนั้น CA อื่นที่มีชื่อเดียวกันอาจลงทะเบียนตัวเองได้ แม้ว่าจะไม่เกี่ยวข้องกับ CA แรกก็ตาม อย่างไรก็ตาม IETF แนะนำว่าไม่ควรนำชื่อผู้ออกหลักทรัพย์และบุคคลมาใช้ซ้ำ ดังนั้นเวอร์ชัน 2 จึงยังไม่แพร่หลายในอินเทอร์เน็ต
#iiii ส่วนขยายได้รับการแนะนำในเวอร์ชัน 3 CA
สามารถใช้ส่วนขยายเพื่อออกใบรับรองได้เฉพาะสำหรับจุดประสงค์เฉพาะ (เช่น
สำหรับการลงนามในวัตถุดิจิทัล เท่านั้น)
#i ส่วนขยายได้รับการแนะนำในเวอร์ชัน 3 CA สามารถใช้ส่วนขยายเพื่อออกใบรับรองได้เฉพาะสำหรับจุดประสงค์เฉพาะ (เช่น สำหรับการลงนามในวัตถุดิจิทัล เท่านั้น)
#i ในทุกเวอร์ชันหมายเลขซีเรียลจะต้องไม่ซ้ำกันสำหรับใบรับรองแต่ละใบที่ออกโดย CA เฉพาะ (ดังที่กล่าวถึงใน RFC 5280)
#iiii ในทุกเวอร์ชันหมายเลขซีเรียลจะต้องไม่ซ้ำกันสำหรับใบรับรองแต่ละใบที่ออกโดย CA เฉพาะ
(ดังที่กล่าวถึงใน RFC 5280)
=== นามสกุลไฟล์ใบรับรอง
#i นามสกุลไฟล์ที่ใช้กันทั่วไปสำหรับใบรับรอง X.509 มีหลายประเภทนามสกุลไฟล์เหล่านี้ยังใช้สำหรับข้อมูลอื่นๆ เช่น คีย์ส่วนตัวด้วย
#iiii นามสกุลไฟล์ที่ใช้กันทั่วไปสำหรับใบรับรอง X.509
มีหลายประเภทนามสกุลไฟล์เหล่านี้ยังใช้สำหรับข้อมูลอื่น เช่น คีย์ส่วนตัวด้วย
- `.pem` -- (อีเมลอิเล็กทรอนิกส์ที่เพิ่มความเป็นส่วนตัว) ใบรับรอง DER ที่เข้ารหัส Base64 แนบระหว่าง `-----BEGIN CERTIFICATE-----` และ `-----END CERTIFICATE-----`
- `.cer`, `.crt`, `.der` -- โดยปกติจะอยู่ในรูปแบบไบนารี DER แต่ใบรับรองที่เข้ารหัส Base64 ก็เป็นเรื่องปกติเช่นกัน (ดู `.pem` ด้านบน)
- `.p8`, `.p8e`, `.pk8` -- คีย์ส่วนตัวที่ส่งออกตามที่ระบุไว้ใน PKCS\#8 อาจอยู่ในรูปแบบ DER หรือ PEM ที่ขึ้นต้นด้วย `-----BEGIN PRIVATE KEY-----` คีย์ที่เข้ารหัสจะขึ้นต้นด้วย `-----BEGIN ENCRYPTED PRIVATE KEY-----` และอาจมี `.p8e` เป็นนามสกุลไฟล์
- `.p10`, `.csr` -- PKCS\#10 เป็นคำขอลงนามใบรับรอง (CSR) ในรูปแบบ PEM ขึ้นต้นด้วย `-----BEGIN CERTIFICATE REQUEST-----` บบฟอร์มเหล่านี้สร้างขึ้นเพื่อส่งไปยังผู้ออกใบรับรอง (CA) แบบฟอร์มประกอบด้วยรายละเอียดสำคัญของใบรับรองที่ร้องขอ เช่น ชื่อสามัญ (/CN), หัวเรื่อง, องค์กร, รัฐ, ประเทศ รวมถึงคีย์สาธารณะของใบรับรองที่ต้องการให้ลงนาม คีย์เหล่านี้จะได้รับการลงนามโดย CA และใบรับรองจะถูกส่งกลับคืน ใบรับรองที่ส่งคืนคือใบรับรอง สาธารณะ (ซึ่งมีคีย์สาธารณะแต่ไม่มีคีย์ส่วนตัว) ซึ่งตัวใบรับรองเองสามารถอยู่ในรูปแบบต่างๆ ได้หลายรูปแบบ แต่โดยปกติจะเป็น `.p7r`
- `.p7r` -- คำตอบ ของ PKCS\#7 ต่อ CSR ประกอบด้วยใบรับรองที่เพิ่งลงนาม และใบรับรองของ CA เอง
- `.p7s` -- ลายเซ็นดิจิทัล PKCS\#7 อาจมีไฟล์หรือข้อความที่ลงนามต้นฉบับ ใช้ใน S/MIME สำหรับการลงนามในอีเมลกำหนดไว้ใน RFC 2311
- `.p7m` -- PKCS\#7 (SignedData, EnvelopedData) ข้อความ เช่น ไฟล์ที่เข้ารหัส ("enveloped") ข้อความ หรือจดหมายอีเมล MIME กำหนดไว้ใน RFC 2311
- `.p7c` -- โครงสร้าง SignedData แบบ "certs-only" ของ PKCS\#7 ที่เสื่อมลง โดยไม่มีข้อมูลใดๆ ให้ลงนาม กำหนดไว้ใน RFC 2311
- `.p7b` -- โครงสร้าง SignedData ของ PKCS\#7 ที่ไม่มีข้อมูล มีเพียงใบรับรองแบบบันเดิลหรือ CRL (ไม่ค่อยเกิดขึ้น) แต่ไม่มีคีย์ส่วนตัว ใช้รูปแบบ DER หรือ BER หรือ PEM ที่ขึ้นต้นด้วย `-----BEGIN PKCS7-----` รูปแบบที่ Windows ใช้สำหรับการแลกเปลี่ยนใบรับรอง รองรับโดย Java แต่มักใช้นามสกุล `.keystore` แทน ซึ่งแตกต่างจากใบรับรองแบบ `.pem` รูปแบบนี้มีวิธีที่กำหนดไว้สำหรับการรวมใบรับรองเส้นทางการรับรอง
- `.p12`, `.pfx`, `.pkcs12` -- PKCS\#12 อาจมีใบรับรอง (สาธารณะ) และคีย์ส่วนตัว (ป้องกันด้วยรหัสผ่าน) ในไฟล์เดียว `.pfx` - _Personal Information eXchange_ PFX ซึ่งเป็นรุ่นก่อนของ PKCS\#12 (โดยปกติจะมีข้อมูลในรูปแบบ PKCS\#12 เช่น ไฟล์ PFX ที่สร้างใน IIS)
- `.crl` -- รายการเพิกถอนใบรับรอง (CRL) หน่วยงานที่ออกใบรับรองจะจัดทำรายการเหล่านี้ขึ้นเพื่อใช้ในการเพิกถอนใบรับรองก่อนหมดอายุ
#[
#set enum(indent: 9.75em)
+ `.pem` -- (อีเมลอิเล็กทรอนิกส์ที่เพิ่มความเป็นส่วนตัว) ใบรับรอง DER ที่เข้ารหัส Base64
แนบระหว่าง `-----BEGIN CERTIFICATE-----` ละ `-----END CERTIFICATE-----`
+ `.cer`, `.crt`, `.der` -- โดยปกติจะอยู่ในรูปแบบไบนารี DER แต่ใบรับรองที่เข้ารหัส Base64
ก็เป็นเรื่องปกติเช่นกัน (ดู `.pem` ด้านบน)
+ `.p8`, `.p8e`, `.pk8` -- คีย์ส่วนตัวที่ส่งออกตามที่ระบุไว้ใน PKCS\#8 อาจอยู่ในรูปแบบ DER หรือ
PEM ที่ขึ้นต้นด้วย `-----BEGIN PRIVATE KEY-----` คีย์ที่เข้ารหัสจะขึ้นต้นด้วย
`-----BEGIN ENCRYPTED PRIVATE KEY-----` และอาจมี `.p8e` เป็นนามสกุลไฟล์
+ `.p10`, `.csr` -- PKCS\#10 เป็นคำขอลงนามใบรับรอง (CSR) ในรูปแบบ PEM ขึ้นต้นด้วย
`-----BEGIN CERTIFICATE REQUEST-----` แบบฟอร์มเหล่านี้สร้างขึ้นเพื่อส่งไปยังผู้ออกใบรับรอง
(CA) แบบฟอร์มประกอบด้วยรายละเอียดสำคัญของใบรับรองที่ร้องขอ เช่น ชื่อสามัญ (/CN), หัวเรื่อง,
องค์กร, รัฐ, ประเทศ รวมถึงคีย์สาธารณะของใบรับรองที่ต้องการให้ลงนาม
คีย์เหล่านี้จะได้รับการลงนามโดย CA และใบรับรองจะถูกส่งกลับคืน ใบรับรองที่ส่งคืนคือใบรับรอง
สาธารณะ (ซึ่งมีคีย์สาธารณะแต่ไม่มีคีย์ส่วนตัว) ซึ่งตัวใบรับรองเองสามารถอยู่ในรูปแบบต่างๆ
ได้หลายรูปแบบ แต่โดยปกติจะเป็น `.p7r`
+ `.p7r` -- คำตอบ ของ PKCS\#7 ต่อ CSR ประกอบด้วยใบรับรองที่เพิ่งลงนาม และใบรับรองของ CA
เอง
+ `.p7s` -- ลายเซ็นดิจิทัล PKCS\#7 อาจมีไฟล์หรือข้อความที่ลงนามต้นฉบับ ใช้ใน S/MIME
สำหรับการลงนามในอีเมลกำหนดไว้ใน RFC 2311
+ `.p7m` -- PKCS\#7 (SignedData, EnvelopedData) ข้อความ เช่น ไฟล์ที่เข้ารหัส
("enveloped") ข้อความ หรือจดหมายอีเมล MIME กำหนดไว้ใน RFC 2311
+ `.p7c` -- โครงสร้าง SignedData แบบ "certs-only" ของ PKCS\#7 ที่เสื่อมลง
โดยไม่มีข้อมูลใดๆ ให้ลงนาม กำหนดไว้ใน RFC 2311
+ `.p7b` -- โครงสร้าง SignedData ของ PKCS\#7 ที่ไม่มีข้อมูล มีเพียงใบรับรองแบบบันเดิลหรือ CRL
(ไม่ค่อยเกิดขึ้น) แต่ไม่มีคีย์ส่วนตัว ใช้รูปแบบ DER หรือ BER หรือ PEM ที่ขึ้นต้นด้วย
`-----BEGIN PKCS7-----` รูปแบบที่ Windows ใช้สำหรับการแลกเปลี่ยนใบรับรอง รองรับโดย Java
แต่มักใช้นามสกุล `.keystore` แทน ซึ่งแตกต่างจากใบรับรองแบบ `.pem`
รูปแบบนี้มีวิธีที่กำหนดไว้สำหรับการรวมใบรับรองเส้นทางการรับรอง
+ `.p12`, `.pfx`, `.pkcs12` -- PKCS\#12 อาจมีใบรับรอง (สาธารณะ) และคีย์ส่วนตัว
(ป้องกันด้วยรหัสผ่าน) ในไฟล์เดียว `.pfx` - _Personal Information eXchange_ PFX
ซึ่งเป็นรุ่นก่อนของ PKCS\#12 (โดยปกติจะมีข้อมูลในรูปแบบ PKCS\#12 เช่น ไฟล์ PFX ที่สร้างใน IIS)
+ `.crl` -- รายการเพิกถอนใบรับรอง (CRL)
หน่วยงานที่ออกใบรับรองจะจัดทำรายการเหล่านี้ขึ้นเพื่อใช้ในการเพิกถอนใบรับรองก่อนหมดอายุ
]
#i PKCS\#7 เป็นมาตรฐานสำหรับการลงนามหรือเข้ารหัสข้อมูล (เรียกอย่างเป็นทางการว่า "enveloping") เนื่องจากจำเป็นต้องใช้ใบรับรองเพื่อตรวจสอบข้อมูลที่ลงนามแล้วจึงสามารถรวมใบรับรองไว้ในโครงสร้าง SignedData ได้
#iiii PKCS\#7 เป็นมาตรฐานสำหรับการลงนามหรือเข้ารหัสข้อมูล (เรียกอย่างเป็นทางการว่า
"enveloping")
เนื่องจากจำเป็นต้องใช้ใบรับรองเพื่อตรวจสอบข้อมูลที่ลงนามแล้วจึงสามารถรวมใบรับรองไว้ในโครงสร้าง
SignedData ได้
+21 -9
View File
@@ -1,19 +1,31 @@
#import "../PageTemplate.typ": i
#import "../PageTemplate.typ": *
#set heading(numbering: "1.1", offset: 2)
= X.690 (การเข้ารหัส DER)
X.690 เป็น มาตรฐาน ITU-T ที่ระบุรูปแบบการเข้ารหัส ASN.1 หลายรูปแบบ:
#iii X.690 เป็น มาตรฐาน ITU-T ที่ระบุรูปแบบการเข้ารหัส ASN.1 หลายรูปแบบ
- กฎการเข้ารหัสพื้นฐาน (BER)
- กฎการเข้ารหัสแบบ Canonical (CER)
- กฎการเข้ารหัสที่โดดเด่น (DER)
== กฎการเข้ารหัสพื้นฐาน (BER)
กฎการเข้ารหัสพื้นฐาน (BER) คือกฎดั้งเดิมที่วางไว้โดยมาตรฐาน ASN.1 สำหรับการเข้ารหัสข้อมูลในรูปแบบไบนารี กฎเหล่านี้ ซึ่งเรียกรวมกันว่าไวยากรณ์การถ่ายโอนในภาษา ASN.1 กำหนดจำนวนอ็อกเท็ต (ไบต์ 8 บิต) ที่ใช้ในการเข้ารหัสข้อมูล
#iiii กฎการเข้ารหัสพื้นฐาน (BER) คือกฎดั้งเดิมที่วางไว้โดยมาตรฐาน ASN.1
สำหรับการเข้ารหัสข้อมูลในรูปแบบไบนารี กฎเหล่านี้ ซึ่งเรียกรวมกันว่าไวยากรณ์การถ่ายโอนในภาษา ASN.1
กำหนดจำนวนอ็อกเท็ต (ไบต์ 8 บิต) ที่ใช้ในการเข้ารหัสข้อมูล
#i โดยโครงงานนี้ใช้ใบรับรองในรูปแบบการเข้ารหัส DER ซึ่ง DER (Distinguished Encoding Rules) เป็น BER แบบจำกัดรูปแบบหนึ่งสำหรับการสร้างไวยากรณ์การถ่ายโอนข้อมูลที่ชัดเจนสำหรับโครงสร้างข้อมูลที่อธิบายโดย ASN.1 เช่นเดียวกับ CER การเข้ารหัส DER ถือเป็นการเข้ารหัส BER ที่ถูกต้อง DER เหมือนกับ BER โดยตัดตัวเลือกของผู้ส่งออกทั้งหมด ยกเว้นตัวเลือกเดียว
== กฎการเข้ารหัสที่โดดเด่น (DER)
DER เป็นส่วนย่อยของ BER ที่ให้วิธีการเข้ารหัสค่า ASN.1 เพียงวิธีเดียว DER มีไว้สำหรับสถานการณ์ที่จำเป็นต้องมีการเข้ารหัสเฉพาะ เช่น ในการเข้ารหัสลับและช่วยให้มั่นใจว่าโครงสร้างข้อมูลที่จำเป็นต้องมีการลงนามดิจิทัลจะสร้างการแสดงแบบอนุกรมที่ไม่ซ้ำกัน DER ถือเป็นรูปแบบมาตรฐานของ BER ตัวอย่างเช่นใน BER ค่าบูลีน true สามารเข้ารหัสเป็นค่าไบต์ที่ไม่ใช่ศูนย์ 255 ค่า ในขณะที่ DER มีวิธีการเข้ารหัสค่าบูลีน true เพียงวิธีเดียว
#iiii โดยโครงงานนี้ใช้ใบรับรองในรูปแบบการเข้ารหัส DER ซึ่ง DER (Distinguished Encoding
Rules) เป็น BER
แบบจำกัดรูปแบบหนึ่งสำหรับการสร้างไวยากรณ์การถ่ายโอนข้อมูลที่ชัดเจนสำหรับโครงสร้างข้อมูลที่อธิบายโดย
ASN.1 เช่นเดียวกับ CER การเข้ารหัส DER ถือเป็นการเข้ารหัส BER ที่ถูกต้อง DER เหมือนกับ BER
โดยตัดตัวเลือกของผู้ส่งออกทั้งหมด ยกเว้นตัวเลือกเดียว
#iiii DER เป็นส่วนย่อยของ BER ที่ให้วิธีการเข้ารหัสค่า ASN.1 เพียงวิธีเดียว DER
มีไว้สำหรับสถานการณ์ที่จำเป็นต้องมีการเข้ารหัสเฉพาะ เช่น
ในการเข้ารหัสลับและช่วยให้มั่นใจว่าโครงสร้างข้อมูลที่จำเป็นต้องมีการลงนามดิจิทัลจะสร้างการแสดงแบบอนุกรมที่ไม่ซ้ำกัน
DER ถือเป็นรูปแบบมาตรฐานของ BER ตัวอย่างเช่นใน BER ค่าบูลีน true
สามารถเข้ารหัสเป็นค่าไบต์ที่ไม่ใช่ศูนย์ 255 ค่า ในขณะที่ DER มีวิธีการเข้ารหัสค่าบูลีน true เพียงวิธีเดียว
#pagebreak()
ข้อจำกัดการเข้ารหัส DER ที่สำคัญที่สุดคือ:
@@ -22,4 +34,4 @@ DER เป็นส่วนย่อยของ BER ที่ให้วิ
2. บิตสตริง อ็อกเท็ตสตริง และสตริงอักขระที่จำกัดต้องใช้การเข้ารหัสแบบดั้งเดิม
3. องค์ประกอบของชุดจะถูกเข้ารหัสตามลำดับการเรียงลำดับตามค่าแท็ก
DER ถูกใช้กันอย่างแพร่หลายสำหรับใบรับรอง ดิจิทัลเช่น X.509
DER ถูกใช้กันอย่างแพร่หลายสำหรับใบรับรอง ดิจิทัลเช่น X.509
-410
View File
@@ -1,410 +0,0 @@
#import "PageTemplate.typ": *
#import "@preview/fletcher:0.5.8" as fletcher: diagram, edge, node
#import fletcher.shapes: circle, diamond, pill
#show: chapter-page
#set heading(numbering: "บทที่ 1")
#heading([#linebreak()วิธีการดำเนินโครงงาน])
#set heading(numbering: "1.1")
#i ในการดำเนินการศึกษาครั้งนี้
คณะผู้จัดทำโครงงานได้ศึกษาข้อมูลเบื้องต้นในการสร้างเครื่องยืนยันตัวตนด้วย NFC
และได้ดำเนินการตามขั้นตอนนี้
+ วางแผนการดำเนินงาน
+ การออกแบบ
+ วัสดุอุปกรณ์
+ ขั้นตอนการประกอบ
+ การทดลอง
+ การวิเคราะห์ข้อมูล
== วางแผนการดำเนินงาน
#show table.cell.where(y: 1): strong
#set par(leading: 0.5em)
#let arrow = [
#place(
left + horizon,
text(weight: "bold", size: 14pt)[#sym.arrow.l],
dx: -5pt,
dy: -0.7pt,
)
#place(
horizon,
line(length: 100%, stroke: (thickness: 1pt)),
dx: 0pt,
dy: 0pt,
)
#place(
right + horizon,
text(weight: "bold", size: 14pt)[#sym.arrow.r],
dx: 5pt,
dy: -0.7pt,
)
]
=== แผนขั้นตอนและวิธีการดำเนินงาน
#table(
columns: 12,
align: (
left + horizon,
center,
center,
center,
center,
center,
center,
center,
center,
center,
center,
center,
),
table.header(
table.cell(
[ขั้นตอนการ\ ดำเนินการ],
rowspan: 2,
),
table.cell(
[พ.ศ.2568],
colspan: 3,
),
table.cell(
[พ.ศ.2569],
colspan: 8,
),
[ต.ค.],
[พ.ย.],
[ธ.ค.],
[ม.ค.],
[ก.พ.],
[มี.ค],
[เม.ย],
[พ.ค.],
[มิ.ย.],
[ก.ค.],
[ส.ค.],
),
[ศึกษาค้นคว้าข้อมูล],
table.cell(arrow, colspan: 3),
[],
[],
[],
[],
[],
[],
[],
[],
[เสนอหัวข้อ], arrow, [], [], [], [], [], [], [], [], [], [],
[เสนอครั้งที่ 1], [], arrow, [], [], [], [], [], [], [], [], [],
[ออกแบบและสร้าง], [], table.cell(arrow, colspan: 5), [], [], [], [], [],
[จัดซื้ออุปกรณ์ทดลอง],
[],
table.cell(arrow, colspan: 3),
[],
[],
[],
[],
[],
[],
[],
[ทดลองการทำงาน], [], [], table.cell(arrow, colspan: 4), [], [], [], [], [],
[ปรับปรุงแก้ไข], [], [], [], [], table.cell(arrow, colspan: 5), [], [],
[เสนอครั้งที่ 2], [], [], [], arrow, [], [], [], [], [], [], [],
[จัดทำรูปเล่ม], table.cell(arrow, colspan: 11),
[นำเสนอโครงงาน], [], [], [], [], [], [], [], [], [], [], [],
)
=== ผังการดำเนินงาน
#diagram(
node-stroke: 1pt,
spacing: 2em,
node((0, 0), [เริ่มต้น], shape: pill),
edge("-|>"),
node((0, 1), shape: circle, radius: 1em),
edge("-|>"),
node((0, 2), [ศึกษาข้อมูลและทฤษฏีที่เกี่ยวข้อง], width: 2.5in),
edge("-|>"),
node((0, 3), [ออกแบบและวางแผนการดําเนินงาน], width: 2.5in),
edge("-|>"),
node((0, 4), [เครื่องยืนยันตัวตนด้วย NFC], width: 2.5in),
edge("-|>"),
node((0, 5), [ทดสอบประสิทธิภาพ], shape: diamond),
edge("r,u,u,u,u,l", "-|>", [ไม่ผ่าน]),
edge("-|>", [ผ่าน]),
node((0, 6), [จัดทำเอกสาร], width: 2.5in),
edge("-|>"),
node((0, 7), [นำเสนอ], width: 2.5in),
edge("-|>"),
node((0, 8), [สิ้นสุด], shape: pill),
)
#pagebreak()
=== ผังการทำงาน
#diagram(
node-stroke: 1pt,
spacing: 2em,
node([เริ่มต้น], shape: pill),
edge("-|>"),
node((1, 0), [ตั้งค่า LittleFS]),
edge("-|>"),
node((1, 2), [มี Wi-Fi บันทึก\ ไว้อยู่หรือไม่], shape: diamond),
edge("l", "-|>", [ไม่มี]),
edge((1, 2), (1, 3), "-|>", [มี]),
node((0, 2), [รอรับรายละเอียดเครือข่าย\ (ESP-Touch)]),
edge("d,r", "-|>"),
node((1, 3), [เชื่อมต่อเครือข่าย]),
edge("-|>"),
node((0, 4), [มีอุปกรณ์ควบคุม\ หลักแล้วหรือไม่], shape: diamond),
edge("-|>", [ไม่มี]),
edge("d", "-|>", [มี]),
node((1, 4), [สร้างโทเค็นสำหรับการยืนยัน\ อุปกรณ์ควบคุมหลัก]),
edge("-|>"),
node((1, 5), [รออุปกรณ์ควบคุมหลัก\ แตะเซนเซอร์ NFC]),
edge("-|>"),
node((0, 5), [ตั้งค่าเซิร์ฟเวอร์ HTTPS]),
edge("-|>"),
node((0, 6), shape: circle, radius: 1em),
edge("-|>"),
node((0, 7), [มีการแตะเซนเซอร์\ NFC ขาเข้าหรือไม่], shape: diamond),
edge("-|>", [ไม่มี]),
node((0, 9), [มีคนผ่านเซนเซอร์ PIR\ โดยไม่ได้รับอนุญาตหรือไม่], shape: diamond),
edge((0, 9), (0, 10), [ไม่มี]),
edge((0, 7), (1, 6), "-|>", [มี]),
node((1, 6), [อยู่ในโหมดลงทะเบียน\ หรือไม่], shape: diamond),
edge("-|>", [ใช่]),
edge((1, 6), (2, 7), [ไม่]),
node((1, 7), [นำ ID อุปกรณ์เข้า\ สู่รายการทะเบียน]),
edge((1, 7), (0.6, 7), (0, 9), "-|>"),
node((2, 7), [ID ของอุปกรณ์อยู่\ ในทะเบียนหรือไม่], shape: diamond),
edge("-|>", [อยู่]),
edge((2, 7), (1, 8), "-|>", [ไม่อยู่], label-sep: -5pt),
node((2, 8), [ส่งเสียงคอนเฟิร์ม]),
edge((2, 8), (2, 8.5), (0.4, 8.5), (0, 9), "-|>"),
node((1, 8), [ส่งเสียงแสดงความผิดพลาด]),
edge((1, 8), (0.5, 8), (0, 9), "-|>"),
node((1, 9), [แจ้งเตือนทางเสียง\ และแอพลิเคชัน]),
edge((1, 9), (0, 10), "-|>"),
edge((0, 10), (1, 10), "-|>", [มี]),
node((0, 10), [มีคำขอ HTTPS\ ใหม่หรือไม่], shape: diamond),
edge((0, 10), (-2, 10), "-|>", [ไม่มี], label-pos: 10%),
edge((0, 9), (1, 9), "-|>", [มี], label-anchor: "center", label-sep: -8pt),
node((1, 10), [ประมวลผลคำขอ HTTPS]),
edge((1, 10), (1, 11), (-2, 11), (-2, 10), "-|>"),
node((-2, 10), shape: circle, radius: 1em),
edge((-2, 10), (-2, 6), (0, 6), "-|>"),
)
#pagebreak()
#set par(leading: 1em)
== การออกแบบ
== วัสดุอุปกรณ์
+ บอร์ด ESP32 (NodeMCU)
+ กล่องพลาสติก
+ Buzzer
+ เซนเซอร์ PIR
+ เซนเซอร์ NFC 2 ชิ้น
== ขั้นตอนการประกอบ
=== การติดตั้งอุปกรณ์
=== การเขียนเฟิร์มแวร์
โครงงานนี้ใช้ซอฟต์แวร์ PlatformIO ในการสร้างและจัดการโปรเจกต์เฟิร์มแวร์
โดยหากต้องการเพียงแค่เขียนเฟิร์มแวร์ลงไปยังบอร์ด ESP32 คุณจำเป็นต้องใช้ซอฟต์แวร์หลัก คือ
PlatformIO Core และ Git (ไม่จำเป็น แต่เพื่อความสะดวกสบาย)
อย่างไรก็ตาม PlatformIO จำเป็นต้องใช้ Python เวอร์ชัน 3.6 ขึ้นไปด้วยเช่นกัน
ดังนั้นคุณจำเป็นต้องติดตั้ง Python ด้วยหากคุณยังไม่มี
ในขั้นตอนแรก โปรดเปิดเทอร์มินัลของคุณ ซึ่งโดยทั่วไปแล้วคุณสามารถค้นหาแอพลิเคชัน "Terminal" ได้เลย
โดยบน Windows 10 เวอร์ชั่นใหม่ และ Windows 11 จะมาพร้อมกับแอพลิเคชัน Windows Terminal
อย่างไรก็ตาม เมื่อเปิดแล้ว โปรดตรวจสอบให้แน่ใจว่าคุณกำลังใช้ PowerShell และไม่ใช่ Command
Prompt
โดยในปัจจุบัน Python เวอร์ชันล่าสุดคือ Python 3.14.2 โดยคุณสามารถติดตั้ง Python และ Git บน
Windows ได้ด้วยการใช้คำสั่งต่อไปนี้
```sh
winget install Python.Python.3.14 Git.Git -e -s winget
```
สำหรับระบบปฏิบัติการอื่นนั้น โดยปกติแล้วจะไม่ต้องติดตั้ง Python
เพิ่มเนื่องจากมีติดมากับระบบปฏิบัติการอยู่แล้ว อย่างไรก็ตาม บน Linux อาจต้องมีการติดตั้งการรองรับ
Virtual Environment แยก โดยแต่ละระบบจะมีชื่อแพคเกจไม่เหมือนกัน โดยบน Debian, Fedora,
และ Arch สามารถใช้คำสั่งต่อไปนี้ในการติดตั้งทั้ง Python Virtual Environment และ Git
พร้อมกันได้
```sh
# Debian
sudo apt install python3-venv git
# Fedora
sudo dnf install python3-virtualenv git
# Arch
sudo pacman -S python-virtualenv git
```
#pagebreak()
#show raw.where(block: true): set block(below: 2em)
==== การติดตั้ง PlatformIO Core ผ่านแพคเกจ
หากคุณใช้ Fedora Linux หรือ Arch Linux (หรือลูก ของมัน) คุณสามารถติดตั้งแพคเกจ
PlatformIO ได้โดยตรง โดยมีคำสั่งดังนี้:
```sh
# Fedora Linux
sudo dnf install platformio
# Arch Linux
sudo pacman -S platformio-core
```
หากคุณติดตั้งแพคเกจ Fedora นั้นแล้ว คุณไม่จำเป็นที่จะต้องติดตั้งกฎ udev ด้วยตนเอง
(ที่จะถูกกล่าวถึงใน@pioudev)
หากคุณใช้ Arch คุณสามารถติดตั้งแพคเกจกฎ udev ได้โดยตรงโดยไม่ต้องดาวน์โหลดเอง
```sh
sudo pacman -S --asdeps platformio-core-udev
```
==== การติดตั้ง PlatformIO Core ผ่านสคริปต์
ถัดไป ในการติดตั้ง PlatformIO Core สามารถทำได้โดยการใช้สคริปต์ติดตั้ง โดยสำหรับ `curl`
สามารถใช้คำสั่งนี้ได้:
```sh
curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
```
หรือหากต้องการใช้ `wget`:
```sh
wget -O get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
```
หรือสำหรับ PowerShell, สามารถใช้ `iwr` (หรือชื่อเต็มคือ `Invoke-WebRequest`) ได้:
```sh
iwr -OutFile get-platformio.py -Uri https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
```
(มีการเว้นบรรทัดใหม่เนื่องจากพื้นที่ไม่เพียงพอ โปรดอย่าเว้นบรรทัดเมื่อพิมพ์คำสั่งจริง)
แล้วดังนั้นจึงใช้คำสั่ง `python3 get-platformio.py` ในการรันสคริปต์ติดตั้งที่ได้ทำการดาวน์โหลดมา
โดยค่าเริ่มต้นแล้ว PlatformIO จะไม่เพิ่มตนเองเข้าไปยังตัวแปรสิ่งแวดล้อม PATH
ซึ่งจำเป็นในการใช้คำสั่งจากที่ใหนก็ได้โดยไม่ต้องกล่าวถึงไฟล์พาธ
โดยสำหรับ Linux แล้วนั้น คุณต้องเพิ่ม `$HOME/.local/bin/` เข้าไปยัง PATH ของคุณ โดยหากคุณใช้
Bash คุณสามารถแก้ไข `~/.bash_profile` และเพิ่มบรรทัดนี้เข้าไปได้:
```sh
export PATH=$PATH:$HOME/.local/bin
```
หากคุณใช้ Zsh สามารถใช้โคดเดียวกันได้ เพียงแต่คุณต้องแก้ไขไฟล์ `~/.zprofile` หรือ `~/.zshrc`
แทน
โดยบน Windows มีขั้นตอนดังนี้:
+ กด Windows + R
+ พิมพ์ `sysdm.cpl` และกด Enter
+ ในหน้าต่าง *System Properties* คลิกไปยังแท็บ *Advanced*
+ คลิกปุ่ม *Environment Variables*
หลังจากนั้น เลือกตัวแปร *Path* ในส่วน *User variables* แล้วจึงกด *Edit* แล้วเพิ่ม
`%USERPROFILE%\.platformio\penv\Scripts\` เข้าไปในรายการ
==== 99-platformio-udev.rules <pioudev>
ผู้ใช้ Linux จำเป็นที่จะต้องติดตั้งกฎ udev โดยสามารถดูไฟล์กฎ udev เวอร์ชันล่าสุดได้ที่\
https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules
*หมายเหตุ:* โปรดตรวจสอบว่า PID และ VID ของบอร์ดคุณอยู่ในไฟล์กฎนั้น โดยคุณสามารถดู PID/VID
ของบอร์ดคุณได้ผ่านคำสั่ง `pio device list`
โดยไฟล์นั้นต้องถูกวางอยู่ที่ `/etc/udev/rules.d/99-platformio-udev.rules` (ตำแหน่งที่ดีที่สุด)
หรือ `/lib/udev/rules.d/99-platformio-udev.rules` (อาจจำเป็นสำหรับบางระบบที่พัง)
โปรดใช้คำสั่งต่อไปนี้ในการดาวน์โหลดและวางไฟล์นั้นไว้ในสถานที่ที่ถูกต้อง:
```sh
curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules
```
หรือคุณก็สามารถดาวน์โหลดไฟล์นั้นด้วยตัวเองและคัดลอกมันไปในโฟลเดอร์ที่หมายได้เช่นกัน
```sh
sudo cp 99-platformio-udev.rules /etc/udev/rules.d/99-platformio-udev.rules
```
หลังจากนั้น รีสตาร์ทบริการ udev:
```sh
sudo service udev restart
```
หรือ:
```sh
sudo udevadm control --reload-rules
sudo udevadm trigger
```
หลังจากติดตั้งไฟล์นี้แล้ว ถอดสายที่เชื่อมต่อระหว่างบอร์ดและคอมพิวเตอร์ของคุณแล้วเสียบมันใหม่
==== การดาวน์โหลดโปรเจกต์
สามารถใช้ Git ในการ clone โปรเจกต์ได้ด้วยคำสั่งต่อไปนี้:
```sh
git clone https://gitskette.dailitation.xyz/linesofcodes/liteauth-firmware32.git
```
โดย Git นั้นจะทำการโคลนโปรเจกต์ไปที่โฟลเดอร์ `liteauth-firmware32` เนื่องจากเป็นชื่อของ Git
repository
หรือไปที่ https://gitskette.dailitation.xyz/linesofcodes/liteauth-firmware32
และทำการคลิกปุ่ม *Code* แล้วกด *Download ZIP* หรือ *Download TAR.GZ*
แล้วทำการแตกไฟล์ได้ตามปกติ
หลังจากนั้น ไปที่โฟลเดอร์ของคุณในเทอร์มินัลโดยใช้คำสั่ง `cd`
==== คำสั่ง PlatformIO เบื้องต้น
- `pio run --list-targets`: ดูรายการเป้าหมายคำสั่งรัน
- `pio run upload`: รันเป้าหมายอัพโหลด ซึ่งนี่คือคำสั่งที่คุณควรจะใช้ในการเขียนเฟิร์มแวร์ลงบนบอร์ด
- `pio device monitor`: เปิด Serial Monitor
*หมายเหตุ:* โปรดใช้คำสั่งประเภท `pio run` ในโฟลเดอร์ของโปรเจกต์
== การทดสอบ
== การวิเคราะห์ข้อมูล
+258
View File
@@ -0,0 +1,258 @@
#import "../PageTemplate.typ": *
== สร้างไฟล์แอปพลิเคชันด้วยตนเอง
#i โครงงานนี้ใช้แอปพลิเคชันที่สร้างขึ้นมาเอง โดยในการพัฒนาแอปพลิเคชัน
อย่างน้อยต้องมีส่วนประกอบดังกล่าวก่อน
- Flutter
- Git (ซึ่งคุณจะติดตั้งแล้วหากคุณทำตาม@writingFirmware)
#i อย่างไรก็ตาม Flutter มีข้อจำกัดว่า มีเพียง Android
เท่านั้นที่ไม่ว่าแพลตฟอร์มไหนก็จะสามารถคอมไพล์ไฟล์ `.apk` ออกมาได้ ดังนั้น
การสร้างแอปพลิเคชันสำหรับ Linux ต้องทำบน Linux เท่านั้น และการสร้างแอปพลิเคชันสำหรับ Windows
ต้องทำบน Windows เท่านั้น
=== การติดตั้งโปรแกรมเขียนโคด
#iii จริง แล้วนั้น Flutter สามารถทำงานกับโปรแกรมเขียนโคดใดก็ได้
แต่มีโปรแกรมเหล่านี้ที่อาจมีประสบการณ์การพัฒนาที่ดีกว่าโปรแกรมอื่น:
- Visual Studio Code (VS Code)
- Android Studio
- JetBrains IntelliJ
- Firebase Studio
#iii โครงงานนี้ใช้โปรแกรมเขียนโคด Android Studio เป็นหลักเนื่องจากแอปพลิเคชันโครงงานมี
Android เป็นเป้าหมายหลัก และ Android SDK สามารถจัดการได้ง่ายกว่าใน Android Studio
#iii การติดตั้ง Flutter สามารถทำได้สองวิธีด้วยกัน คือการติดตั้งผ่าน Visual Studio Code (VS
Code) และการติดตั้งด้วยตนเอง โดยหากต้องการใช้ VS Code เป็นโปรแกรมเขียนโคดอยู่แล้ว
สามารถติดตั้งผ่าน VS Code ได้เลย แต่ก่อนอื่น ต้องทำการติดตั้งโปรแกรมและไลบรารีพื้นฐานที่จำเป็นสำหรับ
Flutter ก่อน
#pagebreak()
=== การติดตั้งโปรแกรมและไลบรารีที่จำเป็น
#[
#set enum(indent: 5.5em)
+ Windows: ติดตั้ง Git สำหรับ Windows ซึ่งคุณสามารถดูขั้นตอนการติดตั้งได้ที่
https://git-scm.com/install/windows หรือเพียงแค่ใช้คำสั่งด้านล่าง
#afigure(
```sh
winget install --id Git.Git -e --source winget
```,
kind: image,
caption: [คำสั่งในการติดตั้ง Git],
)
+ Linux: โปรดดู@flLinuxDetails สำหรับรายละเอียดแพคเกจและคำสั่งที่ต้องใช้สำหรับระบบต่าง
+ macOS: ใช้คำสั่งต่อไปนี้ในการติดตั้งเครื่องมือ Xcode ต่าง รวมถึง Git
#afigure(
```sh
xcode-select --install
```,
kind: image,
caption: [คำสั่งในการติดตั้งเครื่องมือ Xcode],
)
]
=== การติดตั้งผ่าน Visual Studio Code
#block(inset: (left: 4.5em))[
#set enum(indent: 1em)
+ เปิด VSCode
+ ติดตั้งส่วนขยาย Flutter \
อยู่ภายใต้ ID `Dart-Code.flutter` ทั้งบน Visual Studio Marketplace และ OpenVSX
+ ติดตั้ง Flutter ด้วย VS Code
+ เปิด Command Palette ด้วยเมนู *View* > *Command Palette* หรือกด Ctrl + Shift +
P
+ ใน Command Palette พิมพ์ `flutter`.
+ เลือก *Flutter: New Project*
+ VS Code จะให้คุณเลือก Flutter SDK บนคอมพิวเตอร์ของคุณ เลือก *Download SDK*
+ เมือหน้าไดอะลอก *Select Folder for Flutter SDK* แสดงขึ้น เลือกสถานที่ที่คุณอยากติดตั้ง
Flutter
+ คลิก *Clone Flutter* \
ในระหว่างการดาวน์โหลด VS Code จะแสดงการแจ้งเตือนนี้:
```
Downloading the Flutter SDK. This may take a few minutes.
```
การดาวน์โหลดนี้จะใช้เวลาสองสามนาที หากคุณเชื่อว่าการดาวน์โหลดหยุดชะงัก คุณสามารถคลิก
*Cancel* แล้วเริ่มต้นการติดตั้งใหม่ได้
+ คลิก *Add SDK to PATH* \
เมื่อเสร็จสิ้น จะมีการแจ้งเตือน
```
The Flutter SDK was added to your PATH
```
+ VS Code อาจแสดงการแจ้งเตือนเกี่ยวกับการเก็บข้อมูลของ Google หากคุณยินยอม คลิก *OK*
+ เพื่อความแน่ใจ กรุณาปิดเทอร์มินัลทุกหน้าต่างหรือรีสตาร์ท VS Code เพื่อให้แน่ใจว่า Flutter
จะสามารถใช้ผ่านเทอร์มินัลได้
+ เมื่อเสร็จสิ้น ใช้คำสั่ง `flutter doctor -v` ในเทอร์มินัลที่คุณเลือกเพื่อตรวจสอบการติดตั้ง
Flutter ของคุณ \
หากคำสั่งไม่เจอหรือเกิดข้อผิดพลาดขึ้น ตรวจสอบ
https://docs.flutter.dev/install/troubleshoot สำหรับข้อมูลเพิ่มเติม
]
=== การติดตั้งด้วยตนเอง
#iii แนะนำให้ทำตาม https://docs.flutter.dev/install/manual#install-flutter
เนื่องจากกระบวนการนี้ต้องใช้ข้อมูลที่ใหม่ล่าสุด
1. ดาวน์โหลด Flutter (สามารถหาปุ่มดาวน์โหลดได้จากลิงก์ด้านบน)
2. สร้างโฟลเดอร์สำหรับเก็บ Flutter SDK
3. ทำการแตกไฟล์ที่ดาวน์โหลดมา
4. เพิ่ม Flutter เข้าไปยัง PATH ของคุณ (วิธีการขึ้นอยู่กับระบบปฏิบัติการ)
5. ยืนยันความถูกต้องของการติดตั้งของคุณด้วยคำสั่ง `flutter doctor -v`
=== ข้อมูลเฉพาะแพลตฟอร์ม
==== Android <flAndroid>
#iiii ในการพัฒนาแอปพลิเคชัน Android โดยใช้เฟรมเวิร์ก Flutter
จำเป็นต้องใช้ส่วนประกอบเครื่องมือพัฒนา Android ดังนี้
- Android SDK (API Level 36 เวลาที่พิมพ์)
- Android SDK Build-Tools
- Android SDK Command-line Tools
- Android SDK Platform-Tools
- Android Emulator (ไม่บังคับ)
โดยแนะนำให้จัดการและติดตั้งเครื่องมือเหล่านี้ผ่าน Android Studio
#iiii ในการติดตั้ง Android SDK ควรติดตั้ง Android SDK
ล่าสุดถึงแม้ว่าอุปกรณ์ของคุณจะใช้เวอร์ชันที่เก่ากว่านั้น
เพื่อความมั่นใจว่าแอปพลิเคชันจะสามารถใช้กับอุปกรณ์ที่ใหม่ล่าสุดได้
#iiii แอปพลิเคชัน Android จะมี SDK/API level เป้าหมาย (Target SDK/API level) และ
SDK/API level ขั้นต่ำ (Minimum SDK/API level) โครงงานนี้ เวลาที่พิมพ์ ใช้ API level
เป้าหมาย 36 (Android 16) และ API level ขั้นต่ำ 24 (Android 7) ซึ่งรวมกันแล้ว
แอปพลิเคชัน#jb Android จะสามารถติดตั้งได้บนระบบตั้งแต่ API level ขั้นต่ำจนถึง API level
เป้าหมาย หรือก็คือ แอปพลิเคชันในโครงงานนี้สามารถติดตั้งได้ตั้งแต่บนระบบ Android 7 ถึง Android 16
นั่นเอง
===== Java/Kotlin
#iiiii Java และ Kotlin เป็นภาษาสำคัญสำหรับการพัฒนาแอปพลิเคชัน Android ถึงอย่างไรก็ตาม
แอปพลิเคชัน Flutter นั้นถูกเขียนด้วยภาษา Dart แต่ยังจำเป็นต้องมีโคด Java และ Kotlin
เล็กน้อยเพื่อเริ่มต้นแอปพลิเคชัน Flutter
#iiiii โดยปกติแล้ว Flutter จะสร้างโคดพื้นฐานขึ้นมาให้สำหรับการเริ่มแอปพลิเคชันแบบพื้นฐาน
ดังนั้นจึงไม่จำเป็นต้องมีการเขียนโคด Java หรือ Kotlin เอง แต่ในบางกรณี
อาจต้องเขียนโคดเพิ่มเองหากมีความต้องการเข้าถึงฟีเจอร์พื้นฐานระบบที่ Flutter ไม่มี API
เพื่อให้เข้าถึงได้และไม่มีแพคเกจเพื่อรองรับฟีเจอร์ที่ต้องการ
#iiiii โครงการนี้ใช้ Java 21 (JetBrains Runtime/Azul Zulu OpenJDK)
เป็นหลักในการทำงานกับ Gradle แต่แอปพลิเคชัน Android ที่ผลิตออกมานั้น
เพื่อให้เข้ากับเวอร์ชันที่เก่ากว่าของระบบปฏิบัติการได้ ใช้ Java 11
===== Gradle
#iiiii Gradle เป็นเครื่องมือสร้างระบบอัตโนมัติสำหรับการพัฒนาซอฟต์แวร์หลายภาษา จัดการงานต่าง
เช่น การคอมไพล์ การแพ็คเกจ การทดสอบ การปรับใช้ และการเผยแพร่ ภาษาที่รองรับ ได้แก่ Java
(รวมถึงภาษา Kotlin, Groovy, Scala ที่ใช้ JDK), C/C++ และ JavaScript Gradle
พัฒนาต่อยอดจากแนวคิดของ Apache Ant และ Apache Maven และนำเสนอภาษาเฉพาะโดเมนที่ใช้
Groovy และ Kotlin ซึ่งต่างจากการกำหนดค่าโครงการที่ใช้ XML ที่ Maven ใช้ Gradle
ใช้กราฟแบบอะไซคลิกกำกับทิศทางเพื่อจัดการการอ้างอิง กราฟนี้ใช้เพื่อกำหนดลำดับของงานที่ควรดำเนินการ
Gradle ทำงานบน Java Virtual Machine
#iiiii Gradle คือเครื่องมือหลักที่ใช้ในการจัดการโปรเจกต์ Java ส่วนใหญ่ รวมถึงโปรเจกต์ Android
โดยในโครงการนี้ จะใช้ Gradle เวอร์ชัน 8.14.3 เป็นหลัก
#iiiii โดยปกติแล้ว ผู้พัฒนานั้นไม่มีความจำเป็นที่จะต้องแตะต้อง Gradle ด้วยตนเอง และ Flutter
จะทำการจัดการเอง แต่หากมีความจำเป็นต้องใช้คำสั่ง Gradle ด้วยตนเอง จะมีสคริปต์ `gradlew` (หรือ
`gradlew.bat` สำหรับผู้ใช้ Windows) ภายในโฟลเดอร์ `android` ของโปรเจกต์ Flutter
เสมอเพื่อเรียกใช้ Gradle ที่ถูกดาวน์โหลดมาสำหรับโปรเจกต์นั้น
==== Linux <flLinuxDetails>
#iiii เช่นเดียวกับ Android ที่กล่าวไปข้างต้น Flutter
มีการสร้างโคดสำหรับการเปิดแอปพลิเคชันแบบพื้นฐาน แต่สำหรับ Linux แล้วนั้น Flutter ใช้โคด C++
และเฟรมเวิร์ก CMake ในการสร้างรากฐานของแอปพลิเคชัน
#iiii ในการพัฒนาแอปพลิเคชันสำหรับ Linux ต้องติดตั้งโปรแกรมเพิ่มเติม#jb (build dependencies)
ขยายความคือ ด้านบนคือสิ่งที่จำเป็นหากมีระบบอื่นเป็นเป้าหมาย แต่หากต้องการพัฒนาแอปพลิเคชัน Linux
ต้องติดตั้งโปรแกรมในรายการหน้าถัดไปเพิ่ม
#pagebreak()
#grid(
columns: 2,
column-gutter: 1in,
[
- GTK 3 (ไลบรารีสำหรับการพัฒนา)
- pkg-config
- ไลบรารี GNU Standard C++ v3
],
[
- Clang
- CMake
- Ninja
],
)
#iiii การติดตั้งไลบรารีและโปรแกรมที่กล่าวไปข้างต้นจะแตกต่างกันไปแต่ละการแจกจ่าย Linux และ
Flutter ใช้ไลบรารีพื้นฐานดังกล่าวในการทำงานของแอปพลิเคชัน (runtime dependencies)
- GTK 3
- blkid
- LZMA
แต่โดยทั่วไปแล้ว ไลบรารีเหล่านี้ควรถูกติดตั้งมาอยู่แล้วหากคุณใช้ graphical desktop ทั่วไป
===== Debian
#afigure(
```sh
# Development dependencies:
sudo apt install curl git unzip xz-utils zip libglu1-mesa
# Linux build dependencies:
sudo apt install clang cmake ninja-build pkg-config libgtk-3-dev libstdc++-12-dev
# Runtime dependencies:
sudo apt install libgtk-3-0 libblkid1 liblzma5
```,
kind: image,
caption: [คำสั่งในการติดตั้งรายการแพคเกจต่าง บน Debian],
)
===== Fedora Linux
#afigure(
```sh
# Development dependencies:
sudo dnf install curl git unzip xz zip mesa-libglu
# Linux build dependencies:
sudo dnf install clang cmake ninja-build pkgconf gtk3
# Runtime dependencies:
sudo dnf install gtk3 libblkid xz
```,
kind: image,
caption: [คำสั่งในการติดตั้งรายการแพคเกจต่าง บน Fedora Linux],
)
===== Arch Linux
#afigure(
```sh
# Development dependencies:
sudo pacman -S --needed curl git unzip xz zip glu
# Linux build dependencies:
sudo pacman -S --needed clang cmake ninja pkgconf gtk3
# Runtime dependencies:
sudo pacman -S --needed util-linux-libs xz gtk3
```,
kind: image,
caption: [คำสั่งในการติดตั้งรายการแพคเกจต่าง บน Arch Linux],
)
==== macOS/iOS
#iiii การพัฒนาแอปพลิเคชันสำหรับ macOS และ iOS นั้นต้องทำบน#jb macOS
เท่านั้นและจำเป็นต้องพึ่งพาเครื่องมือ Xcode แต่เนื่องจากในโครงงานนี้ไม่มีผู้ใช้ macOS
จึงไม่สามารถสร้างไบนารีสำหรับ macOS และ iOS ออกมาได้ และไม่ใช่เป้าหมายของโครงงานนี้เช่นกัน
+351
View File
@@ -0,0 +1,351 @@
#import "../PageTemplate.typ": *
#import "@preview/tiaoma:0.3.0"
#import "@preview/fletcher:0.5.8" as fletcher: diagram, edge, node
#import fletcher.shapes: circle, diamond, pill
#show: chapter-page
#set heading(numbering: "บทที่ 1")
#heading([#linebreak()วิธีการดำเนินโครงงาน])
#set heading(numbering: "1.1")
#i ในการดำเนินการศึกษาครั้งนี้
คณะผู้จัดทำโครงงานได้ศึกษาข้อมูลเบื้องต้นในการสร้างเครื่องยืนยันตัวตนด้วย NFC
และได้ดำเนินการตามขั้นตอนนี้
+ วางแผนการดำเนินงาน
+ การออกแบบ
+ วัสดุอุปกรณ์
+ ขั้นตอนการประกอบ
+ การทดลอง
+ การวิเคราะห์ข้อมูล
== วางแผนการดำเนินงาน
#show table.cell.where(y: 1): strong
#set par(leading: 0.5em)
#let arrow = [
#place(
left + horizon,
text(weight: "bold", size: 14pt)[#sym.arrow.l],
dx: -5pt,
dy: -0.7pt,
)
#place(
horizon,
line(length: 100%, stroke: (thickness: 1pt)),
dx: 0pt,
dy: 0pt,
)
#place(
right + horizon,
text(weight: "bold", size: 14pt)[#sym.arrow.r],
dx: 5pt,
dy: -0.7pt,
)
]
=== แผนขั้นตอนและวิธีการดำเนินงาน
#table(
columns: 12,
align: (
left + horizon,
center,
center,
center,
center,
center,
center,
center,
center,
center,
center,
center,
),
table.header(
table.cell(
[ขั้นตอนการ\ ดำเนินการ],
rowspan: 2,
),
table.cell(
[พ.ศ.2568],
colspan: 3,
),
table.cell(
[พ.ศ.2569],
colspan: 8,
),
[ต.ค.],
[พ.ย.],
[ธ.ค.],
[ม.ค.],
[ก.พ.],
[มี.ค],
[เม.ย],
[พ.ค.],
[มิ.ย.],
[ก.ค.],
[ส.ค.],
),
[ศึกษาค้นคว้าข้อมูล],
table.cell(arrow, colspan: 3),
[],
[],
[],
[],
[],
[],
[],
[],
[เสนอหัวข้อ], arrow, [], [], [], [], [], [], [], [], [], [],
[เสนอครั้งที่ 1], [], arrow, [], [], [], [], [], [], [], [], [],
[ออกแบบและสร้าง], [], table.cell(arrow, colspan: 5), [], [], [], [], [],
[จัดซื้ออุปกรณ์ทดลอง],
[],
table.cell(arrow, colspan: 3),
[],
[],
[],
[],
[],
[],
[],
[ทดลองการทำงาน], [], [], table.cell(arrow, colspan: 4), [], [], [], [], [],
[ปรับปรุงแก้ไข], [], [], [], [], table.cell(arrow, colspan: 5), [], [],
[เสนอครั้งที่ 2], [], [], [], arrow, [], [], [], [], [], [], [],
[จัดทำรูปเล่ม], table.cell(arrow, colspan: 11),
[นำเสนอโครงงาน], [], [], [], [], [], [], [], [], [], [], [],
)
#show: page-theme
#set par(leading: 0.5em)
=== ผังการดำเนินงาน
#include "ProjectFlowchart.typ"
#pagebreak()
=== ผังการทำงาน
#include "ProductFlowchart.typ"
#pagebreak()
#set par(leading: 1em)
== การออกแบบ
== วัสดุอุปกรณ์
+ บอร์ด ESP32 (NodeMCU)
+ กล่องพลาสติก
+ Buzzer
+ เซนเซอร์ PIR
+ เซนเซอร์ NFC 2 ชิ้น
== ขั้นตอนการประกอบ
โครงงานแบ่งออกเป็น 3 โมดูล
+ โมดูลเซนเซอร์ NFC ขาเข้าและบอร์ด ESP32
+ โมดูลเซนเซอร์ NFC ขาออก
+ โมดูลเซนเซอร์ PIR
#show heading: it => {
if it.level > 2 {
block(
it,
inset: (left: -3em * (it.level - 2)),
)
} else {
it
}
}
=== โมดูลเซนเซอร์ NFC ขาออก
#i ดำเนินการเจาะรูบริเวณตัวกล่องเพื่อใช้เป็นช่องสำหรับสายไฟ
จากนั้นนำสายไฟร้อยผ่านช่องดังกล่าวและต่อเข้ากับเซนเซอร์ NFC ให้เรียบร้อยตามขั้นตอน
=== การติดตั้งอุปกรณ์
=== การเขียนเฟิร์มแวร์ <writingFirmware>
#iii โครงงานนี้ใช้ซอฟต์แวร์ PlatformIO ในการสร้างและจัดการโปรเจกต์เฟิร์มแวร์
โดยหากต้องการเพียงแค่เขียนเฟิร์มแวร์ลงไปยังบอร์ด ESP32 คุณจำเป็นต้องใช้ซอฟต์แวร์หลัก คือ
PlatformIO Core และ Git (ไม่จำเป็น แต่เพื่อความสะดวกสบาย) อย่างไรก็ตาม PlatformIO
จำเป็นต้องใช้ Python เวอร์ชัน 3.6 ขึ้นไปด้วยเช่นกัน ดังนั้นคุณจำเป็นต้องติดตั้ง Python
ด้วยหากคุณยังไม่มี
#iii ในขั้นตอนแรก โปรดเปิดเทอร์มินัลของคุณ ซึ่งโดยทั่วไปแล้วคุณสามารถค้นหาแอปพลิเคชัน#jb
"Terminal" ได้เลย โดยบน Windows 10 เวอร์ชั่นใหม่ และ Windows 11 จะมาพร้อมกับแอปพลิเคชัน
Windows Terminal อย่างไรก็ตาม เมื่อเปิดแล้ว โปรดตรวจสอบให้แน่ใจว่าคุณกำลังใช้ PowerShell
และไม่ใช่ Command Prompt
#iii โดยในปัจจุบัน Python เวอร์ชันล่าสุดคือ Python 3.14.2 โดยคุณสามารถติดตั้ง Python และ Git
บน Windows ได้ด้วยการใช้คำสั่งต่อไปนี้
```sh
winget install Python.Python.3.14 Git.Git -e -s winget
```
#iii สำหรับระบบปฏิบัติการอื่นนั้น โดยปกติแล้วจะไม่ต้องติดตั้ง Python
เพิ่มเนื่องจากมีติดมากับระบบปฏิบัติการอยู่แล้ว อย่างไรก็ตาม บน Linux อาจต้องมีการติดตั้งการรองรับ
Virtual Environment แยก โดยแต่ละระบบจะมีชื่อแพคเกจไม่เหมือนกัน โดยบน Debian, Fedora,
และ Arch สามารถใช้คำสั่งต่อไปนี้ในการติดตั้งทั้ง Python Virtual Environment และ Git
พร้อมกันได้
#pagebreak()
```sh
# Debian
sudo apt install python3-venv git
# Fedora
sudo dnf install python3-virtualenv git
# Arch
sudo pacman -S python-virtualenv git
```
#show raw.where(block: true): set block(below: 2em)
==== การติดตั้ง PlatformIO Core ผ่านแพคเกจ
#iiii หากคุณใช้ Fedora Linux หรือ Arch Linux (หรือลูก ของมัน) คุณสามารถติดตั้งแพคเกจ
PlatformIO ได้โดยตรง โดยมีคำสั่งดังนี้:
```sh
# Fedora Linux
sudo dnf install platformio
# Arch Linux
sudo pacman -S platformio-core
```
- หากคุณติดตั้งแพคเกจ Fedora นั้นแล้ว คุณไม่จำเป็นที่จะต้องติดตั้งกฎ udev ด้วยตนเอง
(ที่จะถูกกล่าวถึงใน@pioudev)
- หากคุณใช้ Arch คุณสามารถติดตั้งแพคเกจกฎ udev ได้โดยตรงโดยไม่ต้องดาวน์โหลดเอง
```sh
sudo pacman -S --asdeps platformio-core-udev
```
==== การติดตั้ง PlatformIO Core ผ่านสคริปต์
#iiii ถัดไป ในการติดตั้ง PlatformIO Core สามารถทำได้โดยการใช้สคริปต์ติดตั้ง โดยสำหรับ `curl`
สามารถใช้คำสั่งนี้ได้:
```sh
curl -fsSL -o get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
```
หรือหากต้องการใช้ `wget`:
```sh
wget -O get-platformio.py https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
```
#pagebreak()
หรือสำหรับ PowerShell, สามารถใช้ `iwr` (หรือชื่อเต็มคือ `Invoke-WebRequest`) ได้:
```sh
iwr -OutFile get-platformio.py -Uri https://raw.githubusercontent.com/platformio/platformio-core-installer/master/get-platformio.py
```
(มีการเว้นบรรทัดใหม่เนื่องจากพื้นที่ไม่เพียงพอ โปรดอย่าเว้นบรรทัดเมื่อพิมพ์คำสั่งจริง)
#iiii แล้วดังนั้นจึงใช้คำสั่ง `python3 get-platformio.py`
ในการรันสคริปต์ติดตั้งที่ได้ทำการดาวน์โหลดมา โดยค่าเริ่มต้นแล้ว PlatformIO
จะไม่เพิ่มตนเองเข้าไปยังตัวแปรสิ่งแวดล้อม PATH
ซึ่งจำเป็นในการใช้คำสั่งจากที่ใหนก็ได้โดยไม่ต้องกล่าวถึงไฟล์พาธ
#iiii โดยสำหรับ Linux แล้วนั้น คุณต้องเพิ่ม `$HOME/.local/bin/` เข้าไปยัง PATH ของคุณ
โดยหากคุณใช้ Bash คุณสามารถแก้ไข `~/.bash_profile` และเพิ่มบรรทัดนี้เข้าไปได้:
```sh
export PATH=$PATH:$HOME/.local/bin
```
#iiii หากคุณใช้ Zsh สามารถใช้โคดเดียวกันได้ เพียงแต่คุณต้องแก้ไขไฟล์ `~/.zprofile` หรือ
`~/.zshrc` แทน
โดยบน Windows มีขั้นตอนดังนี้:
+ กด Windows + R
+ พิมพ์ `sysdm.cpl` และกด Enter
+ ในหน้าต่าง *System Properties* คลิกไปยังแท็บ *Advanced*
+ คลิกปุ่ม *Environment Variables*
หลังจากนั้น เลือกตัวแปร *Path* ในส่วน *User variables* แล้วจึงกด *Edit* แล้วเพิ่ม
`%USERPROFILE%\.platformio\penv\Scripts\` เข้าไปในรายการ
==== 99-platformio-udev.rules <pioudev>
#iiii ผู้ใช้ Linux จำเป็นที่จะต้องติดตั้งกฎ udev โดยสามารถดูไฟล์กฎ udev เวอร์ชันล่าสุดได้ที่
https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules
*หมายเหตุ:* โปรดตรวจสอบว่า PID และ VID ของบอร์ดคุณอยู่ในไฟล์กฎนั้น โดยคุณสามารถดู PID/VID
ของบอร์ดคุณได้ผ่านคำสั่ง `pio device list`
#iiii โดยไฟล์นั้นต้องถูกวางอยู่ที่ `/etc/udev/rules.d/99-platformio-udev.rules`
(ตำแหน่งที่ดีที่สุด) หรือ `/lib/udev/rules.d/99-platformio-udev.rules`
(อาจจำเป็นสำหรับบางระบบที่พัง)
โปรดใช้คำสั่งต่อไปนี้ในการดาวน์โหลดและวางไฟล์นั้นไว้ในสถานที่ที่ถูกต้อง:
```sh
curl -fsSL https://raw.githubusercontent.com/platformio/platformio-core/develop/platformio/assets/system/99-platformio-udev.rules | sudo tee /etc/udev/rules.d/99-platformio-udev.rules
```
หรือคุณก็สามารถดาวน์โหลดไฟล์นั้นด้วยตัวเองและคัดลอกมันไปในโฟลเดอร์ที่หมายได้เช่นกัน
```sh
sudo cp 99-platformio-udev.rules /etc/udev/rules.d/99-platformio-udev.rules
```
หลังจากนั้น รีสตาร์ทบริการ udev:
```sh
sudo service udev restart
```
หรือ:
```sh
sudo udevadm control --reload-rules
sudo udevadm trigger
```
หลังจากติดตั้งไฟล์นี้แล้ว ถอดสายที่เชื่อมต่อระหว่างบอร์ดและคอมพิวเตอร์ของคุณแล้วเสียบมันใหม่
==== การดาวน์โหลดโปรเจกต์
#iiii สามารถใช้ Git ในการ clone โปรเจกต์ได้ด้วยคำสั่งต่อไปนี้:
```sh
git clone https://gitskette.dailitation.xyz/linesofcodes/liteauth-firmware32.git
```
#iiii โดย Git นั้นจะทำการโคลนโปรเจกต์ไปที่โฟลเดอร์ `liteauth-firmware32`
เนื่องจากเป็นชื่อของ Git repository หรือหากไม่ต้องการใช้ Git กรุณาไปที่
https://gitskette.dailitation.xyz/linesofcodes/liteauth-firmware32 และทำการคลิกปุ่ม
*Code* แล้วกด *Download ZIP* หรือ *Download TAR.GZ* แล้วทำการแตกไฟล์ได้ตามปกติ
หลังจากนั้น ไปที่โฟลเดอร์ของคุณในเทอร์มินัลโดยใช้คำสั่ง `cd`
#pagebreak()
==== คำสั่ง PlatformIO เบื้องต้น
#[
#set list(indent: 9.25em)
- `pio run --list-targets`: ดูรายการเป้าหมายคำสั่งรัน
- `pio run upload`: รันเป้าหมายอัพโหลด
ซึ่งนี่คือคำสั่งที่คุณควรจะใช้ในการเขียนเฟิร์มแวร์ลงบนบอร์ด
- `pio device monitor`: เปิด Serial Monitor
]
#iiii *หมายเหตุ:* โปรดใช้คำสั่งประเภท `pio run` ในโฟลเดอร์ของโปรเจกต์
#include "BuildApp.typ"
== การทดสอบ
== การวิเคราะห์ข้อมูล
+74
View File
@@ -0,0 +1,74 @@
#import "@preview/fletcher:0.5.8" as fletcher: diagram, edge, node
#import fletcher.shapes: circle, diamond, pill
#diagram(
node-stroke: 1pt,
spacing: 2em,
node([เริ่มต้น], shape: pill),
edge("-|>"),
node((1, 0), [ตั้งค่า LittleFS]),
edge("-|>"),
node((1, 2), [มี Wi-Fi บันทึก\ ไว้อยู่หรือไม่], shape: diamond),
edge("l", "-|>", [ไม่มี]),
edge((1, 2), (1, 3), "-|>", [มี]),
node((0, 2), [รอรับรายละเอียดเครือข่าย\ (ESP-Touch)]),
edge("d,r", "-|>"),
node((1, 3), [เชื่อมต่อเครือข่าย]),
edge("-|>"),
node((0, 4), [มีอุปกรณ์ควบคุม\ หลักแล้วหรือไม่], shape: diamond),
edge("-|>", [ไม่มี]),
edge("d", "-|>", [มี]),
node((1, 4), [สร้างโทเค็นสำหรับการยืนยัน\ อุปกรณ์ควบคุมหลัก]),
edge("-|>"),
node((1, 5), [รออุปกรณ์ควบคุมหลัก\ แตะเซนเซอร์ NFC]),
edge("-|>"),
node((0, 5), [ตั้งค่าเซิร์ฟเวอร์ HTTPS]),
edge("-|>"),
node((0, 6), shape: circle, radius: 1em),
edge("-|>"),
node((0, 7), [มีการแตะเซนเซอร์\ NFC ขาเข้าหรือไม่], shape: diamond),
edge("-|>", [ไม่มี]),
node((0, 9), [มีคนผ่านเซนเซอร์ PIR\ โดยไม่ได้รับอนุญาตหรือไม่], shape: diamond),
edge((0, 9), (0, 10), [ไม่มี]),
edge((0, 7), (1, 6), "-|>", [มี]),
node((1, 6), [อยู่ในโหมดลงทะเบียน\ หรือไม่], shape: diamond),
edge("-|>", [ใช่]),
edge((1, 6), (2, 7), [ไม่]),
node((1, 7), [นำ ID อุปกรณ์เข้า\ สู่รายการทะเบียน]),
edge((1, 7), (0.6, 7), (0, 9), "-|>"),
node((2, 7), [ID ของอุปกรณ์อยู่\ ในทะเบียนหรือไม่], shape: diamond),
edge("-|>", [อยู่]),
edge((2, 7), (1, 8), "-|>", [ไม่อยู่], label-sep: -5pt),
node((2, 8), [ส่งเสียงคอนเฟิร์ม]),
edge((2, 8), (2, 8.5), (0.4, 8.5), (0, 9), "-|>"),
node((1, 8), [ส่งเสียงแสดงความผิดพลาด]),
edge((1, 8), (0.5, 8), (0, 9), "-|>"),
node((1, 9), [แจ้งเตือนทางเสียง\ และแอปพลิเคชัน]),
edge((1, 9), (0, 10), "-|>"),
edge((0, 10), (1, 10), "-|>", [มี]),
node((0, 10), [มีคำขอ HTTPS\ ใหม่หรือไม่], shape: diamond),
edge((0, 10), (-2, 10), "-|>", [ไม่มี], label-pos: 10%),
edge((0, 9), (1, 9), "-|>", [มี], label-anchor: "center", label-sep: -8pt),
node((1, 10), [ประมวลผลคำขอ HTTPS]),
edge((1, 10), (1, 11), (-2, 11), (-2, 10), "-|>"),
node((-2, 10), shape: circle, radius: 1em),
edge((-2, 10), (-2, 6), (0, 6), "-|>"),
)
+25
View File
@@ -0,0 +1,25 @@
#import "@preview/fletcher:0.5.8" as fletcher: diagram, edge, node
#import fletcher.shapes: circle, diamond, pill
#diagram(
node-stroke: 1pt,
spacing: 2em,
node((0, 0), [เริ่มต้น], shape: pill),
edge("-|>"),
node((0, 1), shape: circle, radius: 1em),
edge("-|>"),
node((0, 2), [ศึกษาข้อมูลและทฤษฏีที่เกี่ยวข้อง], width: 2.5in),
edge("-|>"),
node((0, 3), [ออกแบบและวางแผนการดําเนินงาน], width: 2.5in),
edge("-|>"),
node((0, 4), [เครื่องยืนยันตัวตนด้วย NFC], width: 2.5in),
edge("-|>"),
node((0, 5), [ทดสอบประสิทธิภาพ], shape: diamond),
edge("r,u,u,u,u,l", "-|>", [ไม่ผ่าน]),
edge("-|>", [ผ่าน]),
node((0, 6), [จัดทำเอกสาร], width: 2.5in),
edge("-|>"),
node((0, 7), [นำเสนอ], width: 2.5in),
edge("-|>"),
node((0, 8), [สิ้นสุด], shape: pill),
)
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

+5 -5
View File
@@ -3,7 +3,7 @@
set page(
paper: "a4",
margin: (
top: 1.5in,
top: 4cm,
left: 1.5in,
right: 1in,
bottom: 1in,
@@ -29,15 +29,15 @@
"assets/nktc.jpg",
width: 4cm,
alt: "วิทยาลัยเทคนิคหนองคาย",
)
)\
เครื่องยืนยันตัวตนด้วย NFC
#v(8em)
#v(1fr)
#grid(
columns: 2,
align: (right, left),
align: left,
column-gutter: 1em,
row-gutter: 0.75em,
"ประภากร", "ศรีวรสาร",
@@ -45,7 +45,7 @@
"ศตคุณ", "อุตมะ",
)
#v(10em)
#v(1fr)
โครงงานนี้เป็นส่วนหนึ่งของ วิชาโครงงานรหัสวิชา 21909-2023 \
ตามหลักสูตรประกาศนียบัตรวิชาชีพ พุทธศักราช 2567 \
+940
View File
@@ -0,0 +1,940 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Dracula Theme v1.4.3
#
# https://github.com/dracula/sublime
#
# Copyright 2013-present, All rights reserved
#
# Code licensed under the MIT license
#
# @author Zeno Rocha <hi@zenorocha.com>
-->
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>name</key>
<string>Dracula</string>
<key>settings</key>
<array>
<dict>
<key>settings</key>
<dict>
<key>background</key>
<string>#282a36</string>
<key>caret</key>
<string>#f8f8f0</string>
<key>block_caret</key>
<string>#999a9e</string>
<key>foreground</key>
<string>#f8f8f2</string>
<key>invisibles</key>
<string>#3B3A32</string>
<key>lineHighlight</key>
<string>#44475a</string>
<key>selection</key>
<string>#44475a</string>
<key>findHighlight</key>
<string>#effb7b</string>
<key>findHighlightForeground</key>
<string>#000000</string>
<key>selectionBorder</key>
<string>#222218</string>
<key>activeGuide</key>
<string>#9D550FB0</string>
<key>bracketsForeground</key>
<string>#F8F8F2A5</string>
<key>bracketsOptions</key>
<string>underline</string>
<key>bracketContentsForeground</key>
<string>#F8F8F2A5</string>
<key>bracketContentsOptions</key>
<string>underline</string>
<key>tagsOptions</key>
<string>stippled_underline</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Comment</string>
<key>scope</key>
<string>comment</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#6272a4</string>
<key>fontStyle</key>
<string></string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String</string>
<key>scope</key>
<string>string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f1fa8c</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Number</string>
<key>scope</key>
<string>constant.numeric</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bd93f9</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Built-in constant</string>
<key>scope</key>
<string>constant.language</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bd93f9</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>User-defined constant</string>
<key>scope</key>
<string>constant.character, constant.other</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bd93f9</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variable</string>
<key>scope</key>
<string>variable</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Ruby's @variable</string>
<key>scope</key>
<string>variable.other.readwrite.instance</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ffb86c</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>String interpolation</string>
<key>scope</key>
<string>constant.character.escaped, constant.character.escape, string source, string source.ruby</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Ruby Regexp</string>
<key>scope</key>
<string>source.ruby string.regexp.classic.ruby,source.ruby string.regexp.mod-r.ruby</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ff5555</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Keyword</string>
<key>scope</key>
<string>keyword</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage</string>
<key>scope</key>
<string>storage</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage type</string>
<key>scope</key>
<string>storage.type</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#8be9fd</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage Type Namespace</string>
<key>scope</key>
<string>storage.type.namespace</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#8be9fd</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage Type Class</string>
<key>scope</key>
<string>storage.type.class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Class name</string>
<key>scope</key>
<string>entity.name.class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>underline</string>
<key>foreground</key>
<string>#8be9fd</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Meta Path</string>
<key>scope</key>
<string>meta.path</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>underline</string>
<key>foreground</key>
<string>#66d9ef</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Inherited class</string>
<key>scope</key>
<string>entity.other.inherited-class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic underline</string>
<key>foreground</key>
<string>#8be9fd</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Function name</string>
<key>scope</key>
<string>entity.name.function</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#50fa7b</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Function argument</string>
<key>scope</key>
<string>variable.parameter</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#ffb86c</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Tag name</string>
<key>scope</key>
<string>entity.name.tag</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Tag attribute</string>
<key>scope</key>
<string>entity.other.attribute-name</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#50fa7b</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Library function</string>
<key>scope</key>
<string>support.function</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#8be9fd</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Library constant</string>
<key>scope</key>
<string>support.constant</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#6be5fd</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Library class&#x2f;type</string>
<key>scope</key>
<string>support.type, support.class</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#66d9ef</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Library variable</string>
<key>scope</key>
<string>support.other.variable</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string></string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support Other Namespace</string>
<key>scope</key>
<string>support.other.namespace</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#66d9ef</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid</string>
<key>scope</key>
<string>invalid</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#ff79c6</string>
<key>fontStyle</key>
<string></string>
<key>foreground</key>
<string>#F8F8F0</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Invalid deprecated</string>
<key>scope</key>
<string>invalid.deprecated</string>
<key>settings</key>
<dict>
<key>background</key>
<string>#bd93f9</string>
<key>foreground</key>
<string>#F8F8F0</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON String</string>
<key>scope</key>
<string>meta.structure.dictionary.json string.quoted.double.json</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CFCFC2</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.header</string>
<key>scope</key>
<string>meta.diff, meta.diff.header</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#6272a4</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.deleted</string>
<key>scope</key>
<string>markup.deleted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.inserted</string>
<key>scope</key>
<string>markup.inserted</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#50fa7b</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>diff.changed</string>
<key>scope</key>
<string>markup.changed</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E6DB74</string>
</dict>
</dict>
<dict>
<key>scope</key>
<string>constant.numeric.line-number.find-in-files - match</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bd93f9</string>
</dict>
</dict>
<dict>
<key>scope</key>
<string>entity.name.filename</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#E6DB74</string>
</dict>
</dict>
<dict>
<key>scope</key>
<string>message.error</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#F83333</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON Punctuation</string>
<key>scope</key>
<string>punctuation.definition.string.begin.json - meta.structure.dictionary.value.json, punctuation.definition.string.end.json - meta.structure.dictionary.value.json</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#EEEEEE</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON Structure</string>
<key>scope</key>
<string>meta.structure.dictionary.json string.quoted.double.json</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8be9fd</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON String</string>
<key>scope</key>
<string>meta.structure.dictionary.value.json string.quoted.double.json</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#f1fa8c</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON: 6 deep</string>
<key>scope</key>
<string>meta meta meta meta meta meta meta.structure.dictionary.value string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#50fa7b</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON: 5 deep</string>
<key>scope</key>
<string>meta meta meta meta meta meta.structure.dictionary.value string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ffb86c</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON: 4 deep</string>
<key>scope</key>
<string>meta meta meta meta meta.structure.dictionary.value string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON: 3 deep</string>
<key>scope</key>
<string>meta meta meta meta.structure.dictionary.value string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bd93f9</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON: 2 deep</string>
<key>scope</key>
<string>meta meta meta.structure.dictionary.value string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#50fa7b</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>JSON: 1 deep</string>
<key>scope</key>
<string>meta meta.structure.dictionary.value string</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ffb86c</string>
</dict>
</dict>
<!-- Markdown Tweaks -->
<dict>
<key>name</key>
<string>Markup: strike</string>
<key>scope</key>
<string>markup.strike</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#FFB86C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: bold</string>
<key>scope</key>
<string>markup.bold</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>bold</string>
<key>foreground</key>
<string>#FFB86C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: italic</string>
<key>scope</key>
<string>markup.italic</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#FFB86C</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markdown: heading</string>
<key>scope</key>
<string>markup.heading</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8BE9FD</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markdown: List Items Punctuation</string>
<key>scope</key>
<string>punctuation.definition.list_item.markdown</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#FF79C6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markdown: Blockquote</string>
<key>scope</key>
<string>markup.quote</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#6272A4</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markdown: Blockquote Punctuation</string>
<key>scope</key>
<string>punctuation.definition.blockquote.markdown</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>background</key>
<string>#6272A4</string>
<key>foreground</key>
<string>#6272A4</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markdown: Separator</string>
<key>scope</key>
<string>meta.separator</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#6272A4</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: raw inline</string>
<key>scope</key>
<string>text.html.markdown markup.raw.inline</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#50FA7B</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: underline</string>
<key>scope</key>
<string>markup.underline</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>underline</string>
<key>foreground</key>
<string>#BD93F9</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markup: Raw block</string>
<key>scope</key>
<string>markup.raw.block</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#CFCFC2</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markdown: Raw Block fenced source</string>
<key>scope</key>
<string>markup.raw.block.fenced.markdown source</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#F8F8F2</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markdown: Fenced Bode Block</string>
<key>scope</key>
<string>punctuation.definition.fenced.markdown, variable.language.fenced.markdown</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#6272A4</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Markdown: Fenced Language</string>
<key>scope</key>
<string>variable.language.fenced.markdown</string>
<key>settings</key>
<dict>
<key>fontStyle</key>
<string>italic</string>
<key>foreground</key>
<string>#6272A4</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation Accessor</string>
<key>scope</key>
<string>punctuation.accessor</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#FF79C6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Meta Function Return Type</string>
<key>scope</key>
<string>meta.function.return-type</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#FF79C6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation Section Block Begin</string>
<key>scope</key>
<string>punctuation.section.block.begin</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ffffff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation Section Block End</string>
<key>scope</key>
<string>punctuation.section.block.end</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ffffff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation Section Embedded Begin</string>
<key>scope</key>
<string>punctuation.section.embedded.begin</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation Section Embedded End</string>
<key>scope</key>
<string>punctuation.section.embedded.end</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Punctuation Separator Namespace</string>
<key>scope</key>
<string>punctuation.separator.namespace</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variable Function</string>
<key>scope</key>
<string>variable.function</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#50fa7b</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variable Other</string>
<key>scope</key>
<string>variable.other</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ffffff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Variable Language</string>
<key>scope</key>
<string>variable.language</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bd93f9</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Entity Name Module Ruby</string>
<key>scope</key>
<string>entity.name.module.ruby</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8be9fd</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Entity Name Constant Ruby</string>
<key>scope</key>
<string>entity.name.constant.ruby</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#bd93f9</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Support Function Builtin Ruby</string>
<key>scope</key>
<string>support.function.builtin.ruby</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ffffff</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Storage Type Namespace CS</string>
<key>scope</key>
<string>storage.type.namespace.cs</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#ff79c6</string>
</dict>
</dict>
<dict>
<key>name</key>
<string>Entity Name Namespace CS</string>
<key>scope</key>
<string>entity.name.namespace.cs</string>
<key>settings</key>
<dict>
<key>foreground</key>
<string>#8be9fd</string>
</dict>
</dict>
</array>
<key>uuid</key>
<string>83091B89-765E-4F0D-9275-0EC6CB084126</string>
<key>colorSpaceName</key>
<string>sRGB</string>
<key>semanticClass</key>
<string>theme.dracula</string>
<key>author</key>
<string>Zeno Rocha</string>
</dict>
</plist>
+8 -5
View File
@@ -1,3 +1,6 @@
#import "PageTemplate.typ": *
#show: page-theme
= ประวัติย่อผู้จัดทำ
#place(right, box(stroke: (thickness: 1pt), width: 0.8in, height: 1in))
@@ -7,11 +10,11 @@
row-gutter: 1em,
column-gutter: 2em,
[ชื่อ], [นางสาวประภากร ศรีวรสาร],
[เกิด], [วันที่ 2 ตุลาคม พ.ศ.255x],
[เกิด], [วันที่ 2 ตุลาคม พ.ศ.2551],
[ที่อยู่],
[
บ้านเลขที่ หมู่ที่ ตำบล \
อำเภอ จังหวัด หนองคาย
บ้านเลขที่ 192 หมู่ที่ 15 ตำบล ในเมือง\
อำเภอ เมืองหนองคาย จังหวัด หนองคาย
],
)
@@ -21,8 +24,8 @@
columns: 3,
row-gutter: 1em,
column-gutter: 2em,
[พ.ศ.25xx], [ป.6], [โรงเรียน x],
[พ.ศ.25xx], [ม.3], [โรงเรียน y],
[พ.ศ.2564], [ป.6], [โรงเรียน อนุบาลหนองคาย],
[พ.ศ.2567], [ม.3], [โรงเรียน ปทุมเทพวิทยาคาร],
[พ.ศ.2569], [ปวช.], [สาขาวิชาช่างเทคนิคคอมพิวเตอร์ วิทยาลัยเทคนิคหนองคาย],
)
+116 -9
View File
@@ -16,14 +16,28 @@
right: 1in,
bottom: 1in,
),
header: context [
#h(1fr)
#counter(page).display(thai-numbering)
],
header: none,
)
doc
}
/// Sane indentation
#let i = h(3em)
/// Insane shit forced upon by my teacher
/// For indenting in 3rd level subheadings
// #let iii = h(3em)
#let iii = h(5.5em)
/// For indenting in 4th level subheadings
// #let iiii = h(6em)
#let iiii = h(9.25em)
#let iiiii = h(13em)
#let iiiiii = h(16.85em)
#let page-theme(doc) = {
set page(
paper: "a4",
@@ -51,12 +65,107 @@
leading: 1em,
)
set list(indent: 1em)
show raw.where(block: false): set text(font: "Laksaman", size: 10.5pt)
show raw.where(block: true): set block(
fill: rgb("#282A36"),
stroke: black + 2pt,
inset: 1.5em,
)
show raw.where(block: true): set raw(theme: "Dracula.tmTheme")
show raw.where(block: true): set text(
fill: rgb("#F8F8F2"),
font: "Cascadia Code",
size: 10pt,
)
show heading: set text(size: 10.5pt, weight: "regular")
show heading: set block(below: 1em)
show heading.where(level: 1): set text(size: 12pt, weight: "bold")
show heading.where(level: 1): set align(center)
show heading.where(level: 1): set block(below: 2em)
show heading.where(level: 2): set block(above: 2em)
show heading.where(level: 2): set text(weight: "bold")
show heading: it => {
if it.level > 2 {
block(
it,
inset: (left: 3em * (it.level - 2)),
)
} else {
it
}
}
show math.equation: set text(font: "Laksaman")
show table.cell.where(y: 0): strong
show image: it => {
block(stroke: black + 2pt, it)
}
show figure.where(kind: "i-figured-table"): set align(start)
show figure.where(kind: table): set figure.caption(position: top)
show figure.caption: it => {
text(weight: "bold")[
#it.supplement
#it.counter.display(it.numbering)
]
it.body
}
show figure.caption.where(position: bottom): it => place(center, it, dy: 2em)
set figure.caption(separator: "")
// show figure.where(kind: image): set figure(gap: 2em)
show figure.where(kind: image): set block(below: 2.5em)
set enum(number-align: start + top)
set ref(supplement: "หัวข้อ")
doc
}
#let fake-h1(body) = {
align(center, text(body, weight: "bold", size: 12pt))
}
#let sane-theme(doc) = {
set page(
paper: "a4",
margin: (
top: 1.5in,
left: 1.5in,
right: 1in,
bottom: 1in,
),
header: context [
#h(1fr)
#counter(page).display(thai-numbering)
],
)
set text(
lang: "th",
font: "Laksaman",
size: 10.5pt,
)
set par(
justify: true,
justification-limits: (
tracking: (min: -1pt, max: 3pt),
),
leading: 1em,
)
set list(indent: 1em)
show raw: set text(font: "Cascadia Code")
show heading: set text(size: 10.5pt)
show heading: set block(below: 1em)
show heading.where(level: 1): set text(size: 12pt)
show heading.where(level: 1): set text(size: 12pt, weight: "bold")
show heading.where(level: 1): set align(center)
show raw: set text(font: "Cascadia Code", size: 10pt)
show heading.where(level: 2): set text(weight: "bold")
show math.equation: set text(font: "Laksaman")
show table.cell.where(y: 0): strong
show figure.caption: it => {
text(weight: "bold")[
#it.supplement
#it.counter.display(it.numbering)
#it.separator
]
it.body
}
set figure.caption(separator: "")
set enum(number-align: start + top)
set ref(supplement: "หัวข้อ")
doc
}
@@ -64,7 +173,7 @@
// Figure with attribution information
#let afigure(
body,
attr: "",
attr: none,
..args,
) = [
#figure(body, ..args)
@@ -75,6 +184,4 @@
) <afig>
]
#let i = h(3em)
#let jb = linebreak(justify: true)
+300 -277
View File
@@ -1,353 +1,376 @@
wkNodeMcu:
type: Web
title: NodeMCU
date: 2025-08-15
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-8
value: https://en.wikipedia.org/w/index.php?title=NodeMCU&oldid=1306030712
type: Web
title: NodeMCU
date: 2025-08-15
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-8
value: https://en.wikipedia.org/w/index.php?title=NodeMCU&oldid=1306030712
wkEsp32:
type: Web
title: ESP32
date: 2025-11-2
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-8
value: https://en.wikipedia.org/w/index.php?title=ESP32&oldid=1320113248
type: Web
title: ESP32
date: 2025-12-27
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-28
value: https://en.wikipedia.org/w/index.php?title=ESP32&oldid=1329754183
wkEspressif:
type: Web
title: Espressif Systems
date: 2025-10-6
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-8
value: https://en.wikipedia.org/w/index.php?title=Espressif_Systems&oldid=1315427960
type: Web
title: Espressif Systems
date: 2025-11-28
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-29
value: https://en.wikipedia.org/w/index.php?title=Espressif_Systems&oldid=1324514195
wkMicrocontroller:
type: Web
title: Microcontroller
date: 2025-12-21
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-28
value: https://en.wikipedia.org/w/index.php?title=Microcontroller&oldid=1328645390
wkFlutter:
type: Web
title: Flutter
date: 2025-11-12
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=Flutter_(software)&oldid=1321794260
type: Web
title: Flutter
date: 2025-11-12
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=Flutter_(software)&oldid=1321794260
wkGit:
type: Web
title: Git
date: 2025-11-1
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=Git&oldid=1319901866
type: Web
title: Git
date: 2025-11-1
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=Git&oldid=1319901866
wkGitea:
type: Web
title: Gitea
date: 2025-11-17
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=Gitea&oldid=1322631603
type: Web
title: Gitea
date: 2025-11-17
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=Gitea&oldid=1322631603
wkHttps:
type: Web
title: HTTPS
date: 2025-11-30
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
type: Web
title: HTTPS
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=HTTPS&oldid=1324964055
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=HTTPS&oldid=1324964055
wkTls:
type: Web
title: Transport Layer Security
date: 2025-11-24
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=Transport_Layer_Security&oldid=1323879251
type: Web
title: Transport Layer Security
date: 2025-11-24
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=Transport_Layer_Security&oldid=1323879251
wkC:
type: Web
title: C (programming language)
date: 2025-11-26
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=C_(programming_language)&oldid=1324211766
type: Web
title: C (programming language)
date: 2026-1-3
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2026-1-5
value: https://en.wikipedia.org/w/index.php?title=C_(programming_language)&oldid=1330924334
wkGcc:
type: Web
title: GNU Compiler Collection
date: 2025-11-30
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
type: Web
title: GNU Compiler Collection
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=GNU_Compiler_Collection&oldid=1324929423
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-30
value: https://en.wikipedia.org/w/index.php?title=GNU_Compiler_Collection&oldid=1324929423
wkDart:
type: Web
title: Dart (programming language)
date: 2025-11-21
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-8
value: https://en.wikipedia.org/w/index.php?title=Dart_(programming_language)&oldid=1323401675
type: Web
title: Dart (programming language)
date: 2025-11-21
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-8
value: https://en.wikipedia.org/w/index.php?title=Dart_(programming_language)&oldid=1323401675
wkX509:
type: Web
title: X.509
date: 2025-11-11
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-29
value: https://en.wikipedia.org/w/index.php?title=X.509&oldid=1321610537
type: Web
title: X.509
date: 2025-11-11
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-29
value: https://en.wikipedia.org/w/index.php?title=X.509&oldid=1321610537
wkDerEncoding:
type: Web
title: X.690
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
date: 2025-10-6
url:
date: 2025-12-3
value: https://en.wikipedia.org/w/index.php?title=X.690&oldid=1315457524#DER_encoding
type: Web
title: X.690
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
date: 2025-10-6
url:
date: 2025-12-3
value: https://en.wikipedia.org/w/index.php?title=X.690&oldid=1315457524#DER_encoding
wkOpenSSL:
type: Web
title: OpenSSL
date: 2025-12-1
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-3
value: https://en.wikipedia.org/w/index.php?title=OpenSSL&oldid=1325138239
type: Web
title: OpenSSL
date: 2025-12-1
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-3
value: https://en.wikipedia.org/w/index.php?title=OpenSSL&oldid=1325138239
wkMaterial:
type: Web
title: Material Design
date: 2025-11-15
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-6
value: https://en.wikipedia.org/w/index.php?title=Material_Design&oldid=1322252287
type: Web
title: Material Design
date: 2025-11-15
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-6
value: https://en.wikipedia.org/w/index.php?title=Material_Design&oldid=1322252287
wkBuzzer:
type: Web
title: Buzzer
date: 2025-11-13
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-10
value: https://en.wikipedia.org/w/index.php?title=Buzzer&oldid=1321902450
type: Web
title: Buzzer
date: 2025-11-13
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-10
value: https://en.wikipedia.org/w/index.php?title=Buzzer&oldid=1321902450
wkNFC:
type: Web
title: Near-field communication
date: 2025-11-5
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-10
value: https://en.wikipedia.org/w/index.php?title=Near-field_communication&oldid=1320616102
type: Web
title: Near-field communication
date: 2025-11-5
language: en
publisher: มูลนิธิวิกิมีเดีย (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-10
value: https://en.wikipedia.org/w/index.php?title=Near-field_communication&oldid=1320616102
androidJdkVersion:
type: Web
title: Java versions in Android builds
publisher: Android Developers (ภายใต้สัญญาอนุญาต Apache License 2.0)
language: en
# Publishing date/Last updated
date: 2025-11-21
url:
value: https://developer.android.com/build/jdks
# Date of research
date: 2025-11-26
type: Web
title: Java versions in Android builds
publisher: Android Developers (ภายใต้สัญญาอนุญาต Apache License 2.0)
language: en
# Publishing date/Last updated
date: 2025-11-21
url:
value: https://developer.android.com/build/jdks
# Date of research
date: 2025-11-26
sofFlutterMinSdk:
type: Web
title: Where is the value of "flutter.minSdkVersion" in Flutter project initialized?
date: 2025-08-26
language: en
publisher: Stackoverflow (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-26
value: https://stackoverflow.com/a/79746636
type: Web
title: Where is the value of "flutter.minSdkVersion" in Flutter project initialized?
date: 2025-08-26
language: en
publisher: Stackoverflow (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-11-26
value: https://stackoverflow.com/a/79746636
sofCDataModel:
type: Web
title: Are data models - ILP32 or LP64 decided by OS or the Hardware Architecture?
date: 2020-10-14
language: en
publisher: Stackoverflow (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-9
value: https://stackoverflow.com/a/79746636
type: Web
title: Are data models - ILP32 or LP64 decided by OS or the Hardware Architecture?
date: 2020-10-14
language: en
publisher: Stackoverflow (ภายใต้ CC BY-SA 4.0)
url:
date: 2025-12-9
value: https://stackoverflow.com/a/79746636
flInstallManually:
type: Web
title: Install Flutter manually
date: 2025-10-28
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-6
value: https://docs.flutter.dev/install/manual
type: Web
title: Install Flutter manually
date: 2025-10-28
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-6
value: https://docs.flutter.dev/install/manual
flVsCode:
type: Web
title: Install Flutter using VS Code
date: 2025-10-28
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-6
value: https://docs.flutter.dev/install/with-vs-code
type: Web
title: Install Flutter using VS Code
date: 2025-10-28
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-6
value: https://docs.flutter.dev/install/with-vs-code
flLinuxDev:
type: Web
title: Set up Linux development
date: 2025-9-25
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-6
value: https://docs.flutter.dev/platform-integration/linux/setup
type: Web
title: Set up Linux development
date: 2025-9-25
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-6
value: https://docs.flutter.dev/platform-integration/linux/setup
flLinuxBuild:
type: Web
title: Build Linux apps with Flutter
date: 2025-9-5
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-6
value: https://docs.flutter.dev/platform-integration/linux/building
type: Web
title: Build Linux apps with Flutter
date: 2025-9-5
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-6
value: https://docs.flutter.dev/platform-integration/linux/building
flArchOverview:
type: Web
title: Flutter architectural overview
date: 2025-12-8
language: en
publisher: Flutter (ภายใต้ CC BY 3.0 และ BSD License)
url:
date: 2025-12-30
value: https://docs.flutter.dev/resources/architectural-overview
archPkgs:
type: Web
title: Arch Linux - Package Search
date: 2025-12-15
language: en
url:
type: Web
title: Arch Linux - Package Search
date: 2025-12-15
value: https://archlinux.org/packages/
language: en
url:
date: 2025-12-15
value: https://archlinux.org/packages/
fedoraPkgs:
type: Web
title: Fedora Packages
date: 2025-12-15
language: en
url:
type: Web
title: Fedora Packages
date: 2025-12-15
value: https://packages.fedoraproject.org/
language: en
url:
date: 2025-12-15
value: https://packages.fedoraproject.org/
debianPkgs:
type: Web
title: Debian -- Packages
date: 2025-12-15
language: en
url:
type: Web
title: Debian -- Packages
date: 2025-12-15
value: https://www.debian.org/distrib/packages
language: en
url:
date: 2025-12-15
value: https://www.debian.org/distrib/packages
gitWindows:
type: Web
title: Git - Install for Windows
date: 2025-11-30
language: en
url:
date: 2025-12-1
value: https://git-scm.com/install/windows
type: Web
title: Git - Install for Windows
date: 2025-11-30
language: en
url:
date: 2025-12-1
value: https://git-scm.com/install/windows
twMaterialYou:
type: Post
title: "The latest in Material Design is NOW available"
date: 2021-10-28
author: Material Design [@materialdesign]
url:
date: 2025-12-1
value: https://x.com/materialdesign/status/1453409331697885192
type: Post
title: "The latest in Material Design is NOW available"
date: 2021-10-28
author: Material Design [@materialdesign]
url:
date: 2025-12-1
value: https://x.com/materialdesign/status/1453409331697885192
cpprefCBasics:
type: Web
title: Declarations
date: 2025-02-09
publisher: cppreference.com (ภายใต้ CC BY-SA 3.0 Unported)
url:
date: 2025-12-08
value: https://cppreference.com/w/c/language/declarations.html
type: Web
title: Declarations
date: 2025-02-09
publisher: cppreference.com (ภายใต้ CC BY-SA 3.0 Unported)
url:
date: 2025-12-08
value: https://cppreference.com/w/c/language/declarations.html
cpprefATypes:
type: Web
title: Arithmetic types
date: 2025-02-09
publisher: cppreference.com (ภายใต้ CC BY-SA 3.0 Unported)
url:
date: 2025-12-09
value: https://cppreference.com/w/c/language/arithmetic_types.html
type: Web
title: Arithmetic types
date: 2025-02-09
publisher: cppreference.com (ภายใต้ CC BY-SA 3.0 Unported)
url:
date: 2025-12-09
value: https://cppreference.com/w/c/language/arithmetic_types.html
ansiC:
type: Book
title: The ANSI C Programming Language
page-total: 238
author:
- Brian W. Kernighan
- Dennis M. Ritchie
publisher: Prentice Hall
language: en
edition: ฉบับที่สอง (Second edition)
date: 1988
url: https://archive.org/details/the-ansi-c-programming-language-by-brian-w.-kernighan-dennis-m.-ritchie.org
type: Book
title: The ANSI C Programming Language
page-total: 238
author:
- Brian W. Kernighan
- Dennis M. Ritchie
publisher: Prentice Hall
language: en
edition: ฉบับที่สอง (Second edition)
date: 1988
serial-number:
isbn: 0131101633
url:
date: 2025-12-11
value: https://archive.org/details/the-ansi-c-programming-language-by-brian-w.-kernighan-dennis-m.-ritchie.org
ghEsp32Partition:
type: Web
title: default.csv
date: 2024-4-15
url:
date: 2025-12-9
value: https://github.com/espressif/arduino-esp32/blob/2ede5ac10923afd1e3a42ce1fb41930a9de05d16/tools/partitions/default.csv
type: Web
title: default.csv
date: 2024-4-15
url:
date: 2025-12-9
value: https://github.com/espressif/arduino-esp32/blob/2ede5ac10923afd1e3a42ce1fb41930a9de05d16/tools/partitions/default.csv
pioPython:
type: Web
title: Install Python Interpreter
date: 2024-9-14
publisher: PlatformIO Docs (ภายใต้ Apache License 2.0)
url:
date: 2025-12-15
value: https://docs.platformio.org/en/latest/faq/install-python.html
type: Web
title: Install Python Interpreter
date: 2024-9-14
publisher: PlatformIO Docs (ภายใต้ Apache License 2.0)
url:
date: 2025-12-15
value: https://docs.platformio.org/en/latest/faq/install-python.html
pioSysReq:
type: Web
date: 2022-5-30
title: System Requirements
publisher: PlatformIO Docs (ภายใต้ Apache License 2.0)
url:
date: 2025-12-15
value: https://docs.platformio.org/en/latest/core/installation/requirements.html
type: Web
date: 2022-5-30
title: System Requirements
publisher: PlatformIO Docs (ภายใต้ Apache License 2.0)
url:
date: 2025-12-15
value: https://docs.platformio.org/en/latest/core/installation/requirements.html
pioInsScript:
type: Web
date: 2023-8-14
title: Installer Script (Recommended)
publisher: PlatformIO Docs (ภายใต้ Apache License 2.0)
url:
date: 2025-12-15
value: https://docs.platformio.org/en/latest/core/installation/methods/installer-script.html
type: Web
date: 2023-8-14
title: Installer Script (Recommended)
publisher: PlatformIO Docs (ภายใต้ Apache License 2.0)
url:
date: 2025-12-15
value: https://docs.platformio.org/en/latest/core/installation/methods/installer-script.html
+111 -60
View File
@@ -9,72 +9,123 @@
),
)
#include "ปก.typ"
#counter(page).update(1)
#show: page-theme
#include "Abstract.typ"
#pagebreak()
#include "Acknowledgements.typ"
#pagebreak()
#show outline: set heading(outlined: true)
#show outline.entry: it => {
show linebreak: [ ]
link(
it.element.location(),
it.indented(it.prefix(), context [
#it.body()
#box(width: 1fr, repeat[.])
#context thai-numbering(counter(page).at(it.element.location()).first())
]),
#[
#show raw.where(block: false): set text(font: "Laksaman", size: 10.5pt)
#show raw.where(block: true): set block(fill: rgb("#282A36"), inset: 1.5em)
#show raw.where(block: true): set raw(theme: "Dracula.tmTheme")
#show raw.where(block: true): set text(
fill: rgb("#F8F8F2"),
font: "Cascadia Code",
size: 10pt,
)
}
#outline(depth: 2, indent: 3.75em)
#include "Cover.typ"
#pagebreak()
#counter(page).update(1)
#show: page-theme
#include "Abstract.typ"
#pagebreak()
#include "Acknowledgements.typ"
#pagebreak()
#import "@preview/i-figured:0.2.4"
#i-figured.outline(target-kind: table, title: [สารบัญตาราง])
#pagebreak()
#i-figured.outline(
title: [สารบัญภาพ],
)
#include "Chapter1.typ"
#include "Chapter2/Chapter2.typ"
#include "Chapter3.typ"
#include "Chapter4.typ"
#include "Chapter5.typ"
#bibliography("References.yaml", title: "บรรณานุกรม", full: true, style: "chicago-author-date")
#pagebreak()
= บรรณานุกรมภาพ
#let image-credits() = context {
let figures = query(figure.where(kind: "i-figured-image"))
let attributions = query(<afig>)
for (idx, f) in figures.enumerate() {
if (idx >= attributions.len()) {
return
}
f.caption
// f.counter.display(f.numbering)
h(2.2em)
attributions.at(idx).body.body
#show outline: set heading(outlined: true)
#show outline.entry: it => {
show linebreak: [ ]
link(
it.element.location(),
grid(
columns: 3,
column-gutter: 1fr,
it.indented(it.prefix(), it.body()),
h(1em),
context thai-numbering(counter(page).at(it.element.location()).first()),
),
)
}
}
#image-credits()
#[
#set page(header: none)
#show outline.entry: it => {
it
context {
let outline-pages = counter(page).at(it.location()).first()
let current-page = counter(page).get().first()
if current-page > outline-pages {
fake-h1("สารบัญ (ต่อ)")
v(1em)
}
}
}
#outline(depth: 2, indent: 3.75em)
]
#pagebreak()
#import "@preview/i-figured:0.2.4"
#i-figured.outline(target-kind: table, title: [สารบัญตาราง])
#pagebreak()
#i-figured.outline(
title: [สารบัญภาพ],
)
#show heading: i-figured.reset-counters
#show figure: i-figured.show-figure
#include "Chapter1.typ"
#include "Chapter2/Chapter2.typ"
#include "Chapter3/Chapter3.typ"
#include "Chapter4.typ"
#include "Chapter5.typ"
#bibliography(
"References.yaml",
title: "บรรณานุกรม",
full: true,
style: "nong-khai-technical-college-project-guidelines.csl",
)
#pagebreak()
= บรรณานุกรมภาพ
#let image-credits() = context {
let figures = query(figure.where(kind: "i-figured-image"))
let attributions = query(<afig>)
let offset = 0
for (idx, f) in figures.enumerate() {
if idx >= attributions.len() {
return
}
if attributions.at(idx).body.body == [] {
offset += 1
if idx + offset >= attributions.len() {
return
}
if attributions.at(idx + offset).body.body == [] {
continue
}
}
f.caption
linebreak()
h(2.2em)
attributions.at(idx + offset).body.body
linebreak()
}
}
#image-credits()
]
#include "ภาคผนวก/ภาคผนวก.typ"
#include "History.typ"
@@ -0,0 +1,406 @@
<?xml version="1.0" encoding="utf-8"?>
<style xmlns="http://purl.org/net/xbiblio/csl" class="in-text" version="1.0" demote-non-dropping-particle="sort-only">
<!-- This style was edited with the Visual CSL Editor (https://editor.citationstyles.org/visualEditor/) -->
<info>
<title>Nong Khai Technical College Project Guidelines</title>
<title-short>NKTC</title-short>
<id>http://www.zotero.org/styles/nong-khai-technical-college-project-guidelines</id>
<link rel="self" href="http://www.zotero.org/styles/nong-khai-technical-college-project-guidelines"/>
<link href="https://staticlines.dailitation.xyz/Documents/NKTCProjectGuidelines.pdf" rel="documentation"/>
<author>
<email>linesofcodes@dailitation.xyz</email>
<name>Satakun Utama</name>
</author>
<category citation-format="numeric"/>
<category field="engineering"/>
<category field="generic-base"/>
<summary>NKTC College Project Bibliography (Modified from IEEE)</summary>
<updated>2025-12-27T05:32:04+00:00</updated>
<rights license="http://creativecommons.org/licenses/by-sa/3.0/">This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 License</rights>
</info>
<locale xml:lang="en">
<date form="text">
<date-part name="month" form="short" suffix=" "/>
<date-part name="day" form="numeric-leading-zeros" suffix=", "/>
<date-part name="year"/>
</date>
<terms>
<term name="chapter" form="short">ch.</term>
<term name="presented at">presented at the</term>
<term name="available at">available</term>
</terms>
</locale>
<macro name="status">
<choose>
<if variable="page issue volume" match="none">
<text variable="status" text-case="capitalize-first" suffix="" font-weight="bold"/>
</if>
</choose>
</macro>
<macro name="edition">
<choose>
<if type="bill book chapter graphic legal_case legislation motion_picture paper-conference report song" match="any">
<choose>
<if is-numeric="edition">
<group delimiter=" ">
<number variable="edition" form="ordinal"/>
<text term="edition" form="short"/>
</group>
</if>
<else>
<text variable="edition" text-case="capitalize-first" suffix="."/>
</else>
</choose>
</if>
</choose>
</macro>
<macro name="issued">
<choose>
<if type="article-journal report" match="any">
<date variable="issued">
<date-part name="month" form="short" suffix=" "/>
<date-part name="year" form="long"/>
</date>
</if>
<else-if type="bill book chapter graphic legal_case legislation song thesis" match="any">
<date date-parts="year" variable="issued">
<date-part name="year" form="long"/>
</date>
</else-if>
<else-if type="paper-conference" match="any">
<date variable="issued">
<date-part name="month" form="short"/>
<date-part name="year" prefix=" "/>
</date>
</else-if>
<else-if type="motion_picture" match="any">
<date variable="issued" form="text" prefix="(" suffix=")"/>
</else-if>
<else>
<date variable="issued" form="text"/>
</else>
</choose>
</macro>
<macro name="author">
<names variable="author">
<name and="text" et-al-min="7" et-al-use-first="1" initialize="false" initialize-with=". "/>
<label form="short" prefix=", " text-case="capitalize-first"/>
<et-al font-style="italic"/>
<substitute>
<names variable="editor"/>
<names variable="translator"/>
</substitute>
</names>
</macro>
<macro name="editor">
<names variable="editor">
<name initialize-with=". " delimiter=", " and="text"/>
<label form="short" prefix=", " text-case="capitalize-first"/>
</names>
</macro>
<macro name="locators">
<group delimiter=", ">
<text macro="edition"/>
<group delimiter=" ">
<text term="volume" form="short"/>
<number variable="volume" form="numeric"/>
</group>
<group delimiter=" ">
<number variable="number-of-volumes" form="numeric"/>
<text term="volume" form="short" plural="true"/>
</group>
<group delimiter=" ">
<text term="issue" form="short"/>
<number variable="issue" form="numeric"/>
</group>
</group>
</macro>
<macro name="title">
<choose>
<if type="bill book graphic legal_case legislation motion_picture song" match="any">
<text variable="title" font-style="normal" font-weight="bold"/>
</if>
<else>
<text variable="title" quotes="false" font-weight="bold" suffix=" "/>
</else>
</choose>
</macro>
<macro name="publisher">
<choose>
<if type="bill book chapter graphic legal_case legislation motion_picture paper-conference song" match="any">
<group delimiter="; ">
<text variable="publisher-place"/>
<text variable="publisher"/>
</group>
</if>
<else>
<group delimiter=", ">
<text variable="publisher"/>
<text variable="publisher-place"/>
</group>
</else>
</choose>
</macro>
<macro name="event">
<choose>
<if type="paper-conference speech" match="any">
<choose>
<if variable="container-title" match="any">
<group delimiter=", ">
<group delimiter=" ">
<text term="in"/>
<text variable="container-title" font-style="italic"/>
</group>
<text variable="event-place"/>
</group>
</if>
<else>
<group delimiter=", ">
<group delimiter=" ">
<text term="presented at"/>
<text variable="event"/>
</group>
<text variable="event-place"/>
</group>
</else>
</choose>
</if>
</choose>
</macro>
<macro name="access">
<choose>
<if type="webpage post post-weblog" match="any">
<choose>
<if variable="URL">
<group delimiter=" . " prefix=" ">
<text variable="URL"/>
<group delimiter=" ">
<text term="accessed" text-case="capitalize-first"/>
<date variable="accessed" form="text"/>
</group>
</group>
</if>
</choose>
</if>
<else-if match="any" variable="DOI">
<text variable="DOI" prefix=" doi: " suffix="."/>
</else-if>
<else-if variable="URL">
<group delimiter=". " prefix=" " suffix=". ">
<group delimiter=" ">
<text term="accessed" text-case="capitalize-first"/>
<date variable="accessed" form="text"/>
</group>
<group prefix="[" suffix="]" delimiter=" ">
<choose>
<if variable="medium" match="any">
<text variable="medium" text-case="capitalize-first"/>
</if>
<else>
<text term="online" text-case="capitalize-first"/>
<choose>
<if type="motion_picture">
<text term="video" text-case="capitalize-first"/>
</if>
</choose>
</else>
</choose>
</group>
</group>
<group delimiter=": " prefix=" ">
<text term="available at" text-case="capitalize-first"/>
<text variable="URL"/>
</group>
</else-if>
</choose>
</macro>
<macro name="page">
<choose>
<if type="article-journal" variable="number" match="all">
<group delimiter=" ">
<text value="Art."/>
<text term="issue" form="short"/>
<text variable="number"/>
</group>
</if>
<else>
<group delimiter=" ">
<label variable="page" form="short"/>
<text variable="page"/>
</group>
</else>
</choose>
</macro>
<macro name="citation-locator">
<group delimiter=" ">
<choose>
<if locator="page">
<label variable="locator" form="short"/>
</if>
<else>
<label variable="locator" form="short" text-case="capitalize-first"/>
</else>
</choose>
<text variable="locator"/>
</group>
</macro>
<macro name="geographic-location">
<group delimiter=", " suffix=".">
<choose>
<if variable="publisher-place">
<text variable="publisher-place" text-case="title"/>
</if>
<else-if variable="event-place">
<text variable="event-place" text-case="title"/>
</else-if>
</choose>
</group>
</macro>
<citation collapse="citation-number">
<sort>
<key variable="citation-number"/>
</sort>
<layout delimiter=", ">
<group delimiter=", " prefix="(" suffix=")">
<text variable="citation-number"/>
<text macro="citation-locator"/>
</group>
</layout>
</citation>
<bibliography entry-spacing="0" second-field-align="flush">
<layout>
<text variable="citation-number" prefix="(" suffix=")"/>
<text macro="author" suffix=" . "/>
<choose>
<if type="article-journal">
<group delimiter=", ">
<text macro="title"/>
<text variable="container-title" font-style="italic" form="short"/>
<text macro="locators"/>
<text macro="page"/>
<text macro="issued"/>
<text macro="status"/>
</group>
<choose>
<if variable="URL DOI" match="none">
<text value="."/>
</if>
<else>
<text value=","/>
</else>
</choose>
<text macro="access"/>
</if>
<else-if type="paper-conference speech" match="any">
<group delimiter=", " suffix=".">
<text macro="title"/>
<text macro="event"/>
<text macro="issued"/>
<text macro="locators"/>
<text macro="page"/>
<text macro="status"/>
</group>
<text macro="access"/>
</else-if>
<else-if type="report">
<group delimiter=", " suffix=".">
<text macro="title"/>
<text macro="publisher"/>
<group delimiter=" ">
<text variable="genre"/>
<text variable="number"/>
</group>
<text macro="issued"/>
</group>
<text macro="access"/>
</else-if>
<else-if type="thesis">
<group delimiter=", " suffix=".">
<text macro="title"/>
<text variable="genre"/>
<text macro="publisher"/>
<text macro="issued"/>
</group>
<text macro="access"/>
</else-if>
<else-if type="webpage post-weblog post" match="any">
<group delimiter=". " suffix=".">
<text macro="title"/>
<text variable="container-title" font-style="normal"/>
<text macro="issued"/>
</group>
<text macro="access"/>
</else-if>
<else-if type="patent">
<group delimiter=", ">
<text macro="title"/>
<text variable="number"/>
<text macro="issued"/>
</group>
<text macro="access"/>
</else-if>
<else-if type="motion_picture">
<text macro="geographic-location" suffix=". "/>
<group delimiter=", " suffix=".">
<text macro="title"/>
<text macro="issued"/>
</group>
<text macro="access"/>
</else-if>
<else-if type="bill book graphic legal_case legislation report song" match="any">
<group delimiter=" . " suffix=". ">
<text macro="title"/>
<text macro="locators"/>
</group>
<group delimiter=". " suffix=".">
<text macro="publisher"/>
<text macro="issued"/>
<text macro="page"/>
</group>
<text macro="access"/>
</else-if>
<else-if type="article-magazine article-newspaper broadcast interview manuscript map patent personal_communication song speech thesis webpage" match="any">
<group delimiter=", " suffix=".">
<text macro="title"/>
<text variable="container-title" font-style="italic"/>
<text macro="locators"/>
<text macro="publisher"/>
<text macro="page"/>
<text macro="issued"/>
</group>
<text macro="access"/>
</else-if>
<else-if type="chapter paper-conference" match="any">
<group delimiter=". " suffix=". ">
<text macro="title"/>
<group delimiter=" ">
<text term="in"/>
<text variable="container-title" font-style="italic"/>
</group>
<text macro="locators"/>
</group>
<text macro="editor" suffix=" "/>
<group delimiter=", " suffix=".">
<text macro="publisher"/>
<text macro="issued"/>
<text macro="page"/>
</group>
<text macro="access"/>
</else-if>
<else>
<group delimiter=", " suffix=". ">
<text macro="title"/>
<text variable="container-title" font-style="italic"/>
<text macro="locators"/>
</group>
<group delimiter=", " suffix=".">
<text macro="publisher"/>
<text macro="page"/>
<text macro="issued"/>
</group>
<text macro="access"/>
</else>
</choose>
</layout>
</bibliography>
</style>
File diff suppressed because it is too large Load Diff
+35 -25
View File
@@ -1,39 +1,49 @@
#import "../PageTemplate.typ": *
#show: page-theme
= ภาคผนวก
#[
#show: page-theme
= ภาคผนวก
== ลิขสิทธิ์เนื้อหาโครงงาน
== ลิขสิทธิ์เนื้อหาโครงงาน
#i #sym.copyright พ.ศ. 2568 งานนี้อยู่ภายใต้สัญญาอนุญาต Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) หากต้องการดูรายละเอียดเพิ่มเติมเกี่ยวกับสัญญาอนุญาตนี้ โปรดไปที่ https://creativecommons.org/licenses/by-sa/4.0/
#i #sym.copyright พ.ศ. 2568 งานนี้อยู่ภายใต้สัญญาอนุญาต Creative Commons
Attribution-ShareAlike 4.0 International (CC BY-SA 4.0)
หากต้องการดูรายละเอียดเพิ่มเติมเกี่ยวกับสัญญาอนุญาตนี้ โปรดไปที่
https://creativecommons.org/licenses/by-sa/4.0/
#i นอกจากที่กล่าวถึงในบรรณานุกรมภาพแล้ว หนังสือโครงงานนี้มีการใช้ไอคอนจาก Visual Studio Code (จาก GitHub repository `microsoft/vscode-codicons`) เวอร์ชัน 0.0.43 และไอคอนจากปลั๊กอิน Dart ใน Visual Studio Code (`Dart-Code/Dart-Code`) เวอร์ชัน 3.124.0 ซึ่งทั้งคู่อยู่ภายใต้ MIT license
#i นอกจากที่กล่าวถึงในบรรณานุกรมภาพแล้ว หนังสือโครงงานนี้มีการใช้ไอคอนจาก Visual Studio
Code (จาก GitHub repository `microsoft/vscode-codicons`) เวอร์ชัน 0.0.43
และไอคอนจากปลั๊กอิน Dart ใน Visual Studio Code (`Dart-Code/Dart-Code`) เวอร์ชัน
3.124.0 ซึ่งทั้งคู่อยู่ภายใต้ MIT license
== ลิขสิทธิ์ซอร์สโคดโครงงาน
== ลิขสิทธิ์ซอร์สโคดโครงงาน
#i เนื่องจากโคดในโครงการนี้เป็นสาธารณะและถูกปกป้องด้วยกฎหมายลิขสิทธิ์
โคดนี้จึงมาพร้อมกับสัญญาอนุญาตในการใช้งานโคดสาธารณะทั่วไปของ GNU (GNU Public License) เวอร์ชัน 3
#i เนื่องจากโคดในโครงการนี้เป็นสาธารณะและถูกปกป้องด้วยกฎหมายลิขสิทธิ์
โคดนี้จึงมาพร้อมกับสัญญาอนุญาตในการใช้งานโคดสาธารณะทั่วไปของ GNU (GNU Public License)
เวอร์ชัน 3
#i โดยสรุปแล้ว สัญญาอนุญาตนี้มีคุณสมบัติดังนี้ (ไม่ใช่คำแนะนำทางกฎหมาย
โปรดอ่านเนื้อหาสัญญาเต็มเพื่อรายละเอียดที่ชัดเจน)
#i โดยสรุปแล้ว สัญญาอนุญาตนี้มีคุณสมบัติดังนี้ (ไม่ใช่คำแนะนำทางกฎหมาย
โปรดอ่านเนื้อหาสัญญาเต็มเพื่อรายละเอียดที่ชัดเจน)
การอนุญาต:
- อนุญาตการใช้เนื้อหาที่ติดลิขสิทธิ์ในเชิงพาณิชย์
- อนุญาตให้สามารถเผยแพร่เนื้อหาที่ติดลิขสิทธ์ได้
- อนุญาตให้ดัดแปลงเนื้อหาที่ติดลิขสิทธิ์ได้
- ใบอนุญาตนี้ให้สิทธิ์ในการจดสิทธิบัตรจากผู้สนับสนุน
- อนุญาตให้ใช้และดัดแปลงเนื้อหาที่ติดลิขสิทธิ์อย่างเป็นส่วนตัวได้
การอนุญาต:
- อนุญาตการใช้เนื้อหาที่ติดลิขสิทธิ์ในเชิงพาณิชย์
- อนุญาตให้สามารถเผยแพร่เนื้อหาที่ติดลิขสิทธ์ได้
- อนุญาตให้ดัดแปลงเนื้อหาที่ติดลิขสิทธิ์ได้
- ใบอนุญาตนี้ให้สิทธิ์ในการจดสิทธิบัตรจากผู้สนับสนุน
- อนุญาตให้ใช้และดัดแปลงเนื้อหาที่ติดลิขสิทธิ์อย่างเป็นส่วนตัวได้
โดยมีเงื่อนไขว่า:
- โคดต้องถูกเปิดเผยหากเนื้อหาที่ติดลิขสิทธิ์ถูกแจกจ่าย
- สัญญาอนุญาตต้องถูกรวมกับเนื้อหาที่ติดลิขสิทธิ์ที่ถูกเผยแพร่
- การแก้ไขเนื้อหาที่ติดลิขสิทธิ์จะต้องอยู่ภายใต้สัญญาอนุญาตเดียวกัน
- หากมีการแก้ไขเนื้อหาที่ติดลิขสัทธิ์ ต้องมีหมายเหตุชัดเจนว่างานนั้นถูกแก้ไขจากงานต้นฉบับ
โดยมีเงื่อนไขว่า:
- โคดต้องถูกเปิดเผยหากเนื้อหาที่ติดลิขสิทธิ์ถูกแจกจ่าย
- สัญญาอนุญาตต้องถูกรวมกับเนื้อหาที่ติดลิขสิทธิ์ที่ถูกเผยแพร่
- การแก้ไขเนื้อหาที่ติดลิขสิทธิ์จะต้องอยู่ภายใต้สัญญาอนุญาตเดียวกัน
- หากมีการแก้ไขเนื้อหาที่ติดลิขสัทธิ์ ต้องมีหมายเหตุชัดเจนว่างานนั้นถูกแก้ไขจากงานต้นฉบับ
และมีข้อจำกัดว่า:
- ผู้ที่เป็นเจ้าของงานไม่มีความรับผิดชอบใด ทั้งสิ้นหากเกิดความเสียหายต่อการใช้หรือใช้ไม่ได้ของโปรแกรม
- โปรแกรมไม่มีการรับประกันใด ทั้งสิ้น
และมีข้อจำกัดว่า:
- ผู้ที่เป็นเจ้าของงานไม่มีความรับผิดชอบใด
ทั้งสิ้นหากเกิดความเสียหายต่อการใช้หรือใช้ไม่ได้ของโปรแกรม
- โปรแกรมไม่มีการรับประกันใด ทั้งสิ้น
สัญญาอนุญาตแบบเต็มที่ถูกบังคับใช้กับโคดในโครงงานนี้มีดังนี้
สัญญาอนุญาตแบบเต็มที่ถูกบังคับใช้กับโคดในโครงงานนี้มีดังนี้
]
#include "gpl-3.0.typ"