Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
J
jensen
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Skye Yu
jensen
Commits
c2355191
Commit
c2355191
authored
Aug 05, 2025
by
martin hou
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 录音试听测试
parent
2589667c
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
325 additions
and
122 deletions
+325
-122
jensen.d.ts
jensen.d.ts
+17
-6
audio-worker.js
src/audio-worker.js
+12
-7
index.tsx
src/index.tsx
+89
-17
jensen.js
src/utils/jensen.js
+130
-92
waveform-worker.js
src/waveform-worker.js
+77
-0
No files found.
jensen.d.ts
View file @
c2355191
...
@@ -5,6 +5,13 @@ export type DeviceInfo = {
...
@@ -5,6 +5,13 @@ export type DeviceInfo = {
versionCode
:
string
;
// 固件版本号的字符串表示,如1.2.3
versionCode
:
string
;
// 固件版本号的字符串表示,如1.2.3
};
};
// 电池电量信息
export
type
BatteryStatus
=
{
status
:
'idle'
|
'charging'
|
'full'
;
// 电池状态,idle:闲置,charging:充电中,full:满电
battery
:
number
;
// 电量百分比,整型,0~100
voltage
:
number
;
// 电池电压,单位:微伏
}
// 常规指令的应答结构,表示指令的结果是成功或是失败
// 常规指令的应答结构,表示指令的结果是成功或是失败
export
type
ReturnStruct
=
{
export
type
ReturnStruct
=
{
common
:
{
result
:
'failed'
|
'success'
};
common
:
{
result
:
'failed'
|
'success'
};
...
@@ -168,14 +175,17 @@ declare class Jensen {
...
@@ -168,14 +175,17 @@ declare class Jensen {
// 注意:文件传输进度和数据并不是同时到达的,在文件传输到100%时才会开始调用on回调进行转移数据
// 注意:文件传输进度和数据并不是同时到达的,在文件传输到100%时才会开始调用on回调进行转移数据
getFile
:
(
fileName
:
string
,
length
:
number
,
on
?:
(
msg
:
Uint8Array
|
'fail'
)
=>
void
,
onprogress
?:
(
size
:
number
)
=>
void
)
=>
void
;
getFile
:
(
fileName
:
string
,
length
:
number
,
on
?:
(
msg
:
Uint8Array
|
'fail'
)
=>
void
,
onprogress
?:
(
size
:
number
)
=>
void
)
=>
void
;
// 持续传输文件,filename为文件名称,length为文件长度,ondata为数据回调,seconds为超时时长
transferFile
:
(
filename
:
string
,
length
:
number
,
ondata
:
(
msg
:
Uint8Array
|
'fail'
)
=>
void
,
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
// 获取指定长度的录音文件内容,length参数可以小于或等于文件的原始长度,其它参数与getFile()方法一致
// 获取指定长度的录音文件内容,length参数可以小于或等于文件的原始长度,其它参数与getFile()方法一致
getFilePart
:
(
fileName
:
string
,
length
:
number
,
on
?:
(
msg
:
Uint8Array
|
'fail'
)
=>
void
,
onprogress
?:
(
size
:
number
)
=>
void
)
=>
void
;
getFilePart
:
(
fileName
:
string
,
length
:
number
,
on
?:
(
msg
:
Uint8Array
|
'fail'
)
=>
void
,
onprogress
?:
(
size
:
number
)
=>
void
)
=>
void
;
// 暂不使用
// 暂不使用
getFileBlock
:
(
fileName
:
string
,
length
:
number
,
on
?:
(
msg
:
Uint8Array
|
'fail'
)
=>
void
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
getFileBlock
:
(
fileName
:
string
,
length
:
number
,
on
?:
(
msg
:
Uint8Array
|
'fail'
)
=>
void
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
// 录音文件随机读取,从指定位置起读取指定数量个字节
readFile
:
(
fname
:
string
,
offset
:
number
,
length
:
number
)
=>
Promise
<
Uint8Array
>
;
// 传输文件
transferFile
:
(
filename
:
string
,
length
:
number
,
ondata
:
(
msg
:
Uint8Array
|
'fail'
)
=>
void
,
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
// 请求固件更新
// 请求固件更新
// #versionNumber 新固件的版本号
// #versionNumber 新固件的版本号
...
@@ -183,6 +193,9 @@ declare class Jensen {
...
@@ -183,6 +193,9 @@ declare class Jensen {
// #time 超时时长
// #time 超时时长
requestFirmwareUpgrade
:
(
versionNumber
:
number
,
length
:
number
,
time
?:
number
)
=>
Promise
<
{
result
:
'accepted'
|
'fail'
}
>
;
requestFirmwareUpgrade
:
(
versionNumber
:
number
,
length
:
number
,
time
?:
number
)
=>
Promise
<
{
result
:
'accepted'
|
'fail'
}
>
;
// 获取电池电量信息
getBatteryStatus
:
(
time
?:
number
)
=>
Promise
<
BatteryStatus
>
;
// 发送新固件内容到设备端
// 发送新固件内容到设备端
// #data 为固件数据内容
// #data 为固件数据内容
// #seconds 为超时时长
// #seconds 为超时时长
...
@@ -277,9 +290,6 @@ declare class Jensen {
...
@@ -277,9 +290,6 @@ declare class Jensen {
// 获取实时音频流数据
// 获取实时音频流数据
getRealtime
:
(
frames
:
number
)
=>
Promise
<
{
data
:
Uint8Array
;
rest
:
number
}
>
;
getRealtime
:
(
frames
:
number
)
=>
Promise
<
{
data
:
Uint8Array
;
rest
:
number
}
>
;
// 录音文件随机读取,从指定位置起读取指定数量个字节
readFile
:
(
fname
:
string
,
offset
:
number
,
length
:
number
)
=>
Promise
<
Uint8Array
>
;
// 请求设备提示音更新
// 请求设备提示音更新
requestToneUpdate
:
(
signature
:
string
,
size
:
number
,
seconds
?:
number
)
=>
Promise
<
ToneUpdateResponse
>
;
requestToneUpdate
:
(
signature
:
string
,
size
:
number
,
seconds
?:
number
)
=>
Promise
<
ToneUpdateResponse
>
;
...
@@ -291,6 +301,7 @@ declare class Jensen {
...
@@ -291,6 +301,7 @@ declare class Jensen {
// 更新设备UAC固件
// 更新设备UAC固件
updateUAC
:
(
data
:
Uint8Array
,
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
updateUAC
:
(
data
:
Uint8Array
,
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
}
}
export
=
Jensen
;
export
=
Jensen
;
src/audio-worker.js
View file @
c2355191
...
@@ -31,36 +31,41 @@ async function initFFmpeg() {
...
@@ -31,36 +31,41 @@ async function initFFmpeg() {
}
}
// 解码mp3数据为pcm数据
// 解码mp3数据为pcm数据
async
function
decode_mp3
(
data
)
{
async
function
decode_mp3
(
req
)
{
try
{
try
{
const
ffmpeg
=
await
initFFmpeg
();
const
ffmpeg
=
await
initFFmpeg
();
// 检查FFmpeg是否已加载
// 检查FFmpeg是否已加载
if
(
!
ffmpeg
||
!
ffmpeg
.
loaded
)
{
if
(
!
ffmpeg
||
!
ffmpeg
.
loaded
)
{
throw
new
Error
(
'FFmpeg not properly loaded'
);
// 如果没有加载完成,就一直等待
while
(
!
ffmpeg
||
!
ffmpeg
.
loaded
)
{
await
new
Promise
(
resolve
=>
setTimeout
(
resolve
,
100
));
}
// throw new Error('FFmpeg not properly loaded');
}
}
console
.
log
(
'FFmpeg is ready, starting MP3 decode...'
);
console
.
log
(
'FFmpeg is ready, starting MP3 decode...'
);
// 将MP3数据写入FFmpeg
// 将MP3数据写入FFmpeg
await
ffmpeg
.
writeFile
(
'input.mp3'
,
data
);
let
fname
=
req
.
name
;
await
ffmpeg
.
writeFile
(
fname
+
'.mp3'
,
req
.
data
);
// 使用FFmpeg解码MP3为PCM s16le格式
// 使用FFmpeg解码MP3为PCM s16le格式
await
ffmpeg
.
exec
([
await
ffmpeg
.
exec
([
'-i'
,
'input
.mp3'
,
'-i'
,
fname
+
'
.mp3'
,
'-f'
,
's16le'
,
'-f'
,
's16le'
,
'-acodec'
,
'pcm_s16le'
,
'-acodec'
,
'pcm_s16le'
,
'-ar'
,
'16000'
,
'-ar'
,
'16000'
,
'-ac'
,
'1'
,
'-ac'
,
'1'
,
'
output.pcm'
fname
+
'-
output.pcm'
]);
]);
// 读取解码后的PCM数据
// 读取解码后的PCM数据
const
pcmData
=
await
ffmpeg
.
readFile
(
'output.pcm'
);
const
pcmData
=
await
ffmpeg
.
readFile
(
'output.pcm'
);
// 清理临时文件
// 清理临时文件
await
ffmpeg
.
deleteFile
(
'input
.mp3'
);
await
ffmpeg
.
deleteFile
(
fname
+
'
.mp3'
);
await
ffmpeg
.
deleteFile
(
'
output.pcm'
);
await
ffmpeg
.
deleteFile
(
fname
+
'-
output.pcm'
);
// 将Uint8Array转换为Uint16Array (s16le格式)
// 将Uint8Array转换为Uint16Array (s16le格式)
const
uint8Array
=
new
Uint8Array
(
pcmData
);
const
uint8Array
=
new
Uint8Array
(
pcmData
);
...
...
src/index.tsx
View file @
c2355191
...
@@ -98,7 +98,9 @@ export function Home() {
...
@@ -98,7 +98,9 @@ export function Home() {
}
}
const
getTime
=
async
()
=>
{
const
getTime
=
async
()
=>
{
let
time
=
await
jensen
.
getTime
();
console
.
log
(
jensen
);
jensen
.
dump
();
let
time
=
await
jensen
.
getTime
(
5
);
alert
(
JSON
.
stringify
(
time
));
alert
(
JSON
.
stringify
(
time
));
}
}
...
@@ -223,11 +225,17 @@ export function Home() {
...
@@ -223,11 +225,17 @@ export function Home() {
// 先创建audio-worker,给到后面使用
// 先创建audio-worker,给到后面使用
const
audioWorker
=
new
Worker
(
new
URL
(
'./audio-worker.js'
,
import
.
meta
.
url
),
{
type
:
'module'
});
const
audioWorker
=
new
Worker
(
new
URL
(
'./audio-worker.js'
,
import
.
meta
.
url
),
{
type
:
'module'
});
const
waveformWorker
=
new
Worker
(
new
URL
(
'./waveform-worker.js'
,
import
.
meta
.
url
),
{
type
:
'module'
});
waveformWorker
.
onmessage
=
(
e
)
=>
{
console
.
log
(
'waveformWorker'
,
e
);
}
audioWorker
.
onmessage
=
(
e
)
=>
{
audioWorker
.
onmessage
=
(
e
)
=>
{
// console.log(e);
// console.log(e);
if
(
e
.
data
.
waveformData
)
if
(
e
.
data
.
waveformData
)
{
{
console
.
log
(
e
.
data
.
waveformData
);
console
.
log
(
'waveform'
,
e
.
data
.
waveformData
);
// 把e.data.waveformData追加到waveformData的末尾
// 把e.data.waveformData追加到waveformData的末尾
// let waveform = [];
// let waveform = [];
/*
/*
...
@@ -292,6 +300,7 @@ export function Home() {
...
@@ -292,6 +300,7 @@ export function Home() {
const
prepareAudio
=
()
=>
{
const
prepareAudio
=
()
=>
{
const
mediaSource
=
new
MediaSource
();
const
mediaSource
=
new
MediaSource
();
const
audioElement
=
document
.
createElement
(
'audio'
);
const
audioElement
=
document
.
createElement
(
'audio'
);
audioElement
.
autoplay
=
true
;
audioElement
.
src
=
URL
.
createObjectURL
(
mediaSource
);
audioElement
.
src
=
URL
.
createObjectURL
(
mediaSource
);
document
.
body
.
appendChild
(
audioElement
);
document
.
body
.
appendChild
(
audioElement
);
...
@@ -299,34 +308,34 @@ export function Home() {
...
@@ -299,34 +308,34 @@ export function Home() {
// Create source buffer for MP3
// Create source buffer for MP3
let
sourceBuffer
=
mediaSource
.
addSourceBuffer
(
'audio/mpeg'
);
let
sourceBuffer
=
mediaSource
.
addSourceBuffer
(
'audio/mpeg'
);
setSourceBuffer
(
sourceBuffer
);
setSourceBuffer
(
sourceBuffer
);
// sourceBuffer.mode = 'sequence';
alert
(
'sourceopen'
);
alert
(
'sourceopen'
);
// Feed MP3 data to source buffer
// Feed MP3 data to source buffer
sourceBuffer
.
addEventListener
(
'updateend'
,
()
=>
{
sourceBuffer
.
addEventListener
(
'updateend'
,
()
=>
{
if
(
!
sourceBuffer
.
updating
&&
mediaSource
.
readyState
===
'open'
)
{
// dequeue();
mediaSource
.
endOfStream
();
audioElement
.
play
();
}
if
(
mp3
.
length
>
0
)
{
sourceBuffer
.
appendBuffer
(
mp3
.
shift
());
}
});
});
});
});
}
}
const
enqueue
=
(
clip
:
Uint8Array
)
=>
{
const
dequeue
=
()
=>
{
if
(
!
sourceBuffer
)
return
;
if
(
sourceBuffer
?.
updating
==
false
&&
mp3
.
length
>
0
&&
sourceBuffer
.
buffered
.
length
<
100
)
if
(
!
sourceBuffer
.
updating
&&
mp3
.
length
===
0
)
{
{
let
clip
=
mp3
.
shift
();
sourceBuffer
.
appendBuffer
(
clip
);
sourceBuffer
.
appendBuffer
(
clip
);
}
else
{
console
.
log
(
'appendBuffer'
,
clip
.
length
);
mp3
.
push
(
clip
);
}
else
{
setTimeout
(()
=>
dequeue
(),
100
);
}
}
}
}
const
mp3data
:
any
[]
=
[];
const
test
=
async
()
=>
{
const
test
=
async
()
=>
{
let
idx
=
prompt
(
'请输入文件序号'
,
'
0
'
);
let
idx
=
prompt
(
'请输入文件序号'
,
'
8
'
);
if
(
idx
===
null
||
idx
===
undefined
)
return
;
if
(
idx
===
null
||
idx
===
undefined
)
return
;
let
file
=
files
[
parseInt
(
idx
)];
let
file
=
files
[
parseInt
(
idx
)];
if
(
file
===
null
||
file
===
undefined
)
return
alert
(
'文件不存在'
);
if
(
file
===
null
||
file
===
undefined
)
return
alert
(
'文件不存在'
);
...
@@ -334,11 +343,73 @@ export function Home() {
...
@@ -334,11 +343,73 @@ export function Home() {
jensen
.
transferFile
(
file
.
name
,
file
.
length
,
(
data
:
Uint8Array
|
'fail'
)
=>
{
jensen
.
transferFile
(
file
.
name
,
file
.
length
,
(
data
:
Uint8Array
|
'fail'
)
=>
{
if
(
data
instanceof
Uint8Array
)
if
(
data
instanceof
Uint8Array
)
{
{
enqueue
(
data
);
if
(
sourceBuffer
?.
updating
==
false
)
{
sourceBuffer
.
appendBuffer
(
data
);
console
.
log
(
'directly appendBuffer'
,
data
.
length
);
}
else
{
console
.
log
(
'enqueue'
,
data
.
length
);
mp3
.
push
(
data
);
dequeue
();
}
mp3data
.
push
(
data
);
let
totalLength
=
0
;
for
(
let
i
=
0
;
i
<
mp3data
.
length
;
i
++
)
{
totalLength
+=
mp3data
[
i
].
length
;
}
if
(
totalLength
==
file
.
length
)
{
let
audioData
=
new
Uint8Array
(
totalLength
);
let
offset
=
0
;
for
(
let
i
=
0
;
i
<
mp3data
.
length
;
i
++
)
{
audioData
.
set
(
mp3data
[
i
],
offset
);
offset
+=
mp3data
[
i
].
length
;
}
decodeAudioData
(
audioData
);
}
}
}
});
});
}
}
const
decodeAudioData
=
(
audioData
:
Uint8Array
)
=>
{
// 将audioData分成10块,分别发送给audioWorker进行处理
let
clips
=
1
;
let
blockSize
=
Math
.
ceil
(
audioData
.
length
/
clips
);
let
audioContext
=
new
AudioContext
();
for
(
let
i
=
0
;
i
<
clips
;
i
++
)
{
let
block
=
audioData
.
buffer
.
slice
(
i
*
blockSize
,
(
i
+
1
)
*
blockSize
);
let
name
=
'block-'
+
i
;
// audioWorker.postMessage({ data: block, name: name });
audioContext
.
decodeAudioData
(
block
).
then
((
buffer
)
=>
{
// console.log('decodeAudioData' + i, buffer);
waveformWorker
.
postMessage
({
id
:
name
,
pcmdata
:
buffer
});
}).
catch
((
err
)
=>
{
console
.
log
(
'decodeAudioData'
+
i
,
err
);
});
}
}
const
transmit
=
()
=>
{
let
idx
=
prompt
(
'请输入文件序号'
,
'10'
);
if
(
idx
===
null
||
idx
===
undefined
)
return
;
let
file
=
files
[
parseInt
(
idx
)];
if
(
file
===
null
||
file
===
undefined
)
return
alert
(
'文件不存在'
);
jensen
.
getFile
(
file
.
name
,
file
.
length
,
(
data
:
Uint8Array
|
'fail'
)
=>
{},
(
b
:
number
)
=>
{
console
.
log
(
'progress'
,
b
)});
setTimeout
(()
=>
{
jensen
.
stopReceive
();
console
.
log
(
'stop receive.......'
);
setTimeout
(()
=>
{
jensen
.
resumeReceive
();
console
.
log
(
'resume receive.......'
);
},
1500
);
},
5000
);
}
return
(
return
(
<>
<>
<
div
style=
{
{
display
:
'flex'
,
flexDirection
:
'row'
,
gap
:
'16px'
,
padding
:
'16px'
,
alignItems
:
'center'
,
flexWrap
:
'wrap'
}
}
>
<
div
style=
{
{
display
:
'flex'
,
flexDirection
:
'row'
,
gap
:
'16px'
,
padding
:
'16px'
,
alignItems
:
'center'
,
flexWrap
:
'wrap'
}
}
>
...
@@ -346,6 +417,7 @@ export function Home() {
...
@@ -346,6 +417,7 @@ export function Home() {
<
button
onClick=
{
listFiles
}
>
文件列表
</
button
>
<
button
onClick=
{
listFiles
}
>
文件列表
</
button
>
<
button
onClick=
{
prepareAudio
}
>
准备音频
</
button
>
<
button
onClick=
{
prepareAudio
}
>
准备音频
</
button
>
<
button
onClick=
{
test
}
>
传输与播放
</
button
>
<
button
onClick=
{
test
}
>
传输与播放
</
button
>
<
button
onClick=
{
transmit
}
>
传输中断测试
</
button
>
<
button
onClick=
{
getFilePart
}
>
获取文件
</
button
>
<
button
onClick=
{
getFilePart
}
>
获取文件
</
button
>
<
button
onClick=
{
writeSN
}
>
SN写号
</
button
>
<
button
onClick=
{
writeSN
}
>
SN写号
</
button
>
<
button
onClick=
{
getTime
}
>
获取时间
</
button
>
<
button
onClick=
{
getTime
}
>
获取时间
</
button
>
...
...
src/utils/jensen.js
View file @
c2355191
import
{
Logger
as
internalLogger
,
formatTime
,
shortcutKeys
,
sliceTime
}
from
'./utils'
;
import
{
Logger
as
internalLogger
,
formatTime
,
shortcutKeys
,
sliceTime
}
from
'./utils'
;
import
md5
from
'js-md5'
;
const
INVAILD
=
0x00
;
const
INVAILD
=
0x00
;
const
QUERY_DEVICE_INFO
=
0x01
;
const
QUERY_DEVICE_INFO
=
0x01
;
...
@@ -26,7 +27,7 @@ const TONE_UPDATE = 0x17;
...
@@ -26,7 +27,7 @@ const TONE_UPDATE = 0x17;
const
REQUEST_UAC_UPDATE
=
0x18
;
const
REQUEST_UAC_UPDATE
=
0x18
;
const
UAC_UPDATE
=
0x19
;
const
UAC_UPDATE
=
0x19
;
const
FACTORY_RESET
=
0xf00b
;
const
FACTORY_RESET
=
0xf00b
;
const
GET_BATTERY_STATUS
=
0x1004
;
const
REALTIME_READ_SETTING
=
0x20
;
const
REALTIME_READ_SETTING
=
0x20
;
const
REALTIME_CONTROL
=
0x21
;
const
REALTIME_CONTROL
=
0x21
;
const
REALTIME_TRANSFER
=
0x22
;
const
REALTIME_TRANSFER
=
0x22
;
...
@@ -50,20 +51,20 @@ const COMMAND_NAMES = {
...
@@ -50,20 +51,20 @@ const COMMAND_NAMES = {
[
DELETE_FILE
]:
'delete-file'
,
[
DELETE_FILE
]:
'delete-file'
,
[
REQUEST_FIRMWARE_UPGRADE
]:
'request-firmware-upgrade'
,
[
REQUEST_FIRMWARE_UPGRADE
]:
'request-firmware-upgrade'
,
[
FIRMWARE_UPLOAD
]:
'firmware-upload'
,
[
FIRMWARE_UPLOAD
]:
'firmware-upload'
,
[
READ_CARD_INFO
]:
'read
-card-
info'
,
[
READ_CARD_INFO
]:
'read
card
info'
,
[
FORMAT_CARD
]:
'format
-
card'
,
[
FORMAT_CARD
]:
'format
card'
,
[
GET_RECORDING_FILE
]:
'get
-recording-
file'
,
[
GET_RECORDING_FILE
]:
'get
recording
file'
,
[
RESTORE_FACTORY_SETTINGS
]:
'restore
-factory-
settings'
,
[
RESTORE_FACTORY_SETTINGS
]:
'restore
factory
settings'
,
[
SCHEDULE_INFO
]:
'
calendar
'
,
[
SCHEDULE_INFO
]:
'
send meeting schedule info
'
,
[
DEVICE_MSG_TEST
]:
'test'
,
[
DEVICE_MSG_TEST
]:
'
device msg
test'
,
[
BNC_DEMO_TEST
]:
'bnc
-demo
'
,
[
BNC_DEMO_TEST
]:
'bnc
demo test
'
,
[
GET_SETTINGS
]:
'get-settings'
,
[
GET_SETTINGS
]:
'get-settings'
,
[
SET_SETTINGS
]:
'set-settings'
,
[
SET_SETTINGS
]:
'set-settings'
,
[
GET_FILE_BLOCK
]:
'get
-file-
block'
,
[
GET_FILE_BLOCK
]:
'get
file
block'
,
[
FACTORY_RESET
]:
'factory
-
reset'
,
[
FACTORY_RESET
]:
'factory
reset'
,
[
TEST_SN_WRITE
]:
'test
-sn-
write'
,
[
TEST_SN_WRITE
]:
'test
sn
write'
,
[
RECORD_TEST_START
]:
'record
-test-
start'
,
[
RECORD_TEST_START
]:
'record
test
start'
,
[
RECORD_TEST_END
]:
'record
-test-
end'
,
[
RECORD_TEST_END
]:
'record
test
end'
,
[
BLUETOOTH_SCAN
]:
'bluetooth-scan'
,
[
BLUETOOTH_SCAN
]:
'bluetooth-scan'
,
[
BLUETOOTH_CMD
]:
'bluetooth-cmd'
,
[
BLUETOOTH_CMD
]:
'bluetooth-cmd'
,
[
BLUETOOTH_STATUS
]:
'bluetooth-status'
[
BLUETOOTH_STATUS
]:
'bluetooth-status'
...
@@ -86,9 +87,11 @@ function Jensen(log, conn) {
...
@@ -86,9 +87,11 @@ function Jensen(log, conn) {
let
totalBytes
=
0
;
let
totalBytes
=
0
;
let
handlers
=
{};
let
handlers
=
{};
let
pid
=
0
;
let
pid
=
0
;
let
recvable
=
true
;
let
self
=
this
;
let
self
=
this
;
this
.
data
=
{};
this
.
data
=
{};
this
.
sqidx
=
new
Date
().
getTime
();
// 消息
// 消息
this
.
decodeTimeout
=
0
;
this
.
decodeTimeout
=
0
;
this
.
timewait
=
1
;
this
.
timewait
=
1
;
...
@@ -122,6 +125,20 @@ function Jensen(log, conn) {
...
@@ -122,6 +125,20 @@ function Jensen(log, conn) {
self
.
versionNumber
=
null
;
self
.
versionNumber
=
null
;
};
};
function
determineModel
(
productId
)
{
if
(
productId
==
0xb00c
)
return
'hidock-h1'
;
if
(
productId
==
0xb00d
)
return
'hidock-h1e'
;
if
(
productId
==
0xb00e
)
return
'hidock-p1'
;
if
(
productId
==
0xb00f
)
return
'hidock-p1:mini'
;
if
(
productId
==
0x0100
)
return
'hidock-h1'
;
if
(
productId
==
0x0101
)
return
'hidock-h1e'
;
if
(
productId
==
0x0102
)
return
'hidock-h1'
;
if
(
productId
==
0x0103
)
return
'hidock-h1e'
;
if
(
productId
==
0x2040
)
return
'hidock-p1'
;
if
(
productId
==
0x2041
)
return
'hidock-p1:mini'
;
return
'unknown'
;
}
const
setup
=
async
function
(
disableOnConnect
)
{
const
setup
=
async
function
(
disableOnConnect
)
{
if
(
ready
)
return
;
if
(
ready
)
return
;
self
.
versionCode
=
null
;
self
.
versionCode
=
null
;
...
@@ -132,10 +149,7 @@ function Jensen(log, conn) {
...
@@ -132,10 +149,7 @@ function Jensen(log, conn) {
await
device
.
claimInterface
(
0
);
await
device
.
claimInterface
(
0
);
await
device
.
selectAlternateInterface
(
0
,
0
);
await
device
.
selectAlternateInterface
(
0
,
0
);
pid
=
device
.
productId
;
pid
=
device
.
productId
;
self
.
model
=
device
.
productId
==
0xb00c
?
'hidock-h1'
self
.
model
=
determineModel
(
device
.
productId
);
:
device
.
productId
==
0xb00d
?
'hidock-h1e'
:
device
.
productId
==
0xb00e
?
'hidock-p1'
:
device
.
productId
==
0xb00f
?
'hidock-p1:mini'
:
'unknown'
;
Logger
.
info
(
'jensen'
,
'connect'
,
'device pid: '
+
device
.
productId
);
Logger
.
info
(
'jensen'
,
'connect'
,
'device pid: '
+
device
.
productId
);
}
catch
(
e
)
{
}
catch
(
e
)
{
Logger
.
error
(
'jensen'
,
'setup'
,
String
(
e
));
Logger
.
error
(
'jensen'
,
'setup'
,
String
(
e
));
...
@@ -152,26 +166,27 @@ function Jensen(log, conn) {
...
@@ -152,26 +166,27 @@ function Jensen(log, conn) {
}
}
};
};
this
.
initialize
=
async
function
()
{
this
.
initialize
=
async
function
()
{
if
(
conn
)
if
(
conn
)
{
{
if
(
!
conn
.
opened
)
conn
.
open
();
if
(
!
conn
.
opened
)
conn
.
open
();
await
setup
();
await
setup
();
}
}
return
true
;
return
true
;
}
}
this
.
sequence
=
function
()
{
return
this
.
sqidx
++
;
}
this
.
reconnect
=
async
function
()
{
this
.
reconnect
=
async
function
()
{
try
try
{
{
await
device
.
close
();
await
device
.
close
();
await
device
.
open
();
await
device
.
open
();
ready
=
false
;
ready
=
false
;
await
setup
();
await
setup
();
return
true
;
return
true
;
}
}
catch
(
ex
)
catch
(
ex
)
{
{
Logger
.
error
(
'jensen'
,
'reconnect'
,
ex
);
Logger
.
error
(
'jensen'
,
'reconnect'
,
ex
);
}
}
}
}
...
@@ -182,7 +197,7 @@ function Jensen(log, conn) {
...
@@ -182,7 +197,7 @@ function Jensen(log, conn) {
if
(
r
)
return
;
if
(
r
)
return
;
let
conn
=
await
navigator
.
usb
.
requestDevice
({
let
conn
=
await
navigator
.
usb
.
requestDevice
({
filters
:
[{
vendorId
:
0x10d6
}]
filters
:
[{
vendorId
:
0x10d6
}
,
{
vendorId
:
0x3887
}
]
});
});
await
conn
.
open
();
await
conn
.
open
();
// self.model = conn.productId == 45069 ? 'hidock-h1e' : 'hidock-h1';
// self.model = conn.productId == 45069 ? 'hidock-h1e' : 'hidock-h1';
...
@@ -232,6 +247,19 @@ function Jensen(log, conn) {
...
@@ -232,6 +247,19 @@ function Jensen(log, conn) {
setup
();
setup
();
}
}
this
.
stopReceive
=
function
()
{
recvable
=
false
;
}
this
.
resumeReceive
=
async
function
()
{
recvable
=
true
;
if
(
current
)
trigger
(
null
,
current
.
replace
(
/^cmd-
(\d
+
)
-
(\d
+
)
$/gi
,
'$1'
));
blocks
.
length
=
0
;
totalBytes
=
0
;
// 不发送一下,是不会回应数据的
await
this
.
getTime
(
5
);
}
this
.
isConnected
=
function
()
{
this
.
isConnected
=
function
()
{
return
device
!=
null
;
return
device
!=
null
;
};
};
...
@@ -240,7 +268,7 @@ function Jensen(log, conn) {
...
@@ -240,7 +268,7 @@ function Jensen(log, conn) {
Logger
.
info
(
'jensen'
,
'disconnect'
,
'disconnect'
);
Logger
.
info
(
'jensen'
,
'disconnect'
,
'disconnect'
);
try
{
try
{
await
device
?.
close
();
await
device
?.
close
();
}
catch
(
e
)
{}
}
catch
(
e
)
{
}
};
};
this
.
send
=
function
(
cmd
,
seconds
,
onprogress
)
{
this
.
send
=
function
(
cmd
,
seconds
,
onprogress
)
{
...
@@ -309,8 +337,8 @@ function Jensen(log, conn) {
...
@@ -309,8 +337,8 @@ function Jensen(log, conn) {
let
tag
=
'cmd-'
+
cmd
.
command
+
'-'
+
cmd
.
index
;
let
tag
=
'cmd-'
+
cmd
.
command
+
'-'
+
cmd
.
index
;
let
t
=
seconds
let
t
=
seconds
?
setTimeout
(()
=>
{
?
setTimeout
(()
=>
{
timeout
(
tag
);
timeout
(
tag
);
},
seconds
*
1000
)
},
seconds
*
1000
)
:
null
;
:
null
;
return
new
Promise
((
resolve
,
reject
)
=>
{
return
new
Promise
((
resolve
,
reject
)
=>
{
actions
[
tag
]
=
{
actions
[
tag
]
=
{
...
@@ -322,11 +350,16 @@ function Jensen(log, conn) {
...
@@ -322,11 +350,16 @@ function Jensen(log, conn) {
});
});
};
};
this
.
_trigger
=
function
(
resp
,
msgid
)
{
trigger
(
resp
,
msgid
);
}
const
trigger
=
function
(
resp
,
msgid
)
{
const
trigger
=
function
(
resp
,
msgid
)
{
if
(
current
==
null
)
return
;
if
(
current
==
null
)
return
;
Logger
.
debug
(
'jensen'
,
'trigger'
,
pid
+
':trigger - '
+
current
.
substring
(
0
,
current
.
lastIndexOf
(
'-'
))
+
' <---> cmd-'
+
(
msgid
||
'err'
));
Logger
.
debug
(
'jensen'
,
'trigger'
,
pid
+
':trigger - '
+
current
.
substring
(
0
,
current
.
lastIndexOf
(
'-'
))
+
' <---> cmd-'
+
(
msgid
||
'err'
));
if
(
current
.
substring
(
0
,
current
.
lastIndexOf
(
'-'
))
!=
'cmd-'
+
msgid
)
{
if
(
current
.
substring
(
0
,
current
.
lastIndexOf
(
'-'
))
!=
'cmd-'
+
msgid
)
{
// current = null;
// current = null;
Logger
.
debug
(
'jensen'
,
'trigger'
,
'msgid mismatched'
);
return
;
return
;
}
}
if
(
current
in
actions
==
false
)
{
if
(
current
in
actions
==
false
)
{
...
@@ -345,6 +378,7 @@ function Jensen(log, conn) {
...
@@ -345,6 +378,7 @@ function Jensen(log, conn) {
let
p
=
actions
[
tag
];
let
p
=
actions
[
tag
];
p
.
resolve
(
null
);
p
.
resolve
(
null
);
delete
actions
[
tag
];
delete
actions
[
tag
];
current
=
null
;
};
};
this
.
dump
=
function
()
{
this
.
dump
=
function
()
{
...
@@ -355,7 +389,7 @@ function Jensen(log, conn) {
...
@@ -355,7 +389,7 @@ function Jensen(log, conn) {
};
};
const
tryReceive
=
function
()
{
const
tryReceive
=
function
()
{
if
(
device
)
if
(
device
&&
recvable
)
// console.log('trace', device);
// console.log('trace', device);
device
.
transferIn
(
2
,
RECV_BUFF_SIZE
).
then
((
r
)
=>
{
device
.
transferIn
(
2
,
RECV_BUFF_SIZE
).
then
((
r
)
=>
{
Logger
.
save
?.(
'jensen'
,
'tryReceive'
,
r
?.
data
);
Logger
.
save
?.(
'jensen'
,
'tryReceive'
,
r
?.
data
);
...
@@ -378,9 +412,13 @@ function Jensen(log, conn) {
...
@@ -378,9 +412,13 @@ function Jensen(log, conn) {
blocks
.
push
(
result
.
data
);
blocks
.
push
(
result
.
data
);
tryReceive
();
tryReceive
();
if
(
self
.
decodeTimeout
)
clearTimeout
(
self
.
decodeTimeout
);
if
(
self
.
decodeTimeout
)
clearTimeout
(
self
.
decodeTimeout
);
self
.
decodeTimeout
=
setTimeout
(
function
()
{
tryDecode
();
},
self
.
timewait
);
self
.
decodeTimeout
=
setTimeout
(
function
()
{
tryDecode
();
},
self
.
timewait
);
if
(
self
.
onreceive
)
{
if
(
self
.
onreceive
)
{
try
{
self
.
onreceive
(
totalBytes
);
}
catch
(
e
)
{}
try
{
self
.
onreceive
(
totalBytes
);
}
catch
(
e
)
{
}
}
}
};
};
...
@@ -451,6 +489,7 @@ function Jensen(log, conn) {
...
@@ -451,6 +489,7 @@ function Jensen(log, conn) {
if
(
!
handler
)
handler
=
Jensen
.
handlers
[
msgid
];
if
(
!
handler
)
handler
=
Jensen
.
handlers
[
msgid
];
handler
(
null
,
self
);
handler
(
null
,
self
);
}
catch
(
e
)
{
}
catch
(
e
)
{
console
.
error
(
e
);
trigger
(
e
);
trigger
(
e
);
Logger
.
error
(
'jensen'
,
'decode'
,
'decode error: '
+
String
(
e
));
Logger
.
error
(
'jensen'
,
'decode'
,
'decode error: '
+
String
(
e
));
}
}
...
@@ -667,14 +706,12 @@ Jensen.prototype.listFiles = async function () {
...
@@ -667,14 +706,12 @@ Jensen.prototype.listFiles = async function () {
this
[
tag
]
=
[];
this
[
tag
]
=
[];
this
.
registerHandler
(
QUERY_FILE_LIST
,
(
msg
,
jensen
)
=>
{
this
.
registerHandler
(
QUERY_FILE_LIST
,
(
msg
,
jensen
)
=>
{
console
.
log
(
'tag'
,
tag
);
console
.
log
(
'tag'
,
tag
);
if
(
msg
.
body
.
length
==
0
)
if
(
msg
.
body
.
length
==
0
)
{
{
console
.
log
(
'remove tag1: '
+
tag
);
console
.
log
(
'remove tag1: '
+
tag
);
jensen
[
tag
]
=
null
;
jensen
[
tag
]
=
null
;
return
[];
return
[];
}
}
if
(
jensen
[
tag
]
==
null
)
if
(
jensen
[
tag
]
==
null
)
{
{
console
.
trace
(
'no tag for: '
+
tag
);
console
.
trace
(
'no tag for: '
+
tag
);
return
'x'
;
return
'x'
;
}
}
...
@@ -693,7 +730,7 @@ Jensen.prototype.listFiles = async function () {
...
@@ -693,7 +730,7 @@ Jensen.prototype.listFiles = async function () {
let
fnpad
=
function
(
v
)
{
let
fnpad
=
function
(
v
)
{
return
v
>
9
?
v
:
'0'
+
v
;
return
v
>
9
?
v
:
'0'
+
v
;
};
};
for
(
let
i
=
start
;
i
<
data
.
length
;
)
{
for
(
let
i
=
start
;
i
<
data
.
length
;)
{
let
len
=
0
;
let
len
=
0
;
let
fname
=
[];
let
fname
=
[];
...
@@ -728,24 +765,19 @@ Jensen.prototype.listFiles = async function () {
...
@@ -728,24 +765,19 @@ Jensen.prototype.listFiles = async function () {
ftime
=
new
Date
(
ftime
);
ftime
=
new
Date
(
ftime
);
duration
=
(
flen
/
32
)
*
4
;
duration
=
(
flen
/
32
)
*
4
;
}
}
else
else
{
{
ftime
=
null
;
ftime
=
null
;
}
}
if
(
ver
==
1
)
if
(
ver
==
1
)
{
{
duration
=
duration
*
2
;
duration
=
duration
*
2
;
}
}
else
if
(
ver
==
2
)
else
if
(
ver
==
2
)
{
{
duration
=
(
flen
-
44
)
/
48
/
2
;
duration
=
(
flen
-
44
)
/
48
/
2
;
}
}
else
if
(
ver
==
3
)
else
if
(
ver
==
3
)
{
{
duration
=
(
flen
-
44
)
/
48
/
2
/
2
;
duration
=
(
flen
-
44
)
/
48
/
2
/
2
;
}
}
else
if
(
ver
==
5
)
else
if
(
ver
==
5
)
{
{
duration
=
flen
/
12
;
duration
=
flen
/
12
;
}
}
let
createDate
=
''
;
let
createDate
=
''
;
...
@@ -771,7 +803,7 @@ Jensen.prototype.listFiles = async function () {
...
@@ -771,7 +803,7 @@ Jensen.prototype.listFiles = async function () {
if
(
fcount
==
-
1
)
{
if
(
fcount
==
-
1
)
{
// return [];
// return [];
}
}
// 如果files有重复的signature,那就持续改为不重复的为止
// 如果files有重复的signature,那就持续改为不重复的为止
// Check for duplicate signatures and regenerate if needed
// Check for duplicate signatures and regenerate if needed
const
signatureCounts
=
{};
const
signatureCounts
=
{};
...
@@ -790,11 +822,10 @@ Jensen.prototype.listFiles = async function () {
...
@@ -790,11 +822,10 @@ Jensen.prototype.listFiles = async function () {
// 如果已经等待过长的时间了,那就直接返回好了
// 如果已经等待过长的时间了,那就直接返回好了
let
kv
=
tag
+
'-timer'
;
let
kv
=
tag
+
'-timer'
;
let
now
=
new
Date
().
getTime
();
let
now
=
new
Date
().
getTime
();
if
(
kv
in
jensen
)
if
(
kv
in
jensen
)
{
{
window
.
clearTimeout
(
jensen
[
kv
]);
window
.
clearTimeout
(
jensen
[
kv
]);
}
}
jensen
[
kv
]
=
now
;
jensen
[
kv
]
=
now
;
// 要怎么样触发这个回调?
// 要怎么样触发这个回调?
...
@@ -830,27 +861,6 @@ Jensen.prototype.readFile = async function (filename, offset, length, seconds) {
...
@@ -830,27 +861,6 @@ Jensen.prototype.readFile = async function (filename, offset, length, seconds) {
return
this
.
send
(
new
Command
(
TRANSFER_FILE_PARTIAL
).
body
(
data
),
seconds
);
return
this
.
send
(
new
Command
(
TRANSFER_FILE_PARTIAL
).
body
(
data
),
seconds
);
}
}
Jensen
.
prototype
.
transferFile
=
async
function
(
filename
,
length
,
ondata
,
seconds
)
{
let
fname
=
[];
for
(
let
i
=
0
;
i
<
filename
.
length
;
i
++
)
fname
.
push
(
filename
.
charCodeAt
(
i
));
let
flen
=
0
;
this
.
registerHandler
(
TRANSFER_FILE
,
(
msg
)
=>
{
if
(
msg
!=
null
)
{
flen
+=
msg
.
body
.
length
||
msg
.
body
.
byteLength
;
ondata
(
msg
.
body
);
Logger
.
info
(
'jensen'
,
'transfer-file'
,
`
${
length
}
${
flen
}
`
);
if
(
flen
>=
length
)
{
Logger
.
info
(
'jensen'
,
'transfer-file'
,
'file transfer finish.'
);
return
'OK'
;
}
}
else
{
Logger
.
info
(
'jensen'
,
'transfer-file'
,
'file transfer fail.'
);
ondata
(
'fail'
);
}
});
return
this
.
send
(
new
Command
(
TRANSFER_FILE
).
body
(
fname
),
seconds
);
}
Jensen
.
prototype
.
setTime
=
async
function
(
time
,
seconds
)
{
Jensen
.
prototype
.
setTime
=
async
function
(
time
,
seconds
)
{
let
str
=
let
str
=
time
.
getFullYear
()
+
time
.
getFullYear
()
+
...
@@ -1006,17 +1016,14 @@ Jensen.prototype.getFile = async function (filename, length, ondata, onprogress)
...
@@ -1006,17 +1016,14 @@ Jensen.prototype.getFile = async function (filename, length, ondata, onprogress)
};
};
// this.onreceive = onprogress;
// this.onreceive = onprogress;
this
.
_progress_report
=
{};
this
.
_progress_report
=
{};
this
.
onreceive
=
function
(
recvBytes
)
this
.
onreceive
=
function
(
recvBytes
)
{
{
let
percent
=
Math
.
floor
(
recvBytes
/
length
*
100
);
let
percent
=
Math
.
floor
(
recvBytes
/
length
*
100
);
let
k
=
't'
+
percent
;
let
k
=
't'
+
percent
;
if
(
percent
%
5
==
0
&&
percent
>
0
&&
percent
<
100
)
if
(
percent
%
5
==
0
&&
percent
>
0
&&
percent
<
100
)
{
{
this
.
_progress_report
[
k
]
&&
onprogress
?.(
recvBytes
);
this
.
_progress_report
[
k
]
&&
onprogress
?.(
recvBytes
);
this
.
_progress_report
[
k
]
=
true
;
this
.
_progress_report
[
k
]
=
true
;
}
}
if
(
percent
==
100
)
if
(
percent
==
100
)
{
{
onprogress
?.(
recvBytes
);
onprogress
?.(
recvBytes
);
}
}
}
}
...
@@ -1129,7 +1136,10 @@ Jensen.prototype.getFileBlock = async function (filename, length, ondata) {
...
@@ -1129,7 +1136,10 @@ Jensen.prototype.getFileBlock = async function (filename, length, ondata) {
return
this
.
send
(
new
Command
(
GET_FILE_BLOCK
).
body
(
data
));
return
this
.
send
(
new
Command
(
GET_FILE_BLOCK
).
body
(
data
));
};
};
Jensen
.
prototype
.
getBatteryStatus
=
function
(
seconds
)
{
if
(
this
.
model
!=
'hidock-p1'
)
return
null
;
return
this
.
send
(
new
Command
(
GET_BATTERY_STATUS
),
seconds
);
}
Jensen
.
prototype
.
writeSerialNumber
=
async
function
(
sn
)
{
Jensen
.
prototype
.
writeSerialNumber
=
async
function
(
sn
)
{
let
data
=
[];
let
data
=
[];
for
(
let
i
=
0
;
i
<
sn
.
length
;
i
++
)
{
for
(
let
i
=
0
;
i
<
sn
.
length
;
i
++
)
{
...
@@ -1169,7 +1179,27 @@ Jensen.prototype.sendScheduleInfo = function (infos) {
...
@@ -1169,7 +1179,27 @@ Jensen.prototype.sendScheduleInfo = function (infos) {
return
this
.
send
(
new
Command
(
SCHEDULE_INFO
).
body
(
bodys
));
return
this
.
send
(
new
Command
(
SCHEDULE_INFO
).
body
(
bodys
));
}
}
};
};
Jensen
.
prototype
.
transferFile
=
async
function
(
filename
,
length
,
ondata
,
seconds
)
{
let
fname
=
[];
for
(
let
i
=
0
;
i
<
filename
.
length
;
i
++
)
fname
.
push
(
filename
.
charCodeAt
(
i
));
let
flen
=
0
;
this
.
registerHandler
(
TRANSFER_FILE
,
(
msg
)
=>
{
if
(
msg
!=
null
)
{
flen
+=
msg
.
body
.
length
||
msg
.
body
.
byteLength
;
ondata
(
msg
.
body
);
// Logger.info('jensen', 'transfer-file', `${length} ${flen}`);
if
(
flen
>=
length
)
{
// Logger.info('jensen', 'transfer-file', 'file transfer finish.');
ondata
(
null
);
return
'OK'
;
}
}
else
{
Logger
.
info
(
'jensen'
,
'transfer-file'
,
'file transfer fail.'
);
ondata
(
'fail'
);
}
});
return
this
.
send
(
new
Command
(
TRANSFER_FILE
).
body
(
fname
),
seconds
);
}
Jensen
.
prototype
.
getRealtimeSettings
=
async
function
()
{
Jensen
.
prototype
.
getRealtimeSettings
=
async
function
()
{
return
this
.
send
(
new
Command
(
REALTIME_READ_SETTING
));
return
this
.
send
(
new
Command
(
REALTIME_READ_SETTING
));
};
};
...
@@ -1189,10 +1219,9 @@ Jensen.prototype.getRealtime = async function (frames) {
...
@@ -1189,10 +1219,9 @@ Jensen.prototype.getRealtime = async function (frames) {
let
d
=
(
frames
>>
0
)
&
0xff
;
let
d
=
(
frames
>>
0
)
&
0xff
;
return
this
.
send
(
new
Command
(
REALTIME_TRANSFER
).
body
([
a
,
b
,
c
,
d
]));
return
this
.
send
(
new
Command
(
REALTIME_TRANSFER
).
body
([
a
,
b
,
c
,
d
]));
};
};
Jensen
.
prototype
.
requestToneUpdate
=
async
function
(
signature
,
size
,
seconds
)
{
Jensen
.
prototype
.
requestToneUpdate
=
async
function
(
signature
,
size
,
seconds
)
{
let
data
=
[];
let
data
=
[];
for
(
let
i
=
0
;
i
<
signature
.
length
;
i
+=
2
)
for
(
let
i
=
0
;
i
<
signature
.
length
;
i
+=
2
)
{
{
let
b
=
signature
.
substring
(
i
,
i
+
2
);
let
b
=
signature
.
substring
(
i
,
i
+
2
);
data
.
push
(
parseInt
(
b
,
16
));
data
.
push
(
parseInt
(
b
,
16
));
}
}
...
@@ -1202,13 +1231,12 @@ Jensen.prototype.requestToneUpdate = async function(signature, size, seconds) {
...
@@ -1202,13 +1231,12 @@ Jensen.prototype.requestToneUpdate = async function(signature, size, seconds) {
data
.
push
((
size
>>
0
)
&
0xff
);
data
.
push
((
size
>>
0
)
&
0xff
);
return
this
.
send
(
new
Command
(
REQUEST_TONE_UPDATE
).
body
(
data
),
seconds
);
return
this
.
send
(
new
Command
(
REQUEST_TONE_UPDATE
).
body
(
data
),
seconds
);
}
}
Jensen
.
prototype
.
updateTone
=
async
function
(
toneFile
,
seconds
)
{
Jensen
.
prototype
.
updateTone
=
async
function
(
toneFile
,
seconds
)
{
return
this
.
send
(
new
Command
(
TONE_UPDATE
).
body
(
toneFile
),
seconds
);
return
this
.
send
(
new
Command
(
TONE_UPDATE
).
body
(
toneFile
),
seconds
);
}
}
Jensen
.
prototype
.
requestUACUpdate
=
async
function
(
signature
,
size
,
seconds
)
{
Jensen
.
prototype
.
requestUACUpdate
=
async
function
(
signature
,
size
,
seconds
)
{
let
data
=
[];
let
data
=
[];
for
(
let
i
=
0
;
i
<
signature
.
length
;
i
+=
2
)
for
(
let
i
=
0
;
i
<
signature
.
length
;
i
+=
2
)
{
{
let
b
=
signature
.
substring
(
i
,
i
+
2
);
let
b
=
signature
.
substring
(
i
,
i
+
2
);
data
.
push
(
parseInt
(
b
,
16
));
data
.
push
(
parseInt
(
b
,
16
));
}
}
...
@@ -1218,7 +1246,7 @@ Jensen.prototype.requestUACUpdate = async function(signature, size, seconds) {
...
@@ -1218,7 +1246,7 @@ Jensen.prototype.requestUACUpdate = async function(signature, size, seconds) {
data
.
push
((
size
>>
0
)
&
0xff
);
data
.
push
((
size
>>
0
)
&
0xff
);
return
this
.
send
(
new
Command
(
REQUEST_UAC_UPDATE
).
body
(
data
),
seconds
);
return
this
.
send
(
new
Command
(
REQUEST_UAC_UPDATE
).
body
(
data
),
seconds
);
}
}
Jensen
.
prototype
.
updateUAC
=
async
function
(
uacFile
,
seconds
)
{
Jensen
.
prototype
.
updateUAC
=
async
function
(
uacFile
,
seconds
)
{
return
this
.
send
(
new
Command
(
UAC_UPDATE
).
body
(
uacFile
),
seconds
);
return
this
.
send
(
new
Command
(
UAC_UPDATE
).
body
(
uacFile
),
seconds
);
}
}
Jensen
.
registerHandler
(
REALTIME_CONTROL
,
commonMessageParser
);
Jensen
.
registerHandler
(
REALTIME_CONTROL
,
commonMessageParser
);
...
@@ -1226,6 +1254,16 @@ Jensen.registerHandler(REALTIME_READ_SETTING, (msg) => {
...
@@ -1226,6 +1254,16 @@ Jensen.registerHandler(REALTIME_READ_SETTING, (msg) => {
// console.log(msg);
// console.log(msg);
return
msg
;
return
msg
;
});
});
Jensen
.
registerHandler
(
GET_BATTERY_STATUS
,
(
msg
)
=>
{
let
status
=
msg
.
body
[
0
]
&
0xff
;
let
percent
=
msg
.
body
[
1
]
&
0xff
;
let
voltage
=
((
msg
.
body
[
2
]
&
0xff
)
<<
24
)
|
((
msg
.
body
[
3
]
&
0xff
)
<<
16
)
|
((
msg
.
body
[
4
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
5
]
&
0xff
);
return
{
status
:
status
==
0
?
'idle'
:
(
status
==
1
?
'charging'
:
'full'
),
battery
:
percent
,
voltage
:
voltage
};
})
Jensen
.
registerHandler
(
REALTIME_TRANSFER
,
(
msg
)
=>
{
Jensen
.
registerHandler
(
REALTIME_TRANSFER
,
(
msg
)
=>
{
let
a
=
msg
.
body
[
0
]
&
0xff
;
let
a
=
msg
.
body
[
0
]
&
0xff
;
let
b
=
msg
.
body
[
1
]
&
0xff
;
let
b
=
msg
.
body
[
1
]
&
0xff
;
...
@@ -1336,8 +1374,7 @@ Jensen.registerHandler(READ_CARD_INFO, (msg) => {
...
@@ -1336,8 +1374,7 @@ Jensen.registerHandler(READ_CARD_INFO, (msg) => {
});
});
Jensen
.
registerHandler
(
TRANSFER_FILE_PARTIAL
,
(
msg
)
=>
{
Jensen
.
registerHandler
(
TRANSFER_FILE_PARTIAL
,
(
msg
)
=>
{
let
buf
=
new
Uint8Array
(
msg
.
body
.
length
);
let
buf
=
new
Uint8Array
(
msg
.
body
.
length
);
for
(
let
i
=
0
;
i
<
msg
.
body
.
length
;
i
++
)
for
(
let
i
=
0
;
i
<
msg
.
body
.
length
;
i
++
)
{
{
buf
[
i
]
=
msg
.
body
[
i
]
&
0xff
;
buf
[
i
]
=
msg
.
body
[
i
]
&
0xff
;
}
}
return
buf
;
return
buf
;
...
@@ -1385,6 +1422,7 @@ Jensen.registerHandler(GET_RECORDING_FILE, (msg) => {
...
@@ -1385,6 +1422,7 @@ Jensen.registerHandler(GET_RECORDING_FILE, (msg) => {
Jensen
.
registerHandler
(
BLUETOOTH_SCAN
,
(
msg
)
=>
{
Jensen
.
registerHandler
(
BLUETOOTH_SCAN
,
(
msg
)
=>
{
// console.log('bluetooth-scan', msg);
// console.log('bluetooth-scan', msg);
if
(
msg
.
body
.
length
==
0
)
return
[];
let
nums
=
((
msg
.
body
[
0
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
1
]
&
0xff
);
let
nums
=
((
msg
.
body
[
0
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
1
]
&
0xff
);
let
devices
=
[];
let
devices
=
[];
let
decoder
=
new
TextDecoder
(
'UTF-8'
);
let
decoder
=
new
TextDecoder
(
'UTF-8'
);
...
@@ -1449,7 +1487,7 @@ Jensen.registerHandler(REQUEST_TONE_UPDATE, (msg) => {
...
@@ -1449,7 +1487,7 @@ Jensen.registerHandler(REQUEST_TONE_UPDATE, (msg) => {
else
if
(
rst
==
0x03
)
txt
=
'card-full'
;
else
if
(
rst
==
0x03
)
txt
=
'card-full'
;
else
if
(
rst
==
0x04
)
txt
=
'card-error'
;
else
if
(
rst
==
0x04
)
txt
=
'card-error'
;
else
txt
=
String
(
rst
);
else
txt
=
String
(
rst
);
return
{
code
:
rst
,
result
:
txt
};
return
{
code
:
rst
,
result
:
txt
};
});
});
Jensen
.
registerHandler
(
TONE_UPDATE
,
commonMessageParser
);
Jensen
.
registerHandler
(
TONE_UPDATE
,
commonMessageParser
);
Jensen
.
registerHandler
(
REQUEST_UAC_UPDATE
,
(
msg
)
=>
{
Jensen
.
registerHandler
(
REQUEST_UAC_UPDATE
,
(
msg
)
=>
{
...
@@ -1460,7 +1498,7 @@ Jensen.registerHandler(REQUEST_UAC_UPDATE, (msg) => {
...
@@ -1460,7 +1498,7 @@ Jensen.registerHandler(REQUEST_UAC_UPDATE, (msg) => {
else
if
(
rst
==
0x03
)
txt
=
'card-full'
;
else
if
(
rst
==
0x03
)
txt
=
'card-full'
;
else
if
(
rst
==
0x04
)
txt
=
'card-error'
;
else
if
(
rst
==
0x04
)
txt
=
'card-error'
;
else
txt
=
String
(
rst
);
else
txt
=
String
(
rst
);
return
{
code
:
rst
,
result
:
txt
};
return
{
code
:
rst
,
result
:
txt
};
});
});
Jensen
.
registerHandler
(
UAC_UPDATE
,
commonMessageParser
);
Jensen
.
registerHandler
(
UAC_UPDATE
,
commonMessageParser
);
export
{
Jensen
};
export
{
Jensen
};
\ No newline at end of file
src/waveform-worker.js
0 → 100644
View file @
c2355191
/**
* 模拟 Recorder.getRecordAnalyseData 的功能
* @param {Int16Array} pcmData PCM 原始数据,s16le 格式
* @returns {Uint8Array} 长度固定 1024,范围 0–255 的波形数据
*/
function
getRecordAnalyseData
(
pcmData
)
{
const
BUF_LEN
=
800
;
const
out
=
new
Uint8Array
(
BUF_LEN
);
const
pcm
=
[];
for
(
let
i
=
0
;
i
<
pcmData
.
length
;
i
+=
2
)
{
let
h
=
pcmData
[
i
]
&
0xff
;
let
l
=
pcmData
[
i
+
1
]
&
0xff
;
let
p
=
(
l
<<
8
)
|
h
;
// 如果p是负数,则取反
if
(
p
&
0x8000
)
p
=
(
p
&
0x7fff
)
-
0x8000
;
pcm
.
push
(
p
);
}
const
len
=
pcm
.
length
;
if
(
len
===
0
)
return
out
.
fill
(
128
);
// 空数据,填充中值
const
step
=
len
/
BUF_LEN
;
let
rst
=
[];
for
(
let
i
=
0
;
i
<
BUF_LEN
;
i
++
)
{
const
start
=
Math
.
floor
(
i
*
step
);
const
end
=
Math
.
min
(
Math
.
floor
((
i
+
1
)
*
step
),
len
);
// 计算这一段的平均值(保持正负号,显示真实波形)
let
sum
=
0
;
for
(
let
j
=
start
;
j
<
end
;
j
++
)
{
sum
+=
Math
.
abs
(
pcm
[
j
]);
}
const
avg
=
Math
.
floor
(
sum
/
(
end
-
start
));
rst
.
push
(
avg
);
// 将平均值从 [-32768, 32767] 映射到 [0, 255]
// 128 是中心线(静音),0是最负值,255是最正值
const
normalized
=
avg
/
32767
;
// 归一化到 [0, 1]
out
[
i
]
=
Math
.
max
(
0
,
Math
.
min
(
127
,
Math
.
round
(
normalized
*
127
)));
}
return
out
;
}
self
.
addEventListener
(
'message'
,
async
function
(
e
)
{
try
{
const
task
=
e
.
data
;
// pcmdata的值为浮点类型的0~1,需要转换为s16le格式
const
pcmData
=
new
Int16Array
(
task
.
pcmdata
.
length
);
for
(
let
i
=
0
;
i
<
task
.
pcmdata
.
length
;
i
++
)
{
pcmData
[
i
]
=
Math
.
round
(
task
.
pcmdata
[
i
]
*
32767
);
}
// 生成波形分析数据
const
waveformData
=
getRecordAnalyseData
(
pcmData
);
// 返回结果给主线程
self
.
postMessage
({
id
:
task
.
id
,
success
:
true
,
waveform
:
waveformData
,
});
}
catch
(
error
)
{
console
.
error
(
'Worker error:'
,
error
);
// 返回错误信息给主线程
self
.
postMessage
({
id
:
task
.
id
,
success
:
false
,
error
:
error
.
message
});
}
});
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment