forked from yudi_xiao/expo-ble-app-demo
expo-ble模块测试demo 联调BLE模块 take 3 添加跟多log
This commit is contained in:
parent
56a5d0d45e
commit
1d3a7eba45
|
|
@ -17,6 +17,7 @@ export const FRAME_CONSTANTS = {
|
||||||
FOOTER_SIZE: 1,
|
FOOTER_SIZE: 1,
|
||||||
FRAME_INTERVAL: 35,
|
FRAME_INTERVAL: 35,
|
||||||
} as const;
|
} as const;
|
||||||
|
export type FRAME_HEAD = typeof FRAME_CONSTANTS.HEAD_DEVICE_TO_APP | typeof FRAME_CONSTANTS.HEAD_APP_TO_DEVICE;
|
||||||
|
|
||||||
export const COMMAND_TYPES = {
|
export const COMMAND_TYPES = {
|
||||||
ACTIVATION_QUERY: 0x01,
|
ACTIVATION_QUERY: 0x01,
|
||||||
|
|
@ -30,6 +31,7 @@ export const COMMAND_TYPES = {
|
||||||
DEVICE_INFO_SETTINGS: 0x0d,
|
DEVICE_INFO_SETTINGS: 0x0d,
|
||||||
DEVICE_IDENTITY_CHECK: 0x0e,
|
DEVICE_IDENTITY_CHECK: 0x0e,
|
||||||
} as const;
|
} as const;
|
||||||
|
export type COMMAND_TYPES = typeof COMMAND_TYPES[keyof typeof COMMAND_TYPES];
|
||||||
|
|
||||||
export const RESPONSE_TYPES = {
|
export const RESPONSE_TYPES = {
|
||||||
ACTIVATION_STATUS: 0x01,
|
ACTIVATION_STATUS: 0x01,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import {ProtocolFrame} from './types';
|
import {ProtocolFrame} from './types';
|
||||||
import {FRAME_CONSTANTS} from './Constants';
|
import {FRAME_CONSTANTS, COMMAND_TYPES, FRAME_HEAD} from './Constants';
|
||||||
|
|
||||||
export class ProtocolManager {
|
export class ProtocolManager {
|
||||||
|
|
||||||
|
|
@ -15,22 +15,26 @@ export class ProtocolManager {
|
||||||
}
|
}
|
||||||
const checksumV1 = (0 - sum) & 0xff
|
const checksumV1 = (0 - sum) & 0xff
|
||||||
const checksum = (~sum + 1) & 0xff
|
const checksum = (~sum + 1) & 0xff
|
||||||
console.debug(`[ProtocolManager] Checksum V1 calculated: 0 - ${sum} = ${checksumV1}`);
|
console.debug(`[ProtocolManager] Checksum V1 calculated: 0 - ${sum} = ${checksumV1.toString(16).padStart(2, '0')}`);
|
||||||
console.debug(`[ProtocolManager] Checksum calculated: 0 - ${sum} = ${checksum}`);
|
console.debug(`[ProtocolManager] Checksum calculated: 0 - ${sum} = ${checksum.toString(16).padStart(2, '0')}`);
|
||||||
return checksum;
|
return checksum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static verifyChecksum(frameData: Uint8Array, expectedChecksum: number): boolean {
|
static verifyChecksum(frameData: Uint8Array, expectedChecksum: number): boolean {
|
||||||
const calculated = this.calculateChecksum(frameData);
|
return (frameData.length + expectedChecksum) === 0;
|
||||||
return calculated === expectedChecksum;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static createFrame(
|
static createFrame(
|
||||||
type: number,
|
type: COMMAND_TYPES,
|
||||||
data: Uint8Array,
|
data: Uint8Array,
|
||||||
head: number = FRAME_CONSTANTS.HEAD_APP_TO_DEVICE,
|
head: FRAME_HEAD = FRAME_CONSTANTS.HEAD_APP_TO_DEVICE,
|
||||||
requireFragmentation: boolean = true
|
requireFragmentation: boolean = true
|
||||||
): Uint8Array[] {
|
): Uint8Array[] {
|
||||||
|
// Max pages index is 4 bytes, so we can fit up to 65535 pages of data
|
||||||
|
const maxDataSize = 0xffff * (FRAME_CONSTANTS.HEADER_SIZE + FRAME_CONSTANTS.MAX_DATA_SIZE + FRAME_CONSTANTS.FOOTER_SIZE);
|
||||||
|
if (data.length > maxDataSize) {
|
||||||
|
throw new Error(`Data size ${data.length} exceeds max size ${maxDataSize}`);
|
||||||
|
}
|
||||||
if (data.length <= FRAME_CONSTANTS.MAX_DATA_SIZE || !requireFragmentation) {
|
if (data.length <= FRAME_CONSTANTS.MAX_DATA_SIZE || !requireFragmentation) {
|
||||||
console.debug(`[ProtocolManager] Frame size ${data.length} is less than max size ${FRAME_CONSTANTS.MAX_DATA_SIZE}, not fragmented`);
|
console.debug(`[ProtocolManager] Frame size ${data.length} is less than max size ${FRAME_CONSTANTS.MAX_DATA_SIZE}, not fragmented`);
|
||||||
return [this.createSingleFrame(type, data, head)];
|
return [this.createSingleFrame(type, data, head)];
|
||||||
|
|
@ -40,7 +44,7 @@ export class ProtocolManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static createSingleFrame(type: number, data: Uint8Array, head: number): Uint8Array {
|
private static createSingleFrame(type: COMMAND_TYPES, data: Uint8Array, head: FRAME_HEAD): Uint8Array {
|
||||||
const buffer = new Uint8Array(FRAME_CONSTANTS.HEADER_SIZE + data.length + FRAME_CONSTANTS.FOOTER_SIZE);
|
const buffer = new Uint8Array(FRAME_CONSTANTS.HEADER_SIZE + data.length + FRAME_CONSTANTS.FOOTER_SIZE);
|
||||||
let offset = 0;
|
let offset = 0;
|
||||||
|
|
||||||
|
|
@ -71,7 +75,7 @@ export class ProtocolManager {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static createFragmentedFrames(type: number, data: Uint8Array, head: number): Uint8Array[] {
|
private static createFragmentedFrames(type: COMMAND_TYPES, data: Uint8Array, head: FRAME_HEAD): Uint8Array[] {
|
||||||
const frames: Uint8Array[] = [];
|
const frames: Uint8Array[] = [];
|
||||||
const totalSize = data.length;
|
const totalSize = data.length;
|
||||||
const maxDataSize = FRAME_CONSTANTS.MAX_DATA_SIZE;
|
const maxDataSize = FRAME_CONSTANTS.MAX_DATA_SIZE;
|
||||||
|
|
@ -92,9 +96,7 @@ export class ProtocolManager {
|
||||||
buffer[offset++] = (totalPages >> 8) & 0xff;
|
buffer[offset++] = (totalPages >> 8) & 0xff;
|
||||||
buffer[offset++] = totalPages & 0xff;
|
buffer[offset++] = totalPages & 0xff;
|
||||||
|
|
||||||
// curPage (descending order usually? No, BleManagerV2 comments said: "Protocol specifies: page numbers count down from highest to 0")
|
// Protocol specifies: page numbers count down from highest to 0
|
||||||
// Wait, ProtocolUtilsV2 code:
|
|
||||||
// const curPageVal = totalPages - 1 - i;
|
|
||||||
const curPageVal = totalPages - 1 - i;
|
const curPageVal = totalPages - 1 - i;
|
||||||
|
|
||||||
buffer[offset++] = (curPageVal >> 8) & 0xff;
|
buffer[offset++] = (curPageVal >> 8) & 0xff;
|
||||||
|
|
@ -103,13 +105,15 @@ export class ProtocolManager {
|
||||||
// dataLen
|
// dataLen
|
||||||
buffer[offset++] = (chunk.length >> 8) & 0xff;
|
buffer[offset++] = (chunk.length >> 8) & 0xff;
|
||||||
buffer[offset++] = chunk.length & 0xff;
|
buffer[offset++] = chunk.length & 0xff;
|
||||||
console.debug(`chunk length = ${chunk.length}, buffer 8 header = ${buffer.slice(0, 8).toString()}`)
|
const hexHeader = Array.from(buffer.slice(0, offset)).map(b => b.toString(16).padStart(2, '0')).join(' ');
|
||||||
|
console.debug(`chunk length = ${chunk.length}, buffer 8 header = ${hexHeader}`)
|
||||||
// data
|
// data
|
||||||
buffer.set(chunk, offset);
|
buffer.set(chunk, offset);
|
||||||
offset += chunk.length;
|
offset += chunk.length;
|
||||||
|
|
||||||
buffer[offset] = this.calculateChecksum(buffer.slice(0, offset));
|
buffer[offset] = this.calculateChecksum(buffer.slice(0, offset));
|
||||||
|
const verify = this.verifyChecksum(buffer.slice(0, offset), buffer[offset]);
|
||||||
|
console.debug(`[ProtocolManager] Verify checksum: ${verify}`);
|
||||||
frames.push(buffer);
|
frames.push(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {BleClient} from '../core/BleClient';
|
import {BleClient} from '../core/BleClient';
|
||||||
import {ProtocolManager} from '../protocol/ProtocolManager';
|
import {ProtocolManager} from '../protocol/ProtocolManager';
|
||||||
import {BLE_UUIDS, FRAME_CONSTANTS} from '../protocol/Constants';
|
import {BLE_UUIDS, COMMAND_TYPES, FRAME_CONSTANTS} from '../protocol/Constants';
|
||||||
import {ProtocolFrame} from '../protocol/types';
|
import {ProtocolFrame} from '../protocol/types';
|
||||||
import {Buffer} from 'buffer';
|
import {Buffer} from 'buffer';
|
||||||
import {Subscription} from 'react-native-ble-plx';
|
import {Subscription} from 'react-native-ble-plx';
|
||||||
|
|
@ -139,7 +139,7 @@ export class BleProtocolService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async send(deviceId: string, type: number, data: object | ArrayBuffer, onProgress?: (progress: number) => void): Promise<void> {
|
public async send(deviceId: string, type: COMMAND_TYPES, data: object | ArrayBuffer, onProgress?: (progress: number) => void): Promise<void> {
|
||||||
let payload: Uint8Array;
|
let payload: Uint8Array;
|
||||||
if (data instanceof ArrayBuffer) {
|
if (data instanceof ArrayBuffer) {
|
||||||
payload = new Uint8Array(data);
|
payload = new Uint8Array(data);
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ export class FileTransferService {
|
||||||
return FileTransferService.instance;
|
return FileTransferService.instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async transferFile(deviceId: string, filePath: string, type: number, onProgress?: (progress: number) => void): Promise<void> {
|
public async transferFile(deviceId: string, filePath: string, type: COMMAND_TYPES, onProgress?: (progress: number) => void): Promise<void> {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(filePath);
|
const response = await fetch(filePath);
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue