java写微信小程序答辩问题_自己写微信小程序MQTT模拟器

本文介绍了如何使用Java编写微信小程序MQTT模拟器,包括创建新项目、下载支持MQTT的js库、改写小程序代码,以及通过阿里云物联网平台进行测试和设备操作,如上线、上报数据、告警、订阅主题和下线等。
摘要由CSDN通过智能技术生成

自己写微信小程序MQTT模拟器

陈拓 chentuo@ms.xab.ac.cn 2019.10.6/2019.10.11

1. MQTT模拟器体验

在自己写MQTT模拟器之前先从网上安装一个现成的体验一下,这可以先看看我之前写的文章《微信小程序MQTT模拟器阿里云物联网平台测试》,在下面的网址可以找到这篇文章:

https://mp.csdn.net/postedit/102216865

https://zhuanlan.zhihu.com/p/84810734

下面我们自己写一个MQTT模拟器实现这些功能。

2. 创建新项目

2.1 打开微信开发者工具,新建项目

ff2b9f2887e14f3e56211754031881d3.png

填写你的AppID,新建。

在默认情况下,项目路径为C:UsersAdministratorWeChatProjects。

2.2 准备图片

fe7adb17495b6790716905d18883f1ae.png

放在pages下的images目录中。

3d6f23670fa35f38343081ea88d62bbc.png

2.3 改写系统生成的代码

2.3.1 改写app.json

{

"pages": [

"pages/index/index",

"pages/logs/logs"

],

"window": {

"backgroundTextStyle": "light",

"navigationBarBackgroundColor": "#fff",

"navigationBarTitleText": "我的MQTT模拟器",

"navigationBarTextStyle": "black"

},

"sitemapLocation": "sitemap.json"

}

只改“我的MQTT模拟器”这里。

2.3.2 下载支持MQTT协议的js库和支持sha1加密的库

  • 下载mqtt.js

https://github.com/mqttjs/MQTT.js

或者下载mqtt.min.js

https://unpkg.com/mqtt@3.0.0/dist/mqtt.min.js

mqtt.min.js小一些。

  • 下载hex_hmac_sha1.js

https://github.com/xihu-fm/aliyun-iot-client-sdk/tree/master/lib

两个js文件都放在utils目录下:

6bf9b41ed7fd6f7bc1037acb043d6c9f.png

2.3.3 改写index.wxml

<!--index.wxml-->

<view>

<view class="main-center">

<image src="{{imageUrl}}" class="ledinfo-avatar"></image>

<view class="ledinfo-values">

<text>湿度:</text><text>{{humidity}}</text><text>%</text>

<text>温度:</text><text>{{temperature}}</text><text>℃</text>

</view>

</view>

<text class='subheading'>设备身份三元组</text>

<view style='margin-top: 20rpx;'>

<view class='connect-info background-white'>

<text class='text'>productKey:</text>

<input class='input' name='productKey' placeholder='替换'

bindinput='productKeyInput'/>

</view>

<view class='connect-info background-white'>

<text class='text'>deviceName:</text>

<input class='input' name='deviceName' placeholder='替换'

bindinput='deviceNameInput'/>

</view>

<view class='connect-info background-white'>

<text class='text'>deviceSecret:</text>

<input class='input' name='deviceSecret' placeholder='替换'

bindinput='deviceSecretInput'/>

</view>

</view>

<view class="buttons">

<view class="button-container" bindtap='online'>

<text class="button">设备上线</text>

</view>

<view class="button-container" bindtap='publish'>

<text class="button">上报数据</text>

</view>

<view class="button-container" bindtap='event'>

<text class="button">告 警</text>

</view>

<view class="button-container" bindtap='service'>

<text class="button">订阅主题</text>

</view>

<view class="button-container" bindtap='offline'>

<text class="button">设备下线</text>

</view>

</view>

<text class='subheading'>设备日志</text>

<view style='margin-top: 20rpx;'>

<view class='deviceState background-white'>

<text class='text'>{{deviceState}}</text>

</view>

</view>

<view class='devicelog'>

<text>{{deviceLog}}</text>

</view>

</view>

2.3.4 改写index.wxss

/**index.wxss**/

page {

background-color: rgb(240, 240, 240);

font-size: 26rpx;

}

.main-center {

display: flex;

flex-direction: column;

align-items: center;

}

.connect-info {

display: flex;

flex-direction: row;

margin-top: 1rpx;

height: 60rpx;

}

.background-white {

background-color: #FFF;

}

.buttons {

display: flex;

flex-direction: row;

justify-content: space-between;

align-items:center;

margin-left: 10rpx;

margin-right: 10rpx;

margin-top: 30rpx;

margin-bottom: 30rpx;

}

.button {

line-height: 60rpx;

}

.button-container {

margin-top: 0px;

border: 1px solid #aaa;

width: 140rpx;

height: 60rpx;

border-radius: 5px;

text-align: center;

}

.ledinfo-values {

color: #92ADF0;

margin: 20rpx;

}

.ledinfo-avatar {

width: 128rpx;

height: 128rpx;

margin: 20rpx;

}

.subheading {

color: rgb(128, 128, 128);

margin: 20rpx;

}

.text {

width: 220rpx;

height: 30rpx;

margin-left: 20rpx;

margin-top: 10rpx;

}

.input {

width: 100%;

height: 30rpx;

margin-left: 20rpx;

margin-top: 10rpx;

color: rgb(128, 128, 128);

}

.deviceState {

color: #1d953f;

}

.devicelog {

margin-top: 20rpx;

word-break:break-all;

color: #426ab3;

}

2.3.5 改写index.js

//index.js

// 设备身份三元组+区域

const deviceConfig = {

productKey: "替换",

deviceName: "替换",

deviceSecret: "替换",

regionId: "cn-shanghai"

};

function getPostData() {

const payloadJson = {

id: Date.now(),

params: {

temperature: Math.floor((Math.random() * 20) + 10),

humidity: Math.floor((Math.random() * 20) + 60)

},

method: "thing.event.property.post"

}

return JSON.stringify(payloadJson);

}

function getAlarmPostData() {

const payloadJson = {

id: Date.now(),

params: {

temperature: Math.floor((Math.random() * 20) + 10)

},

method: "thing.event.hotAlarm.post"

}

return JSON.stringify(payloadJson);

}

const util = require('../../utils/util.js')

var mqtt = require('../../utils/mqtt.min.js')

const crypto = require('../../utils/hex_hmac_sha1.js')

var client

Page({

data: {

temperature: '0',

humidity: '0',

imageUrl: '../images/iLED1.png',

deviceLog: '',

deviceState: ''

},

// 设备身份三元组输入框事件处理函数

productKeyInput: function (e) {

deviceConfig.productKey = e.detail.value

},

deviceNameInput: function (e) {

deviceConfig.deviceName = e.detail.value

},

deviceSecretInput: function (e) {

deviceConfig.deviceSecret = e.detail.value

},

// 设备上线 按钮点击事件

online: function (e) {

this.doConnect()

},

doConnect() {

var that = this;

const options = this.initMqttOptions(deviceConfig);

console.log(options)

client = mqtt.connect('wxs://productKey.iot-as-mqtt.cn-shanghai.aliyuncs.com', options)

client.on('connect', function () {

console.log('连接服务器成功')

let dateTime = util.formatTime(new Date());

that.setData({

deviceState: dateTime + ' Connect Success!'

})

})

},

//IoT平台mqtt连接参数初始化

initMqttOptions(deviceConfig) {

const params = {

productKey: deviceConfig.productKey,

deviceName: deviceConfig.deviceName,

timestamp: Date.now(),

clientId: Math.random().toString(36).substr(2),

}

//CONNECT参数

const options = {

keepalive: 60, //60s

clean: true, //cleanSession不保持持久会话

protocolVersion: 4 //MQTT v3.1.1

}

//1.生成clientId,username,password

options.password = this.signHmacSha1(params, deviceConfig.deviceSecret);

options.clientId = `${params.clientId}|securemode=2,signmethod=hmacsha1,timestamp=${params.timestamp}|`;

options.username = `${params.deviceName}&${params.productKey}`;

return options;

},

/*

生成基于HmacSha1的password

参考文档:https://help.aliyun.com/document_detail/73742.html?#h2-url-1

*/

signHmacSha1(params, deviceSecret) {

let keys = Object.keys(params).sort();

// 按字典序排序

keys = keys.sort();

const list = [];

keys.map((key) => {

list.push(`${key}${params[key]}`);

});

const contentStr = list.join('');

return crypto.hex_hmac_sha1(deviceSecret, contentStr);

},

// 上报数据 按钮点击事件

publish: function (e) {

var that = this;

let topic = `/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/event/property/post`;

// 注意用`符号,不是' !!!!!

let JSONdata = getPostData()

console.log("===postDatan topic=" + topic)

console.log("payload=" + JSONdata)

client.publish(topic, JSONdata)

that.setData({

deviceLog: 'topic=' + topic + 'n' + 'payload=' + JSONdata

})

},

// 告警 按钮点击事件

event: function (e) {

var that = this;

let topic_alarm = `/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/event/hotAlarm/post`;

let JSONdata = getAlarmPostData()

console.log("===postDatan topic=" + topic_alarm)

console.log("payload=" + JSONdata)

client.publish(topic_alarm, JSONdata)

that.setData({

deviceLog: 'topic=' + topic_alarm + 'n' + 'payload=' + JSONdata

})

},

// 订阅主题 按钮点击事件

service: function (e) {

var that = this;

that.setData({

deviceLog: '接收消息监听'

})

//接收消息监听

let topic = `/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/event/property/post`;

client.on('message', function (topic, message) {

// message is Buffer

let messageStr = message.toString()

console.log('收到消息:' + messageStr)

that.setData({

deviceLog: '收到消息:n' + messageStr

})

if (messageStr.indexOf('on') > 0) {

that.setData({

imageUrl: '../images/iLED2.png',

})

}

if (messageStr.indexOf('off') > 0) {

that.setData({

imageUrl: '../images/iLED1.png',

})

}

if (messageStr.indexOf('blue') > 0) {

that.setData({

imageUrl: '../images/iLED3.png',

})

}

if (messageStr.indexOf('green') > 0) {

that.setData({

imageUrl: '../images/iLED4.png',

})

}

})

},

// 设备下线 按钮点击事件

offline: function () {

var that = this;

client.end() // 关闭连接

console.log('服务器连接断开')

let dateTime = util.formatTime(new Date());

that.setData({

deviceState: dateTime + ' Disconnect!'

})

},

onLoad: function () {

var that = this

setInterval(function () {

that.setData({

temperature: Math.floor((Math.random() * 20) + 10),

humidity: Math.floor((Math.random() * 20) + 60)

})

}, 3000)

},

})

3. 注册阿里云账号

注册阿里云账号,获得三元组:PublicKey、DeviceName、DeviceSecret。

见《微信小程序MQTT模拟器阿里云物联网平台测试》一文。

https://mp.csdn.net/postedit/102216865

https://zhuanlan.zhihu.com/p/84810734

4. 微信小程序测试

4.1 打开MQTT测试平台

  • 进入阿里云产品官网https://aliyun.com/product/iot

8dfff95a827e7066c61d75ce6fbe9c46.png
  • 登录,点击“控制台”,选择物联网平台

cc36fa38727b5afcdb76e863eeedcef5.png

4.2 用微信小程序模拟器测试

在微信开发者工具中打开模拟器。

4.2.1 设备上线

  • 输入设备身份三元组,点击“设备上线”

804b6eeab142ff2cfa1b31f86c05969e.png
  • 回到物联网平台

点击F5刷新设备列表,可以看到设备状态已经是在线,查看小程序设备日志和设备列表页面中的最后上线时间,用模拟器测试慢一秒,用真机测试时间一致。

5248de644f0533fd8f95fb7a5de5df73.png

如果连接参数不正确,或遇到其他连接问题,可以在开发工具的Console中查看,例如productKey输入错误:

b4c13d9d551b30f4213ae6772c5834a8.png

4.2.2 上报数据

  • 回到微信开发者开发工具

在设备上线时,点击“上报数据”,我们看到MQTT模拟器上报了当前湿度温度值。

59a2c954a4d76aca7fb08b966fa6cdfb.png

上报的湿度73%,温度29℃。

  • 回到物联网平台,在设备详情的运行状态看设备上报的数据

6d79bc2121a0d8305de000147608cea5.png

和MQTT模拟器上报的数据一致。

4.2.3 告警

  • 在小程序界面

在设备上线时,点击“告警”,就会生成一条事件告警,并上报当前的温度。

991abfcd7a2aa095d8f552e9f4e62a1f.png
  • 在物联网平台控制台“设备详情”-“事件管理”中查看

fbe22165da2f319f6b55214bf1786ddb.png

可以看到“温度过高报警”。

在实际情况下,报警温度的阈值在客户端设定,当温度超过阈值时发送报警,这里只是演示报警功能,不用在意温度值的大小。

4.2.4 订阅主题

  • 在小程序界面,在设备上线时,点击“订阅主题”:

17faecec643686156079de1aa9e8ba56.png

等待接收消息。

  • 在物联网平台控制台“设备管理 > 设备详情”点击“在线调试”。

1c86f96a42bb7f6c8f738a056051323a.png
  • 转到“在线调试”页面

0be5b1bf76999de2284d65ad5d3d64f0.png

1) 选择设备

2) 选择“调试真实设备”选项卡

3) 选择“服务调用”

4) 选中功能“开灯(switch)”

5) 输入参数{"status":"on"}

6) 点击“发送指令”

查看实时日志:

636d6da1534ea803e787b3b543a3098f.png
  • 回到小程序界面

1845dd7b82fb23755ce882200496d25d.png

看,灯亮了!

还可以在物联网平台上:

1) 发送{"status":"off"},关灯

2) 发送{"status":"blue"},灯发蓝光

3) 发送{"status":" green"},灯发绿光

4.2.5 设备下线

  • 在小程序界面,点击“设备下线”

b59617cedce593df7cb6bfb1bf6e01c2.png
  • 在控制台“设备列表”中可以看到设备已经离线

62439efd3561695c96a7f5be28182aeb.png

4.3 用真机测试

见《微信小程序MQTT模拟器阿里云物联网平台测试》一文。

https://mp.csdn.net/postedit/102216865

https://zhuanlan.zhihu.com/p/84810734

5. 源代码

https://github.com/chentuo2000/MyMQTTsimulator

参考资料

  1. 实例:使用MQTT进行交互https://www.jianshu.com/p/b452e2cee0d6
  2. 微信小程序布局display flex布局介绍https://blog.csdn.net/sinat_17775997/article/details/61428601
  3. 微信小程序以 websocket 连接阿里云IOT物联网平台mqtt服务器,封装起来使用就是这么简单!https://blog.csdn.net/xh870189248/article/details/91490697
  4. 阿里云物联网平台数据格式https://help.aliyun.com/document_detail/73736.html?spm=a2c4g.11186623.6.630.3d1b58009qvHen#title-7r8-lbe-2m1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值