← คู่มือ Mesh Networking — สื่อสารในที่ที่ไม่มีเสาสัญญาณ
LEVEL 4 · ระดับเทพ
ทดสอบโดยไม่มีวิทยุสักตัว
ถ้าอ่านมาถึงตรงนี้แล้วอยากลองทำจริง อุปสรรคแรกคือคุณไม่มีวิทยุสิบตัวและไม่มีภูเขาให้เดินขึ้น บทนี้บอกว่าไม่จำเป็นต้องมี
14.1 ทำไมการจำลองถึงคุ้มกว่าที่คิด
ปัญหาสำคัญเกือบทั้งหมดในเล่มนี้ — flapping, count-to-infinity, ความจุที่หายไปกับตัวเอง, เส้นทางย้ายเมื่อโหนดขยับ — เป็นปัญหาเชิงตรรกะ ไม่ใช่ปัญหาเชิงคลื่น ⇒ ทดสอบได้บนโน้ตบุ๊กตัวเดียว
สิ่งที่จำลองไม่ได้คือคลื่นจริงในภูมิประเทศจริง แต่นั่นเป็นงานของขั้นถัดไป ไม่ใช่ข้ออ้างที่จะไม่ทดสอบตรรกะก่อน
14.2 ตัวจำลองทั้งตัว
import math, heapq
RANGE_M = 300.0 # ระยะที่ยังคุยกันพอได้
class Node:
def __init__(self, name, x, y, vx, vy):
self.name, self.x, self.y, self.vx, self.vy = name, x, y, vx, vy
def step(self, dt):
self.x += self.vx*dt; self.y += self.vy*dt
def etx_between(a, b):
"""ระยะ -> ETX · เกินระยะ = ไม่มีลิงก์"""
d = math.hypot(a.x-b.x, a.y-b.y)
if d > RANGE_M: return None
ratio = max(0.05, 1.0 - (d/RANGE_M)**2) # ใกล้ = ส่งถึงเกือบทุกใบ
return round(1.0/(ratio*ratio), 2)
def route(nodes, src, dst):
idx = {n.name: n for n in nodes}
dist = {src: 0.0}; prev = {}; pq = [(0.0, src)]
while pq:
d, u = heapq.heappop(pq)
if u == dst: break
if d > dist.get(u, float("inf")): continue
for n in nodes:
if n.name == u: continue
w = etx_between(idx[u], n)
if w is None: continue
nd = d + w
if nd < dist.get(n.name, float("inf")):
dist[n.name] = nd; prev[n.name] = u; heapq.heappush(pq, (nd, n.name))
if dst not in dist: return None, None
p = [dst]
while p[-1] in prev: p.append(prev[p[-1]])
return list(reversed(p)), dist[dst]
nodes = [Node("A", 0, 0, 0, 0), # ฐาน อยู่กับที่
Node("B", 250, 0, 0, 8), # เดินขึ้นเหนือ 8 เมตรต่อวินาที
Node("E", 240, -120, 0, 0), # อยู่กับที่ เป็นทางสำรอง
Node("C", 470, -60, 0, 0),
Node("D", 690, -80, 0, 0)]
for t in range(0, 61, 10):
p, cost = route(nodes, "A", "D")
shown = " -> ".join(p) if p else "ส่งไม่ถึง"
print(f"{t:>3} วิ {shown:<22} ETX {round(cost,2) if cost else '-'}")
for n in nodes: n.step(10)ผลรันจริง
0 วิ A -> B -> C -> D ETX 21.09
10 วิ A -> B -> E -> C -> D ETX 33.43
20 วิ A -> E -> C -> D ETX 36.99
30 วิ A -> E -> C -> D ETX 36.99
40 วิ A -> E -> C -> D ETX 36.99
50 วิ A -> E -> C -> D ETX 36.99
60 วิ A -> E -> C -> D ETX 36.99อ่านผลทีละบรรทัด: วินาทีที่ 0 เส้นทางวิ่งผ่าน B ตรง ๆ · วินาทีที่ 10 B เดินห่างจนลิงก์แย่ลง เส้นทางยาวขึ้นเป็น 4 hop เพื่อเลี่ยงลิงก์ที่กำลังเสื่อม · วินาทีที่ 20 B หลุดออกนอกระยะ เครือข่ายย้ายไปใช้ E เป็นการถาวรและนิ่งตั้งแต่นั้น
เครือข่ายซ่อมเส้นทางตัวเองโดยไม่มีใครสั่ง — และคุณเพิ่งเห็นมันเกิดขึ้นบนหน้าจอตัวเองโดยไม่ต้องมีวิทยุสักตัว
14.3 ต่อยอดจากตรงนี้ยังไง
ตัวจำลองข้างบนคือโครงที่เติมได้ทีละชั้น และแต่ละชั้นคือบทหนึ่งในเล่มนี้:
- เพิ่มการหลุดหายของแพ็กเก็ตแบบสุ่มตามค่า ETX แล้ววัดว่าส่งถึงจริงกี่เปอร์เซ็นต์ (บทที่ 4)
- เพิ่ม hello กับเส้นตาย แล้วดูว่ากว่าจะรู้ว่า B หายใช้เวลากี่วินาที (บทที่ 5)
- เพิ่ม hysteresis แล้วนับจำนวนครั้งที่เส้นทางเปลี่ยนตลอดการทดลอง (บทที่ 9)
- เพิ่มช่องคลื่นแล้ววัดความจุตามสูตรบทที่ 11 — และลองปรับ
REUSE_GAPดูว่าเพดานขยับตามไหม (บทที่ 10–11)
เคล็ดลับ: เพิ่มทีละชั้นและวัดผลทุกครั้ง ถ้าเพิ่มสองชั้นพร้อมกันแล้วผลเปลี่ยน คุณจะไม่รู้ว่าชั้นไหนทำ