跳到主要内容

一般情况下,您不用修改三三平台的核心组件,你只需要把三三当作物联网底座或中台,利用三三平台提供的灵活而强大的协议、丰富的 API、强大的应用管理机制,去构建您的物联网应用。

如果您一定要修改核心组件,三三平台采用微服务架构实现了各组件的完全解耦,您可以基于三三已有的组件修改,或用自己编写并替换三三平台的某个组件实现您的需求。

三三的开发遵循一系列规范和协议,包括 API 接口规范、 MQTT 接口、目录规范、配置文件规范。另外,我们还提供了方便您开发服务的核心库。

API 接口规范

请求响应

主要介绍API的请求结构

1、请求URI {URI-scheme}://{Endpoint}/api/{micro-server}/{resource-path} 例:http://ssiot.cc:9000/api/device/find http://ssiot.cc:9000/api/alarm/find

参数说明
URI-scheme请求协议,http/https
Endpoint提供REST服务的端点域名/ip+端口,三三云平台为 ssiot.cc:9000
micro-server微服务节点名称,参考前面章节的系统模块说明(少量接口特例,具体以接口文档为准)
resource-path资源路径,按实际业务访问不同,如对配置的查列表/详情、增、改、删,定义为config/find、get、add、modify、remove

2、请求方法

方法说明
GET查询,请求服务器或返回特定资源
POST增删改,修改或删除特定资源,或执行特殊操作如设备控制下发

3、响应内容

{
"code": 200,
"message": "操作成功",
"result": {},
"success": true,
"timestamp": 1684823798374
}
字段说明
code错误码
message成功/失败消息
result响应结果,json对象,可为空,也可包含分页信息
success成功/失败标志
timestamp响应时间戳

错误码

错误码说明
200成功
0自定义异常
201操作失败
202请求参数错误
203用户名不正确
204密码不正确
205添加失败
206更新失败
207删除失败
208修改失败
209查找失败
210上传失败
211不被识别的手机号
300创建进程失败
301进程启动失败
302进程重复
303进程不存在
304进程删除失败
305缺少进程文件或目录

API 接口清单

三三 API 接口文档

MQTT 接口

业务主题

主题说明
/san/data/handle已处理消息数据流转
/san/event/device/login、/san/event/device/logout上线触发业务
/san/event/device/delete设备操作触发业务
/san/event/device/add设备操作触发业务
/san/alarm/notify告警通知主题
/san/data/forward数据mq转发主题

三三物联协议

详见三三物联协议

SDK

我们提供了 ssiot-core, 高效便捷的开发框架ssiot-core,方便开发者完成集成开发

项目结构

下载源代码, 除了 ui 目录外,其它目录均为后端模块目录

# Gitee仓库

git clone https://gitee.com/sansaniot/ssiot.git

以下以 device 模块为例说明项目目录结果

./
├─cmd # 服务命令
│ └─system # 系统服务模块,如系统初始化
├─common # 通用模块
│ ├─constant # 常量
│ ├─database # 数据库通用业务,如数据初始化、自动生成表
│ ├─dto # 业务DTO数据定义
│ ├─enums # 系统枚举
│ ├─middleware # 应用中间件
│ │ ├─jwt # JWT 鉴权中间
│ │ ├─log # Log中间件
│ │ └─secure # Secure认证中间
│ └─utils # Util工具包
├─config # 配置管理
│ └─settings.yml # 统一配置文件(微服务端口、数据库、MQTT、Redis等)
├─internal # 业务应用模块
│ ├─device # 模块入口
│ │ ├─router # HTTP router
│ │ ├─apis # 业务 API逻辑
│ │ ├─models # 业务model(数据库模型处理,完成前端页面与数据库接口对象转换)
│ │ ├─service # 业务Service,对接apis,调用各models进行业务整合,返回业务数据
│ │ ├─ws # WebSocket API
| └─start.go # 模块启动入口
| ├─data # 模块数据处理
├─ Makefile # Makefile文件
├─ README.md # README 介绍
├─ main.go # 程序入口

配置文件

service:                                   #微服务地址
sansan: #微服务管理服务
port: 9500
ipdb: ./config/ip2region.xdb #ip解析数据库
admin: #权限服务
port: 9510
filepath: ./data/assets #资源文件路径
device: #设备管理服务
port: 9520
alarm: #告警服务
port: 9530
notify: #通知服务
port: 9540
forward: #转发服务
port: 9550
ssiot: #公共配置
http: #http应用访问地址
host: 0.0.0.0
logger: #日志配置
path: ./log
stdout: ''
level: trace
enableddb: true #系统日志记录
mqtt: #后台mqtt服务地址
host: 127.0.0.1
port: 9010
user:
passwd:
timeout: 3
database: #数据库连接
driver: postgres
source: host=127.0.0.1 user=postgres password=123456 dbname=sansaniot port=9020 sslmode=disable TimeZone=Asia/Shanghai
cache: #缓存中间件
redis: #redis
addr: 127.0.0.1:9030
password: '123456'
db: 0
jwt: #接口鉴权jwt配置
secret: ssiot2023
timeout: 3600

代码示例

internal/device/start.go

import (
"gitee.com/sansaniot/ssiot-core/facade/env"
"gitee.com/sansaniot/ssiot-core/facade/httpserver"
"gitee.com/sansaniot/ssiot-core/httpmvc"
"gitee.com/sansaniot/ssiot-core/httpmvc/api"
"github.com/shafreeck/cortana"
...
)
func Start() error {
// 启动参数格式自定义, 如./device -c config/settings.yml
args := struct {
CfgFile string `cortana:"--config, -c, , config file"`
}{}
cortana.Parse(&args)
if args.CfgFile != "" {
constant.ConfigFile = args.CfgFile
}
// 如有需要,向内核注册自己需要的中间件
// 限流
httpserver.RegisterMiddlewareFunction(secure.Sentinel())
// 自动增加requestId
httpserver.RegisterMiddlewareFunction(secure.RequestId(httpmvc.TrafficKey))
// 获取上下文提供的日志
httpserver.RegisterMiddlewareFunction(api.SetRequestLogger)
// 请求日志记录到文件
//httpserver.RegisterMiddlewareFunction(log.LoggerToFile())
// 自定义错误处理
httpserver.RegisterMiddlewareFunction(log.CustomError)
// NoCache is a middleware function that appends headers
httpserver.RegisterMiddlewareFunction(secure.NoCache)
// 跨域处理
httpserver.RegisterMiddlewareFunction(secure.Options)
// Secure is a middleware function that appends security
httpserver.RegisterMiddlewareFunction(secure.Secure)

// 必须,初始化引擎
httpserver.InitEngine(constant.ConfigFile)
env.DefaultConfig.Http.Port = env.ConfigOperator.GetInt64("service.device.port")

// 启动系统业务
system.InitSystemBiz()

// 可选,初始化JWT验证方法组
jwtMiddleware, _ := jwt.AuthInit()
// 必须,向内核注册自己的业务模块路由,如不使用中间件,则使用InitRouters方法
httpserver.InitAuthRouters(router.RouterCheckRole, jwtMiddleware)
httpserver.InitAuthRouters(ruleRouter.RuleRouters, jwtMiddleware)
httpserver.InitRouters(router.RouterNoCheckRole)
// 启动HTTP服务器
_ = httpserver.Run()

return nil
}

internal/device/router/device.go

import (
jwt "gitee.com/sansaniot/ssiot-core/httpmvc/jwtauth"
"github.com/gin-gonic/gin"

"ssdevice/internal/device/apis"
)
func init() {
RouterCheckRole = append(RouterCheckRole, registerDeviceRouter)
}

// v1 注册系统路由, authMiddleware jwt鉴权
func registerDeviceRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
api := apis.Device{}
// 设备
r := v1.Group("/api/device").Use(authMiddleware.MiddlewareFuncWithOutValidate())
{
r.GET("/find", api.FindList)
...
}

internal/device/apis/device.go

import (
"gitee.com/sansaniot/ssiot-core/httpmvc/api"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"

"ssdevice/common/enums"
"ssdevice/internal/device/models"
"ssdevice/internal/device/models/command"
"ssdevice/internal/device/models/query"
"ssdevice/internal/device/service"
)
// 添加设备
func (e Device) AddDevice(c *gin.Context) {
// 请求参数
req := command.DeviceInsertReq{}
// 业务service
s := &service.Device{}
// 上下文
err := e.MakeContext(c).
MakeOrm().
Bind(&req, binding.JSON).
MakeService(&s.Service).
Errors
if err != nil {
e.Logger.Error(err)
e.Fail(0, err.Error())
return
}
// service注入实体
s.SetAllModel()
// 用户信息
req.LoadUser(c)
// 执行
var result models.SysDev
if err, result = s.AddDevice(&req); err != nil {
e.Logger.Error(err)
e.Fail(0, err.Error())
return
}
// 返回
e.Data(result)
}