├── .gitignore ├── README.md ├── _static ├── AI-Thinker.png ├── IMG_20211123_231112.png ├── fonts │ ├── font.wxss │ ├── iconfont.svg │ └── iconfont.ttf ├── gh_860fe35e8c08_344.jpg ├── module.png └── setup.png ├── app.js ├── app.json ├── app.wxss ├── pages ├── airkiss │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── blueDevices │ ├── bluetooth │ │ ├── blueDevices.js │ │ ├── blueDevices.json │ │ ├── blueDevices.wxml │ │ └── blueDevices.wxss │ └── bluetoothChat │ │ ├── index.js │ │ ├── index.json │ │ ├── index.wxml │ │ └── index.wxss └── index │ ├── index.js │ ├── index.json │ ├── index.wxml │ └── index.wxss ├── project.config.json ├── sitemap.json ├── utils └── util.js └── weui.wxss /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows 2 | [Dd]esktop.ini 3 | Thumbs.db 4 | $RECYCLE.BIN/ 5 | 6 | # macOS 7 | .DS_Store 8 | .fseventsd 9 | .Spotlight-V100 10 | .TemporaryItems 11 | .Trashes 12 | 13 | # Node.js 14 | node_modules/ 15 | # libs/xuhongv-airkiss-wx.js 16 | # libs/gl-airkiss-wx.js.bat -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | Banner 3 |

4 | 5 | 6 |
7 | AiThinkerAirkissforWXMini, just an wechat component library!
8 | 可实现airkiss一键配网的微信小程序 9 |
10 | 11 |
12 | 13 |
14 | 15 | 安信可 16 | 17 | 18 | 微信配网 19 | 20 | 21 | 基础库版本 22 | 23 |
24 | 25 | 26 | 27 | ## 维护日志,版本修订; 28 | 29 | |修改时间|更新日志| 30 | |----|----| 31 | |2021.11.24|首次发布| 32 | |2022.6.6|更新airkiss底层库版本,修复当mac地址为空的bug| 33 | 34 | ## 一、关于 WeChatAirkiss 35 | 36 | 本开源工程由半颗心脏基于微信配网airkiss协议做的一个开源微信配网小程序,适合于安信可在售的众多款Wi-Fi模组,包括 ESP32C3\ESP8266\ESP32\ESP32S2系列的模组。 37 | 38 | 如果您需要对应支持airkiss配网协议的无线模组,请到安信可淘宝店购买:[点击访问](https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx610ea582556c983e&token=1116556150&lang=zh_CN) 39 | 40 | ## 二、airkiss 简介 41 | 42 | AirKiss是微信硬件平台为Wi-Fi设备提供的微信配网、局域网发现和局域网通讯的技术。开发者若要实现通过微信客户端对Wi-Fi设备配网、通过微信客户端在局域网发现Wi-Fi设备,或者把微信客户端内的音乐、图片、文件等消息通过局域网发送至Wi-Fi设备。 43 | 44 | 设备进入 Wi-Fi 混杂模式(promiscuous mode)以监听捕获周围的 Wi-Fi 报文。由于设备暂未联网,且 Wi-Fi 网络的数据帧已通过加密,设备无法获取 payload 的内容,但可以获取报文的某些特征数据,例如每个报文的长度,同时对于某些数据帧;例如 UDP 的广播包或多播包,其报文的帧头结构比较固定,较容易识别。 45 | 46 | 此时在手机 App 或者小程序侧,即可通过发送 UDP 的广播包或多播包,并利用报文的特征,例如长度变化进行编码。 47 | 48 | 将目标 Wi-Fi 路由器的 SSID/PSW 字符以约定的编码方式发送出去,设备端在捕获到 UDP 报文后,按约定的方式进行解码,即可得到目标 Wi-Fi 路由器的相关信息并进行联网。 49 | 50 | 更多关于关于微信airkiss说明,请查阅官网文档:[点击我访问](https://iot.weixin.qq.com/wiki/new/index.html?page=4-1-1) 51 | 52 | ## 三、开始使用 53 | 自行注册一个微信小程序,请下载最新版的微信开发者工具。 54 | 55 | 新建项目之后,打开 ```app.js``` 文件添加下面代码: 56 | 57 | ``` 58 | "plugins": { 59 | "airkiss": { 60 | "version": "1.1.2", 61 | "provider": "wx610ea582556c983e" 62 | } 63 | } 64 | ``` 65 | 66 | 然后,会有提示是否添加插件,按照下面提示添加插件使用。 67 | 68 | 69 |

70 | Banner 71 |

72 | 73 | 74 | 75 | 下面举例说明了如何使用,更多使用技巧和方法参考本小程序。 76 | 77 | ```javascript 78 | const airkiss = requirePlugin('hello-plugin'); 79 | 80 | //获取版本 81 | console.log( airkiss.version) 82 | 83 | //这里最好加微信小程序判断账号密码是否为空,以及其长度和是否为5G频段 84 | airkiss.startAirkiss(this.data.ssid, this.data.password, function (res) { 85 | switch (res.code) { 86 | case 0: 87 | wx.showModal({ 88 | title: '初始化失败', 89 | content: res.result, 90 | showCancel: false, 91 | confirmText: '收到', 92 | }) 93 | break; 94 | case 1: 95 | wx.showModal({ 96 | title: '配网成功', 97 | content: '设备IP:' + res.ip + '\r\n 设备Mac:' + res.bssid, 98 | showCancel: false, 99 | confirmText: '好的', 100 | }) 101 | break; 102 | case 2: 103 | wx.showModal({ 104 | title: '配网失败', 105 | content: '请检查密码是否正确', 106 | showCancel: false, 107 | confirmText: '收到', 108 | }) 109 | break; 110 | 111 | default: 112 | break; 113 | } 114 | 115 | }) 116 | 117 | 118 | //停止配网,建议在页面 unload 等生命周期里面调用,释放线程 119 | airkiss.stopAirkiss() 120 | ``` 121 | --------------------------------------- 122 | ## 四、API说明 123 | 124 | ```airkiss.startAirkiss(ssid,password,funtion())``` 125 | 开始配置,需要入参路由器的SSID、密码以及回调函数,出参说明见示例。 126 | 127 | Note:请自行处理是否为2.4G频段路由器,以及密码是否正确。 128 | 129 | ```airkiss.stopAirkiss()``` 130 | 停止配置,释放配网线程的内存。 131 | 132 | Note:建议在建议在页面 unload 等生命周期里面调用。 133 | 134 | ```airkiss.version``` 135 | 获取版本 136 | 137 | ----------- 138 | 139 | ## 五、FAQ 140 | 141 | > Q1: 看样子是加载一个配网插件,这个插件开源吗? 142 | 143 | Answer:考虑到部分版权问题,我把此做成了小程序插件,暂不开源,如需了解此插件更多使用资料,请到安信可小程序配网插件详情页:[点击访问](https://mp.weixin.qq.com/wxopen/plugindevdoc?appid=wx610ea582556c983e) 144 | 145 | > Q2: 这个配网插件是微信官方适配的吗?可商业吗? 146 | 147 | Answer:不是微信官方适配的,是本人适配的,现已上架小程序插件, 可商业用途。 148 | 149 | ----------------------- 150 | 151 | ## 六、本人开源微信物联网控制一览表 152 | 153 | | 开源项目 | 地址 | 开源时间 | 154 | | ------------------------------------------------------------ | ------------------------------------------------------------ | -------- | 155 | | 微信小程序连接mqtt服务器,控制esp8266智能硬件 | https://github.com/xuhongv/WeChatMiniEsp8266 | 2018.11 | 156 | | 微信公众号airkiss配网以及近场发现在esp8266 rtos3.1 的实现 | https://github.com/xuhongv/xLibEsp8266Rtos3.1AirKiss | 2019.3 | 157 | | 微信公众号airkiss配网以及近场发现在esp32 esp-idf 的实现 | https://github.com/xuhongv/xLibEsp32IdfAirKiss | 2019.9 | 158 | | 微信小程序控制esp8266实现七彩效果项目源码 | https://github.com/xuhongv/WCMiniColorSetForEsp8266 | 2019.9 | 159 | | 一个基于安信可Ca-01的微信小程序定位追踪显示工程 | https://github.com/xuhongv/Cat.1TracerWcMini | 2019.9 | 160 | | 微信小程序蓝牙配网blufi实现在esp32源码 | https://github.com/xuhongv/BlufiEsp32WeChat | 2019.11 | 161 | | 微信小程序蓝牙ble控制esp32七彩灯效果 | https://blog.csdn.net/xh870189248/article/details/101849759 | 2019.10 | 162 | | 可商用的事件分发的微信小程序mqtt断线重连框架 | https://blog.csdn.net/xh870189248/article/details/88718302 | 2019.2 | 163 | | 微信小程序以 websocket 连接阿里云IOT物联网平台mqtt服务器 | https://blog.csdn.net/xh870189248/article/details/91490697 | 2019.6 | 164 | | 微信公众号网页实现连接mqtt服务器 | https://blog.csdn.net/xh870189248/article/details/100738444 | 2019.9 | 165 | | 微信小程序 AP 配网安信可 Wi-Fi 模块入网示例 | https://github.com/Ai-Thinker-Open/Ai-Thinker-Open_WeChatMiniAP2Net | 2020.5 | 166 | | 安信可IoT微信小程序全面开源,小程序上实现一键配网+控制+绑定 | https://blog.csdn.net/xh870189248/article/details/107140464 | 2020.8 | 167 | | 微信小程序蓝牙+WiFi控制安信可ESP32-S/C3S模块应用 | https://github.com/xuhongv/ESP32WiFiBleControlProject | 2021.6 | 168 | | 安信可ESP32-S模组适配腾讯物联开发平台llsync蓝牙配网+MQTT远程控制 | https://github.com/xuhongv/qcloud-esp32-llsync-mqtt | 2021.7 | 169 | 170 | ## 讨论交流 171 | 172 | 173 | 174 | 175 | 179 | 183 | 187 | 188 | 189 |
176 | 177 |

QQ群号:434878850

178 |
180 | 181 |

本人微信公众号:徐宏blog

182 |
184 | 185 |

私人工作微信,添加标明来意

186 |
190 | -------------------------------------------------------------------------------- /_static/AI-Thinker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuhongv/WeChatAirkiss/fee8ba7aef97922d0357acf7ef27fc5ffbf9bd60/_static/AI-Thinker.png -------------------------------------------------------------------------------- /_static/IMG_20211123_231112.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuhongv/WeChatAirkiss/fee8ba7aef97922d0357acf7ef27fc5ffbf9bd60/_static/IMG_20211123_231112.png -------------------------------------------------------------------------------- /_static/fonts/font.wxss: -------------------------------------------------------------------------------- 1 | @font-face {font-family: "iconfont"; 2 | src: url('data:application/x-font-woff2;charset=utf-8;base64,d09GMgABAAAAAAVsAAsAAAAACmAAAAUgAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHEIGVgCDHAqIIIZuATYCJAMQCwoABCAFhG0HQhvaCBHVo7uR/UzI8KpxCs1ksjghlmhvivVjcU3w/zX9nbv7kr+/VRVQpcoMtisUClu7UAwS14tHeIxnfDcix7/T3UvawaJN1SdmqM2kDDFNwFNcNEVMPyGbcz2wURFqJGefPPpC2rWD9LLsKQAOjpkuEyzPZnPKChsOcDyggUV+Lpq+QiiE8RfxTDP4n8DdEFCgm2jQdKMWRRAw1FkCtNO9ay2EiBkrYIqgizNuNNApKAluKnYNgBPn7/UPiaoLOCIP6l6zaw07wfhX5Hsa52UeqrwAk7tzAuxt4IERAANtZLqX8J5yxFEXsoqNUYCg/cTBV+Q733talinpUtQB/+WB8DhQDKq6hNjU6NkwicGH4MvHh4dv2owjaJsegCagdUDvgE0aYox8QljJisH1KKVKpdYaOY02WDmSWSER4j0rXL4JdFebSXL5fdIfcLD+rcKWXht2CDtJ/+bVxwYv2EJQpRjXrFSI30zSLOOmgy5BvdadWLuVRQ7UEB2ZmHlEw8pKkpCLxJP5Qz4hMP0+8MZ5AMmlbpERtLdanli0zaidpxXmGSuL2vB12xaFUuuW7NDP0+tD9bk7YkW0wAxCU6nX1xLK6fmb+U0EJW4RthbTRetCR/pbU27uoS0gEfM2Ld48dHKu/bdtKS0GSSq5f794flFKkCSJ4JWlCTSvLFEkyvndT0iSeO9e9qZtJoC3+w3ZiwGP3iDsKGIO3LAjtDJQo8gG8HhsQIsnL1yJKpYcIQjxGJQdRWz2ISQsJEn/fF05r+XniQvUlVGt/6RwQjzGHy/186KQc+dnzcH8uJhwY8j7HkwDFmulIrvHiNERa/hUHkfSu+o2txJu6c2yuBeFBapNZVeI/P/jYJNtyaxjY0FcdNS3D5sjw5kG6f04JCfJckWNKpXKWZQfG9tGqf+H2+FRiU1E4ZYcpgHzIMPoKvfRaS6M4unZy9wXL5frdRyuLHQq2rbFuMFjMWzugNvc8f+oU4pbia9lsB/5jjY/mv9qands4dW1DTFs7GBM/VhfoS5PY9K92JR/C6xi8hlkBcuha1DW1asKPCujc3UjWm3FaFg7HlV6S0WpwDzDqC0c81NmGZdzDo2ad+rYtmVvNGcO6k1xFhddL35QZeWg+Hp0hYfRL9mqeP1asZXhrBzj85a6CwWh0F3ibU+7rK5tO2rFhO2mM/qCqQn9L8VCUEy3a3v72G1zVZtSycWOXXUsnsWDguxvy65i17A3ZfbgO3D5cEPbn+2Z9Tj2UOtqPbIUWzUHouvURBgwhHMYQm4ls8fSGLXTDlTnsoWJ1gbpmtNSgOZZAAdApu53UoHwZkA23I/CBYBsGv4HH/TpTmJ7vs05H5v9N5D3LvZ5oM0TR9gMOdwjAHx/ksqSD1VlnSJkuSJTzWaSMFt2l9Vys5cQDE9cWdBikIHqb/CsC227cjWIQDsAR44u8AR6kIYdgYgiKcQExqDAMI1vL9JkAB5ZMMAQEwFEjZ3gqPABnhrXkYZ9ChEdvkJMTTgUmJNmxSJ9gsPhyKgELegfBEOD021ycGtv6KdOcVjmsF7IY4hBmRXx3BUH5C6WjG9fiThwTD1cYD/sOoLEFNFI1oikOs9d1jNlhvrZgSOjErSgfxAMDc7qLYfE79/QT53igo6y4At5DINDmRUVkFf1UKnjVJrHt68Ekw4cW009XNCJnZYmSNnjIhrJmgbJVOfYzVVVZ8Nr+zPcBxRQLzc5eZkitts0+H8TVhYHv00YPmrwsxk=') format('woff2'), 3 | url('iconfont.ttf?t=1586507740261') format('truetype'), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ 4 | url('iconfont.svg?t=1586507740261#iconfont') format('svg'); /* iOS 4.1- */ 5 | } 6 | 7 | .iconfont { 8 | font-family: "iconfont" !important; 9 | font-size: 16px; 10 | font-style: normal; 11 | -webkit-font-smoothing: antialiased; 12 | -moz-osx-font-smoothing: grayscale; 13 | } 14 | 15 | .icon-kongzhi:before { 16 | content: "\e62a"; 17 | } 18 | 19 | .icon-deng:before { 20 | content: "\e70d"; 21 | } 22 | 23 | .icon-peiwang:before { 24 | content: "\e65f"; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /_static/fonts/iconfont.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | 7 | 8 | Created by iconfont 9 | 10 | 11 | 12 | 13 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /_static/fonts/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuhongv/WeChatAirkiss/fee8ba7aef97922d0357acf7ef27fc5ffbf9bd60/_static/fonts/iconfont.ttf -------------------------------------------------------------------------------- /_static/gh_860fe35e8c08_344.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuhongv/WeChatAirkiss/fee8ba7aef97922d0357acf7ef27fc5ffbf9bd60/_static/gh_860fe35e8c08_344.jpg -------------------------------------------------------------------------------- /_static/module.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuhongv/WeChatAirkiss/fee8ba7aef97922d0357acf7ef27fc5ffbf9bd60/_static/module.png -------------------------------------------------------------------------------- /_static/setup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xuhongv/WeChatAirkiss/fee8ba7aef97922d0357acf7ef27fc5ffbf9bd60/_static/setup.png -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | //app.js 2 | App({ 3 | buf2hex: function (buffer) { 4 | return Array.prototype.map.call(new Uint8Array(buffer), x => ('00' + x.toString(16)).slice(-2)).join('') 5 | }, 6 | buf2string: function (buffer) { 7 | var arr = Array.prototype.map.call(new Uint8Array(buffer), x => x) 8 | var str = '' 9 | for (var i = 0; i < arr.length; i++) { 10 | str += String.fromCharCode(arr[i]) 11 | } 12 | return str 13 | }, 14 | onLaunch: function () { 15 | this.globalData.SystemInfo = wx.getSystemInfoSync() 16 | //console.log(this.globalData.SystemInfo) 17 | }, 18 | globalData: { 19 | SystemInfo: {} 20 | } 21 | }) -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "pages": [ 3 | "pages/index/index", 4 | "pages/airkiss/index", 5 | "pages/blueDevices/bluetooth/blueDevices", 6 | "pages/blueDevices/bluetoothChat/index" 7 | ], 8 | "window": { 9 | "backgroundTextStyle": "light", 10 | "navigationBarBackgroundColor": "#fff", 11 | "navigationBarTitleText": "物联网常用开发工具", 12 | "navigationBarTextStyle": "black" 13 | }, 14 | "style": "v2", 15 | "sitemapLocation": "sitemap.json", 16 | "plugins": { 17 | "airkiss": { 18 | "version": "1.1.2", 19 | "provider": "wx610ea582556c983e" 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /app.wxss: -------------------------------------------------------------------------------- 1 | 2 | @import "weui.wxss" 3 | @import "_static/fonts/font.wxss"; 4 | 5 | .container { 6 | height: 100vh; 7 | background: #f6f6f6; 8 | font-size: 32rpx; 9 | } 10 | /* flex布局 */ 11 | .flex { 12 | display: flex; 13 | } 14 | /* flex布局-水平居中 */ 15 | .flex-jcc { 16 | justify-content: center; 17 | } 18 | /* flex布局-垂直居中 */ 19 | .flex-ac { 20 | align-items: center; 21 | } 22 | /* flex布局-水平两端显示 */ 23 | .flex-jcb { 24 | justify-content: space-between; 25 | } 26 | .flex-v { 27 | flex-direction: column; 28 | } 29 | .flex-1 { 30 | flex: 1; 31 | } 32 | .header-wrapper { 33 | height: 55vh; 34 | width: 100%; 35 | background: #ffffff; 36 | border-bottom-right-radius: 80rpx; 37 | border-bottom-left-radius: 80rpx; 38 | } 39 | .header-image { 40 | width: 29vh; 41 | height: 29vh; 42 | position: relative; 43 | top: -7.5vh; 44 | } 45 | .content-wrapper { 46 | position: absolute; 47 | top: 43vh; 48 | left: 30rpx; 49 | min-height: 50vh; 50 | width: calc(100% - 60rpx); 51 | padding: 60rpx 40rpx; 52 | box-sizing: border-box; 53 | background: #fff; 54 | border-radius: 10px; 55 | box-shadow: 0px 0px 6rpx #fff; 56 | color: #818181; 57 | } 58 | .btn { 59 | width: 100%; 60 | font-size: 28rpx; 61 | padding: 8rpx 0; 62 | background: #e8352c; 63 | border: 1px solid #e8352c; 64 | color: #fff; 65 | border-radius: 100rpx; 66 | } 67 | -------------------------------------------------------------------------------- /pages/airkiss/index.js: -------------------------------------------------------------------------------- 1 | const airkiss = requirePlugin('airkiss'); 2 | 3 | 4 | /*********** hal_version 版本迭代 ***********/ 5 | // 211209 :纠正输入的SSID判断长度问题 6 | /*************************************/ 7 | 8 | Page({ 9 | data: { 10 | ssid: '', 11 | password: '', 12 | is5G: true, 13 | showClearBtn: false, 14 | isWaring: false, 15 | hal_version: 211209, 16 | ui: { 17 | background: [ 18 | { url: 'https://aithinker-static.oss-cn-shenzhen.aliyuncs.com/officialwebsite/banner/ESP32-C3.png' }, 19 | { url: 'https://aithinker-static.oss-cn-shenzhen.aliyuncs.com/officialwebsite/banner/banner32.jpg' }, 20 | { url: 'https://aithinker-static.oss-cn-shenzhen.aliyuncs.com/officialwebsite/banner/banner32.jpg' }, 21 | ], 22 | indicatorDots: true, 23 | vertical: false, 24 | autoplay: false, 25 | interval: 2000, 26 | duration: 500 27 | } 28 | }, 29 | onLoad(opt) { 30 | this.setData({ 31 | version: airkiss.version, 32 | }) 33 | let that = this 34 | wx.startWifi({ 35 | success(res) { 36 | console.log(res.errMsg, 'wifi初始化成功') 37 | that.getWifiInfo(); 38 | }, 39 | fail: function (res) { 40 | wx.showToast({ 41 | title: '请连接路由器!', 42 | duration: 2000, 43 | icon: 'none' 44 | }) 45 | } 46 | }) 47 | this.getWifiInfo() 48 | }, 49 | getWifiInfo() { 50 | let that = this 51 | wx.getConnectedWifi({ 52 | success(res) { 53 | console.log("getConnectedWifi ok:", JSON.stringify(res)) 54 | if ('getConnectedWifi:ok' === res.errMsg) { 55 | that.setData({ 56 | ssid: res.wifi.SSID, 57 | bssid: res.wifi.BSSID, 58 | is5G: res.wifi.frequency > 4900 59 | }) 60 | } else { 61 | wx.showToast({ 62 | title: '请连接路由器', 63 | duration: 2000, 64 | icon: 'none' 65 | }) 66 | } 67 | }, 68 | fail(res) { 69 | wx.showToast({ 70 | title: '请连接路由器', 71 | duration: 2000, 72 | icon: 'none' 73 | }) 74 | } 75 | }) 76 | }, 77 | onInputSSID(evt) { 78 | const { 79 | value 80 | } = evt.detail; 81 | this.setData({ 82 | ssid: value, 83 | }); 84 | }, 85 | onInputPassword(evt) { 86 | const { 87 | value 88 | } = evt.detail; 89 | this.setData({ 90 | password: value, 91 | showClearBtn: !!value.length, 92 | isWaring: false, 93 | }); 94 | }, 95 | onClear() { 96 | this.setData({ 97 | password: '', 98 | showClearBtn: false, 99 | isWaring: false, 100 | }); 101 | }, 102 | onConfirm() { 103 | console.log("ssid:", this.data.ssid, ",password:", this.data.password) 104 | 105 | if (this.data.ssid == '') { 106 | wx.showToast({ 107 | title: '请连接路由器', 108 | duration: 2000, 109 | icon: 'none' 110 | }) 111 | return; 112 | } 113 | 114 | if (this.data.password.length < 8) { 115 | wx.showToast({ 116 | title: '请输出不少于8位的密码', 117 | duration: 2000, 118 | icon: 'none' 119 | }) 120 | return; 121 | } 122 | 123 | if (this.data.is5G) { 124 | wx.showToast({ 125 | title: '请链接至2.4G频段的路由器', 126 | duration: 2000, 127 | icon: 'none' 128 | }) 129 | return; 130 | } 131 | wx.showLoading({ 132 | title: '配网中', 133 | }) 134 | //这里最好加微信小程序判断账号密码是否为空,以及其长度和是否为5G频段 135 | airkiss.startAirkiss(this.data.ssid, this.data.password, function (res) { 136 | wx.hideLoading(); 137 | switch (res.code) { 138 | case 0: 139 | wx.showModal({ 140 | title: '初始化失败', 141 | content: res.result, 142 | showCancel: false, 143 | confirmText: '收到', 144 | }) 145 | break; 146 | case 1: 147 | wx.showModal({ 148 | title: '配网成功', 149 | content: '设备IP:' + res.ip + '\r\n 设备Mac:' + res.bssid, 150 | showCancel: false, 151 | confirmText: '好的', 152 | }) 153 | break; 154 | case 2: 155 | wx.showModal({ 156 | title: '配网失败', 157 | content: '请检查密码是否正确', 158 | showCancel: false, 159 | confirmText: '收到', 160 | }) 161 | break; 162 | 163 | default: 164 | break; 165 | } 166 | 167 | }) 168 | }, 169 | }); 170 | -------------------------------------------------------------------------------- /pages/airkiss/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "usingComponents": {} 3 | } -------------------------------------------------------------------------------- /pages/airkiss/index.wxml: -------------------------------------------------------------------------------- 1 | 8 | 9 | 10 | 11 | 12 | 13 | 1)先连接到家庭路由器2.4G频段网络。 14 | 2)使用安信可Wi-Fi模组开启微信配网。 15 | 3)再输入家庭路由器密码,点击确定。 16 | 17 | 18 | 19 | 20 | 家庭路由器信息 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 确定 48 | 49 | 50 | 51 | 库版本 {{version}}-{{hal_version}} 52 | Copyright 半颗心脏 CSDN 53 | -------------------------------------------------------------------------------- /pages/airkiss/index.wxss: -------------------------------------------------------------------------------- 1 | pager{ 2 | width: 100%; 3 | } -------------------------------------------------------------------------------- /pages/blueDevices/bluetooth/blueDevices.js: -------------------------------------------------------------------------------- 1 | const app = getApp() 2 | Page({ 3 | data: { 4 | searching: false, 5 | devicesList: [] 6 | }, 7 | onPullDownRefresh: function () { 8 | var that = this 9 | if (!that.data.searching) { 10 | wx.closeBluetoothAdapter({ 11 | complete: function (res) { 12 | console.log(res) 13 | wx.openBluetoothAdapter({ 14 | success: function (res) { 15 | console.log(res) 16 | wx.getBluetoothAdapterState({ 17 | success: function (res) { 18 | console.log(res) 19 | } 20 | }) 21 | wx.startBluetoothDevicesDiscovery({ 22 | allowDuplicatesKey: false, 23 | success: function (res) { 24 | console.log(res) 25 | that.setData({ 26 | searching: true, 27 | devicesList: [] 28 | }) 29 | } 30 | }) 31 | }, 32 | fail: function (res) { 33 | console.log(res) 34 | wx.showModal({ 35 | title: '提示', 36 | content: '请检查手机蓝牙是否打开', 37 | showCancel: false, 38 | success: function (res) { 39 | that.setData({ 40 | searching: false 41 | }) 42 | } 43 | }) 44 | } 45 | }) 46 | } 47 | }) 48 | } else { 49 | wx.stopBluetoothDevicesDiscovery({ 50 | success: function (res) { 51 | that.setData({ 52 | searching: false 53 | }) 54 | } 55 | }) 56 | } 57 | }, 58 | Connect: function (e) { 59 | console.log(JSON.stringify(e)) 60 | var that = this 61 | var advertisData, name , deviceId 62 | for (var i = 0; i < that.data.devicesList.length; i++) { 63 | if (e.currentTarget.id == that.data.devicesList[i].deviceId) { 64 | name = that.data.devicesList[i].name 65 | deviceId = that.data.devicesList[i].deviceId 66 | advertisData = that.data.devicesList[i].advertisData 67 | } 68 | } 69 | wx.stopBluetoothDevicesDiscovery({ 70 | success: function (res) { 71 | that.setData({ 72 | searching: false 73 | }) 74 | } 75 | }) 76 | wx.showLoading({ 77 | title: '连接蓝牙设备中...', 78 | }) 79 | wx.createBLEConnection({ 80 | deviceId, 81 | success: function (res) { 82 | wx.hideLoading() 83 | wx.showToast({ 84 | title: '连接成功', 85 | icon: 'success', 86 | duration: 1000 87 | }) 88 | wx.navigateTo({ 89 | url: '/pages/blueDevices/bluetoothChat/index?deviceId=' + e.currentTarget.id + '&name=' + name 90 | }) 91 | }, 92 | fail: function (res) { 93 | console.log(JSON.stringify(res)) 94 | wx.hideLoading() 95 | wx.showModal({ 96 | title: '提示', 97 | content: '连接失败', 98 | showCancel: false 99 | }) 100 | } 101 | }) 102 | }, 103 | onLoad: function (options) { 104 | var that = this 105 | var list_height = ((app.globalData.SystemInfo.windowHeight - 50) * (750 / app.globalData.SystemInfo.windowWidth)) - 60 106 | that.setData({ 107 | list_height: list_height 108 | }) 109 | wx.onBluetoothAdapterStateChange(function (res) { 110 | 111 | that.setData({ 112 | searching: res.discovering 113 | }) 114 | if (!res.available) { 115 | that.setData({ 116 | searching: false 117 | }) 118 | } 119 | }) 120 | wx.onBluetoothDeviceFound(function (devices) { 121 | //剔除重复设备,过滤名字是否为 Ai-Thinker 122 | var isnotexist = true 123 | if (devices.deviceId) { 124 | if (devices.advertisData) { 125 | devices.advertisData = app.buf2hex(devices.advertisData) 126 | } else { 127 | devices.advertisData = '' 128 | } 129 | console.log(devices) 130 | for (var i = 0; i < that.data.devicesList.length; i++) { 131 | if (devices.deviceId == that.data.devicesList[i].deviceId) { 132 | isnotexist = false 133 | } 134 | } 135 | if (isnotexist && (devices[0].name === 'aithinker' || devices[0].name === 'Ai-Thinker' || devices[0].name === 'ai-thinker')) { 136 | that.data.devicesList.push(devices[0]) 137 | } 138 | } else if (devices.devices) { 139 | if (devices.devices[0].advertisData) { 140 | devices.devices[0].advertisData = app.buf2hex(devices.devices[0].advertisData) 141 | } else { 142 | devices.devices[0].advertisData = '' 143 | } 144 | 145 | for (var i = 0; i < that.data.devicesList.length; i++) { 146 | if (devices.devices[0].deviceId == that.data.devicesList[i].deviceId) { 147 | isnotexist = false 148 | } 149 | } 150 | if (isnotexist && (devices.devices[0].name === 'aithinker' || 151 | devices.devices[0].name === 'Ai-Thinker' || devices.devices[0].name === 'ai-thinker')) { 152 | that.data.devicesList.push(devices.devices[0]) 153 | } 154 | } else if (devices[0]) { 155 | if (devices[0].advertisData) { 156 | devices[0].advertisData = app.buf2hex(devices[0].advertisData) 157 | } else { 158 | devices[0].advertisData = '' 159 | } 160 | 161 | for (var i = 0; i < devices_list.length; i++) { 162 | if (devices[0].deviceId == that.data.devicesList[i].deviceId) { 163 | isnotexist = false 164 | } 165 | } 166 | if (isnotexist && (devices[0].name === 'aithinker' || devices[0].name === 'Ai-Thinker' || devices[0].name === 'ai-thinker')) { 167 | that.data.devicesList.push(devices[0]) 168 | } 169 | } 170 | 171 | console.log(JSON.stringify(that.data.devicesList)) 172 | 173 | that.setData({ 174 | devicesList: that.data.devicesList 175 | }) 176 | }) 177 | }, 178 | onHide: function () { 179 | var that = this 180 | that.setData({ 181 | devicesList: [] 182 | }) 183 | if (this.data.searching) { 184 | wx.stopBluetoothDevicesDiscovery({ 185 | success: function (res) { 186 | that.setData({ 187 | searching: false 188 | }) 189 | } 190 | }) 191 | } 192 | } 193 | }) 194 | -------------------------------------------------------------------------------- /pages/blueDevices/bluetooth/blueDevices.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "安信可蓝牙模组通讯", 3 | "enablePullDownRefresh": true 4 | } -------------------------------------------------------------------------------- /pages/blueDevices/bluetooth/blueDevices.wxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {{item.name}} 8 | Rssi: {{item.RSSI}} 9 | 10 | 11 | -------------------------------------------------------------------------------- /pages/blueDevices/bluetooth/blueDevices.wxss: -------------------------------------------------------------------------------- 1 | /* pages/blueDevices/blueDevices.wxss */ 2 | .prompt-title { 3 | height: 50rpx; 4 | border-top: 1px solid #999; 5 | border-bottom: 1px solid #999; 6 | width: 100%; 7 | } 8 | .item { 9 | display: flex; 10 | height: 130rpx; 11 | width: 100%; 12 | padding: 30rpx; 13 | align-items: center; 14 | border-bottom: 1px solid #eee; 15 | background: #fff; 16 | box-sizing: border-box; 17 | } 18 | .item-img { 19 | flex: 0 0 90rpx; 20 | height: 90rpx; 21 | display: flex; 22 | justify-content: center; 23 | align-items: center; 24 | border-radius: 100%; 25 | background: #f6f6f6; 26 | box-shadow: 0 0 10px #f6f6f6; 27 | } 28 | .icon-deng { 29 | font-size: 50rpx; 30 | color: #e8352c; 31 | } 32 | .item-name { 33 | flex: 1; 34 | padding-left: 10px; 35 | display: flex; 36 | flex-direction: column; 37 | font-size: 32rpx; 38 | } 39 | .text-rssi { 40 | font-size: 28rpx; 41 | color: #999; 42 | } -------------------------------------------------------------------------------- /pages/blueDevices/bluetoothChat/index.js: -------------------------------------------------------------------------------- 1 | const app = getApp() 2 | Page({ 3 | data: { 4 | inputText: 'Hello World!', 5 | receiveText: '', 6 | receiveArry: [], 7 | name: '', 8 | connectedDeviceId: '', 9 | serviceId: "55535343-FE7D-4AE5-8FA9-9FAFD205E455", //可写的服务ID 10 | characteristics: '49535343-8841-43F4-A8D4-ECBE34729BB3',//可写的characteristics ID 11 | read_characteristics: '49535343-1E4D-4BD9-BA61-23C647249616', //49535343-1E4D-4BD9-BA61-23C647249616 12 | connected: true, 13 | }, 14 | bindInput: function (e) { 15 | this.setData({ 16 | inputText: e.detail.value 17 | }) 18 | console.log(e.detail.value) 19 | }, 20 | SendTap: function () { 21 | var that = this 22 | if (that.data.connected) { 23 | var buffer = new ArrayBuffer(that.data.inputText.length) 24 | var dataView = new Uint8Array(buffer) 25 | for (var i = 0; i < that.data.inputText.length; i++) { 26 | dataView[i] = that.data.inputText.charCodeAt(i) 27 | } 28 | wx.writeBLECharacteristicValue({ 29 | deviceId: that.data.connectedDeviceId, 30 | serviceId: that.data.serviceId, 31 | characteristicId: that.data.characteristics, 32 | value: buffer, 33 | success: function (res) { 34 | console.log('发送成功') 35 | } 36 | }) 37 | } else { 38 | wx.showModal({ 39 | title: '提示', 40 | content: '蓝牙已断开', 41 | showCancel: false, 42 | success: function (res) { 43 | that.setData({ 44 | searching: false 45 | }) 46 | } 47 | }) 48 | } 49 | }, 50 | onLoad: function (options) { 51 | var that = this 52 | 53 | that.setData({ 54 | name: options.name, 55 | connectedDeviceId: options.deviceId 56 | }) 57 | 58 | wx.getBLEDeviceServices({ 59 | deviceId: that.data.connectedDeviceId, 60 | success: function (res) { 61 | var all_UUID = res.services; 62 | var index_uuid = -1; 63 | var UUID_lenght = all_UUID.length; 64 | //console.log("service:" + JSON.stringify(res)) 65 | /* 遍历服务数组 */ 66 | for (var index = 0; index < UUID_lenght; index++) { 67 | var ergodic_UUID = all_UUID[index].uuid; 68 | /* 判断是否是我们需要的服务UUID*/ 69 | if (ergodic_UUID === that.data.serviceId) { 70 | index_uuid = index; 71 | }; 72 | }; 73 | 74 | if (index_uuid == -1) { 75 | wx.showModal({ 76 | title: '提示', 77 | content: '非我方出售的设备', 78 | showCancel: false, 79 | success: function (res) { 80 | that.setData({ 81 | searching: false 82 | }) 83 | } 84 | }) 85 | } else { 86 | wx.getBLEDeviceCharacteristics({ 87 | deviceId: that.data.connectedDeviceId, 88 | serviceId: that.data.serviceId, 89 | success: function (res) { 90 | wx.notifyBLECharacteristicValueChange({ 91 | state: true, 92 | deviceId: that.data.connectedDeviceId, 93 | serviceId: that.data.serviceId, 94 | characteristicId: that.data.read_characteristics, 95 | success: function (res) { 96 | console.log('启用notify成功') 97 | }, 98 | fail(res) { 99 | console.log(res) 100 | } 101 | }) 102 | }, 103 | fail(res) { 104 | console.log(res) 105 | } 106 | }) 107 | } 108 | } 109 | }) 110 | wx.onBLEConnectionStateChange(function (res) { 111 | console.log(res.connected) 112 | that.setData({ 113 | connected: res.connected 114 | }) 115 | }) 116 | wx.onBLECharacteristicValueChange(function (res) { 117 | console.log('接收到数据:' + app.buf2string(res.value)) 118 | var time = that.getNowTime() 119 | that.setData({ 120 | receiveText: that.data.receiveText + time + (app.buf2string(res.value)) 121 | }) 122 | }) 123 | }, 124 | onUnload: function () { 125 | wx.closeBLEConnection({ 126 | deviceId: this.data.connectedDeviceId, 127 | success: function (res) { }, 128 | }) 129 | }, 130 | SendCleanTap: function () { 131 | this.setData({ 132 | inputText: '' 133 | }) 134 | }, 135 | 136 | RecvCleanTap: function () { 137 | this.setData({ 138 | receiveText: '' 139 | }) 140 | }, 141 | SendValue: function (e) { 142 | this.setData({ 143 | inputText: e.detail.value 144 | }) 145 | }, 146 | getNowTime: function () { 147 | // 加0 148 | function add_10(num) { 149 | if (num < 10) { 150 | num = '0' + num 151 | } 152 | return num; 153 | } 154 | var myDate = new Date(); 155 | myDate.getYear(); //获取当前年份(2位) 156 | myDate.getFullYear(); //获取完整的年份(4位,1970-????) 157 | myDate.getMonth(); //获取当前月份(0-11,0代表1月) 158 | myDate.getDate(); //获取当前日(1-31) 159 | myDate.getDay(); //获取当前星期X(0-6,0代表星期天) 160 | myDate.getTime(); //获取当前时间(从1970.1.1开始的毫秒数) 161 | myDate.getHours(); //获取当前小时数(0-23) 162 | myDate.getMinutes(); //获取当前分钟数(0-59) 163 | myDate.getSeconds(); //获取当前秒数(0-59) 164 | myDate.getMilliseconds(); //获取当前毫秒数(0-999) 165 | myDate.toLocaleDateString(); //获取当前日期 166 | var nowTime = add_10(myDate.getHours()) + '时' + add_10(myDate.getMinutes()) + '分' + add_10(myDate.getSeconds()) + '秒 收到:'; 167 | return nowTime; 168 | } 169 | }) -------------------------------------------------------------------------------- /pages/blueDevices/bluetoothChat/index.json: -------------------------------------------------------------------------------- 1 | { 2 | "navigationBarTitleText": "安信可蓝牙模组通讯" 3 | } 4 | -------------------------------------------------------------------------------- /pages/blueDevices/bluetoothChat/index.wxml: -------------------------------------------------------------------------------- 1 | 2 | 连接设备名:{{name}} 3 | 已连接 4 | 未连接 5 | 6 | 7 | 8 | 9 | 10 |