12.2. ארבע השכבות

ספריית הפרוטוקול בנויה כמחסנית של ארבע שכבות, שכל אחת מהן פותרת בעיה יחידה ונשענת על השכבה שמתחתיה. שאר הפרק עובר על המחסנית מלמטה למעלה.

A vertical stack of four labelled layers: transport at the bottom (USB or UART), framing above it (packet header with CRC), reliability above that (sequence numbers, ACK / NAK, retransmits), and channels at the top (named logical streams).

12.2.1. תעבורה (Transport)

בתחתית נמצא צינור הבייטים בין המצלמה למארח. ספריית הפרוטוקול אינה אכפת לה איזה מהם נושא את הבייטים:

  • USB-CDC מעל פורט ה-USB שאליו המצלמה מחוברת. האפשרות שבברירת המחדל ובעלת רוחב הפס הגבוה ביותר לכל מצלמה.

  • UART מעל זוג פיני GPIO על המצלמה המחוברים למתאם serial על המארח. שימושי לפריסות ללא צג שבהן פורט ה-USB עסוק או אינו נגיש פיזית.

תפקידה היחיד של התעבורה (transport) הוא ”בייטים נכנסים, בייטים יוצאים, לפי הסדר“. כל מה שמעל שכבה זו מניח שהתעבורה מספקת בייטים בסדר שבו הם נכתבו, אך מאפשר לבייטים עצמם להיות משובשים או לקישור ליפול לחלוטין. פרצים מאבדים (כמה בייטים חסרים) ונפילות נקיות (כל הקישור נעלם לזמן מה, ואז חוזר) מטופלים שניהם ברמה גבוהה יותר.

12.2.2. מסגור (Framing)

השכבה הבאה כלפי מעלה כופה מבנה על זרם הבייטים. כל הודעה הופכת למנה (packet) – כותרת בת 10 בייטים ואחריה מטען ואחריו סיומת בת 4 בייטים. הכותרת נושאת:

  • מילת סנכרון בת 2 בייטים (0xD5AA) המאפשרת למקלט למצוא מחדש את תחילת המנה לאחר אובדן סנכרון.

  • מספר רצף בן בייט אחד המשמש את שכבת המהימנות.

  • מזהה ערוץ בן בייט אחד האומר לאיזה זרם לוגי המנה שייכת.

  • שדה דגלים בן בייט אחד עבור ביטי ACK / NAK / fragment / event.

  • אופקוד בן בייט אחד המבחין בין פקודות פרוטוקול, פקודות מערכת, ופקודות ערוץ.

  • אורך מטען בן 2 בייטים.

  • CRC בן 2 בייטים על שמונת בייטי הכותרת הקודמים.

המטען בא בהמשך, ואז CRC בן 4 בייטים על המטען עצמו. שני ה-CRC תופסים שיבושים באופן עצמאי: ביט שהתהפך בכותרת פוסל את ה-CRC של הכותרת, והמקלט יכול לזרוק את המנה בלי שיצטרך אי-פעם לקרוא את המטען.

12.2.3. מהימנות

שכבת המהימנות הופכת ”מנות שאולי יגיעו“ ל“מנות שהגיעו”. היא עוקבת אחר מספרי הרצף בכותרת, מבקשת מהצד השני לשלוח אישורי קבלה עבור כל מנה הדורשת זאת, ומשדרת מחדש כאשר אישור קבלה אינו מגיע בתוך פסק זמן. כברירת מחדל, פסק הזמן לשידור חוזר מתחיל ב-500 ms ומוכפל בכל ניסיון חוזר, עם שלושה ניסיונות חוזרים לפני ויתור.

כל אחת מההתנהגויות הללו ניתנת להגדרה בקריאת protocol.init(): ניתן לכבות ACK עבור זרמים חד-כיווניים, ניתן לדלג על אימות CRC על תעבורות נקיות לחלוטין, וניתן לכוונן את פרמטרי השידור החוזר עבור קישורים איטיים או בעלי השהיה גבוהה.

12.2.4. ערוצים

השכבה העליונה היא מה שקוד האפליקציה רואה. ערוץ הוא זרם לוגי בעל שם המזוהה על ידי מזהה ערוץ מ-0 עד 31. עד 32 ערוצים יכולים להתקיים יחד על תעבורה אחת; כל אחד מהם עצמאי מהאחרים, ממוען על ידי המזהה שלו בכותרת של כל מנה. המצלמה מאתחלת עם ארבעה ערוצים מובנים – stdin, stdout, stream, ו-profile – וקוד אפליקציה רושם נוספים מעליהם על ידי קריאה ל-protocol.register() עם מחלקת Python.

ארבע השכבות אינן מערבבות תחומי אחריות. מסגור אינו יודע על ערוצים; מהימנות אינה יודעת על תוכן המנות; שכבת הערוצים אינה יודעת כיצד הבייטים מגיעים. הפרדה זו היא הסיבה לכך שהחלפת תעבורה (transport) (USB ל-UART, למשל) אינה מתפשטת כלפי מעלה לתוך קוד הערוצים, והיא מה שמאפשר לעבור על שאר הפרק שכבה אחת בכל פעם.