门磁每天上报几次、农田传感器每十分钟上传一包、门锁要求用户靠近后立即响应,三者都可以叫“低功耗 IoT”,却需要不同的网络和接收策略。选型先问有效载荷、周期、下行时限、供电与基础设施,再看协议名称;不宜把距离、功耗和速率填成没有条件的固定排名。
技术 在体系中的位置 更适合先评估的约束
Zigbee 基于 802.15.4 等基础的完整组网/应用体系 节点角色、路由覆盖、设备功能互操作
Thread IPv6 低功耗 Mesh 网络 父节点、边界路由、IP 连通性
Matter 基于 IP 的应用互操作与安全体系 设备类型、控制器、Fabric 与授权
Z-Wave 设备控制生态,含传统 Mesh 和 LR 等模式 地区/设备模式及控制器支持
LoRa / LoRaWAN 调制/物理技术与广域网络协议 空中时间、网关、下行窗口与网络容量
NB-IoT / LTE-M 蜂窝 IoT 接入 运营网络、覆盖、功耗状态与资费运维
NFC / RFID 近距离交互、标签识别等 读写器、供能、标签类型与安全能力
UWB 宽带测距/定位与相应通信 测距协议、锚点几何、遮挡与功耗周期
Mesh 扩大的是可达路径,不是让所有电池节点常开接收
Zigbee 常区分 Coordinator、Router 和 End Device。Coordinator 建立网络并承担相应管理职责,Router 转发,End Device 依附父节点;休眠终端不能作为别人的中继。路由节点需要保持可达,因此通常由持续电源供电,但不能仅凭“插电设备”推断它一定以 Router 角色工作。Silicon Labs:Zigbee 节点类型
父节点为休眠子设备缓存下行,子设备唤醒后取走。这样的省电来自减少监听,也意味着下行不能随时到达。多跳可以绕过部分失效路径,但只有存在其他可用路由、资源和覆盖时才有意义;全屋路由灯泡被墙壁开关断电时,电池门磁并不会自动替它们承担 Mesh 主干。
Coordinator 不等于应用网关:同一个硬件盒子可能同时提供协调、协议转换和自动化服务,但三个角色应分别分析。Zigbee 产品互操作还涉及设备类型、Cluster、扩展和控制器支持,不能简单归纳成“同协议必然完全通用”或“全部供应商锁定”。
Z-Wave 也不能只列成一种 Mesh:传统 Z-Wave 与 Z-Wave Long Range 的拓扑不同,LR 使用设备到中心控制器的星形连接。兼容的控制器可以管理相应网络,但需核对设备模式及地区能力。Z-Wave Alliance:Long Range
Thread 与 Matter:网络互通之后,应用仍要认识彼此
Thread 常见部署基于 2.4 GHz IEEE 802.15.4,使用 6LoWPAN 等机制承载 IPv6。不能因为 802.15.4 家族包含其他频段,就给所有 Thread 产品统一标上 Sub-GHz。Thread 路由角色、休眠终端和 Border Router 分工,也不能由“原生 IPv6”推断全网每个节点都直接接入 Wi-Fi。
Border Router 在 Thread 与其他 IP 网络间路由,并承担相关发现/网络服务工作,通常无需把每一种应用命令翻译成私有协议;但它不是任意透明二层桥。一个隔离 Thread 网络内部可以通信,要访问外部 IP 网络才需要相应边界路径。Thread Group:边界路由器
休眠门磁 Matter over Thread Thread 父节点 接收上行、缓存下行 Border Router Thread 与其他 IP 网络 Matter Controller 订阅、权限与自动化 IP 一个物理盒子可以承担多个角色 但 Border Router 不等于应用控制器 门磁到自动化:无线转发、IP 路由和 Matter 控制分别负责一段 门磁不为其他节点转发;失去唯一边界路由器会影响外部访问,多角色合一也可能形成共同故障点。
Thread 有可重新选举的 Leader 等机制,但并非没有角色,也不是任何部署都没有单点故障。若只有一个 Border Router,其失效会切断相应外部路径;若自动化只运行在一个控制器上,网络路由正常也无法替代该控制器执行逻辑。多个边界路由器还需配置为适当的共同网络,不是购买多个盒子就自然形成同一个 Mesh。Thread Group:典型网络拓扑
Matter 定义应用层设备模型、交互及安全等,常运行于 Thread、Wi-Fi 或 Ethernet 之上;BLE 常用于发现/配网,不是日常 Matter 控制数据的通用承载。Matter Controller、配网 Commissioner、Thread Border Router、桥接旧设备的 Matter Bridge 是不同角色,一个盒子可承担多种角色。CSA:Matter
一次门磁事件如何抵达自动化
门磁醒来检测到打开,将属性/事件按 Matter 交互发送,通过 Thread 父节点和路由抵达控制器;若控制器位于 Wi-Fi/Ethernet 网络,中间经 Border Router。控制器依据已建立的订阅和授权收到更新,再决定是否开灯。物理无线应答、IP 抵达、Matter 交互成功和灯真正打开是不同完成点。
Matter 的多管理员机制允许在多个 Fabric 中授权管理,但并不意味着购买后所有生态自动获得权限。设备类型、可选功能和平台支持仍影响可用控制。网络加密保护传输,应用权限决定谁能开锁/改配置;跨品牌互操作不应被理解为省略授权。
LoRa 与 LoRaWAN:先区分无线包与网络服务
LoRa 是 Semtech 推动的扩频调制技术体系;LoRaWAN 定义设备接入、消息、安全及网络行为。使用 LoRa 调制发送私有点对点包,不会自动成为可被 LoRaWAN 网络管理的设备。频段、信道及发送限制依地区参数与设备实现确定,不能把 433/868/915 MHz 当作可在任何地方自由互换的菜单。
常见 LoRaWAN 是星中之星:同一上行可被多个 Gateway 接收,经 IP 回传给 Network Server,由网络侧协调去重和相应网络管理。Gateway 仍执行射频接收、包转发及下行调度等工作,不是“不做任何协议”的无状态电线。应用数据由应用侧服务处理,网络与应用密钥有不同职责,不能统一写成所有应用载荷都由 Network Server 解密。LoRa Alliance:LoRaWAN 架构
OTAA 通过入网过程建立会话关系;会话密钥、计数器和重启后的状态保持需要正确处理。无线 ACK 或网络服务器收到上行,不代表业务数据库已经存储,应用仍可使用消息编号进行确认、去重与故障恢复。
SF 增大时,同一包占用空口更久
传统 LoRa 模型的符号时间为 Tsym=2^SF/BW。带宽 125 kHz 时,SF7 每符号 1.024 ms,SF12 为 32.768 ms。较高 SF 改变解调能力与空中时间,不能一概说必然更远、更可靠;更长占用也增加碰撞机会和发送能耗。Semtech:LoRa FAQ
取明确的调制教学条件:物理载荷 20 byte、显式头、CRC 开启、编码率 4/5、前导 8 symbol,SF12 开启低数据率优化。按传统 LoRa 包长公式,SF7 空中时间约 56.576 ms,SF12 约 1318.912 ms。这里的 20 byte 是调制器载荷,不是“20 byte LoRaWAN 应用数据”;后者还需加上协议字段。Semtech:SX1276 数据手册,LoRa time-on-air
假设 100 个节点都采用后者、每 600 s 发一包且集中在同一信道/SF,单看发送时长之和就占约 21.98% 的时间;随机重叠、重传和下行还会改变容量。这是负载估计,不是某地区允许的占空比,更不是承诺成功率。实际部署需按地区参数、法规和网络策略重新预算。
下行延迟从接收窗口决定
TX 上行 RX1 窗口 1 RX2 窗口 2 等待 等待 返回休眠 若 RX1 已收到相应有效下行,不再为该上行打开 RX2 LoRaWAN Class A:下行机会跟随上行,而非随时可达 窗口时刻及参数依规范与配置;错过可用窗口的命令可能等到下一次上行,图不按时间比例。
类别 接收安排 下行/能耗边界
Class A 上行后安排 RX1/RX2 错过窗口可能要等下一次上行;适合低占空比
Class B 借助同步信标安排额外接收时隙 更可预测的机会,但需同步与监听成本
Class C 在不发送等条件下尽量持续接收 降低等待,不是零延迟;仍受调度和空口限制
Class C 不是“必须插电”的物理规则,而是持续接收通常更适合电量充足场景。所有节点都频繁要求确认也会增加下行压力;LoRaWAN 适合小量周期数据,不能由公里覆盖推断适合频繁低延迟控制或大文件升级。
多一个字节,为什么可能多出一整组符号?
先保持SF不变,逐字节增加载荷,观察平台与跳变;再把SF7换成SF12,同一个20 B包会从56.576 ms变成1318.912 ms。纵轴固定,便于比较真实时间尺度;这不是覆盖距离或发送成功率的预测。
正在呈现知识画面 重新加载
多一个字节,为什么可能多出一整组符号? 符号时间随2^SF增长,载荷编码还按组向上取整,所以空中时间对字节数呈阶梯变化。
{"id":"lora-airtime-staircase","title":"多一个字节,为什么可能多出一整组符号?","summary":"符号时间随2^SF增长,载荷编码还按组向上取整,所以空中时间对字节数呈阶梯变化。","height":1000,"html":"<h2 data-i18n=\"heading\"></h2><p class=\"intro\" data-i18n=\"intro\"></p><div class=\"control\"><label for=\"payload\" data-i18n=\"payload\"></label><output for=\"payload\" id=\"payload-value\"></output><input id=\"payload\" type=\"range\" min=\"1\" max=\"64\" value=\"20\" step=\"1\"></div><div class=\"control\"><label for=\"sf\" data-i18n=\"sf\"></label><output for=\"sf\" id=\"sf-value\"></output><input id=\"sf\" type=\"range\" min=\"7\" max=\"12\" value=\"7\" step=\"1\"></div><div class=\"chart-wrap\"><div class=\"chart-label\" data-i18n=\"packing\"></div><svg id=\"stairs\" class=\"curve\" viewBox=\"0 0 360 210\" role=\"img\" data-i18n-label=\"packing\"></svg></div><div class=\"chart-wrap\"><div class=\"chart-label\" data-i18n=\"plot\"></div><svg id=\"plot\" class=\"curve\" viewBox=\"0 0 360 210\" role=\"img\" data-i18n-label=\"plot\"></svg></div><div class=\"metrics\"><div><span data-i18n=\"symbols\"></span><strong id=\"symbols\"></strong></div><div><span data-i18n=\"symbol\"></span><strong id=\"symbol\"></strong></div><div><span data-i18n=\"time\"></span><strong id=\"time\"></strong></div></div><p id=\"eq\" class=\"formula\"></p><details class=\"scope\"><summary data-i18n=\"scopeLabel\"></summary><p data-i18n=\"scope\"></p></details>","css":".intro{margin:8px 0 18px;color:var(--muted);font-size:14px}.caption,.hint{font-size:12px;color:var(--muted);margin-top:12px}.control{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:6px 12px;align-items:center;margin:14px 0;font-size:13px}.control label{font-size:13px}.control output{color:var(--accent);min-width:5em;text-align:right;font-variant-numeric:tabular-nums}.control input{grid-column:1/-1;width:100%;margin:0}.presets{display:flex;gap:4px;align-items:stretch}.presets button{flex:1 1 0;min-width:0;overflow-wrap:anywhere;font-size:13px}.actions{display:flex;gap:8px;flex-wrap:wrap;margin:14px 0}.actions button{flex:1;min-width:0;font-size:13px;min-height:42px}.copy{display:grid;font-size:14px;margin:16px 0}.copy>*{grid-area:1/1;margin:0}.reserve{visibility:hidden}.scope{margin-top:14px;color:var(--muted);font-size:12px}.scope summary{padding:8px 0;cursor:pointer}.scope p{margin-top:10px}.two{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.card{border:1px solid var(--rule);border-radius:9px;padding:14px;min-width:0}.card header{font-size:14px;font-weight:600;margin-bottom:10px}.card button{font-size:12px;width:100%;min-width:0}.card small{display:block;font-size:12px;color:var(--muted)}.card code{font-size:12px;overflow-wrap:anywhere}.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:16px 0}.metrics>div{border-left:2px solid var(--accent);padding-left:10px;min-width:0}.metrics span{display:block;min-height:3.2em;color:var(--muted);font-size:12px}.metrics strong{font-size:23px;display:block;font-weight:550;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.formula{border-top:1px solid var(--rule);padding-top:12px;margin-top:14px;font-size:13px;font-variant-numeric:tabular-nums;overflow-wrap:anywhere}.value{font:550 20px ui-monospace,monospace}.legend{display:flex;flex-wrap:wrap;gap:6px 14px;font-size:12px;color:var(--muted);margin:12px 0}.legend span:before{content:'';display:inline-block;width:8px;height:8px;border-radius:2px;background:var(--accent);margin-right:6px}.legend .second:before{background:var(--second)}.check{display:flex;align-items:center;gap:8px;font-size:13px;margin:12px 0}.check input{width:16px;height:16px;flex-shrink:0;accent-color:var(--accent)}select,input[type=text],input[type=number]{background:var(--paper);color:var(--ink);font:inherit;font-size:13px;padding:10px;border:1px solid var(--rule);border-radius:7px;max-width:100%;min-width:0}select{width:100%;min-height:42px}.band{height:20px;display:flex;background:var(--surface);border-radius:4px;overflow:hidden}.band i{height:100%;display:block;background:var(--accent);transition:width .25s}.band i.second{background:var(--second)}button:disabled{cursor:default}.status{font-size:13px;min-height:4.8em}.mono{font-family:ui-monospace,monospace;font-variant-numeric:tabular-nums}.muted{color:var(--muted)}\n@media(max-width:480px){.two{gap:8px}.card{padding:12px 9px}.actions button,.presets button{font-size:12px}.metrics strong{font-size:20px}.metrics{gap:8px}}\n@media(prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important}}\n.track-row{margin:16px 0}.track-row>span{display:block;font-size:12px;color:var(--muted);margin-bottom:7px}.track{display:flex;gap:5px;min-width:0}.cell{flex:1;min-width:0;min-height:48px;border:1px solid var(--rule);border-radius:5px;background:var(--surface);display:flex;align-items:center;justify-content:center;text-align:center;padding:5px 3px;font-size:12px;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}.cell.on{background:var(--accent-soft);border-color:var(--accent)}.cell.gold{background:var(--second-soft);border-color:var(--second)}.cell.empty{border-style:dashed;color:var(--muted)}.cell.error{border-color:var(--second);text-decoration:line-through}.choices{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px;margin:14px 0}.choices button{min-width:0;padding:10px 4px;font-size:12px;overflow-wrap:anywhere}.choices button[aria-current=true]{border-color:var(--accent);background:var(--accent-soft)}.relation{display:grid;grid-template-columns:minmax(0,1fr) 28px minmax(0,1fr);align-items:center;gap:6px;margin:12px 0}.relation .cell{min-height:72px}.relation>i{text-align:center;font-style:normal;color:var(--accent)}.readout{font-size:13px;white-space:pre-line;min-height:6.4em;overflow-wrap:anywhere}.plot{position:relative;border-left:1px solid var(--rule);border-bottom:1px solid var(--rule);padding:8px 0;margin:18px 0}.plot-row{height:28px;position:relative;margin:4px 0;background:var(--surface)}.plot-row i{position:absolute;inset-block:5px;background:var(--accent);min-width:2px;transition:width .2s,left .2s}.plot-row b{position:relative;padding:4px 6px;font:11px/28px ui-monospace,monospace;background:var(--paper);border-radius:3px}.axis{display:flex;justify-content:space-between;font-size:11px;color:var(--muted)}\n\n/* Action labels must remain readable across locales and narrow embeds. */\n.actions{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:8px}\n.actions button{overflow-wrap:anywhere;white-space:normal;min-height:58px;padding:8px}\nbutton{overflow-wrap:anywhere}\n@media(min-width:640px){.actions{grid-template-columns:repeat(3,minmax(0,1fr))}}\n\n.metrics span{overflow-wrap:anywhere}\n.panel{border:1px solid var(--rule);border-radius:9px;padding:12px;margin:14px 0;min-width:0}.panel h3{font-size:13px;margin:0 0 10px;color:var(--muted)}.source{font:13px/1.8 ui-monospace,monospace;white-space:pre-wrap;overflow-wrap:anywhere;margin:12px 0}.source mark{background:var(--accent-soft);color:var(--ink);border-bottom:2px solid var(--accent)}.source .fault{background:var(--second-soft);border-color:var(--second)}.diagram{display:block;width:100%;height:auto;max-height:320px;margin:14px 0;overflow:visible}.diagram text{fill:var(--ink);font:12px ui-monospace,monospace}.diagram .edge{stroke:var(--muted);stroke-width:1.5;fill:none}.diagram .edge.on{stroke:var(--accent);stroke-width:3}.diagram .node{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.diagram .node.on{fill:var(--accent-soft);stroke:var(--accent)}.diagram .node.gold{fill:var(--second-soft);stroke:var(--second)}.log{font:12px/1.8 ui-monospace,monospace;white-space:pre-line;overflow-wrap:anywhere;min-height:7.2em}.table{display:grid;gap:5px;margin:14px 0}.table .tr{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:5px}.table .tr>*{padding:8px 5px;background:var(--surface);border-radius:4px;min-width:0;overflow-wrap:anywhere;font-size:12px}.table .tr .on{background:var(--accent-soft)}.table .tr .gold{background:var(--second-soft)}.choices button{min-height:44px}.metrics strong{min-height:1.6em}.code-line{display:block}.code-line.on{background:var(--accent-soft);border-left:2px solid var(--accent);padding-left:6px}.status-badge{font-size:12px;color:var(--accent)}.tile-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:6px}.tile-grid .cell{min-height:40px}.actions button{min-height:48px}.form-field{display:grid;gap:8px;margin:14px 0;font-size:13px}.form-field input{width:100%;font-family:ui-monospace,monospace}.metrics.three{grid-template-columns:repeat(3,minmax(0,1fr))}.formula{min-height:3.2em}.presets{flex-wrap:wrap}.presets button{flex-basis:25%;min-height:44px}\n\n.budget{display:flex;height:28px;margin:16px 0;background:var(--surface);border-radius:5px;overflow:hidden}.budget i{display:block;background:var(--accent);transition:width .2s}.budget i.gold{background:var(--second)}.intervals{margin:16px 0}.interval{position:relative;height:36px;background:var(--surface);margin:6px 0;border-radius:4px;overflow:hidden}.interval i{position:absolute;height:100%;background:var(--accent-soft);border-left:2px solid var(--accent)}.interval i.gold{background:var(--second-soft);border-color:var(--second)}.interval span{position:relative;z-index:1;font:12px/36px ui-monospace,monospace;padding-left:7px}.table .tr>*{min-height:4.8em}.formula{white-space:pre-line;min-height:7.2em}.actions:has(>button:only-child){grid-template-columns:1fr}.metrics strong{min-height:3.2em}.rangegrid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));gap:3px;margin:14px 0}.rangegrid .cell{min-height:30px;padding:3px 1px;font-size:10px}.message{min-height:7.2em;white-space:pre-line;font:13px/1.8 ui-monospace,monospace;overflow-wrap:anywhere}\n/* Allow CJK hanging punctuation without overflowing a metric's border box. */\n.metrics>div{padding-right:4px}.metrics span{line-break:anywhere}\n\n.chart-wrap{margin:18px 0}.chart-label{font-size:12px;color:var(--muted);min-height:3.2em}.curve{display:block;width:100%;height:auto;max-height:320px;overflow:visible}.curve text{font:11px ui-monospace,monospace;fill:var(--muted)}.gridline{stroke:var(--rule);stroke-width:1}.metrics strong{font-size:20px;min-height:3.2em}.formula{font:12px/1.8 ui-monospace,monospace;min-height:9em}.readout{min-height:8em}.presets button{flex-basis:30%}.scope p{overflow-wrap:anywhere} .unit-note{font-size:12px;color:var(--muted);margin:10px 0}\n\n.metrics span{word-break:break-all;line-break:strict}.metrics>div{padding-right:6px}\n\n","js":"const $=s=>document.querySelector(s);const set=(id,v)=>$('#'+id).textContent=v;const t=k=>viz.t(k);function cells(id,values){$('#'+id).replaceChildren(...values.map(v=>{const e=document.createElement('div');e.className='cell '+(v.cls||'');e.textContent=v.text;e.title=v.title||v.text;return e;}));}function pressed(mode){document.querySelectorAll('[data-mode]').forEach(e=>e.setAttribute('aria-pressed',String(e.dataset.mode===mode)));}const esc=s=>String(s).replace(/[&<>\"']/g,c=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));const fmt=s=>'{'+[...s].sort().join(', ')+'}';function graph(id,nodes,edges){const el=$('#'+id);el.setAttribute('viewBox','0 0 360 200');el.innerHTML='<defs><marker id=\"arrow-'+id+'\" viewBox=\"0 0 10 10\" refX=\"8\" refY=\"5\" markerWidth=\"5\" markerHeight=\"5\" orient=\"auto-start-reverse\"><path d=\"M 0 0 L 10 5 L 0 10 z\" fill=\"var(--muted)\"/></marker></defs>'+edges.map(e=>{const a=nodes[e[0]],b=nodes[e[1]],dx=b.x-a.x,dy=b.y-a.y,d=Math.hypot(dx,dy)||1;if(edges.some(r=>r[0]===e[1]&&r[1]===e[0])){const nx=-dy/d,ny=dx/d;return '<path class=\"edge '+(e[2]?'on':'')+'\" d=\"M '+(a.x+dx/d*22+nx*12)+' '+(a.y+dy/d*22+ny*12)+' Q '+((a.x+b.x)/2+nx*38)+' '+((a.y+b.y)/2+ny*38)+' '+(b.x-dx/d*25+nx*12)+' '+(b.y-dy/d*25+ny*12)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}return '<line class=\"edge '+(e[2]?'on':'')+'\" x1=\"'+(a.x+dx/d*25)+'\" y1=\"'+(a.y+dy/d*25)+'\" x2=\"'+(b.x-dx/d*28)+'\" y2=\"'+(b.y-dy/d*28)+'\" marker-end=\"url(#arrow-'+id+')\"/>';}).join('')+nodes.map(n=>'<g><circle class=\"node '+(n.cls||'')+'\" cx=\"'+n.x+'\" cy=\"'+n.y+'\" r=\"25\"/><text x=\"'+n.x+'\" y=\"'+(n.y+4)+'\" text-anchor=\"middle\">'+esc(n.name)+'</text>'+(n.sub?'<text x=\"'+n.x+'\" y=\"'+(n.y+43)+'\" text-anchor=\"middle\">'+esc(n.sub)+'</text>':'')+'</g>').join('');}function table(id,rows){$('#'+id).classList.add('table');$('#'+id).replaceChildren(...rows.map(r=>{const row=document.createElement('div');row.className='tr';row.style.gridTemplateColumns='repeat('+r.length+',minmax(0,1fr))';r.forEach(x=>{const c=document.createElement('div');if(typeof x==='object'){c.textContent=x.text;c.className=x.cls||'';}else c.textContent=x;row.append(c)});return row;}));}function band(id,parts,total){$('#'+id).replaceChildren(...parts.map((p,i)=>{const e=document.createElement('i');e.style.width=(100*p.value/total)+'%';e.className=i%2?'gold':'on';e.title=p.name+': '+p.value;return e}));}function intervals(id,items,total){$('#'+id).replaceChildren(...items.map(p=>{const row=document.createElement('div');row.className='interval';const bar=document.createElement('i');bar.style.left=(100*p.start/total)+'%';bar.style.width=(100*(p.end-p.start)/total)+'%';bar.className=p.cls||'';const label=document.createElement('span');label.textContent=p.label;row.append(bar,label);return row;}));}function plot(id,series,xr,yr,opts={}){const e=$('#'+id),X=x=>42+(x-xr[0])/(xr[1]-xr[0])*298,Y=y=>175-(y-yr[0])/(yr[1]-yr[0])*148;let out='<defs><clipPath id=\"clip-'+id+'\"><rect x=\"42\" y=\"27\" width=\"298\" height=\"148\"/></clipPath></defs>';for(let i=0;i<3;i++){let x=xr[0]+i*(xr[1]-xr[0])/2,y=yr[0]+i*(yr[1]-yr[0])/2;out+='<path class=\"gridline\" d=\"M '+X(x)+' 27V175M42 '+Y(y)+'H340\"/><text x=\"'+X(x)+'\" y=\"194\" text-anchor=\"middle\">'+esc(opts.xfmt?opts.xfmt(x):Number(x.toFixed(2)))+'</text><text x=\"36\" y=\"'+(Y(y)+4)+'\" text-anchor=\"end\">'+esc(opts.yfmt?opts.yfmt(y):Number(y.toFixed(2)))+'</text>';}out+='<g clip-path=\"url(#clip-'+id+')\">';for(const s of series){out+='<path fill=\"none\" stroke=\"'+(s.color||'var(--accent)')+'\" stroke-width=\"2.5\" '+(s.dash?'stroke-dasharray=\"5 4\"':'')+' d=\"'+s.pts.map((p,i)=>(i?'L':'M')+X(p[0]).toFixed(2)+','+Y(p[1]).toFixed(2)).join(' ')+'\"/>';}for(const p of opts.points||[])out+='<circle cx=\"'+X(p[0])+'\" cy=\"'+Y(p[1])+'\" r=\"4\" fill=\"var(--second)\" stroke=\"var(--paper)\" stroke-width=\"1.5\"/>';if(opts.cursor!==undefined)out+='<path d=\"M'+X(opts.cursor)+' 27V175\" stroke=\"var(--muted)\" stroke-dasharray=\"3 3\"/>';e.innerHTML=out+'</g>';e.dataset.curves=JSON.stringify(series.map(s=>s.pts));}const curve=(fn,lo,hi,n=120)=>Array.from({length:n+1},(_,i)=>{const x=lo+(hi-lo)*i/n;return[x,fn(x)]});function inputs(draw){document.querySelectorAll('input,select').forEach(e=>{e.addEventListener('input',draw);e.addEventListener('change',draw)});draw()}const n=id=>+$('#'+id).value;const show=(id,v,d=3)=>set(id,Number(v.toFixed(d)));function draw(){let p=n('payload'),sf=n('sf'),de=sf>=11?1:0,ts=2**sf/125,raw=x=>(8*x-4*sf+28+16)/(4*(sf-2*de)),sy=x=>8+Math.max(Math.ceil(raw(x))*5,0),time=x=>(12.25+sy(x))*ts,pts=[];for(let i=1;i<=64;i++)pts.push([i,time(i)],[i+1,time(i)]);show('payload-value',p);show('sf-value',sf);plot('stairs',[{pts:pts.map(([x,y])=>[x,y/ts-12.25])}],[1,65],[0,128],{points:[[p,sy(p)]]});plot('plot',[{pts}],[1,65],[0,3000],{points:[[p,time(p)]]});show('symbols',sy(p));show('symbol',ts,3);show('time',time(p),3);set('eq','DE = '+de+'; Tsym = 2^SF / BW\\nceil((8PL − 4SF + 44)/(4(SF−2DE))) = '+Math.ceil(raw(p))+'\\nNpayload = 8 + 5 × max(ceil(…), 0)\\nT = (8 + 4.25 + Npayload)Tsym');}inputs(draw);","audio":false,"strings":{"heading":"多一个字节,为什么可能多出一整组符号?","intro":"调整载荷和SF,查看取整前后与空中时间。","packing":"横轴载荷字节;纵轴载荷符号数","payload":"物理载荷(B)","plot":"横轴载荷B,纵轴空中时间ms","reset":"重置","scope":"传统LoRa:BW=125 kHz、CR=4/5、显式头、CRC、前导8符号;SF11/12开启低数据率优化。载荷是物理载荷,不是LoRaWAN应用字节。","scopeLabel":"模型范围与约定","sf":"SF","symbol":"每符号(ms)","symbols":"载荷符号数","time":"空中时间(ms)"}}
蜂窝 IoT:不自建网关,仍需管理网络与唤醒
NB-IoT/LTE-M 借助蜂窝基础设施,省去现场自建 LPWAN 网关的一部分工作,但仍需要兼容模块、SIM/eSIM、网络覆盖和服务管理。不同部署的移动性、速率、漫游与覆盖增强能力不同,不用“NB-IoT 固定 250 kbit/s”代表全部版本和现场表现。
PSM 让设备进入更深省电状态,期间通常不可被网络随时寻呼;eDRX 拉长寻呼监听周期,换来更长下行等待。附着、弱覆盖重试、覆盖增强重复发送可能消耗远多于应用小包本身的能量。网络是否缓存下行、缓存多久也取决于部署,不能把云端命令已发送等同于设备即将收到。GSMA:Mobile IoT 部署指南
NFC/RFID:距离短不等于身份可信
NFC 基于 13.56 MHz 的近场交互,常见用途包括读写标签与卡模拟。无源标签从读写器场中取能,指标签无需电池,并非整套系统零功耗;读取范围受线圈、匹配、金属环境和设备能力影响,不能把某种标签统一保证为一米读取。NFC Forum:技术概览
NFC Forum Tag Type 描述协议和数据映射等,不是产品品牌、固定容量或安全等级的同义词。Type 4 不自动意味着所有标签都具备同一安全机制,Type 5 与 ISO 15693 相关也不等于手机可按工业远距离读写器方式使用。应查实际芯片的认证、存储访问和密钥能力。NFC Forum:规范
RFID 范围更广,LF/HF 常利用近场耦合,UHF 标签常采用反向散射。读到 UID 只能说明收到一个标识;若用作门禁,应依据具体协议的认证和防重放设计判断,而不能把 UID 本身当作不可复制的秘密。
UWB:ToF 是距离,定位还需要几何与校准
UWB 的宽带时域特性有助于精确估计到达时间。若已正确扣除应答处理时间,往返传播剩余 20 ns,则 d=c×20ns/2≈3.0 m;仅 1 ns 的往返测量误差就对应约 15 cm 距离误差。处理延迟、两端时钟、天线延迟都不能忽略。FiRa:UWB 技术 FAQ
单个距离只约束一个圆/球面,完整位置还要结合多个锚点、角度或运动信息。非视距、人体遮挡、多径和锚点几何可能引入偏差,“厘米级”应带上测试条件。安全测距也需要相应协议和身份绑定,不是任何 UWB 脉冲都天然具备完整门锁安全性。
UWB 可与 BLE 配合:BLE 用于低功耗发现与控制,在需要精细测距时唤醒 UWB。整体功耗取决于测距频率和收发安排,不能把技术名称直接换成“中等功耗”。
把需求写成可计算的选择条件
需求例子 优先验证的问题 可能的技术方向
家庭门磁,电池供电,事件上报 路由常在线、控制器互操作、事件时限 Thread/Matter、Zigbee 等
农田十分钟一包 链路预算、网关回传、空中时间及下行等待 LoRaWAN 或有覆盖的蜂窝 IoT
城市分散抄表 现场覆盖、运营维护、深睡唤醒成本 NB-IoT/LTE-M 等
靠近触发配网或读标签 操作距离、手机 API、标签认证 NFC
门锁附近精细测距 身份绑定、NLOS、功耗与校准 UWB 配合发现链路
这些是评估方向,不是脱离地区、设备和业务条件的固定推荐。
复算 LoRa 空中时间与 ToF
from math import ceil , isclose
def airtime ( sf , payload_bytes = 20 , bw = 125000 ) :
de = int ( sf >= 11 ) tsym = 2 * * sf / bw
numerator = 8 * payload_bytes - 4 * sf + 28 + 16
payload_symbols = 8 + max ( ceil ( numerator / ( 4 * ( sf - 2 * de ) ) ) * 5 , 0 )
return ( 8 + 4. 25 + payload_symbols ) * tsym
assert isclose ( airtime ( 7 ) , 0. 056576 )
assert isclose ( airtime ( 12 ) , 1. 318912 )
assert isclose ( 100 * airtime ( 12 ) / 600 , 0. 2198186666666667 )
c = 299792458
assert isclose ( c * 20e-9 / 2 , 2. 99792458 )
assert isclose ( c * 1e-9 / 2 , 0. 149896229 )
print ( ' LoRa 包时长、聚合负载及往返 ToF 换算检查通过' )
此处是模型预算,未发射无线包,也未测量现场覆盖或定位精度。
继续查阅