轻量物联网云平台
拼个 URL 就能读写数据 — 基于 VBMAN
cHttpServer构建的轻量级 HTTP 数据存储服务,让物联网设备数据上云变得极其简单。📎 来源地址:轻量物联网云平台 - 用户文档
项目概览
| 项目信息 | 详情 |
|---|---|
| 项目名称 | 轻量物联网云平台 |
| 作者 | 技术宅老白 |
| 核心模块 | VBMAN cHttpServer |
| 应用领域 | 物联网 / 智能硬件 / 数据采集 |
| 技术难度 | 进阶 |
| 更新日期 | 2026-06-12 |
适用场景
- 🌡️ 物联网传感器数据上传(温湿度、空气质量、水位等)
- 💡 设备远程控制(开关、调光、电机等)
- 📱 网页/小程序数据展示
- 🏠 智能家居数据中枢
- 🔧 项目原型快速验证
核心优势
| 特点 | 说明 |
|---|---|
| ⚡ 极速接入 | 无需 SDK,发个 HTTP 请求就能用,30秒跑通 |
| 💰 读不扣费 | 读操作全免费,只有写才扣次数 |
| 🌐 跨域友好 | 原生支持 CORS,前端直接调用 |
| 🔒 数据安全 | 每个 Key 独立存储空间,互不干扰 |
| 💾 持久存储 | 数据自动落盘,服务重启不丢失 |
VBMAN 技术实现
本项目核心基于 VBMAN cHttpServer 的以下能力:
1. 自定义路由映射
利用 VBMAN cHttpServer 的路由系统,将 /yun/w/{key}/{var}/{val}、/yun/r/{key}/{var} 等路径映射到业务处理类:
' === 注册业务类 ===
Dim HttpServer As New cHttpServer
With HttpServer
.Router.Reg "Yun", New bYunCloud ' 注册云平台业务类
.Router.AutoRoute = True ' 开启自动路由
.Start 800 ' 监听 800 端口
End With2. 业务处理类
' === bYunCloud.cls - 云平台核心业务 ===
' 写数据: /yun/w/{key}/{var}/{val}
Public Sub W(ctx As cHttpServerContext)
Dim sKey As String: sKey = ctx.Request.UrlParam(1)
Dim sVar As String: sVar = ctx.Request.UrlParam(2)
Dim sVal As String: sVal = ctx.Request.UrlParam(3)
' 验证 Key 合法性
If Not ValidateKey(sKey) Then
ctx.Response.Json "{""status"":""fail"",""msg"":""invalid key""}"
Exit Sub
End If
' 检查写次数
If GetWriteCount(sKey) <= 0 Then
ctx.Response.Json "{""status"":""fail"",""msg"":""no count""}"
Exit Sub
End If
' 存储数据并扣减次数
SaveData sKey, sVar, sVal
DeductCount sKey
ctx.Response.Json "{""status"":""ok"",""var"":""" & sVar & """,""val"":""" & sVal & """,""count"":" & GetWriteCount(sKey) & "}"
End Sub
' 读数据: /yun/r/{key}/{var}
Public Sub R(ctx As cHttpServerContext)
Dim sKey As String: sKey = ctx.Request.UrlParam(1)
Dim sVar As String: sVar = ctx.Request.UrlParam(2)
Dim sVal As String: sVal = ReadData(sKey, sVar)
If sVal = "" Then
ctx.Response.Json "{""status"":""notfound""}"
Else
ctx.Response.Json "{""status"":""ok"",""var"":""" & sVar & """,""val"":""" & sVal & """}"
End If
End Sub
' 查次数: /yun/q/{key}
Public Sub Q(ctx As cHttpServerContext)
Dim sKey As String: sKey = ctx.Request.UrlParam(1)
ctx.Response.Json "{""status"":""ok"",""count"":" & GetWriteCount(sKey) & "}"
End Sub3. CORS 跨域支持
VBMAN cHttpServer 原生支持 CORS 配置,前端可直接跨域调用:
With HttpServer
.Cors.AllowOrigin = "*" ' 允许所有来源
.Cors.AllowMethods = "GET" ' 仅允许 GET 方法
End WithAPI 接口说明
写数据
向云平台写入一个变量的值。
GET /yun/w/{key}/{var}/{val}| 参数 | 说明 | 示例 |
|---|---|---|
key | 32位授权Key | a1b2c3d4... |
var | 变量名(自定义) | temp、led_state |
val | 变量值(字符串) | 25.6、1、hello |
返回示例:
{
"status": "ok",
"var": "temp",
"val": "25.6",
"count": 999999
}读数据
从云平台读取一个变量的值。
GET /yun/r/{key}/{var}返回示例:
{
"status": "ok",
"var": "temp",
"val": "25.6"
}读操作不扣费
读操作完全免费,想读多少次就读多少次。
查剩余次数
查询 Key 还剩多少次写次数。
GET /yun/q/{key}返回示例:
{
"status": "ok",
"count": 999999
}错误状态
| status | 说明 |
|---|---|
ok | 成功 |
fail | 失败(Key无效、次数不足等) |
notfound | 变量不存在 |
多语言调用示例
浏览器 / 网页端 (fetch)
// 写数据
async function yunWrite(key, varName, value) {
const res = await fetch(
`http://你的服务器地址/yun/w/${key}/${varName}/${value}`,
);
return res.json();
}
// 读数据
async function yunRead(key, varName) {
const res = await fetch(`http://你的服务器地址/yun/r/${key}/${varName}`);
return res.json();
}
// 使用示例
yunWrite("你的Key", "temp", "25.6").then((data) => {
console.log("写入成功,剩余次数:" + data.count);
});
yunRead("你的Key", "temp").then((data) => {
console.log("温度是:" + data.val);
});JSONP 跨域方案
如果遇到跨域问题且 CORS 不可用,可使用路径式 JSONP(无需 ? 参数):
// JSONP 读数据
function yunReadJSONP(key, varName, callbackName) {
var script = document.createElement("script");
script.src =
"http://你的服务器地址/yun/r/" + key + "/" + varName + "/" + callbackName;
document.body.appendChild(script);
script.onload = function () {
document.body.removeChild(script);
};
}
// 定义全局回调函数
function handleTempData(data) {
console.log("温度是:" + data.val);
}
// 调用
yunReadJSONP("你的Key", "temp", "handleTempData");注意
路径式 JSONP 需要服务器端支持。如果不确定,请优先使用 fetch + CORS 方案。
ESP32 / Arduino
#include <HTTPClient.h>
// 写数据
void yunWrite(String key, String varName, String value) {
HTTPClient http;
String url = "http://你的服务器地址/yun/w/" + key + "/" + varName + "/" + value;
http.begin(url);
int httpCode = http.GET();
if (httpCode == 200) {
Serial.println("写入成功");
}
http.end();
}
// 读数据
String yunRead(String key, String varName) {
HTTPClient http;
String url = "http://你的服务器地址/yun/r/" + key + "/" + varName;
http.begin(url);
int httpCode = http.GET();
if (httpCode == 200) {
return http.getString();
}
return "";
}Python
import requests
BASE_URL = "http://你的服务器地址"
KEY = "你的32位Key"
# 写数据
r = requests.get(f"{BASE_URL}/yun/w/{KEY}/temp/25.6")
print(r.json())
# 读数据
r = requests.get(f"{BASE_URL}/yun/r/{KEY}/temp")
print(r.json())
# 查次数
r = requests.get(f"{BASE_URL}/yun/q/{KEY}")
print(r.json())cURL 命令行
# 写数据
curl "http://你的服务器地址/yun/w/你的Key/temp/25.6"
# 读数据
curl "http://你的服务器地址/yun/r/你的Key/temp"
# 查次数
curl "http://你的服务器地址/yun/q/你的Key"重要注意事项
禁止使用 QueryString
绝对不要在 URL 末尾加 ? 参数:
- ❌ 错误:
/yun/r/key/temp?_=123456 - ✅ 正确:
/yun/r/key/temp
平台不支持 ? 后的参数,加了会导致变量名识别错误,数据读不出来。
技术原因
该案例的开发者没有使用 VBMAN 的路由参数(Route Params)机制,而是自行实现了 URL 路径的分割解析(将 /yun/r/key/var 按 / 切割提取参数)。这种自定义解析方式只处理路径段,不处理 QueryString 部分。如果在 URL 后面加了 ?_=123456,自定义解析器会将 ?_=123456 误当作路径的一部分,导致变量名识别出错。
相比之下,VBMAN cHttpServer 提供了标准的路由参数功能(ctx.Request.UrlParam、ctx.Request.QueryString),可以正确区分路径参数和查询参数。如果你在自己的项目中使用 VBMAN 路由参数,则无需担心此问题。
变量名规则
- 变量名可用:字母、数字、下划线
_、减号- - 变量名区分大小写:
Temp和temp是两个不同的变量 - 建议不要用中文变量名
值的限制
- 值的长度建议控制在 1024 字符以内
- 支持中英文、数字、常见符号
- 特殊字符建议使用 URL 编码
数据持久化
- 数据自动保存,服务器重启不丢失
- 数据每 50 秒批量落盘,极端情况下(如突然断电)可能丢失最近 50 秒内的写入
资费说明
| 项目 | 价格 | 说明 |
|---|---|---|
| 读数据 | 免费 | 不限次数 |
| 写数据 | 10元 / 100万次 | 每次写扣1次 |
| 查询次数 | 免费 | 不限次数 |
充值方式: 联系管理员续费,次数到账后可在 /yun/q/{key} 接口查询到最新余额。
常见问题
Q: 忘记 Key 了怎么办?
联系管理员找回。
Q: 数据会被别人看到吗?
只要你的 Key 不泄露,别人就读不到你的数据。Key 相当于密码,请勿公开。
Q: 支持 HTTPS 吗?
目前仅支持 HTTP。如需要 HTTPS 可联系管理员配置,也可结合 VBMAN HttpServer 的 TLS 功能自行部署。
Q: 最多能存多少个变量?
每个 Key 下的变量数量没有限制。
Q: 数据会自动删除吗?
数据永久保存,除非主动覆盖或删除。
Q: 次数用完了会怎样?
写接口会返回失败状态,读和查询仍可正常使用。续费后自动恢复。
项目亮点总结
| 维度 | 亮点 |
|---|---|
| VBMAN 能力展示 | cHttpServer 路由系统 + CORS + JSON 响应 + 数据持久化 |
| 接入极简 | URL 即 API,零 SDK,30 秒跑通 |
| 跨平台调用 | 浏览器 / ESP32 / Arduino / Python / cURL 全覆盖 |
| 商业模式 | 读免费、写按次计费,数据即服务的轻量云 |