教程RFIDIoTindoor tracking

把 RFID 读写器接入室内地图:分步实操指南

在实时 3D 门店地图上显示每一台 RFID 读写器:用小型中继按读写器汇总读数,通过表格 API 批量写入,并按状态在各楼层为读写器着色,再关联到一份全地图报表。

阅读约 10 分钟发布于 更新于 作者 Spatial Map team
Retail Mart Store 的 3D 预览:通道口、电梯和自动扶梯旁是紫色的 RFID 读写器标记,离线读写器显示为红色,货架上带有库存百分比徽标

你将搭建什么

RFID 在门店和仓库里早已是主力技术,但大多数团队仍然把它当成不断滚动的事件日志或一格格计数器来看。这两种方式都告诉不了你哪个月台通道突然没了动静,也看不出二楼自动扶梯处的读写器到底有没有读到东西。本文改为把每台读写器放到平面图上。全文基于 Spatial Map 中一个真实的演示设施,下面每张截图你都可以亲手复现。

演示:三层门店里的 85 台读写器

示例是 Production Corp 演示工作区中的 Retail Mart Store,一家三层门店(Ground、Level 1、Level 2)。店内共有 85 台固定读写器:66 台装在部门之间的门口和通道,9 台在电梯门口,9 台在自动扶梯两端,1 台在楼梯。每台读写器都是地图上的一个标记,以读写器命名,例如“RFID-G-02 · Office ↔ Receiving / Loading Docks”。一张表 Retail Mart · RFID Reader Reads 为每台读写器保存一行。

85
台读写器,分布于 3 层
61,795
今日读数(全部读写器)
69 · 12 · 4
Active · Idle · Offline
18
每行读写器字段数
编辑器中的 Retail Mart Store——通道、电梯和自动扶梯旁的读写器标记
Spatial Map 编辑器俯视 Retail Mart Store 平面图,紫色 RFID 读写器标记分布在各部门门口、EV 1 和 EV 2 电梯门前以及交通核心区的自动扶梯周围,右侧为图层面板
Spatial Map 编辑器俯视 Retail Mart Store 平面图,紫色 RFID 读写器标记分布在各部门门口、EV 1 和 EV 2 电梯门前以及交通核心区的自动扶梯周围,右侧为图层面板

各部分如何衔接

固定式 UHF 读写器通过边缘中间件上报读数——可以是读写器自带的 LLRP 接口,也可以是运行在旁边小主机上的厂商 SDK。中间件很擅长读标签,却说不出地图需要的任何信息。所以你要在中间加一个小部件:一个由你掌控的中继。它监听中间件,按读写器汇总读数,每隔几秒通过表格的写入 API 把结果写进 Spatial Map 的表。地图和报表都从这张表读取。

RFID 读写器 → 中间件 → 中继 → Spatial Map读写器把 EPC 读数上报给边缘中间件;你的中继按读写器计数,每隔几秒向 Spatial Map 表格发送一次批量 JSON 调用,已打开的地图和报表随之刷新。

为什么要汇总,而不是逐条转发?繁忙的通道每分钟会有数百次读取,其中很多是同一个标签被两根天线同时读到。地图无法有意义地展示这些,而且表格 API 按密钥限流。每台读写器一行——今日读数、最近一小时读数、唯一标签数、进出计数、最后的标签和 SKU,以及状态——正是演示表保存的内容,也正是值班主管想看的。如果你需要的是每个标签的位置,同样的模式也适用:每个标签一行,位置取最后读到它的读写器;参见实时室内资产追踪。

接入方式时效适用场景
表格写入 API(POST /rows/bulk)秒级——写入一到,已打开的地图立即重新加载你能在中间件旁运行一个中继。推荐方式。
Pull from a REST API(表格的 API & access 标签页)约一分钟——服务器定时轮询中间件已经通过 REST 接口提供按读写器的计数。
Upload file每次上传时你只有每日导出的 CSV 或 Excel 计数。

第 1 步——创建表格和 API 密钥

  1. 1
    创建表格

    进入 Tables → Create new table,填写名称(演示中为“Retail Mart · RFID Reader Reads”),类型选 RFID tag。系统建议的标准列只是起点:按中继将要发送的内容重命名、改类型或删除。

  2. 2
    每台读写器一行

    添加文本字段 `reader_id` 并勾选 Required 和 Unique,再添加 `reader_name`、`floor`、`reader_type`、`status`、整数计数器(`reads_today`、`reads_last_hour`、`unique_tags_today`、`in_count_today`、`out_count_today`、`alerts_today`)、日期时间类型的 `last_read_at`,以及 `last_tag_epc`、`last_sku`、`last_direction`、`rssi_dbm`、`firmware` 和 `elevation_m`。每次写入都会按此结构校验。

  3. 3
    创建密钥

    在表格的 API & access 标签页输入密钥名称,点击 Create key。密钥以 `sgv_tbl_` 开头,只显示一次,请立即存入中继的密钥配置。一个密钥只能写入这一张表;给每个中继单独的密钥,吊销其中一个不会影响其他。Owner 和 Admin 可以创建密钥。

  4. 4
    复制基础 URL

    同一标签页列出 12 个接口,并附可直接复制的 curl 示例。生产环境的基础地址是 `https://app.spatialmap.io/api/v1/public/tables`;写入哪张表由密钥决定,所以路径中没有表 ID。

Create new table——先选类型,再设计字段
Create new table 页面:Table name 输入框、类型选择(Polygon / area、Circle、Marker / POI、Asset (mobile)、Camera、Sensor、Shipment、RFID tag、Streaming / batch replay),以及包含 Field label、API key、Type 和 Required / Unique 规则的字段列表
Create new table 页面:Table name 输入框、类型选择(Polygon / area、Circle、Marker / POI、Asset (mobile)、Camera、Sensor、Shipment、RFID tag、Streaming / batch replay),以及包含 Field label、API key、Type 和 Required / Unique 规则的字段列表

第 2 步——编写中继

中继只需几十行代码,用团队习惯的任何语言都行。订阅中间件的读取事件(LLRP 报告或 SDK 回调),在内存中为每台读写器维护一个小计数器,并用定时器——每 5 到 10 秒一次足矣——把所有有变化的读写器放进一次批量调用发出。用读写器 ID 作为 `entityKey`,这样每次调用都会更新已有的行,而不是新增一行。

bash·批量写入或更新读写器行(POST /rows/bulk)
curl -X POST https://app.spatialmap.io/api/v1/public/tables/rows/bulk \
  -H "Authorization: Bearer $SPATIALMAP_TABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "rows": [
      {
        "entityKey": "RFID-G-02",
        "payload": {
          "reader_id": "RFID-G-02",
          "reader_name": "RFID-G-02 · Office ↔ Receiving / Loading Docks",
          "floor": "Ground",
          "reader_type": "Gate",
          "status": "Active",
          "reads_today": 590,
          "reads_last_hour": 56,
          "unique_tags_today": 288,
          "in_count_today": 294,
          "out_count_today": 296,
          "last_read_at": "2026-10-08T09:25:12Z",
          "last_tag_epc": "E2801121130DB42AB66C7A7B",
          "last_sku": "SKU-339201 Frozen Peas 1kg",
          "last_direction": "Out",
          "alerts_today": 2,
          "elevation_m": 2.4
        }
      },
      {
        "entityKey": "RFID-L1-15",
        "payload": {
          "reader_id": "RFID-L1-15",
          "reader_name": "RFID-L1-15 · Escalator 2 top · L1",
          "floor": "Level 1",
          "reader_type": "Escalator",
          "status": "Idle",
          "reads_today": 525,
          "reads_last_hour": 29,
          "unique_tags_today": 220,
          "in_count_today": 261,
          "out_count_today": 264,
          "last_read_at": "2026-10-08T09:25:49Z",
          "last_tag_epc": "E280115AC002CF6117A1B75B",
          "last_sku": "SKU-509112 LED TV 55in",
          "last_direction": "Out",
          "alerts_today": 0,
          "elevation_m": 6.067
        }
      }
    ]
  }'

`POST /rows` 和 `POST /rows/bulk` 都是 upsert:你发送的 payload 会成为该行的完整状态,所以请始终发送整行。如果只想改一个字段——例如读写器心跳中断时把它标为 Offline——请用 `PATCH`,它会把改动合并到已存储的 payload 上。

bash·修改单台读写器的一个字段(PATCH /rows/{key})
curl -X PATCH https://app.spatialmap.io/api/v1/public/tables/rows/RFID-G-01 \
  -H "Authorization: Bearer $SPATIALMAP_TABLE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"status":"Offline"}'

不想写中继?还有两种方式

  • Pull from a REST API——在表格的 API & access 标签页填写中间件的 URL、间隔(表单中最少 30 秒)、行键字段、数据项的 JSON 路径、所需请求头和字段映射,然后点击 Start polling。服务器端任务大约每分钟执行一次,即使没有人打开地图也会运行。每次轮询最多读取 1,000 行,响应最大 10 MB。
  • Upload file——适合只导出每日计数的门店。在 Integrations → Add integration → Upload file 中添加 CSV、Excel、JSON 或 GeoJSON 文件,第二天的导出用 Re-import 更新。

无论数据从哪条路进来,下面的地图和报表步骤都一样。API 参考见 Tables,完整示例见 Push rows with the table write API。

第 3 步——把读写器放到地图上

每台读写器都需要一个位于真实位置的标记:门口、电梯门旁、自动扶梯的上端或下端。用 Marker 工具在正确的楼层放置,并让每个标记的名称与中继写入 `reader_name` 的值完全一致。这个名称是下一步的关联键,请复制而不要手敲。多层门店请先建好楼层、电梯和自动扶梯——Multi-floor store with escalators and lifts 讲解的正是同一个 Retail Mart 布局。

选中的标记——数据链接匹配的就是它的名称
Retail Mart Store 编辑器中选中了标记 Consulting Room;侧边面板显示 Move、Fit、Duplicate、Delete 和 Edit linked data 操作、Bearing 滑块,以及可搜索 1,700 多个图标的图标选择器,紫色读写器标记环绕在电梯和自动扶梯周围
Retail Mart Store 编辑器中选中了标记 Consulting Room;侧边面板显示 Move、Fit、Duplicate、Delete 和 Edit linked data 操作、Bearing 滑块,以及可搜索 1,700 多个图标的图标选择器,紫色读写器标记环绕在电梯和自动扶梯周围

第 5 步——实时查看,再做报表

保存链接,在 Preview 或分享链接中打开设施。现在每个读写器标记都会按最近一小时的计数闪烁,并按状态着色。中继一写入,服务器就通知已打开的地图立即重新加载该图层;另有每 30 秒一次的刷新兜底。悬停读写器查看提示,点击查看完整记录及其 History。

Preview 中的 Retail Mart Store——读写器按状态着色
Retail Mart Store 在街道底图上的 3D 预览:紫色 RFID 读写器标记沿通道和自动扶梯分布,离线读写器为红色,货架带库存百分比徽标,右侧有 Layers (11/11) 和 Quality 控件
Retail Mart Store 在街道底图上的 3D 预览:紫色 RFID 读写器标记沿通道和自动扶梯分布,离线读写器为红色,货架带库存百分比徽标,右侧有 Layers (11/11) 和 Quality 控件

对于不在编辑器里工作的人,演示还提供一份全地图报表 Retail Mart · RFID Live Map。左侧是读写器列表,中间是门店实时地图,数字浮在地图上方:行数、今日总读数、最近一小时总读数和今日唯一标签数等 KPI,一个 By status 环形图和一个 Reads today by floor 柱状图。Floor、Status 和 Search 筛选会同时作用于全部内容——选 Offline,就得到早班的维修清单。参见 Full-map reports。

Retail Mart · RFID Live Map——全地图报表
全地图报表 Retail Mart · RFID Live Map:左侧为读写器列表及各自今日读数,中间为门店地图,KPI 卡片 Rows 85、Total reads today 61,795 和 Total reads last hour 6,700,右侧 Insights 面板包含 By status 环形图和 Reads today by floor 柱状图
全地图报表 Retail Mart · RFID Live Map:左侧为读写器列表及各自今日读数,中间为门店地图,KPI 卡片 Rows 85、Total reads today 61,795 和 Total reads last hour 6,700,右侧 Insights 面板包含 By status 环形图和 Reads today by floor 柱状图

我们踩过的坑

“给地图发送状态,而不是事件:每台读写器一行、每隔几秒刷新,值班主管一眼就能看懂。”

下一步

演示还提示了几个自然的扩展方向。为 `alerts_today`(即“Exit alerts today”字段)添加一条样式规则,让有出口告警计数的通道更醒目——它只改变地图和报表上的颜色,不会发送通知。像零售解决方案那样,把读写器状态与同楼层的货架库存和冷链传感器结合起来;或者借助防盗解决方案专注于出口和通道。如果要追踪移动资产而不是固定读写器,请阅读实时室内资产追踪。

让数据落到该在的平台上。

Spatial Map 把电子表格、传感器数据流和 CAD 图纸融合成一张实时的 3D 场地视图 —— 无需安装,七天免费试用。

在线演示

继续阅读