123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338 |
- let ArrNotifyListen = [
- "0000fff1-0000-1000-8000-00805f9b34fb",
- "FFF1"
- ];
- let ArrWriteListen = [
- "0000fff2-0000-1000-8000-00805f9b34fb",
- "FFF2"
- ];
- let ArrReadListen = [
- "0000fff1-0000-1000-8000-00805f9b34fb",
- "FFF1"
- ];
- let bledevice;
- var timeoutId;
- async function requestDevice() {
- return await new Promise((resolve, reject) => {
- navigator.bluetooth.requestDevice({
- // acceptAllDevices: true, //允许连接所有的设备
- filters: [
- { name: 'Tv700u-D54' },
- { services: ["6e400001-b5a3-f393-e0a9-e50e24dcca9e"] },
- { services: ["6e400003-b5a3-f393-e0a9-e50e24dcca9e"] },
- { services: ["6e400002-b5a3-f393-e0a9-e50e24dcca9e"] }
- ],
- //根据设备和服务的UUID读取设备
- optionalServices: [
- "6e400001-b5a3-f393-e0a9-e50e24dcca9e", //设备uuid
- "6e400003-b5a3-f393-e0a9-e50e24dcca9e", //读服务的uuid
- "6e400002-b5a3-f393-e0a9-e50e24dcca9e" //写服务的uuid
- ]
- }).then(device => {
- try {
- bledevice = device;
- resolve(device);
- //连接设备
- return device.gatt.connect();
- }
- catch (e) {
- }
- }).then(server => {
- try {
- //获取设备所有的服务
- return server.getPrimaryServices();
- }
- catch (e) {
- }
- }).then(services => {
- try {
- //绑定特征
- return overrideServices(services);
- }
- catch (e) {
- }
- }).catch(error => {
- console.log(error);
- reject(error)
- return error;
- });
- })
- }
- //把所有的服务的特性读取
- async function bleconnect() {
- try {
- //绑定特征
- const devices = await navigator.bluetooth.getDevices();
- if (devices.length) {
- try {
- bledevice = devices[0];
- const server = await bledevice.gatt.connect();
- const services = await server.getPrimaryServices();
- overrideServices(services);
- return bledevice;
- }
- catch (e) {
- console.log(error);
- }
- }
- return null;
- }
- catch (e) {
- }
- }
- //把所有的服务的特性读取
- async function overrideServices(services) {
- try {
- let queue = Promise.resolve();
- services.forEach(service => {
- queue = queue.then(_ => service.getCharacteristics().then(characteristics => {
- startNotifications(characteristics);
- }));
- });
- return queue;
- }
- catch (e) {
- }
- }
- //服务和读写的功能绑定
- function startNotifications(newservices) {
- try {
- newservices.forEach(newservice => {
- //启动通知
- if (ArrNotifyListen.indexOf(newservice.uuid) != -1) {
- addNotifyListen(newservice);
- }
- //发送api的绑定
- if (ArrWriteListen.indexOf(newservice.uuid) != -1) {
- addWriteListen(newservice);
- }
- //读取api的绑定
- if (ArrReadListen.indexOf(newservice.uuid) != -1) {
- addReadListen(newservice);
- }
- });
- }
- catch (e) {
- }
- }
- //绑定通知服务
- function addNotifyListen(service) {
- if (service.properties.notify) {
- service.startNotifications();//启动通知
- //获取通知信息
- service.addEventListener('characteristicvaluechanged', function (event) {
- // const rechex = new TextDecoder().decode(event.target.value.buffer);
- // console.log(rechex);
- clearTimeout(timeoutId);
- window.blechangedcallback && window.blechangedcallback(event);
- });
- }
- }
- //发送api
- function addWriteListen(service) {
- if (service.properties.write) {
- //由于目前蓝牙设备只有一个写入功能,所以直接把写入公布到window里
- window.blewrite = async function (value, callback) {
- if (value) {
- //如果发送的数据是字符串,转化成unit8Array
- if (typeof value === 'string') {
- value = new TextEncoder().encode(value);
- }
- //发送数据
- const data = await service.writeValue(value);
- return data;
- }
- }
- }
- }
- //读取返回的数据功能
- function addReadListen(service) {
- if (service.properties.read) {
- window.bleread = async function (callback) {
- const data = await service.readValue().then(
- function (resolve) {
- try {
- const rechex = new TextDecoder().decode(resolve.buffer);
- callback(rechex); //监听后获取返回的数据,判断需要发送什么信号过去
- return rechex;
- } catch (e) {
- console.log(e);
- };
- return null;
- },
- function (e) {
- console.error(e);
- return null;
- }
- );
- return data;
- }
- }
- }
- var sendcrc;
- //文件分块发送
- async function blefilesend(event, datas, len) {
- const returnarr = new Uint8Array(event.target.value.buffer);
- //判断信号是否是发送文件的信号
- if (returnarr[0] === returnarr[1] && returnarr[0] === 0xFF) {
- try {
- let split = uint8ArrayToInt(returnarr.slice(2, 8));
- let crc = returnarr.slice(8, 16);
- //已经传输完毕无需再上传
- if (split == len && Uint8ArraysEqual(crc, sendcrc)) {
- window.blewrite(new Uint8Array([0xFF, 0xFF, 0xFF]));
- }
- //断点续传,满足是同一个文件的情况
- else if (split != 0 && split < len) {
- const splitcrc = new TextEncoder().encode((CRC32.buf(new Uint8Array([...datas.subarray(0, split)])) >>> 0).toString(16).padStart(8, '0'));
- if (Uint8ArraysEqual(crc, splitcrc)) {
- // await window.blewrite(new Uint8Array([0xFF, 0xFF, 0x01]));//发送信号说明要发送文件
- for (let i = split; i < datas.length; i += 240) {
- if (i + 240 >= datas.length) {
- timeoutId = setTimeout(() => { window.blewrite(new Uint8Array([0xFF, 0xFF, 0xFF])); }, 2000);
- }
- if (i == split) {
- await window.blewrite(new Uint8Array([
- ...new Uint8Array([0xFF, 0xFF, 0x01]),
- ...datas.subarray(i, i + 240)]));
- }else{
- await window.blewrite(new Uint8Array([...datas.subarray(i, i + 240)]));
- }
- }
- } else {
- // await window.blewrite(new Uint8Array([0xFF, 0xFF, 0xF0]));
- for (let i = 0; i < datas.length; i += 240) {
- if (i + 240 >= datas.length) {
- timeoutId = setTimeout(() => { window.blewrite(new Uint8Array([0xFF, 0xFF, 0xFF])); }, 2000);
- }
- if (i == 0) {
- await window.blewrite(new Uint8Array([
- ...new Uint8Array([0xFF, 0xFF, 0xF0]),
- ...datas.subarray(i, i + 240)]));
- }else{
- await window.blewrite(new Uint8Array([...datas.subarray(i, i + 240)]));
- }
- }
- }
- }
- //文件直接上传
- else {
- // await window.blewrite(new Uint8Array([0xFF, 0xFF, 0xF0]));
- for (let i = 0; i < datas.length; i += 240) {
- if (i + 240 >= datas.length) {
- timeoutId = setTimeout(() => { window.blewrite(new Uint8Array([0xFF, 0xFF, 0xFF])); }, 2000);
- }
- if (i == 0) {
- await window.blewrite(new Uint8Array([
- ...new Uint8Array([0xFF, 0xFF, 0xF0]),
- ...datas.subarray(i, i + 240)]));
- }else{
- await window.blewrite(new Uint8Array([...datas.subarray(i, i + 240)]));
- }
- }
- }
- return true;
- }
- catch (error) {
- return false;
- console.error('发送消息错误:', error);
- }
- }
- }
- //停止运行
- function blestop(callback) {
- window.blewrite(new Uint8Array([0xFF, 0xFF, 0x11]), callback);
- }
- //运行py文件
- function blerun(filename, callback) {
- const start = new Uint8Array([0xFF, 0xFF, 0x10]);
- const sendmessage = new TextEncoder().encode(filename)
- const newarr = new Uint8Array([...start, ...sendmessage]);
- window.blechangedcallback = async function (event) {
- //判断是否结束运行了
- const isrun = new Uint8Array(event.target.value.buffer).toString().indexOf(new Uint8Array([0xFF, 0xFF, 0x1F]).toString()) > -1;
- let rechex = "";
- if (isrun) {
- rechex = new TextDecoder().decode(new Uint8Array(event.target.value.buffer).slice(0, -3));
- }
- else {
- rechex = new TextDecoder().decode(event.target.value.buffer);
- }
- callback(rechex, isrun);
- };
- window.blewrite(newarr);
- }
- //上传py文件
- function bleuploadfile(filename, textarr, callback) {
- const textec = new TextEncoder();
- sendcrc = textec.encode((CRC32.buf(textarr) >>> 0).toString(16).padStart(8, '0'));
- const sendarr = new Uint8Array([
- ...new Uint8Array([0xFF, 0xFF]),
- ...textec.encode(filename),
- ...intToUint8Array(textarr.length),
- ...sendcrc,
- ]);
- console.log(sendarr);
- window.blechangedcallback = async function (event) {
- //window.blechangedcallback = callback;
- window.blechangedcallback = null;
- //上传结束回调
- blefilesend(event, textarr, textarr.length).then(value => {
- callback(value);
- });
- };
- window.blewrite(sendarr);
- }
- function Uint8ArraysEqual(arr1, arr2) {
- if (arr1.length !== arr2.length) {
- return false;
- }
- for (let i = 0; i < arr1.length; i++) {
- if (arr1[i] !== arr2[i]) {
- return false;
- }
- }
- return true;
- }
- function intToUint8Array(num) {
- num = BigInt(num)
- const array = new Uint8Array(6);
- for (let i = 5; i >= 0; i--) {
- array[i] = Number(num % 256n);
- num = num >> 8n;
- }
- return array;
- }
- function uint8ArrayToInt(array) {
- let num = 0n;
- for (let i = 0; i < array.length; i++) {
- num += BigInt(array[i]) << BigInt((array.length - 1 - i) * 8);
- }
- return Number(num);
- }
|