物联网平台作为连接物理世界与数字世界的桥梁,正在重塑传统行业的运营模式。基于Ruoyi框架开发IoT平台的选择,本质上是在快速实现企业级功能与物联网专业能力之间的平衡。我在实际工业物联网项目实施中发现,传统企业数字化转型往往面临两个矛盾:业务系统需要快速上线,而物联网协议对接又需要深度定制。
Ruoyi作为国内广泛使用的开源快速开发框架,其RBAC权限体系、代码生成器和多租户支持等特性,能够节省至少40%的基础功能开发时间。而物联网场景特有的设备管理、数据采集、实时监控等需求,则需要在Ruoyi基础上进行架构扩展。这种组合方案特别适合中小型制造业企业的智能化改造项目,我曾用类似架构在6周内为一家汽配厂完成了从设备联网到生产看板的完整解决方案。
Ruoyi-Vue版本(前后端分离)是更合适IoT场景的选择。其优势在于:
在最近一个智慧农业项目中,我们基于Ruoyi-Vue的代码生成器,仅用3天就完成了温室大棚管理的基础CRUD功能,相比传统开发方式效率提升显著。
需要在标准Ruoyi架构上新增以下核心模块:
特别要注意的是设备鉴权模块的设计。我们采用改良的DTLS握手流程,在设备注册时生成唯一token,后续通信通过token+时间戳签名验证。这种方案在某水务项目中成功抵御了重放攻击。
在ruoyi-admin模块中新建iot-gateway子模块,核心处理流程如下:
java复制// Netty TCP服务端示例
public class ModbusServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ModbusRequest request = (ModbusRequest) msg;
// 协议解析
DeviceCommand command = ModbusParser.parse(request);
// 异步处理避免阻塞IO线程
commandExecutor.execute(() -> processCommand(ctx, command));
}
private void processCommand(ChannelHandlerContext ctx, DeviceCommand cmd) {
// 设备鉴权
if(!deviceAuthService.validate(cmd.getDeviceId(), cmd.getSign())){
ctx.writeAndFlush(ModbusError.ACCESS_DENIED);
return;
}
// 业务处理
Object result = commandDispatcher.dispatch(cmd);
ctx.writeAndFlush(ModbusResponse.success(result));
}
}
对于MQTT协议,需要在application.yml中增加配置:
yaml复制iot:
mqtt:
broker-url: tcp://127.0.0.1:1883
username: admin
password: 123456
client-id: iot-server
default-topic: device/upload
针对传感器数据高频写入的特点,采用分表策略:
sql复制-- TDengine超级表定义
CREATE STABLE IF NOT EXISTS sensor_data (
ts TIMESTAMP,
temperature FLOAT,
humidity FLOAT,
pressure FLOAT
) TAGS (
device_id BINARY(32),
region BINARY(20)
);
在Java中通过MyBatis拦截器实现自动分表:
java复制@Intercepts(@Signature(type= Executor.class, method="update",
args={MappedStatement.class,Object.class}))
public class IotTableInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) {
Object parameter = invocation.getArgs()[1];
if(parameter instanceof DeviceData) {
DeviceData data = (DeviceData)parameter;
String tableName = "sensor_" + data.getDeviceId().substring(0,8);
BoundSql boundSql = ((MappedStatement)invocation.getArgs()[0])
.getBoundSql(parameter);
String newSql = boundSql.getSql().replace("sensor_data", tableName);
resetSql(invocation, newSql);
}
return invocation.proceed();
}
}
在智慧园区项目中遇到的典型问题:由于网络抖动导致设备被误判离线。我们最终采用的解决方案组合:
核心检测逻辑:
java复制// 在设备心跳任务中
public void checkHeartbeat() {
deviceList.forEach(device -> {
long lastActive = redisTemplate.opsForValue()
.get("device:active:"+device.getId());
if(System.currentTimeMillis() - lastActive > 90000) {
// 先标记为疑似离线
deviceStatusService.markAsUnstable(device.getId());
// 30秒后再次检查
delayQueue.add(new OfflineCheckTask(device.getId()));
}
});
}
针对历史数据查询慢的问题,我们采用三级缓存策略:
查询时采用分级查询策略:
java复制public PageResult queryData(DataQuery query) {
// 第一级:查Redis
List<DeviceData> hotData = redisService.query(query);
if(hotData.size() >= query.getPageSize()) {
return wrapPageResult(hotData);
}
// 第二级:查ES
List<DeviceData> warmData = esService.query(query);
if(hotData.size() + warmData.size() >= query.getPageSize()) {
return mergeResults(hotData, warmData);
}
// 第三级:查TDengine
List<DeviceData> coldData = tdengineService.query(query);
return mergeAllResults(hotData, warmData, coldData);
}
在实际项目中,我们通常会根据客户需求扩展以下功能模块:
一个实用的技巧是使用Ruoyi的代码生成器生成基础CRUD代码后,再手动添加物联网特有逻辑。比如在设备管理模块中,除了常规的增删改查,还需要添加:
在最近一个智能楼宇项目中,我们通过这种混合开发模式,将交付周期缩短了35%。平台最终实现了2000+设备的并发接入,日均处理传感器数据超过200万条,95%的API响应时间在200ms以内