// pages/piano/cropper/cropper.js const { BtCmd } = require('../../../devices/bluetooth/bt_cmd'); import EventManager from '../../../utils/event_bus' import { EnumCmdEvent, CmdEvent } from '../../../devices/cmd_key_event'; import route_util from '../../../utils/route_util'; const { BtHelper } = require('../../../devices/bt_helper'); const { uploadImage } = require('../../../request/imageRequest'); Page({ /** * 页面的初始数据 */ data: { navbarData: { showCapsule: 1, //是否显示左上角图标 1表示显示 0表示不显示 title: '壁纸设置', //导航栏 中间的标题 callback: true, }, src: "", width: 320,//宽度 height: 320,//高度 showProgress: false, _chunks: [], progress: 0, _timer: null, // 裁剪后的图片地址 _imgUrl: null, _imgMD5: null, _imgIndex: null, // 从上级界面过来的图片地址,也是要返回去的地址 _imgTopPic: null, _imgNext: 0, max_scale: 2, _hasPermission: false, _hasShowModal: false, _deviceId: null, wallpaper: {}, }, cropper: null, callback() { let that = this if (this.data._chunks.length > 0) { wx.showModal({ title: '保存壁纸中,确定要中断退出吗?', content: '', complete: (res) => { if (res.confirm) { that.endImage(2) wx.navigateBack({ delta: 1, }) } } }) } else { wx.navigateBack({ delta: 1, }) } }, cropperload(e) { console.log('cropper加载完成'); }, upload() { let that = this; wx.chooseMedia({ count: 1, mediaType: ['image'], sourceType: ['album'], success(res) { wx.showLoading({ title: '加载中', }) const tempFilePaths = res.tempFiles[0].tempFilePath; that.cropper.imgReset(); that.setData({ src: tempFilePaths }); // todo 测试用 // that.testUpload(tempFilePaths) }, fail(err2) { console.log(err2) } }) }, testUpload(url) { let _this = this // 读取裁剪的jpg图片 const fs = wx.getFileSystemManager(); fs.readFile({ filePath: url, encoding: '', // 不指定编码以获取原始二进制数据 success: (obj) => { console.log("加载文件成功:", obj.data.byteLength, obj.data.length) fs.getFileInfo({ "filePath": url, "digestAlgorithm": "md5", success: (res) => { console.log("md5:", res) _this.data._imgMD5 = res.digest _this.data._imgIndex = 0 console.log("加载文件成功:", obj.data.byteLength, obj.data.length, obj.getFileInfo) let binData = obj.data; // let myMd5 = _this.getImgMd5(binData) // let my2Md5 = _this.getImg2Md5(binData) // let my3Md5 = _this.getImg3Md5(binData) wx.setClipboardData({ data: res.digest, fail: (err) => { console.error('setClipboardData失败:', err); }, success: (res) => { console.log('setClipboardData成功:', res); }, }) _this.sliceDataIntoChunks(binData, 64); console.log("加载文件成功2:", binData.byteLength, binData.length) _this.data._imageBufferLength = binData.byteLength ?? binData.length wx.hideLoading(); wx.showLoading({ title: '开始传输壁纸', }) console.log("md5 2:", _this.data._imgMD5) _this.startImage() }, fail: (err) => { console.error('getFileInfo失败:', err); }, }) }, fail: (err) => { console.error('读取 .bin 文件失败2:', err); }, }); // 651kb的 // _this.downloadAndSaveFile("https://music-play.oss-cn-shenzhen.aliyuncs.com/backOss/file/8770a6097d9940b59032d099b2fdde3b.bin"); }, loadimage(e) { wx.hideLoading(); console.log('加载壁纸', e); // this.cropper.imgReset(); }, clickcut(e) { console.log("clickcut:", e.detail); //壁纸预览 wx.previewImage({ current: e.detail.url, urls: [e.detail.url] }) }, cancel() { wx.navigateBack({ delta: -1 }) }, async _uploadImgIOS(url) { let _this = this; let res = await uploadImage(url); // 服务器的走下载图片 _this.data._imgTopPic = res.data; console.log("IOS的走下载图片", res) _this._downloadAndSaveFile(_this.data._imgTopPic) }, _uploadImage(url) { const fs = wx.getFileSystemManager(); let _this = this; // app.globalData.imgSrc = obj.url; console.log("裁剪壁纸:", url); _this.data._imgUrl = url fs.readFile({ filePath: _this.data._imgUrl, encoding: '', // 不指定编码以获取原始二进制数据 success: (obj) => { console.log("加载文件成功:", obj.data.byteLength, obj.data.length) fs.getFileInfo({ "filePath": _this.data._imgUrl, "digestAlgorithm": "md5", success: (res2) => { console.log("md5:", res2) _this.data._imgMD5 = res2.digest _this.data._imgIndex = 0 console.log("加载文件成功:", obj.data.byteLength, obj.data.length, obj.getFileInfo) let binData = obj.data; // let myMd5 = _this.getImgMd5(binData) // let my2Md5 = _this.getImg2Md5(binData) // let my3Md5 = _this.getImg3Md5(binData) // todo 测试用 // wx.setClipboardData({ // data: res2.digest, // }) _this.sliceDataIntoChunks(binData, 64); console.log("加载文件成功2:", binData.byteLength, binData.length) _this.data._imageBufferLength = binData.byteLength ?? binData.length wx.hideLoading(); wx.showLoading({ title: '开始传输壁纸', }) console.log("md5 2:", _this.data._imgMD5) _this.startImage() }, fail: (err) => { console.error('getFileInfo失败:', err); }, }) }, fail: (err) => { wx.hideLoading() wx.showToast({ title: '读取该图片失败', }) console.error('读取 .bin 文件失败:', err); }, }); }, submit() { let _this = this // if (_this.data._chunks.length > 0) { // return; // } let _imgTopPic = _this.data._imgTopPic ?? "" if (_imgTopPic.startsWith("http")) { // 服务器的走下载图片 console.log("服务器的走下载图片", _this.data._imgTopPic) _this._downloadAndSaveFile(_this.data._imgTopPic) return; } const res = wx.getSystemInfoSync(); // 获取系统信息 /// android ios const platform = res.platform; // 获取平台类型 wx.showLoading({ title: '壁纸裁剪中', }) // 读取裁剪的jpg图片 this.cropper.getImg((res) => { if (platform === 'ios') { this.cropper.getImg((res) => { _this._uploadImgIOS(res.url) }); } else { _this.data._imgTopPic = res.url _this._uploadImage(res.url) } }); }, _downloadAndSaveFile(url) { let _this = this // 下载文件 wx.downloadFile({ url: url, success: function (res) { if (res.statusCode === 200) { const tempFilePath = res.tempFilePath; _this.data._imgTopPic = url _this._uploadImage(tempFilePath) } else { wx.showToast({ title: '下载图片失败', icon: 'error' }); } }, fail: function (err) { console.error('下载文件失败', err); wx.showToast({ title: '下载失败', icon: 'error' }); } }); }, checkAndRequestImagePermission: function () { const _this = this; // 检查用户是否已经授权访问相册 wx.getSetting({ success(res) { if (!res.authSetting['scope.writePhotosAlbum']) { // 用户未授权访问相册,请求用户授权 wx.authorize({ scope: 'scope.writePhotosAlbum', success() { // 用户同意授权 console.log('用户已授权访问相册1'); _this.upload() // 可以在这里执行访问相册的操作 }, fail() { // 用户拒绝授权 console.log('用户拒绝授权访问相册'); wx.showModal({ title: '提示', content: '您拒绝了访问相册的权限,无法上传壁纸', showCancel: false, success(res) { if (res.confirm) { // 跳转到设置页面 wx.openSetting({ success(settingRes) { if (settingRes.authSetting['scope.writePhotosAlbum']) { console.log('用户已在设置中开启访问相册的权限'); // 可以在这里执行访问相册的操作 _this.upload(); //上传壁纸 } else { console.log('用户仍未授权访问相册'); } } }); } } }); } }); } else { // 用户已授权访问相册 console.log('用户已授权访问相册2'); // 可以在这里执行访问相册的操作 _this.upload() } } }); }, async startImage() { console.log("开始发送壁纸数据: 0x78",) BtHelper.sendCallBack(BtCmd.wallPaper(1), function (res) { if (!res) { wx.hideLoading() wx.setTimeout(function () { wx.showToast({ title: '发送失败', icon: 'error', duration: 2000 }) }, 100) } }); }, sliceDataIntoChunks(data, chunkSize) { let buffer = data; console.log("发送壁纸数据:", buffer.byteLength, buffer.length) let total = buffer.byteLength || buffer.length const chunks = []; // for (let i = 0; i < data.length; i += chunkSize) { for (let i = 0; i < total; i += chunkSize) { const chunk = buffer.slice(i, i + chunkSize); chunks.push(chunk); } // const sliceSize = chunkSize / 2; // 每个 RGB565 占 2 字节 // const chunks = []; // for (let i = 0; i < total; i += sliceSize) { // chunks.push(buffer.slice(i, i + sliceSize)); // } this.data._chunks = chunks; }, // getImgMd5(buffer) { // let md5ctx = js_md5.md5_init(); // js_md5.md5_update(md5ctx, buffer, buffer.byteLength ?? buffer.length); // let result = js_md5.md5_final(md5ctx); // let md5 = js_md5.md5_encode_hex(result, 16); // console.log("result:", md5, result); // return md5 // }, sendImageMD5() { // let lengthCode = this.data._chunks.length // console.log("发送壁纸MD5 1:", lengthCode, this.data._imgMD5) let value = BtCmd.sendWiFiInfo("99", this.data._imgMD5) // console.log("发送壁纸MD5 2:", value) BtHelper.sendCallBack(BtCmd.wallPaperMD5(value), function (res) { if (!res) { wx.hideLoading() wx.showToast({ title: '发送图片失败', icon: 'error' }) } }); }, // 切分高位和低位 splitHighLowBytes(value) { let highByte = (value >> 8) & 0xFF; let lowByte = value & 0xFF; return { highByte, lowByte }; }, async sendImage() { let _this = this let index = _this.data._imgIndex wx.hideLoading() let chunks = _this.data._chunks let total = _this.data._imageBufferLength; let btHelper = BtHelper.getInstance(); // let i = 0; // _this.data._timer = setInterval(async () => { if (index > chunks.length - 1) { // wx.showModal({ // title: '壁纸上传完成md5:' + _this.data._imgMD5, // content: '最终发送数据大小:' + _this.data._imgNext + ',总大小:' + total + '', // showCancel: false, // success(res) { // } // }) _this.endImage(0) return; } const chunk = chunks[index]; _this.data._imgNext += (chunk.byteLength ?? chunk.length); // console.log("发送壁纸数据1:", index, ":", _this.data._imgNext, ":", chunk.length, ":", chunk.byteLength, ":", total, chunks.length) _this.data._imgIndex += 1; let res = await btHelper.wallPaperSyncData(chunk); // let res = true; // btHelper.wallPaperData(chunk); if (!res) { wx.showModal({ title: '壁纸上传失败', showCancel: false }) _this.endImage(2) return } _this.updateProgress(_this.data._imgNext, total); // }, 30); }, async delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }, endImage(value) { let _this = this console.log("结束壁纸上传:", value) if (_this.data._timer) { clearInterval(_this.data._timer) _this.data._timer = null } _this.setData({ progress: 0, showProgress: false }) _this.data._chunks = [] _this.data._imgNext = 0 _this.data._imgMD5 = null _this.data._imgIndex = 0 BtHelper.getInstance().wallPaper(value); }, startProgress() { this.setData({ progress: 0, showProgress: true }) }, updateProgress(chunk, total) { let progress = parseFloat((chunk / total * 100).toFixed(2)); let _this = this if (chunk >= total) { _this.setData({ progress: 100, showCropImg: false }); } else { _this.setData({ progress: progress, }); } }, successSend() { let _this = this wx.showModal({ title: '保存壁纸成功', showCancel: false, success(res) { if (res.confirm) { const pages = getCurrentPages(); // 获取上一级页面实例 const prevPage = pages[pages.length - 2]; // 传递参数 prevPage.updateTopImg(_this.data._imgTopPic) wx.navigateBack({ delta: 1, }) } } }) }, failSend(showToast) { console.log('failSend') let _this = this _this.data._chunks = [] _this.data._imgMD5 = null _this.data._imgIndex = 0 _this.data._imgNext = 0 wx.hideLoading() if (showToast) { // todo 测试注释的 // wx.showModal({ // title: '壁纸上传失败了', // showCancel: false // }) wx.showToast({ title: '发送图片失败', icon: 'error' }) } _this.setData({ progress: 0, showProgress: false, showCropImg: false }); }, hasImage(image) { let that = this; that.cropper.imgReset(); // 有图片的进制缩放 that.setData({ src: image.pic, max_scale: 1, }); that.data._imgTopPic = image.pic }, disconnect(event) { let _this = this; console.log("断开连接--", event.commonValue, event.deviceId); if (event.deviceId === _this.data._deviceId && event.commonValue === "offline" && !_this.data._hasShowModal) { _this.data._hasShowModal = true wx.showModal({ title: '提示', content: '设备断开连接,请重新连接设备', showCancel: false, success: function (res) { _this.data._hasShowModal = false; if (res.confirm) { route_util.goBackHomePage() } } }) } // 设备断开连接,请重新连接设备 }, /** * 生命周期函数--监听页面加载 */ onLoad(options) { this.cropper = this.selectComponent("#image-cropper"); this.cropper.imgReset(); let image = options.param let json = JSON.parse(image) console.log("裁剪页:", image) let topImg = json.topImg ?? {} let deviceId = json.deviceId; _this.data._deviceId = deviceId if (topImg.pic) { this.hasImage(json) } else { console.log("没有图片") this.checkAndRequestImagePermission() } // this.setData({ // scr:json, // }) let _this = this; EventManager.addNotification(CmdEvent.eventName, function (event) { let name = event.cmdEvent; let value = event.wallpaper; let kind = event.heiJiaoKind; // console.log("裁剪页:", name, value, kind) switch (name) { case EnumCmdEvent.onoffline: wx.hideLoading(); _this.disconnect(event) break; case EnumCmdEvent.wallpaper: //0x78 // 小程序:0x78, 1。 开启壁纸 // 黑胶回:0x78, 2, 1 ,1。 0x78, 2, 0, 2 。 1成功,2失败 // 小程序:0x80, [参考wifi指令], [0x22,总长度,0x33,包长,包数,0x44,md5长,md5] // 黑胶回:0x80, 1, 1。 0x80, 0, 2。 1成功,2失败 // 小程序:0x79, 数据长度,数据 // 黑胶回:0x79, 1, 1 。0x79, 0, 2 。 1成功,2失败 // 小程序:0x78, 0。结束了 // 黑胶回:0x78, 2, 0, 1 。 0x78, 2, 0, 3 。 0流程成功,3流程失败 // 小程序: 0x78, 2。异常结束 if (value === 1 && kind == 1) { // 开始校验md5 _this.sendImageMD5() // _this.sendImage() _this.startProgress() } else if (value === 0 && (kind == 2 || kind == 3)) { // 发送失败 _this.failSend(true) } else if (value === 0 && kind == 1) { // 发送完成 _this.successSend() } else { // 发送失败 _this.failSend(true) } break; case EnumCmdEvent.wallPaperMD5: // 0x80 console.log("开始发送MD5回复", kind, value) // 收到回复md5,开始发送图片的第一片 if (kind == 1 && value === 1) { _this.data._imgIndex = 0 _this.sendImage(_this.data._imgIndex) } else if (kind == 0 && value === 3) { _this.failSend(false) wx.showModal({ title: '发送图片失败,请重启设备再试试吧', showCancel: false, success: function (res) { if (res.confirm) { console.log('用户点击确定') } } }) } else { _this.failSend(true) } break; case EnumCmdEvent.wallPaperData: // 0x79 // 收到回复md5,开始发送图片后面N片 if (kind == 1 && value === 1) { _this.sendImage(_this.data._imgIndex) } else { _this.failSend(true) } break; default: break; } }, this) }, /** * 生命周期函数--监听页面初次渲染完成 */ onReady() { }, /** * 生命周期函数--监听页面显示 */ onShow() { }, /** * 生命周期函数--监听页面隐藏 */ onHide() { }, /** * 生命周期函数--监听页面卸载 */ onUnload() { EventManager.removeNotification(CmdEvent.eventName, this); }, /** * 页面相关事件处理函数--监听用户下拉动作 */ onPullDownRefresh() { }, /** * 页面上拉触底事件的处理函数 */ onReachBottom() { }, /** * 用户点击右上角分享 */ onShareAppMessage() { } })