一、wifi操作流程
1、wx.startWifi 开启wifi模块
2、如果需要展示wifi列表则调用 wx.getWifiList(Object object)
注意:
请求获取 Wi-Fi 列表。wifiList 数据会在 onGetWifiList 注册的回调中返回。 Android 调用前需要 用户授权 scope.userLocation。
iOS 上将跳转到系统设置中的微信设置页,需要用户手动进入「无线局域网」设置页,并在系统扫描到设备后,小程序才能收到 onGetWifiList 回调。Android 不会跳转。
3、可以直接连接wifi wx.connectWifi
注意:
有可能wifi连接不上,需要传入forceNewApi 参数,文档中没有说明
wx.connectWifi({
forceNewApi: true,
SSID: "PUNKCYBER",
password: "12345678910", //12345678910
success(res3) {
},
fail(res) {
console.log("wifi连接失败" + res.errCode + " " + res.errMsg);
},
})
},
android 手机连接wifi,连接成功后,会返回wifi信息,但是ios不会返回wifi信息。这个wifi信息有可能在连接tcp的时候会用到bssid,如果没有返回则可以调用 wx.getConnectedWifi
4、canvas保存为临时文件,ios 不显示
注意: backround-url 背景图片不显示 其实在image的组件中是显示的
5、TCP通讯
创建TCP : let tcp = wx.createTCPSocket();
监听绑定wifi事件 :tcp.onBindWifi
监听连接 : tcp.onConnect
监听消息 : tcp.onMessage
监听关闭 : tcp.onClose
监听错误 : tcp.onError
绑定wifi : tcp.bindWifi
连接tcp:tcp.connect
为什么从tcp转为udp:
connect能直接连接电脑端服务器tcp,但是连接硬件需要先绑定wifi,安卓没有问题,ios不支持bindWifi方法,ios一直连不上udp。所以后面从tcp转为了udp
6、UDP通讯
请忽略下面的tcp变量名,因为我是从tcp通讯改的udp通讯 UDP 有可能会限制包大小
创建UDP : let tcp = wx.createUDPSocket();
绑定:
if ("ios" == wx.getSystemInfoSync().platform) {
this.globalData.tcp.bind(); // ios不需要端口
} else {
this.globalData.tcp.bind(20565); // android 需要端口
}
**监听方法事件** : tcp.onListening(();
**监听报文的返回**: tcp.onMessage;
**监听关闭**: tcp.onClose;
**监听错误**: tcp.onError;
发送: tcp.send({
address: '192.168.4.1',
port: 20565,
setBroadcast: true, //ios 需要添加这个
message: bufferArr[subTcpDataIndex]
})
7、wifi框架代码文章来源:https://www.toymoban.com/news/detail-556013.html
// app.js
var packet = require('./utils/packet');
let wifiError = {
"12005": "请打开wifi",
"12006": "请打开GPS",
"12007": "用户拒接连接wifi",
"12010": "系统错误,请重试",
"1505005": "请打开wifi或重启设备",
"1505006": "请连接设备"
}
App({
onLaunch() {
console.log("onLaunch");
// 展示本地存储能力
wx.setEnableDebug({
enableDebug: true
})
let tcp = wx.createUDPSocket();
this.globalData.tcp = tcp;
tcp.onListening((res) => {
console.log("res==>", res);
this.tcpConnectCallback();
});
tcp.onMessage((res) => {
clearTimeout(getApp().globalData.timeoutTimer); //如果监听到有数据返回,在清除超时定时器
let val = this.arrayBufferToHexString(res.message);
console.log('onMessage-val', val)
if (val == "4F4B0D0A") { //”OK\r\n”代表连接正常
this.globalData.tcpDataIndex = this.globalData.tcpDataIndex + 1;
packet.tcpWrite();
} else if (val == "54494D45204F55540D0A") { //超时重新发送
//packet.tcpWrite();
if (this.globalData.timeoutCount < 3) { //需要判断是分包发送还是整包发送
this.globalData.timeoutCount++;
packet.sendDataBySubPackage();
} else {
wx.hideLoading();
wx.showToast({
title: "更新失败,请重试",
mask: true,
icon: "none"
})
}
} else if (val == packet.packageHex) { //分包发送完毕
this.globalData.subTcpDataIndex = this.globalData.subTcpDataIndex + 1;
packet.sendDataBySubPackage();
} else if (val == packet.errorHex) {
wx.hideLoading();
wx.showToast({
title: "更新失败,请重试",
mask: true,
icon: "none"
})
}
})
tcp.onClose((res) => {
console.log('断开了', res)
this.globalData.tcpIsClose = true
})
tcp.onError((res) => {
console.log('tcp-错误了', res)
// wx.hideLoading();
//clearTimeout(this.globalData.timer);
// errCode -2 Network is unreachable //设备断电了
// errCode -2 bind socket fail:errno:48 errmsg:
// wx.showToast({ // 不提示错误信息
// title: res.errMsg,
// mask: true,
// icon: 'none',
// })
if (res.errMsg == "create sock fail udp alread exist") {
wx.hideLoading();
this.tcpConnectCallback();
}
})
},
onHide() {
console.log("onHide")
this.globalData.tcp.close();
},
tcpConnectCallback() {
wx.hideLoading();
clearTimeout(this.globalData.timer);
this.globalData.tcpIsClose = false;
console.log('tcp连接成功')
packet.tcpWrite();
},
wifiInit() {
let that = this;
if ("ios" == wx.getSystemInfoSync().platform) {
wx.showLoading({
title: '连接中',
})
}
wx.connectWifi({
forceNewApi: true,
SSID: "PUNKCYBER",
password: "12345678910", //12345678910
success(res3) {
wx.hideLoading();
console.log("连接wifi成功", res3)
that.getConnectedWifi(); //ios手机会出现问题
//that.connectTcp();
},
fail(res) {
wx.hideLoading();
wx.showToast({
title: wifiError[res.errCode + ''] ? wifiError[res.errCode + ''] : res.errMsg,
mask: true,
icon: "none"
})
console.log("wifi连接失败" + res.errCode + " " + res.errMsg);
},
})
},
connectTcp() {
console.log('链接')
wx.showLoading({
title: "连接中",
mask: true,
})
let timer = setTimeout(() => {
if (this.globalData.tcpIsClose) {
wx.showToast({
title: '连接超时,请重试',
mask: true,
icon: 'none',
})
}
}, 2000)
this.globalData.timer = timer;
this.globalData.tcpIsClose = true;
if ("ios" == wx.getSystemInfoSync().platform) {
this.globalData.tcp.bind(); // ios不需要端口
} else {
this.globalData.tcp.bind(20565); // android 需要端口
}
},
tcpInit() {
this.globalData.timeoutCount = 0;
//判断wifi是否连接,wifi连接,则直接连接tcp,如果wifi未连接,则连接wifi然后再连接tcp
let that = this;
if (this.globalData.startWifi) {
this.getConnectedWifi();
} else {
wx.startWifi({
success(res) {
console.log("初始化wifi模块成功" + res.errMsg)
that.startWifi = true;
that.getConnectedWifi();
},
fail(res) {
wx.showToast({
title: wifiError[res.errCode + ''] ? wifiError[res.errCode + ''] : res.errMsg,
mask: true,
icon: 'none'
})
}
})
}
},
getConnectedWifi() {
let that = this;
wx.getConnectedWifi({
success(res) {
console.log("获取WiFixinxi", res)
if (!res.wifi || res.wifi.SSID != 'PUNKCYBER') {
that.wifiInit();
} else {
that.connectTcp();
}
},
fail(res) {
wx.showToast({
title: wifiError[res.errCode + ''] ? wifiError[res.errCode + ''] : (wifiError[res.errno + ''] ? wifiError[res.errno + ''] : res.errMsg),
mask: true,
icon: 'none'
})
console.log("获取wifi信息失败", res);
}
});
},
//buffer 转16进制
arrayBufferToHexString: function (buffer) {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('').toUpperCase();
},
globalData: {
bufferArr: [],
tcpDataIndex: 0,
subTcpDataIndex: 0,
tcpDataArr: [],
tcp: null,
openid: "",
deviceOnline: !1,
deviceId: "",
userImgList: {},
userLikeList: [],
tcpIsClose: true,
imagesCount: 12,
startWifi: false,
startSendBefore: 0,
ssid: '',
timer: '',
wifi: {},
isUpdateFirstDate: true, //是否第一次校验时间
timeoutCount: 0,
timeoutTimer: 0,
}
})
packet文章来源地址https://www.toymoban.com/news/detail-556013.html
let newLineHex = "0D0A"; //\r\n
let byte4Hex = "00000000"; //预留4字节0x00
let byte2Hex = "0000"; //预留2字节0x00
let testHex = "495053434c4f434b20544553540D0A";
let startSendImagesHex = "55504441544520504943545552450D0A";
let endDiyImagesHex = "5345542044495920454e440D0A";
let endBbdImagesHex = "5345542042424420454e440D0A";
let timeoutHex = "54494d45204f55540D0A"
let setTimeHex = "5345542054494D45"
let setLightHex = "53455420524742204C4544"
let packageHex = "44415441205345474D454E54204F4B0D0A"
let errorHex = "4552524F520D0A"
//16进制转字符串
const hexToStr = (hex, encoding) => {
var trimedStr = hex.trim();
var rawStr = trimedStr.substr(0, 2).toLowerCase() === "0x" ? trimedStr.substr(2) : trimedStr;
var len = rawStr.length;
var curCharCode;
var resultStr = [];
for (var i = 0; i < len; i = i + 2) {
curCharCode = parseInt(rawStr.substr(i, 2), 16);
resultStr.push(curCharCode);
}
var val = "";
var arr = resultStr;
for (let i = 0; i < arr.length; i++) {
val += String.fromCharCode(arr[i]);
}
return val;
}
//字符串转16进制
const stringToHex = (str) => {
var val = "";
for (var i = 0; i < str.length; i++) {
if (val == "") {
val = str.charCodeAt(i).toString(16); //获取字符的Unicode码然后转16进制
} else {
val += str.charCodeAt(i).toString(16); //获取字符的Unicode码然后转16进制再拼接,中间用逗号隔开
}
}
return val;
}
//十进制转十六进制
const tenToHex = (num, digit = 4) => {
const hex = num.toString(16);
return hex.padStart(digit, 0);
}
const firstTcpData = (sendDataArr) => {
let globalData = getApp().globalData;
globalData.tcpDataIndex = 0;
// 全局存放tcp需要发送的数据组
globalData.tcpDataArr = sendDataArr;
globalData.startSendBefore = 0;
}
//tcp 写入数据
const tcpWrite = () => {
let globalData = getApp().globalData;
let isUpdateFirstDate = globalData.isUpdateFirstDate;
if (isUpdateFirstDate && getApp().globalData.tcpDataArr.length != 1 && getApp().globalData.tcpDataArr[0].indexOf(setTimeHex) == -1) { //第一次要发送校验时间并且当前指令不是校验时间指令
getApp().globalData.tcpDataArr.push(getNowTimePacket());
getApp().globalData.isUpdateFirstDate = false;
}
let tcpDataArr = globalData.tcpDataArr;
let tcpDataIndex = globalData.tcpDataIndex;
// 将数据组遍历发送,过滤掉为空的数组
if (tcpDataIndex < tcpDataArr.length) {
// console.log(`发送${tcpDataIndex}次`)
let content = `正在更新${tcpDataIndex+1- globalData.startSendBefore}` + "/" + globalData.imagesCount;
let tcpData = tcpDataArr[tcpDataIndex];
if (tcpData) {
if (tcpData == testHex) {
content = "正在测试连接";
globalData.startSendBefore++;
} else if (tcpData == startSendImagesHex) {
content = "准备更新图片";
globalData.startSendBefore++;
} else if (tcpData == endDiyImagesHex || tcpData == endBbdImagesHex) {
content = "更新图片完毕";
} else if (tcpData.indexOf(setTimeHex) != -1) {
content = "正在同步时间";
} else if (tcpData.indexOf(setLightHex) != -1) {
content = "正在同步灯光";
}
console.log(content)
// console.log("发送的报文",tcpDataArr[tcpDataIndex]);
wx.showLoading({
title: content,
// mask: true,
})
getApp().globalData.subTcpDataIndex = 0;
getApp().globalData.bufferArr = getBufferArrayBy1000(tcpDataArr[tcpDataIndex]);
sendDataBySubPackage();
} else {
getApp().globalData.tcpDataIndex = tcpDataIndex + 1;
tcpWrite();
}
} else {
wx.showToast({
title: '更新成功',
mask: true,
icon: 'success',
})
getApp().globalData.tcp.close(); //tcp 断开,小程序无法再次连接tcp
}
}
const sendDataBySubPackage = () => {
let globalData = getApp().globalData;
let tcp = globalData.tcp;
let subTcpDataIndex = globalData.subTcpDataIndex;
let bufferArr = globalData.bufferArr;
if (subTcpDataIndex < bufferArr.length) {
tcp.send({
address: '192.168.4.1',
port: 20565,
setBroadcast: true, //ios 需要添加这个
message: bufferArr[subTcpDataIndex]
})
//1s未回复,定义为超时
let timer = setTimeout(()=>{
if(getApp().globalData.timeoutCount<3){ //需要判断是分包发送还是整包发送
console.log("响应超时",getApp().globalData.timeoutCount);
getApp().globalData.timeoutCount = getApp().globalData.timeoutCount+1;
sendDataBySubPackage();
}else{
wx.hideLoading();
wx.showToast({
title: "更新失败,请重试",
mask: true,
icon:"none"
})
}
},3000)
getApp().globalData.timeoutTimer = timer;
console.log("我发送了数据",subTcpDataIndex,bufferArr.length)
}
}
const getBufferArrayBy1000 = (data) => {
let num = 0;
let len = 1000;
if (typeof data == "undefined") return [];
let allBuffer = hexStringToArrayBuffer(data);
let bufferLen = allBuffer.byteLength;
let bufferArray = [];
while (bufferLen > 0) {
let buffer;
if (bufferLen > len) {
buffer = allBuffer.slice(num, num + len);
num = num + len;
bufferLen -= len;
bufferArray.push(buffer);
} else {
buffer = allBuffer.slice(num, num + bufferLen);
num += bufferLen;
bufferLen -= bufferLen;
bufferArray.push(buffer);
}
}
return bufferArray;
}
const hexStringToArrayBuffer = (str) => {
//十六进制转ArrayBuffer
return new Uint8Array(str.match(/[\da-f]{2}/gi).map(function (h) {
return parseInt(h, 16)
})).buffer
}
//mode= "DIY" 表盘模式 mode= "BBD" 表白模式
// no: 图片索引 00 - 99 月:10,日11
const getImagePacket = (filePath, no, mode = 'DIY') => {
const fs = wx.getFileSystemManager()
// 同步接口
try {
const fileDataHex = fs.readFileSync(filePath, 'hex', 0)
// ”SET DIY_00.jpg\r\n”+预留4字节0x00+2字节0x00+2字节图片大小+图片数据+”\r\n” 表盘模式
let fileSizeHex = tenToHex(parseInt(fileDataHex.length / 2));
let start = `SET ${mode}_${no}.jpg`;
let startHex = stringToHex(start);
let sendDataHex = (startHex + newLineHex + byte4Hex + byte2Hex + fileSizeHex + fileDataHex + newLineHex).toUpperCase();
// console.log("发送的图片数据报文", sendDataHex)
return sendDataHex;
} catch (e) {
console.error(e)
}
}
//mode= "DIY" 表盘模式 mode= "BBD" 表白模式
// no: 图片索引 00 - 99 月:10,日11
const getImagePacketByHttpUrl = (filePath, no, mode = 'DIY') => {
// 同步接口
return new Promise((resolve, reject) => {
wx.request({
url: filePath, //获取图片的URL
method: "get",
responseType: 'arraybuffer', //ArrayBuffer涉及面比较广,我的理解是ArrayBuffer代表内存之中的一段二进制数据,一旦生成不能再改。可以通过视图(TypedArray和DataView)进行操作。
success: (res) => {
const fileDataHex = arrayBufferToHexString(res.data);
// ”SET DIY_00.jpg\r\n”+预留4字节0x00+2字节0x00+2字节图片大小+图片数据+”\r\n” 表盘模式
let fileSizeHex = tenToHex(parseInt(fileDataHex.length / 2));
let start = `SET ${mode}_${no}.jpg`;
let startHex = stringToHex(start);
let sendDataHex = (startHex + newLineHex + byte4Hex + byte2Hex + fileSizeHex + fileDataHex + newLineHex).toUpperCase();
// console.log("发送的图片数据报文", sendDataHex)
resolve(sendDataHex)
//return sendDataHex;
},
fail(res) {
console.log("失败", res);
}
})
})
}
const arrayBufferToHexString = (buffer) => {
const hexArr = Array.prototype.map.call(
new Uint8Array(buffer),
function (bit) {
return ('00' + bit.toString(16)).slice(-2)
}
)
return hexArr.join('').toUpperCase();
}
//同步时间报文
const getNowTimePacket = () => {
let date = new Date();
let fullYear = date.getFullYear() + '';
const year = tenToHex(parseInt(fullYear.substring(fullYear.length - 2)), 2);
const month = tenToHex(date.getMonth() + 1, 2);
const day = tenToHex(date.getDate(), 2);
const hour = tenToHex(date.getHours(), 2);
const minute = tenToHex(date.getMinutes(), 2);
const second = tenToHex(date.getSeconds(), 2);
let start = `SET TIME`;
let startHex = stringToHex(start);
let dateTimeHex = year + month + day + hour + minute + second;
let sendDataHex = (startHex + newLineHex + byte4Hex + dateTimeHex + byte4Hex + newLineHex).toUpperCase();
//console.log("发送的时间数据报文", sendDataHex)
return sendDataHex;
}
//灯光报文
const getRGBPacket = (onOffStatus, bright, sleepStatus, lightMode, GRB) => {
console.log("原始数据");
console.log(onOffStatus, bright, sleepStatus, lightMode, GRB);
let start = `SET RGB LED`;
let startHex = stringToHex(start);
let onOffStatusHex = onOffStatus ? "01" : "00";
let brightHex = tenToHex(bright, 2);
let sleepStatusHex = sleepStatus ? "01" : "00";;
let lightModeHex = lightMode.toString().padStart(2, 0);
let GRBHex = GRB.substring(1);
console.log("16进制数据");
console.log(onOffStatusHex, brightHex, sleepStatusHex, lightModeHex, GRBHex);
let sendDataHex = (startHex + newLineHex + byte4Hex + onOffStatusHex + brightHex + sleepStatusHex + lightModeHex + GRBHex + byte4Hex + newLineHex).toUpperCase();
console.log("发送的RGB数据报文", sendDataHex)
return sendDataHex;
}
module.exports = {
getImagePacket,
getNowTimePacket,
getRGBPacket,
tcpWrite,
hexStringToArrayBuffer,
testHex,
firstTcpData,
startSendImagesHex,
endDiyImagesHex,
endBbdImagesHex,
timeoutHex,
packageHex,
sendDataBySubPackage,
errorHex,
getImagePacketByHttpUrl
}
到了这里,关于微信小程序哪些wifi+tcp+udp踩过的坑的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!