更新记录
6.2(2024-10-19) 下载此版本
优化物联网设备通信
6.1(2024-10-05) 下载此版本
多版本合并修复
5.9(2024-10-05) 下载此版本
优化门锁添加
查看更多平台兼容性
Vue2 | Vue3 |
---|---|
√ | × |
App | 快应用 | 微信小程序 | 支付宝小程序 | 百度小程序 | 字节小程序 | QQ小程序 |
---|---|---|---|---|---|---|
app-vue app-nvue | √ | √ | √ | √ | √ | √ |
钉钉小程序 | 快手小程序 | 飞书小程序 | 京东小程序 |
---|---|---|---|
√ | √ | √ | √ |
H5-Safari | Android Browser | 微信浏览器(Android) | QQ浏览器(Android) | Chrome | IE | Edge | Firefox | PC-Safari |
---|---|---|---|---|---|---|---|---|
√ | √ | √ | √ | √ | √ | √ | √ | √ |
欢迎使用店滴 cms(ddiot)
店滴云,让经营场所,更智能。围绕茶室、酒店、健身房、公寓、出租房等经营性场所进行物联网改造。同时支持多种物联网通信协议,开放智能门锁,智能开关,智能手环的sdk供开发者使用。
重点重点重点
所有硬件页面都已写好,可直接使用,自己只需要写自己业务部分的,其他交给sdk
0门槛
微信公众号
官方地址
开发者参与
qq群
:789294254,点击可直接加入:点击链接加入群聊【店滴云物联网2群】:
特性
- 对websokect支持友好,支持心跳配置,事件重复监听,握手校验。
- 多种硬件支持,包含智能门锁,开关,插座,通电器,水表,电表
- 强大的请求库,基于luch-request,增加了token校验,刷新,数据签名算法的支持
- 硬件控制常用的组件封装,侧重物联网控制类组件封装
适用范围
使用对象:uniapp开发者
可适用终端:小程序、app、h5
通用功能介绍:
本处理能力可以使用任何后台框架和平台,不限制店滴云物联开源框架
1、满足http请求中全场景问题处理,包括了数据签名,token验证,token刷新,请求队列处理,动态头部,token刷新回调处理。
2、多能力支持,包含了多终端定位,消息弹窗,多终端微信支付,h5授权登录,app和微信小程序扫一扫,地址栏参数解析,文件上传,模态弹窗等多种组件化能力。
3、常用js方法封装,包含了数据规则验证,深度拷贝,获取元素大小及位置,校验微信环境,判断类型集合,格式化时间,验证是否字符串,验证是否是否数字,验证是否是Boolean,验证是否是函数,是否为null,是否undefined,是否对象,浮点数加法运算,浮点数乘法运算,随机数时间戳,数组随机洗牌算法,严格的身份证号码校验,将阿拉伯数字翻译成中文的大写数字等等
物联网能力介绍
1、智能开关,针对单开开关,双开开关,三开开关的指定路数的开与管远程操作控制
2、智能电表,远程购电,通电,断电,远程购电,用电量数据汇总。蓝牙购电,蓝牙通断电操作
计划支持
智能门锁和智能电表的操作sdk正在完善
环境准备:
main.js中引入
import ddiot from '@/uni_modules/ddiot-ui/js_sdk/index.js'
全局挂载
Vue.prototype.ddiot = ddiot
配置
Vue.use(ddiot, {
websoketConf:{
url: "",
heartRateType: '',
heartRate: ,
username: '',
password: '',
AppKey: '',
AppSecret: ''
},
// 请求相关的配置
http: {
successCode: 200,
apiConfig: {
'bloc_id': diandi.bloc_id,
'store_id': diandi.store_id,
'app_secret': '2',
'app_id': '1',
'baseUrl': diandi.baseUrl,
'siteUrl': diandi.siteUrl,
'uploadImgUrl': diandi.baseUrl + '/upload/images',
'imgBaseUrl': diandi.baseUrl + '/attachment/',
// 代理名称
'proxyName': diandi.baseUrl,
'tokenApi': '/wechat/basics/signup',
'refreshApi': '/user/refresh',
// 备用域名配置,至少配置一个,这边会自动设置baseUrl,至少传入一个域名,H5本地调试会自己代理到proxyName
'domain': diandi.baseUrl,
// 签名算法
signFunc: (res, app_id, app_secret) => {
console.log('签名算法', res, app_id, app_secret)
return Object.assign({
sign: 666
}, res)
},
// 动态头部参数
headerFunc: (config) => {
// if(config.url != '/wechat/basics/signup' && config.url != '/wechat/basics/payparameters' && config.url != '/wechat/qrcode/getqrcode'){
// // 从缓存中获取头部参数
// header = {
// 'bloc-id': uni.getStorageSync('bloc-id') || crabRequestConfig.bloc_id,
// 'store-id': uni.getStorageSync('store-id') || crabRequestConfig.store_id,
// }
// }
// if (crabRequestConfig.tokenApi && config.url !== crabRequestConfig.tokenApi) {
// const access_token = crabRequestConfig.getToken()
// access_token && (config.header['access-token'] = `${access_token}`)
// }
return {
'bloc-id': uni.getStorageSync('bloc-id') || diandi.bloc_id,
'store-id': uni.getStorageSync('store-id') || diandi.store_id,
'access-token': uni.getStorageSync('access_token') || ''
}
},
getToken: (config) => {
let accessToken = uni.getStorageSync('access_token');
return accessToken;
},
getRefToken: (config) => {
let refresh_token = uni.getStorageSync('refresh_token');
return refresh_token;
},
refTokenCallBack: (res) => {
// #ifdef MP-WEIXIN
uni.setStorageSync('fans', res.data.wxappFans);
// #endif
// #ifndef MP-WEIXIN
uni.setStorageSync('fans', res.data.wechatFans);
// #endif
uni.setStorageSync('nickname', res.data.member.nickname);
uni.setStorageSync('access_token', res.data.access_token);
uni.setStorageSync('refresh_token', res.data.refresh_token);
uni.setStorageSync('expiration_time', res.data.expiration_time);
uni.setStorageSync('member', res.data.member);
}
},
responseSuccessCallBack: (res, catchObj, query) => {
// console.log('请求触发1', res, catchObj, query);
if (res && res.code === 403) {
// console.log('请求触发1--403');
uni.removeStorageSync('access_token');
fui.toLogin(403)
}
}
}
})
请求示例
post请求
this.ddiot
.request('/diandi_integral/order/list', 'POST', {
page: that.query.page,
pageSize: that.query.pageSize
}, false)
.then(res => {
that.exchangeReList = res.data.list
}).catch(res => {
uni.showToast({
title: res.message,
icon: 'none'
})
})
get请求
this.ddiot.request('/diandi_integral/order/list', 'GET', {
page: that.query.page,
pageSize: that.query.pageSize
}, false)
.then(res => {
that.exchangeReList = res.data.list
}).catch(res => {
uni.showToast({
title: res.message,
icon: 'none'
})
})
请求需要签名
注:第四个参数代表是否需要签名
this.ddiot.request('/diandi_integral/order/list', 'GET', {
page: that.query.page,
pageSize: that.query.pageSize
}, true)
.then(res => {
that.exchangeReList = res.data.list
}).catch(res => {
uni.showToast({
title: res.message,
icon: 'none'
})
})
物联网websoket控制操作
服务器地址
wss://127.0.0.1:9501/
初始化使用
账户授权登录使用
this.ddiot.websocket.login({
username :'',
password :'',
})
this.ddiot.websocket.on('login_res', (message) => {
console.log('登录后', message.data);
})
第三方快捷使用
this.ddiot.websocket.auth({
member_id :res.data.userinfo.member.member_id,//第三方用户ID
platform_code :'malia',//第三方平台标识
})
this.ddiot.websocket.on('auth_res', (message) => {
console.log('授权后', message.data);
that.member = message.data.message.member
})
方法
on
on方法是一个为uni.socket注册自定义事件的方法,该事件将通过你服务器传回的数据触发,因此,你服务器数据返回的格式必须遵守约定。
this.ddiot.websocket.on('event', Function(data){
// .... 在此处理服务器发给你的邮件data
})
服务器返回的数据必须遵守该格式才能保证正常使用:
{type: 'event', data: {}}
data
未必是Object格式,它可以是任意格式,但必须拥有type
和data
,tyep
是服务器与你的约定,它将去使用你注册的事件驱动,也就是说,uni.socket是通过type
字段来进行触发你自定义的事件驱动的。
如果你的第三个参数为true
,那么uni.socket则会检查该事件驱动是否已被注册,如果未被注册,则将它进行注册,默认false
this.ddiot.websocket.on('event', Function, true);
off
撤销注册的事件驱动,在uni.socket中,强制每个页面退出、关闭时调用此方法,因为uni.socket无法处理移除页面存在时注册过的事件驱动从而导致的内存泄漏。
this.ddiot.websocket.off('event', handler);
此方法支持连续注销驱动。
this.ddiot.websocket.off('event', handler1)('event', handler2)('event', handler3);
例如:
export default {
methods: {
hello() {
...
}
},
onLoad() {
this.ddiot.websocket.on('hello', this.hello);
},
onUnload() {
// 监听页面卸载
// 页面退出,撤销hello,释放资源
this.ddiot.websocket.off('hello', this.hello);
}
}
removeEventByName
移除你自定义的事件,因为是危险操作,需要开发者进行二次提交
移除自定义事件包括任何给这个事件注册的驱动
this.ddiot.websocket.removeEventByName('event').then(commit => {
commit();
});
addBuffer
给缓存池添加数据
this.ddiot.websocket.addBuffer({type: 'event', data: {}})
getBuffer
获取缓存池
const buffer = await this.ddiot.websocket.getBuffer();
// or
this.ddiot.websocket.getBuffer().then(buffer => {
// ...处理你的缓存池
});
getState
获取连接状态0 表示连接中,1表示连接成功,2表示重连中,3表示失败
const state = await this.ddiot.websocket.getState();
// or
this.ddiot.websocket.getState().then(state => {
// ...处理你状态
});
killApp
结束心跳,心跳结束后,uni.socket除了心跳发送,在下一次发送心跳时间内,其它功能正常使用,需要后端进行处理
this.ddiot.websocket.killApp();
close
关闭与服务器的连接,注意,它不会触发error
事件
this.ddiot.websocket.close();
emit
给服务器发送消息
this.ddiot.websocket.emit('event', {msg: "hello world"});
关于心跳
uni.socket需向服务器定时发送一次心跳,其触发的事件为HEARTBEAT
,默认心率为60000ms,服务器可根据该事件进行处理,可修改配置进行修改触发事件heartRateType
:
new UniSocket({
url: "wss://127.0.0.1/",
heartRateType: "Your event name..."
});
关于心跳会触发两次的问题,因为uni.socket发送的时候会触发一次心跳事件,而接收到服务端心跳的时候也会触发一次心跳事件。
系统事件
虽然是系统事件,但它和你自定义的事件并无区别,只是uni.socket赋予了它们特别的使命
事件 | 描述 | 返回值描述 |
---|---|---|
error | 错误事件,当socket连接发生错误时会触发 | 错误描述 |
reconnectionerror | 重连过程中发生的错误 | 错误描述 |
connectioned | 连接成功时触发 | 无 |
* | 服务器给客户端发送任何消息时触发 | 客户端消息 |
** | 后端返回的数据格式违背与UniSocket的约定时触发 | 客户端消息 |
HEARTBARE | 每次向服务端发送一次心跳时触发 | uni.socket给你返回的垃圾消息 |
消息结构
json字符串
{
"type":"login",
"device": "watches",
"controller": "Index",
"action":"index",
"AppKey":"",
"param": {
"username": " ",
"password": " ",
"timestamp":" ",
"sign":" "
}
}
type 消息类型 登录:login,心跳:heart,设备操作: operation,默认为设备操作
device 设备标识,目前有 电源通断类:receptacle,智能开关:switchs,智能手表:watches
AppKey 项目AppKey,开放平台添加项目后获取
controller 设备操作的控制器名称
action 设备操作的方法
param 通信参数,除登录、心跳、刷新token外其余里面都需要进行签名,含有字段timestamp和sign
timestamp 时间戳,单位s
sign 签名,详见签名算法
心跳
{
"type":"heart",
"accessToken":"qaFpjmjOi7PRm2ww7Q3/VYQwcbXl7wJ34UuldmFaGuZS/+RW80oh72+ncAYac1C859xMxAIWjuo62eHUho9Hxs+RQLSG94P8Yamdh2tADdfTi5/6Ds3ChlJH13PhAP/qwCnsvEZm+cxxSOOkPxeIRI7gK79H+XULv0ka1mYbpDGjE7/3uvSBNYf1IpIBNW1sskFrTO0US2VoQcoDrycau2UxoARF9hUSad6cWw5hUYcbw7tIau71jrF86DXZzOF9s1h443xT/VA/D8k7T0i7khLrglwG47H6QvLR3MWrir/QiZkHNUIUwaH5pSusyBxcqOIE/RTbl7pkuLLPpnAOMWGezrWzycu/6X6D/8zt5JAGZk00BulZXCrU2uWVijO812uRF7cqWrn2mud+yhMJr+QYWYYLxCsNbr6052VlASZ3TGgOeSc/QLwX9n1NMIAoDSLONujJCz2nf+UF72HyFNV5p3skMJOl+LaK3qNhrsOuln/OJ1CYL6/YkW7/QNhlWEwi1E8byT146uPGhA90Nz6itRb734s5/h6JFkvT/e2fuuPPjEJRuN9wPr5skcSYWaTjbTZe8EB5uGoHX9SOPURZe4nX7Ukx5w51y+Mj7vPJEaAESYY5+yrb6CeZMG5Mhk1/WoawYWBdzavq1+aIUr759NhdYiOHLXYDDTcDLj0="
}
心跳周期设置为60s
登录
发送数据
{
"type":"login",
"AppKey":"Y1NZAM9WK8OSQJCX70NRBVG6AL4FJPUW",
"param": {
"username": "haode1",
"password": "12345678"
}
}
返回数据
{
"status":200,
"type":"login_res",
"message":"登录成功",
"data":{
"member":{
"member_id":6,
"username":"haode1",
"mobile":null,
"address":null,
"nickName":"",
"avatarUrl":"",
"gender":0,
"country":"",
"province":"",
"realname":null
},
"access_token":"qaFpjmjOi7PRm2ww7Q3/VYQwcbXl7wJ34UuldmFaGuZS/+RW80oh72+ncAYac1C859xMxAIWjuo62eHUho9Hxs+RQLSG94P8Yamdh2tADdfTi5/6Ds3ChlJH13PhAP/qwCnsvEZm+cxxSOOkPxeIRI7gK79H+XULv0ka1mYbpDGjE7/3uvSBNYf1IpIBNW1sskFrTO0US2VoQcoDrycau2UxoARF9hUSad6cWw5hUYcbw7tIau71jrF86DXZzOF9s1h443xT/VA/D8k7T0i7khLrglwG47H6QvLR3MWrir/QiZkHNUIUwaH5pSusyBxcqOIE/RTbl7pkuLLPpnAOMWGezrWzycu/6X6D/8zt5JAGZk00BulZXCrU2uWVijO812uRF7cqWrn2mud+yhMJr+QYWYYLxCsNbr6052VlASZ3TGgOeSc/QLwX9n1NMIAoDSLONujJCz2nf+UF72HyFNV5p3skMJOl+LaK3qNhrsOuln/OJ1CYL6/YkW7/QNhlWEwi1E8byT146uPGhA90Nz6itRb734s5/h6JFkvT/e2fuuPPjEJRuN9wPr5skcSYWaTjbTZe8EB5uGoHX9SOPURZe4nX7Ukx5w51y+Mj7vPJEaAESYY5+yrb6CeZMG5Mhk1/WoawYWBdzavq1+aIUr759NhdYiOHLXYDDTcDLj0=",
"refresh_token":"RseHhNxbD8lIja4gymJ6"
}
}
其中的data为其他发送数据的accessToken
刷新token
发送数据
{
"type":"flushToken",
"param": {
"refresh_token":"v9pEimnTMN7ytx02fO8gZ6GHjushYaoqkVBUPzArd5bL4wQ3KR"
}
}
响应数据
{
"status":200,
"type":"flushToken_res",
"message":"刷新token成功",
"data":{
"member":{
"member_id":6,
"username":"haode1",
"mobile":null,
"address":null,
"nickName":"",
"avatarUrl":"",
"gender":0,
"country":"",
"province":"",
"realname":null
},
"access_token":"qaFpjmjOi7PRm2ww7Q3/VYQwcbXl7wJ34UuldmFaGuZS/+RW80oh72+ncAYac1C8fV2KcBk/a0+rvBWekNEbNs+RQLSG94P8Yamdh2tADdd/mSlFTj+EmjfW8HuIPRen0eJjPHpfDOjur9Y7uMkbCo7gK79H+XULv0ka1mYbpDFrtp6kjplISZdrGmdhlpLKpSEH0il3FNpWAc6kQ0/bhbwvsjNQicVY06HLVO0BOfLlghltt3zhx00bakpFKw0uNkfyhoSv+KK8UvP6aY5+/xLrglwG47H6QvLR3MWrir/QiZkHNUIUwaH5pSusyBxcK8w2eul+CGxEUv1mbiHtak4puzMkB1Tu86tSqSmgjlGOr+RuA2y508wmJdBek4ZKijLe1fKnFvGxLFSaAFj/PA5q+ypvWIRDYM3AmI3C1Nme9FY9IzZLfVXjd5A3vrAqPM/PdfTc4PfUo9rerMSULN6r8TpB2pKVm9NM6H7VFYmGQUFd9gY0s6Yjax7zjlWjQHLST1LvqR2fl6iuZw0pZgt1bSTdPvUpK4cPxPAlJGRgaLdas7Tz9tV0eUHaA+v/dX7ZjujHpukR8m4n3NW/ZDoA0yuQrshXmsUDEcRkXaKeHOd5kC1QduAvhv/qFEdRvhgI0YkwxYsapw0wAysJpg/dz4CGjAlQS3+5C9EHiTILa+IcI8DGVvNmMxv27XP7s3bBCz2uHbM3XRiJ20rTMH2J79gM7GSvlgp6CizLiN3ww++oFnMvaTl/VkapRm2mR7Hhywt2IcXFq9HN4yY1UnPS3e776wDOGIURLDPDSSSRS+FGDt1Gomty1SAAPEGzsQgqXPqp2aX87fuZXZL22RsSzXsc9BFbu2T+gVzX39d27xX6IPvI4B5m5wmnq9ZVN863w1ep11lYtcOkA/3Pu2RQBiZqCYBGgvhG1qoJRcq1eaB4YByIg9ouqGMjuTGegBVhzr+Mm8uNrzhB4QB1I8yHezGps5qI9oQsbVzNwTm+Hn625WOML9RUi4cIgK1s",
"refresh_token":"v9pEimnTMN7ytx02fO8gZ6GHjushYaoqkVBUPzArd5bL4wQ3KR"
}
}
操作数据格式/计量插座或通断器操作
{
"type":"operation",
"device":"receptacle",
"AppKey":"Y1NZAM9WK8OSQJCX70NRBVG6AL4FJPUW",
"accessToken":"qaFpjmjOi7PRm2ww7Q3/VYQwcbXl7wJ34UuldmFaGuZS/+RW80oh72+ncAYac1C8WI2w3Pg3CSSAipBavDunV8+RQLSG94P8Yamdh2tADdfRguneSpi8/tTSWBNxVa7rU1X2QYbge7vrpBYRjOKtDo7gK79H+XULv0ka1mYbpDGF4czd9WPN1BHPoH5q31cFyJdOT8U/kFWwuBcPXICI9wuYtvLPCGdcO4qgP2m98uVm7lY3GNfo9qb2dn/m/JQMB4OYsNSVI1jWJaCvzCgN1xLrglwG47H6QvLR3MWrir/QiZkHNUIUwaH5pSusyBxcqOIE/RTbl7pkuLLPpnAOMWGezrWzycu/6X6D/8zt5JAGZk00BulZXCrU2uWVijO812uRF7cqWrn2mud+yhMJr+QYWYYLxCsNbr6052VlASZ3TGgOeSc/QLwX9n1NMIAoDSLONujJCz2nf+UF72HyFNV5p3skMJOl+LaK3qNhrsOuln/OJ1CYL6/YkW7/QNhlWEwi1E8byT146uPGhA90Nz6itRb734s5/h6JFkvT/e2fuuPPjEJRuN9wPr5skcSYWaTjbTZe8EB5uGoHX9SOPe7U4OKaKYHt6yeKoo8Ys6LvDWyRLpgp3wTIPlokwSUGcI4O0N676UcL0amjzjOXLaRqmbEBqhnBjr+KVoBhPt0=",
"controller": "Index",
"action":"index",
"param": {
"device_id": 1,
"behavior": "open",
"timestamp":"1221212121",
"sign":"2332323232"
}
}
零火双开开关控制
{
"type": "operation",
"device": "receptacle",
"AppKey":"",
"accessToken": "qaFpjmjOi7PRm2ww7Q3/VYQwcbXl7wJ34UuldmFaGuZS/+RW80oh72+ncAYac1C8WI2w3Pg3CSSAipBavDunV8+RQLSG94P8Yamdh2tADdfRguneSpi8/tTSWBNxVa7rU1X2QYbge7vrpBYRjOKtDo7gK79H+XULv0ka1mYbpDGF4czd9WPN1BHPoH5q31cFyJdOT8U/kFWwuBcPXICI9wuYtvLPCGdcO4qgP2m98uVm7lY3GNfo9qb2dn/m/JQMB4OYsNSVI1jWJaCvzCgN1xLrglwG47H6QvLR3MWrir/QiZkHNUIUwaH5pSusyBxcqOIE/RTbl7pkuLLPpnAOMWGezrWzycu/6X6D/8zt5JAGZk00BulZXCrU2uWVijO812uRF7cqWrn2mud+yhMJr+QYWYYLxCsNbr6052VlASZ3TGgOeSc/QLwX9n1NMIAoDSLONujJCz2nf+UF72HyFNV5p3skMJOl+LaK3qNhrsOuln/OJ1CYL6/YkW7/QNhlWEwi1E8byT146uPGhA90Nz6itRb734s5/h6JFkvT/e2fuuPPjEJRuN9wPr5skcSYWaTjbTZe8EB5uGoHX9SOPe7U4OKaKYHt6yeKoo8Ys6LvDWyRLpgp3wTIPlokwSUGcI4O0N676UcL0amjzjOXLaRqmbEBqhnBjr+KVoBhPt0=",
"controller": "switchDev",
"action":"index",
"param": {
"device_id": 1,
"behavior": "shut",
"switch_code":"1,2",
"timestamp":"1221212121",
"sign":"2332323232"
}
}
系统基础接口类库
获取全国城市列表
方法 mapdistanceCitylist
使用示例:
this.ddiot.mapdistanceCitylist().then(res=>{
console.log('mapdistanceCitylist',res)
}).catch(err=>{
console.log('ststs-err',err)
})
基础接口
storeinfo 商户信息
storecate 商户分类
storelist 商户列表
storedetailinfo 商户详情
addresslists 地址列表
用户接口
userlogin 用户登录
usersignup 用户注册
userregister 用户注册
userrepassword 修改密码
useruserinfo 用户信息
useredituserinfo 编辑用户资料
usersendcode 发送验证码
userforgetpass 忘记密码
userfeedback
userbindmobile 绑定手机号
userrefresh 刷新token
userrelations
usersmsconf 用户短信配置
uploadimages 上传图片
uploadbaseimg 上传base64图片
小程序接口
wechatbasics 小程序注册
wechatpayparameters 微信支付
wechatsendmsg 小程序发送消息
wechatqrcode 小程序带参数二维码
wechatdecrypt 小程序解密信息
公众号接口
officialaccountsignup 公众号注册
officialaccountauth 公众号授权
officialaccountuserinfo 公众号用户信息
officialaccountpayparameters h5支付
officialaccountbasics app支付
officialaccountqrcode 公众号带参数二维码