Skip to content
Tayakorn

คู่มือ Mesh Networking — สื่อสารในที่ที่ไม่มีเสาสัญญาณ

LEVEL 3 · ระดับสูง

CoT และ ATAK — เอาทั้งทีมขึ้นแผนที่เดียวกัน

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

13.1 ปัญหาที่ไม่ใช่ปัญหาเครือข่าย

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

ATAK (Android Team Awareness Kit) คือแอปแผนที่ที่แสดงตำแหน่งของทุกคนในทีมแบบเรียลไทม์ และภาษาที่มันใช้ชื่อ CoT (Cursor on Target) ซึ่งเป็น XML รูปแบบง่าย ๆ ที่กลายเป็นภาษากลางของงานสายนี้ไปแล้ว

13.2 พิสูจน์ด้วยตาเอง — สร้างข้อความจริงหนึ่งใบ

import xml.etree.ElementTree as ET

def make_cot(uid, lat, lon, cot_type="a-f-G-U-C", callsign="RESCUE-1"):
    """สร้างข้อความ Cursor on Target หนึ่งใบ"""
    ev = ET.Element("event", {
        "version": "2.0", "uid": uid, "type": cot_type,
        "time":  "2026-08-31T09:15:00Z",     # เวลาที่สร้าง
        "start": "2026-08-31T09:15:00Z",     # เริ่มมีผล
        "stale": "2026-08-31T09:20:00Z",     # หมดอายุ — ครบแล้วหมุดจางหายเอง
        "how": "m-g",
    })
    ET.SubElement(ev, "point", {"lat": f"{lat}", "lon": f"{lon}", "hae": "120.0",
                                "ce": "9999999.0", "le": "9999999.0"})
    detail = ET.SubElement(ev, "detail")
    ET.SubElement(detail, "contact", {"callsign": callsign})
    ET.SubElement(detail, "__group", {"name": "Cyan", "role": "Team Member"})
    return ET.tostring(ev, encoding="unicode")

xml = make_cot("RESCUE-1-abc123", 13.6512, 100.4961)
root = ET.fromstring(xml)
pt = root.find("point")
print(f"{root.find('detail/contact').get('callsign')} อยู่ที่ {pt.get('lat')}, {pt.get('lon')}")
print(f"ชนิด {root.get('type')} · หมดอายุ {root.get('stale')} · ขนาด {len(xml.encode('utf-8'))} ไบต์")

ผลรันจริง

RESCUE-1 อยู่ที่ 13.6512, 100.4961
ชนิด a-f-G-U-C · หมดอายุ 2026-08-31T09:20:00Z · ขนาด 334 ไบต์

13.3 สามอย่างในรูปแบบนี้ที่ออกแบบมาเพื่อเครือข่ายแบบเมชโดยเฉพาะ

หนึ่ง — stale คือการยอมรับว่าข้อมูลเน่า ทุกข้อความบอกวันหมดอายุของตัวเองมาด้วย ถ้าไม่มีใบใหม่มาก่อนถึงเวลานั้น หมุดบนแผนที่จะจางหายไปเอง · นี่คือประโยคแก่นของบทที่ 4 ที่ถูกเขียนลงไปในรูปแบบข้อมูลโดยตรง — ระบบไม่แสร้งว่ารู้ตำแหน่งปัจจุบันของทุกคน มันแสดงแค่สิ่งที่รู้ล่าสุดพร้อมบอกว่ารู้มานานแค่ไหน

สอง — 334 ไบต์ต่อใบ เล็กพอที่จะยัดลงวิทยุย่านต่ำที่ช้ามากได้ ถ้าทีมหกคนส่งตำแหน่งทุก 5 วินาที นั่นคือ 6 × 334 × 8 ÷ 5 = ราว 3,200 bps ซึ่งวิทยุ 250 kbps ในบทที่ 8 รับไหวสบาย ๆ

สาม — uid คงที่ต่อคน ไม่ใช่ต่อข้อความ ทำให้ใบใหม่ทับใบเก่าได้เอง แผนที่จึงไม่มีหมุดซ้ำของคนเดียวกันเรียงกันเป็นแถว

13.4 ข้อควรระวังที่กระทบ routing ตรง ๆ

ข้อความตำแหน่งเป็นข้อมูลที่ ส่งซ้ำได้ ไม่จำเป็นต้องถึงทุกใบ — ใบที่หายไปจะถูกแทนที่ด้วยใบถัดไปในอีกห้าวินาทีอยู่แล้ว การพยายามรับประกันว่าทุกใบต้องถึง (ส่งซ้ำจนกว่าจะได้ใบตอบรับ) จึงเป็นการเผาอากาศทิ้งเปล่า ๆ กับข้อมูลที่กำลังจะหมดอายุอยู่แล้ว

ขณะที่เสียงพูดหรือคำสั่งภารกิจเป็นคนละเรื่อง — ใบที่หายคือเนื้อหาที่หายจริง

เครือข่ายภาคสนามที่ออกแบบดีจะแยกชั้นความสำคัญของข้อมูล แล้วปฏิบัติกับมันคนละแบบ ไม่ใช่ยัดทุกอย่างลงท่อเดียวแล้วหวังว่าจะพอ

Read the full book