更新记录

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门槛

微信公众号

在这里插入图片描述

官方地址

店滴云官网 官方开源库 cms源码

开发者参与

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格式,它可以是任意格式,但必须拥有typedatatyep是服务器与你的约定,它将去使用你注册的事件驱动,也就是说,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 公众号带参数二维码

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

使用中有什么不明白的地方,就向插件作者提问吧~ 我要提问