uniapp微信小程序:WIFI设备配网之TCP/UDP开发AP配网

一、AP配网技术原理

1.1 配网模式选择

AP配网(SoftAP模式)是IoT设备配网成功率最高的方案之一

1、其核心原理:

  • ​设备端​​:启动AP模式(如SSID格式YC3000_XXXX,默认IP192.168.4.1
  • ​手机端​​:直连设备热点后建立TCP/UDP通信,传输目标路由器的SSID/Password

1.2 协议交互流程

sequenceDiagram
小程序->>设备AP: 连接热点(SSID:YC3000_XXXX)
小程序->>设备AP: 建立TCP连接(IP:192.168.4.1:8266)
小程序->>设备AP: 发送AT+CJWAP指令
设备AP-->>小程序: 返回"Data Correct"或"Data Error"
小程序->>设备AP: 发送AT+RST指令重启
设备AP->>路由器: 连接目标WiFi
基础描述(大白话)

WiFi设备进入配网状态,实际是进入AP模式,设备开放一个Wifi热点出来。手机通过连接上设备Wifi模块的热点,将路由器名字和密码直接发送给Wifi设备,设备接收成功后,重启设备。

        UDP配网逻辑是一样的,如果需要UDP通信,命令参考UDPSocket | 微信开放文档

二、操作过程

2.1 用户长按按钮,触发WiFi设备进入配网模式。设备在此模式下创建wifi热点(单纯AP模式),开启TCP服务(默认 IP 为192.168.4.1,端口为8266),使指示灯闪烁。
2.2 小程序按照提示依次获取 Wi-Fi 列表,输入目标路由器的 SSID/PSW,再选择设备 softAP 热点的 SSID/PSW。
2.3 手机连接设备 softAP 热点成功后,小程序作为 TCP 客户端会连接 Wi-Fi 设备上面的 TCP 服务。
2.4 小程序给设备 TCP 服务,发送目标 Wi-Fi 路由器的 SSID/PSW 。 

2.5 设备接收成功后重启,配网成功 

三、UniApp开发实现

3.1 开发环境配置

        1.​​manifest.json声明权限​​:

"mp-weixin" : {
        "appid" : "******",//微信小程序appid
        "setting" : {
            "urlCheck" : false,
            "minified" : true
        },
        "usingComponents" : true,
        "permission" : {//必要,获取WiFi配置必须申请使用位置权限
            "scope.userLocation" : {
                "desc" : "用户使用小程序关联物联设备时,需要获取用户的所在位置区域"
            }
        },
        "requiredPrivateInfos" : [ "getLocation", "chooseLocation" ],
    },

        2.设备热点连接​​(需用户手动操作引导) 

uni.connectWifi({
    SSID: 'YC3000_XXXX', // 设备热点名称
    password: 'z111111',
    success: (res) => { console.log("连接成功,开始TCP通信") },
    fail: (err) => { console.log("连接失败", err) }
});

3.2 TCP核心通信模块

连接建立
    this.tcp = wx.createTCPSocket();
    console.log('运行')
    this.tcp.connect({
        address: '192.168.4.1',//默认 IP 为192.168.4.1
        port: 8266,//默认端口为8266
    });

指令发送 

this.tcp.write('AT+CJWAP="WIFI账户名","WIFI密码"');

重启设备 

this.tcp.write('AT+RST');

四、Demo页面源码

<template lang="html">
	<view class="sin-home">
		<view class="">
			设备配网
		</view>
		<input v-model="form.name"  type="text" placeholder="网络1名称" placeholder-class="placeholder" >
		<input v-model="form.pwd"  type="text" placeholder="密码" placeholder-class="placeholder" >
		<view class="">
			获取授权
		</view>
		<button @click="getconfirm()">getconfirm</button>
		<view class="">
			获取wifi
		</view>
		<button @click="getWIFI()">getWIFI</button>
		<view class="">
			测试配网
		</view>
		<button @click="startWifi()">startWifi</button>
		<button @click="connectWifi()">connectWifi</button>
		<button @click="connectTCP()">connectTCP</button>
		<button @click="sendDataTCP()">sendDataTCP</button>
		<button @click="sendRST()">sendRST</button>
		
		<view>
			{{tips}}
		</view>
		{{tips2}}
	</view>
</template>

<script>
	export default {
		name: 'home',
		data() {
			return {
				form: {
					name: '',
					result: '',
					pwd: ''
				},
				tips:'暂无数据',
				tips2:'未连接',
				tcp:'',
			}
		},
		computed: {
			
		},
		watch: {
			
		},
		onLoad() {
			
		},
		async onReady() {
			
		},
		onShow() {
			
		},
		// 下拉刷新
		onPullDownRefresh:function(){
			
		},
		onPageScroll(e) {
			
		},
		methods: {
			getconfirm(){
				// 获取授权状态
				uni.getSetting({
					success: (res) => {
						const hasLocationAuth = res.authSetting['scope.userLocation']
						const hasAgreePrivacy = uni.getStorageSync('hasAgreePrivacy')
						// 如果隐私和位置权限都已授权,直接返回
						if (hasAgreePrivacy && hasLocationAuth) {
							resolve(true)
							return
						}
		
						// 处理隐私协议
						if (!hasAgreePrivacy) {
							uni.showModal({
							  title: '位置信息授权',
							  content: '获取WiFi列表需要位置权限,是否前往设置?',
							  confirmText: '去设置',
							  cancelText: '取消',
							  success: (modalRes) => {
							    if (modalRes.confirm) {
							      // 打开设置页面
							      uni.openSetting({
							        success: (settingRes) => {
							          resolve(!!settingRes.authSetting['scope.userLocation'])
							        },
							        fail: () => {
							          resolve(false)
							        }
							      })
							    } else {
							      resolve(false)
							    }
							  },
							  fail: () => {
							    resolve(false)
							  }
							})
						} 
					},
					fail: () => {
						resolve(false)
					}
				})
			},
			getWIFI(){
				wx.getWifiList({
				success(res) {
					this.tips = JSON.stringify(res)
					wx.onGetWifiList(function(res) {
						console.log("获取wifi列表");
						console.log(res.wifiList,102); //在这里提取列表数据
						this.tips = JSON.stringify(res.wifiList)
					})
				},
				fail(res) {
					console.log(res)
					//报错的相关处理
				},
			})
			},
			// 开启wifi
				startWifi() {
					console.log('开始wifi接口');
					wx.startWifi({
						complete (res) {
							console.log(res)
						}
					})
				},
				// 链接wifi
				connectWifi() {
					uni.connectWifi({
					  SSID: 'YC3000_XXXX', // 设备热点名称
					  password: '',
					  success: (res) => { console.log("连接成功,开始TCP通信") },
					  fail: (err) => { console.log("连接失败", err) }
					});
					return
				},
				// 链接TCP
				connectTCP() {
					this.tcp = wx.createTCPSocket();
					console.log('运行')
					this.tcp.connect({
					  address: '192.168.4.1',
					  port: 8266,
					});
				},
				// 发送命令-账号密码
				sendDataTCP() {
					this.tcp.write('AT+CJWAP="WIFI账户名","WIFI密码"');
				},
				// 发送命令-重启
				sendRST(){
					this.tcp.write('AT+RST');
				},

		}
	}
</script>

<style lang="scss">
	.sin-home{
		padding: 50px 20px;
	}
</style>

demo页面展示

                

五、注意

1、想要获取WiFi列表,必须授权获取位置信息。

2、开发者工具暂时不支持 调试,必须使用真机进行开发

3、使用手机手动切换连接设备热点会出问题,请使用connectWifi()链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值