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
fdfb03b7
Commit
fdfb03b7
authored
Dec 10, 2024
by
Skye
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: send schedule info api
parent
55ef423c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1115 additions
and
939 deletions
+1115
-939
index.ts
index.ts
+26
-61
package-lock.json
package-lock.json
+2
-2
jensen.js
src/jensen.js
+840
-852
utils.ts
src/utils/utils.ts
+247
-24
No files found.
index.ts
View file @
fdfb03b7
import
{
Jensen
as
Jen
}
from
"./src/jensen"
;
import
{
Logger
}
from
"./src/utils/utils"
;
import
{
Jensen
as
Jen
}
from
'./src/jensen'
;
import
{
Logger
}
from
'./src/utils/utils'
;
export
type
DeviceInfo
=
{
sn
:
string
;
...
...
@@ -8,7 +8,7 @@ export type DeviceInfo = {
};
export
type
ReturnStruct
=
{
common
:
{
result
:
"failed"
|
"success"
};
common
:
{
result
:
'failed'
|
'success'
};
};
export
type
FileInfo
=
{
...
...
@@ -24,10 +24,8 @@ export type FileInfo = {
export
type
ScheduleInfo
=
{
startDate
:
Date
;
endDate
:
Date
;
keyAnswer
?:
string
;
keyHangup
?:
string
;
keyReject
?:
string
;
keyMicMute
?:
string
;
os
:
'Windows'
|
'Linux'
|
'Mac'
;
platform
:
string
;
};
declare
class
JensenType
{
...
...
@@ -39,33 +37,20 @@ declare class JensenType {
getDeviceInfo
:
(
time
?:
number
)
=>
Promise
<
DeviceInfo
>
;
listFiles
:
(
time
?:
number
)
=>
Promise
<
FileInfo
[]
>
;
tryconnect
:
(
disableOnConnect
?:
boolean
)
=>
Promise
<
boolean
>
;
getFile
:
(
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"
]
>
;
getFile
:
(
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'
]
>
;
requestFirmwareUpgrade
:
(
vn
:
number
,
length
:
number
,
time
?:
number
,
time
?:
number
)
=>
Promise
<
{
result
:
"accepted"
|
"fail"
;
result
:
'accepted'
|
'fail'
;
}
>
;
beginBNC
:
(
time
?:
number
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
endBNC
:
(
time
?:
number
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
setTime
:
(
date
:
Date
,
timeout
?:
number
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
beginBNC
:
(
time
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
endBNC
:
(
time
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
setTime
:
(
date
:
Date
,
timeout
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
deleteFile
:
(
fileName
:
string
)
=>
Promise
<
{
result
:
string
}
>
;
uploadFirmware
:
(
data
:
number
[],
seconds
?:
number
,
onProgress
?:
(
cur
:
number
,
total
:
number
)
=>
void
,
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
uploadFirmware
:
(
data
:
number
[],
seconds
?:
number
,
onProgress
?:
(
cur
:
number
,
total
:
number
)
=>
void
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
getTime
:
(
time
?:
number
)
=>
Promise
<
{
time
:
string
;
}
>
;
...
...
@@ -74,19 +59,10 @@ declare class JensenType {
autoPlay
:
boolean
;
notification
?:
boolean
;
}
|
null
>
;
setAutoRecord
:
(
enable
:
boolean
,
time
?:
number
,
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
setAutoPlay
:
(
enable
:
boolean
,
time
?:
number
,
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
setAutoRecord
:
(
enable
:
boolean
,
time
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
setAutoPlay
:
(
enable
:
boolean
,
time
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
isConnected
:
()
=>
boolean
;
setNotification
:
(
state
:
boolean
,
time
?:
number
,
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
setNotification
:
(
state
:
boolean
,
time
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
ondisconnect
?:
Function
;
isStopConnectionCheck
:
boolean
;
getRecordingFile
:
()
=>
Promise
<
{
...
...
@@ -94,29 +70,18 @@ declare class JensenType {
createTime
:
string
;
createDate
:
string
;
}
>
;
getCardInfo
:
(
seconds
?:
number
,
)
=>
Promise
<
{
used
:
number
;
capacity
:
number
;
status
:
string
}
>
;
formatCard
:
(
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
factoryReset
:
(
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
restoreFactorySettings
:
(
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
getCardInfo
:
(
seconds
?:
number
)
=>
Promise
<
{
used
:
number
;
capacity
:
number
;
status
:
string
}
>
;
formatCard
:
(
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
factoryReset
:
(
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
restoreFactorySettings
:
(
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
getModel
:
()
=>
string
;
getFileCount
:
(
seconds
?:
number
)
=>
Promise
<
{
count
:
number
}
|
null
>
;
recordTestStart
:
(
type
:
number
,
seconds
?:
number
,
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
recordTestEnd
:
(
type
:
number
,
seconds
?:
number
,
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
test
:
(
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
setBluetoothPromptPlay
:
(
state
:
boolean
,
seconds
?:
number
,
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
writeSerialNumber
:
(
sn
:
string
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
sendScheduleInfo
:
(
info
:
ScheduleInfo
)
=>
Promise
<
ReturnStruct
[
"common"
]
>
;
recordTestStart
:
(
type
:
number
,
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
recordTestEnd
:
(
type
:
number
,
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
test
:
(
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
setBluetoothPromptPlay
:
(
state
:
boolean
,
seconds
?:
number
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
writeSerialNumber
:
(
sn
:
string
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
sendScheduleInfo
:
(
info
:
ScheduleInfo
)
=>
Promise
<
ReturnStruct
[
'common'
]
>
;
}
//@ts-ignore
...
...
package-lock.json
View file @
fdfb03b7
{
"name"
:
"jensen"
,
"version"
:
"1.
1.3
"
,
"version"
:
"1.
0.0
"
,
"lockfileVersion"
:
3
,
"requires"
:
true
,
"packages"
:
{
""
:
{
"name"
:
"jensen"
,
"version"
:
"1.
1.3
"
,
"version"
:
"1.
0.0
"
,
"license"
:
"ISC"
,
"devDependencies"
:
{
"prettier"
:
"^3.3.3"
...
...
src/jensen.js
View file @
fdfb03b7
import
{
Logger
,
Logger
as
internalLogger
,
getTimeStr
}
from
'./utils/utils'
;
import
{
Logger
,
Logger
as
internalLogger
,
getTimeStr
,
shortcutKeys
}
from
'./utils/utils'
;
const
QUERY_DEVICE_INFO
=
0x01
;
const
QUERY_DEVICE_TIME
=
0x02
;
...
...
@@ -25,200 +25,196 @@ const TEST_SN_WRITE = 0xf007;
const
RECORD_TEST_START
=
0xf008
;
// 录音测试开始
const
RECORD_TEST_END
=
0xf009
;
// 录音测试结束
const
COMMAND_NAMES
=
[
'invalid-0'
,
'get-device-info'
,
'get-device-time'
,
'set-device-time'
,
'get-file-list'
,
'transfer-file'
,
'get-file-count'
,
'delete-file'
,
'request-firmware-upgrade'
,
'firmware-upload'
,
'read card info'
,
'format card'
,
'get recording file'
,
'restore factory settings'
,
'device msg test'
,
'bnc demo test'
,
'get-settings'
,
'set-settings'
,
'get file block'
,
'factory reset'
,
'invalid-0'
,
'get-device-info'
,
'get-device-time'
,
'set-device-time'
,
'get-file-list'
,
'transfer-file'
,
'get-file-count'
,
'delete-file'
,
'request-firmware-upgrade'
,
'firmware-upload'
,
'read card info'
,
'format card'
,
'get recording file'
,
'restore factory settings'
,
'device msg test'
,
'bnc demo test'
,
'get-settings'
,
'set-settings'
,
'get file block'
,
'factory reset'
];
function
Jensen
(
log
)
{
const
Logger
=
log
||
internalLogger
let
device
=
null
;
let
actions
=
{};
let
buffer
=
[];
let
blocks
=
[];
let
sequence
=
0
;
let
current
=
null
;
let
commands
=
[];
let
handlers
=
[];
let
statusTimeout
=
null
;
let
recv
=
false
;
let
ready
=
false
;
let
totalBytes
=
0
;
let
self
=
this
;
this
.
data
=
{};
// 消息
this
.
decodeTimeout
=
0
;
this
.
timewait
=
1
;
this
.
ondisconnect
=
null
;
this
.
isStopConnectionCheck
=
false
;
this
.
onconnect
=
null
;
this
.
onreceive
=
null
;
const
RECV_BUFF_SIZE
=
51200
;
const
_check_conn_status
=
()
=>
{
if
(
device
?.
opened
===
false
)
{
try
{
clearTimeout
(
statusTimeout
);
const
audio
=
document
.
getElementById
(
'test_audio'
);
audio
&&
audio
.
pause
()
&&
audio
.
remove
();
if
(
this
.
ondisconnect
&&
!
this
.
isStopConnectionCheck
)
this
.
ondisconnect
();
}
catch
(
e
)
{
console
.
log
(
e
);
}
}
statusTimeout
=
setTimeout
(()
=>
{
_check_conn_status
();
},
100
);
};
const
Logger
=
log
||
internalLogger
;
let
device
=
null
;
let
actions
=
{};
let
buffer
=
[];
let
blocks
=
[];
let
sequence
=
0
;
let
current
=
null
;
let
commands
=
[];
let
handlers
=
[];
let
statusTimeout
=
null
;
let
recv
=
false
;
let
ready
=
false
;
let
totalBytes
=
0
;
let
self
=
this
;
this
.
data
=
{};
// 消息
this
.
decodeTimeout
=
0
;
this
.
timewait
=
1
;
this
.
ondisconnect
=
null
;
this
.
isStopConnectionCheck
=
false
;
this
.
onconnect
=
null
;
this
.
onreceive
=
null
;
const
RECV_BUFF_SIZE
=
51200
;
const
_check_conn_status
=
()
=>
{
if
(
device
?.
opened
===
false
)
{
try
{
clearTimeout
(
statusTimeout
);
const
audio
=
document
.
getElementById
(
'test_audio'
);
audio
&&
audio
.
pause
()
&&
audio
.
remove
();
if
(
this
.
ondisconnect
&&
!
this
.
isStopConnectionCheck
)
this
.
ondisconnect
();
}
catch
(
e
)
{
console
.
log
(
e
);
}
}
statusTimeout
=
setTimeout
(()
=>
{
_check_conn_status
();
},
100
);
};
const
crash
=
async
function
(
procedure
,
error
)
{
Logger
.
error
(
'jensen'
,
procedure
,
String
(
error
));
self
.
versionCode
=
null
;
self
.
versionNumber
=
null
;
};
const
crash
=
async
function
(
procedure
,
error
)
{
Logger
.
error
(
'jensen'
,
procedure
,
String
(
error
));
self
.
versionCode
=
null
;
self
.
versionNumber
=
null
;
};
const
setup
=
async
function
(
disableOnConnect
)
{
self
.
versionCode
=
null
;
self
.
versionNumber
=
null
;
commands
.
length
=
0
;
try
{
await
device
.
selectConfiguration
(
1
);
await
device
.
claimInterface
(
0
);
await
device
.
selectAlternateInterface
(
0
,
0
);
self
.
model
=
device
.
productId
==
45069
?
'hidock-h1e'
:
'hidock-h1'
;
}
catch
(
e
)
{
Logger
.
error
(
'jensen'
,
'setup'
,
String
(
e
));
}
if
(
!
disableOnConnect
)
_check_conn_status
();
current
=
null
;
recv
=
false
;
ready
=
true
;
Logger
.
debug
(
'jensen'
,
'setup'
,
'setup webusb connection'
);
try
{
if
(
!
disableOnConnect
&&
!
self
.
isStopConnectionCheck
)
self
.
onconnect
?.();
}
catch
(
err
)
{
Logger
.
error
(
'jensen'
,
'setup'
,
err
);
}
};
const
setup
=
async
function
(
disableOnConnect
)
{
self
.
versionCode
=
null
;
self
.
versionNumber
=
null
;
commands
.
length
=
0
;
try
{
await
device
.
selectConfiguration
(
1
);
await
device
.
claimInterface
(
0
);
await
device
.
selectAlternateInterface
(
0
,
0
);
self
.
model
=
device
.
productId
==
45069
?
'hidock-h1e'
:
'hidock-h1'
;
}
catch
(
e
)
{
Logger
.
error
(
'jensen'
,
'setup'
,
String
(
e
));
}
if
(
!
disableOnConnect
)
_check_conn_status
();
current
=
null
;
recv
=
false
;
ready
=
true
;
Logger
.
debug
(
'jensen'
,
'setup'
,
'setup webusb connection'
);
try
{
if
(
!
disableOnConnect
&&
!
self
.
isStopConnectionCheck
)
self
.
onconnect
?.();
}
catch
(
err
)
{
Logger
.
error
(
'jensen'
,
'setup'
,
err
);
}
};
this
.
connect
=
async
function
()
{
Logger
.
debug
(
'jensen'
,
'connect'
,
'connect'
);
let
r
=
await
self
.
tryconnect
();
if
(
r
)
return
;
let
conn
=
await
navigator
.
usb
.
requestDevice
({
filters
:
[{
vendorId
:
0x10d6
}],
});
await
conn
.
open
();
self
.
model
=
conn
.
productId
==
45069
?
'hidock-h1e'
:
'hidock-h1'
;
device
=
conn
;
await
setup
();
};
this
.
connect
=
async
function
()
{
Logger
.
debug
(
'jensen'
,
'connect'
,
'connect'
);
let
r
=
await
self
.
tryconnect
();
if
(
r
)
return
;
this
.
getModel
=
function
()
{
return
this
.
model
;
};
let
conn
=
await
navigator
.
usb
.
requestDevice
({
filters
:
[{
vendorId
:
0x10d6
}]
});
await
conn
.
open
();
self
.
model
=
conn
.
productId
==
45069
?
'hidock-h1e'
:
'hidock-h1'
;
device
=
conn
;
await
setup
();
};
this
.
init
=
async
function
_init
()
{
if
(
!
navigator
.
usb
)
{
Logger
.
error
(
'jensen'
,
'init'
,
'webusb not supported'
);
return
;
}
navigator
.
usb
.
onconnect
=
function
(
e
)
{
self
.
tryconnect
();
};
await
self
.
connect
();
};
this
.
getModel
=
function
()
{
return
this
.
model
;
};
this
.
tryconnect
=
async
function
(
disableOnConnect
)
{
await
this
.
disconnect
();
let
devices
=
await
navigator
.
usb
.
getDevices
();
for
(
let
i
=
0
;
i
<
devices
.
length
;
i
++
)
{
let
item
=
devices
[
i
];
if
(
item
.
productName
.
indexOf
(
'HiDock'
)
>
-
1
)
{
Logger
.
debug
(
'jensen'
,
'tryconnect'
,
'detected: '
+
item
.
productName
);
await
item
.
open
();
device
=
item
;
await
setup
(
disableOnConnect
);
return
true
;
}
}
Logger
.
debug
(
'jensen'
,
'tryconnect'
,
'no HiDock found'
);
return
false
;
this
.
init
=
async
function
_init
()
{
if
(
!
navigator
.
usb
)
{
Logger
.
error
(
'jensen'
,
'init'
,
'webusb not supported'
);
return
;
}
navigator
.
usb
.
onconnect
=
function
(
e
)
{
self
.
tryconnect
();
};
await
self
.
connect
();
};
this
.
isConnected
=
function
()
{
return
device
!=
null
;
};
this
.
tryconnect
=
async
function
(
disableOnConnect
)
{
await
this
.
disconnect
();
let
devices
=
await
navigator
.
usb
.
getDevices
();
for
(
let
i
=
0
;
i
<
devices
.
length
;
i
++
)
{
let
item
=
devices
[
i
];
if
(
item
.
productName
.
indexOf
(
'HiDock'
)
>
-
1
)
{
Logger
.
debug
(
'jensen'
,
'tryconnect'
,
'detected: '
+
item
.
productName
);
await
item
.
open
();
device
=
item
;
await
setup
(
disableOnConnect
);
return
true
;
}
}
Logger
.
debug
(
'jensen'
,
'tryconnect'
,
'no HiDock found'
);
return
false
;
};
this
.
disconnect
=
async
function
()
{
Logger
.
info
(
'jensen'
,
'disconnect'
,
'disconnect'
);
try
{
await
device
?.
close
();
}
catch
(
e
)
{
}
};
this
.
isConnected
=
function
()
{
return
device
!=
null
;
};
this
.
send
=
function
(
cmd
,
seconds
,
onprogress
)
{
cmd
.
sequence
(
sequence
++
);
cmd
.
onprogress
=
onprogress
;
if
(
seconds
)
cmd
.
expireAfter
(
seconds
);
commands
.
push
(
cmd
);
sendNext
();
return
register
(
cmd
,
seconds
);
};
this
.
disconnect
=
async
function
()
{
Logger
.
info
(
'jensen'
,
'disconnect'
,
'disconnect'
);
try
{
await
device
?.
close
();
}
catch
(
e
)
{}
};
const
sendNext
=
async
function
()
{
if
(
current
)
{
// Logger.info('jensen', 'sendNext', 'return cuz current is: ' + current);
return
;
}
this
.
send
=
function
(
cmd
,
seconds
,
onprogress
)
{
cmd
.
sequence
(
sequence
++
);
cmd
.
onprogress
=
onprogress
;
if
(
seconds
)
cmd
.
expireAfter
(
seconds
);
commands
.
push
(
cmd
);
sendNext
();
return
register
(
cmd
,
seconds
);
};
let
cmd
=
null
;
let
now
=
new
Date
().
getTime
();
while
(
true
)
{
if
(
commands
.
length
==
0
)
return
;
cmd
=
commands
.
shift
();
if
(
cmd
.
expireTime
>
0
&&
cmd
.
expireTime
<
now
)
{
Logger
.
info
(
'jensen'
,
'sendNext'
,
'expired: cmd-'
+
cmd
.
command
+
'-'
+
cmd
.
index
+
', '
+
COMMAND_NAMES
[
cmd
.
command
]);
continue
;
}
break
;
}
const
sendNext
=
async
function
()
{
if
(
current
)
{
// Logger.info('jensen', 'sendNext', 'return cuz current is: ' + current);
return
;
}
let
cmd
=
null
;
let
now
=
new
Date
().
getTime
();
while
(
true
)
{
if
(
commands
.
length
==
0
)
return
;
cmd
=
commands
.
shift
();
if
(
cmd
.
expireTime
>
0
&&
cmd
.
expireTime
<
now
)
{
Logger
.
info
(
'jensen'
,
'sendNext'
,
'expired: cmd-'
+
cmd
.
command
+
'-'
+
cmd
.
index
+
', '
+
COMMAND_NAMES
[
cmd
.
command
]);
continue
;
}
break
;
}
let
data
=
cmd
.
make
();
current
=
'cmd-'
+
cmd
.
command
+
'-'
+
cmd
.
index
;
Logger
.
debug
(
'jensen'
,
'sendNext'
,
'command: '
+
COMMAND_NAMES
[
cmd
.
command
]
+
', data bytes: '
+
data
.
byteLength
);
let
data
=
cmd
.
make
();
current
=
'cmd-'
+
cmd
.
command
+
'-'
+
cmd
.
index
;
Logger
.
debug
(
'jensen'
,
'sendNext'
,
'command: '
+
COMMAND_NAMES
[
cmd
.
command
]
+
', data bytes: '
+
data
.
byteLength
);
self
.
timewait
=
cmd
.
command
==
TRANSFER_FILE
?
1000
:
10
;
self
.
timewait
=
cmd
.
command
==
TRANSFER_FILE
?
1000
:
10
;
await
device
.
transferOut
(
1
,
data
).
catch
((
e
)
=>
crash
(
'sendNext'
,
e
));
if
(
cmd
.
onprogress
)
cmd
.
onprogress
(
1
,
1
);
/*
await
device
.
transferOut
(
1
,
data
).
catch
((
e
)
=>
crash
(
'sendNext'
,
e
));
if
(
cmd
.
onprogress
)
cmd
.
onprogress
(
1
,
1
);
/*
if (data.byteLength < 1000) await device.transferOut(1, data).catch((e) => crash('sendNext', e));
else
{
...
...
@@ -240,321 +236,309 @@ function Jensen(log) {
}
}
*/
totalBytes
=
0
;
if
(
recv
==
false
)
tryReceive
();
else
recv
=
true
;
};
totalBytes
=
0
;
if
(
recv
==
false
)
tryReceive
();
else
recv
=
true
;
};
const
register
=
function
(
cmd
,
seconds
)
{
let
tag
=
'cmd-'
+
cmd
.
command
+
'-'
+
cmd
.
index
;
let
t
=
seconds
?
setTimeout
(()
=>
{
timeout
(
tag
);
},
seconds
*
1000
)
:
null
;
return
new
Promise
((
resolve
,
reject
)
=>
{
actions
[
tag
]
=
{
tag
:
tag
,
resolve
:
resolve
,
reject
:
reject
,
timeout
:
t
,
};
});
};
const
register
=
function
(
cmd
,
seconds
)
{
let
tag
=
'cmd-'
+
cmd
.
command
+
'-'
+
cmd
.
index
;
let
t
=
seconds
?
setTimeout
(()
=>
{
timeout
(
tag
);
},
seconds
*
1000
)
:
null
;
return
new
Promise
((
resolve
,
reject
)
=>
{
actions
[
tag
]
=
{
tag
:
tag
,
resolve
:
resolve
,
reject
:
reject
,
timeout
:
t
};
});
};
const
trigger
=
function
(
resp
,
msgid
)
{
if
(
current
==
null
)
return
;
Logger
.
debug
(
'jensen'
,
'trigger'
,
'trigger - '
+
current
.
substring
(
0
,
current
.
lastIndexOf
(
'-'
))
+
' <---> cmd-'
+
msgid
);
if
(
current
.
substring
(
0
,
current
.
lastIndexOf
(
'-'
))
!=
'cmd-'
+
msgid
)
{
current
=
null
;
return
;
}
if
(
current
in
actions
==
false
)
{
Logger
.
debug
(
'jensen'
,
'trigger'
,
'no action registered'
);
return
;
}
let
p
=
actions
[
current
];
if
(
p
.
timeout
)
clearTimeout
(
p
.
timeout
);
p
.
resolve
(
resp
);
delete
actions
[
current
];
current
=
null
;
};
const
trigger
=
function
(
resp
,
msgid
)
{
if
(
current
==
null
)
return
;
Logger
.
debug
(
'jensen'
,
'trigger'
,
'trigger - '
+
current
.
substring
(
0
,
current
.
lastIndexOf
(
'-'
))
+
' <---> cmd-'
+
msgid
);
if
(
current
.
substring
(
0
,
current
.
lastIndexOf
(
'-'
))
!=
'cmd-'
+
msgid
)
{
current
=
null
;
return
;
}
if
(
current
in
actions
==
false
)
{
Logger
.
debug
(
'jensen'
,
'trigger'
,
'no action registered'
);
return
;
}
let
p
=
actions
[
current
];
if
(
p
.
timeout
)
clearTimeout
(
p
.
timeout
);
p
.
resolve
(
resp
);
delete
actions
[
current
];
current
=
null
;
};
const
timeout
=
function
(
tag
)
{
Logger
.
debug
(
'jensen'
,
'timeout'
,
'timeout '
+
tag
);
let
p
=
actions
[
tag
];
p
.
resolve
(
null
);
delete
actions
[
tag
];
};
const
timeout
=
function
(
tag
)
{
Logger
.
debug
(
'jensen'
,
'timeout'
,
'timeout '
+
tag
);
let
p
=
actions
[
tag
];
p
.
resolve
(
null
);
delete
actions
[
tag
];
};
this
.
dump
=
function
()
{
console
.
log
(
'actions'
,
actions
);
console
.
log
(
'pending commands'
,
commands
);
console
.
log
(
'current'
,
current
);
console
.
log
(
'device'
,
device
);
};
this
.
dump
=
function
()
{
console
.
log
(
'actions'
,
actions
);
console
.
log
(
'pending commands'
,
commands
);
console
.
log
(
'current'
,
current
);
console
.
log
(
'device'
,
device
);
};
const
tryReceive
=
function
()
{
if
(
device
)
device
.
transferIn
(
2
,
RECV_BUFF_SIZE
).
then
((
r
)
=>
{
Logger
.
save
?.(
'jensen'
,
'tryReceive'
,
r
?.
data
);
receive
(
r
);
});
};
const
tryReceive
=
function
()
{
if
(
device
)
device
.
transferIn
(
2
,
RECV_BUFF_SIZE
).
then
((
r
)
=>
{
Logger
.
save
?.(
'jensen'
,
'tryReceive'
,
r
?.
data
);
receive
(
r
);
});
};
const
read_int
=
function
(
a
,
b
,
c
,
d
)
{
if
(
arguments
.
length
===
2
)
{
return
((
a
&
0xff
)
<<
8
)
|
(
b
&
0xff
);
}
else
if
(
arguments
.
length
===
4
)
{
return
((
a
&
0xff
)
<<
24
)
|
((
b
&
0xff
)
<<
16
)
|
((
c
&
0xff
)
<<
8
)
|
(
d
&
0xff
);
}
};
const
read_int
=
function
(
a
,
b
,
c
,
d
)
{
if
(
arguments
.
length
===
2
)
{
return
((
a
&
0xff
)
<<
8
)
|
(
b
&
0xff
);
}
else
if
(
arguments
.
length
===
4
)
{
return
((
a
&
0xff
)
<<
24
)
|
((
b
&
0xff
)
<<
16
)
|
((
c
&
0xff
)
<<
8
)
|
(
d
&
0xff
);
}
};
const
receive
=
function
(
result
)
{
totalBytes
+=
result
.
data
.
byteLength
;
// 做一个回调,怎么样找到它呢?
blocks
.
push
(
result
.
data
);
tryReceive
();
tryDecode
();
if
(
self
.
onreceive
)
{
try
{
self
.
onreceive
(
totalBytes
);
}
catch
(
e
)
{
}
}
else
{
// if (self.decodeTimeout) clearTimeout(self.decodeTimeout);
// self.decodeTimeout = setTimeout(function () {
// tryDecode();
// }, self.timewait);
}
};
const
receive
=
function
(
result
)
{
totalBytes
+=
result
.
data
.
byteLength
;
// 做一个回调,怎么样找到它呢?
blocks
.
push
(
result
.
data
);
tryReceive
();
tryDecode
();
if
(
self
.
onreceive
)
{
try
{
self
.
onreceive
(
totalBytes
);
}
catch
(
e
)
{}
}
else
{
// if (self.decodeTimeout) clearTimeout(self.decodeTimeout);
// self.decodeTimeout = setTimeout(function () {
// tryDecode();
// }, self.timewait);
}
};
// 持续解码
const
continueDecode
=
(
block
)
=>
{
const
buff
=
new
ArrayBuffer
(
RECV_BUFF_SIZE
*
2
);
let
bview
=
new
Uint8Array
(
buff
);
for
(
let
k
=
0
;
k
<
block
.
byteLength
;
k
++
)
{
bview
[
k
]
=
block
.
getInt8
(
k
);
}
let
result
=
null
;
try
{
result
=
decodeMessage
(
bview
,
0
,
block
.
byteLength
);
}
catch
(
err
)
{
console
.
error
(
'ci decode'
,
err
);
}
sendNext
();
const
msg
=
result
.
message
;
return
result
&&
msg
.
id
===
TRANSFER_FILE
?
msg
.
body
:
null
;
};
// 持续解码
const
continueDecode
=
(
block
)
=>
{
const
buff
=
new
ArrayBuffer
(
RECV_BUFF_SIZE
*
2
);
let
bview
=
new
Uint8Array
(
buff
);
for
(
let
k
=
0
;
k
<
block
.
byteLength
;
k
++
)
{
bview
[
k
]
=
block
.
getInt8
(
k
);
const
tryDecode
=
function
()
{
// 一个容器,比单独任意一个小包要大一点儿,好像还差一点儿
let
stime
=
new
Date
();
let
buff
=
new
ArrayBuffer
(
RECV_BUFF_SIZE
*
2
);
let
bview
=
new
Uint8Array
(
buff
);
// buff中实际使用的字节数,有效字节数
let
buffLength
=
0
;
let
crash
=
false
;
for
(
let
i
=
0
,
l
=
blocks
.
length
;
i
<
l
;
i
++
)
{
let
block
=
blocks
.
shift
();
// 把block加到buff的最末尾
for
(
let
k
=
0
;
k
<
block
.
byteLength
;
k
++
)
{
bview
[
k
+
buffLength
]
=
block
.
getInt8
(
k
);
}
buffLength
+=
block
.
byteLength
;
let
startIndex
=
0
;
while
(
true
)
{
let
rst
=
null
;
try
{
rst
=
decodeMessage
(
bview
,
startIndex
,
buffLength
);
}
catch
(
e
)
{
crash
=
true
;
break
;
}
if
(
rst
==
null
)
{
break
;
}
startIndex
+=
rst
.
length
;
let
msg
=
rst
.
message
;
// WARN: 接下来怎么整
let
cname
=
msg
.
id
===
FACTORY_RESET
?
'factory-reset'
:
COMMAND_NAMES
[
msg
.
id
];
let
heading
=
[];
for
(
let
x
=
0
;
x
<
msg
.
body
?.
byteLength
&&
x
<
32
;
x
++
)
{
heading
.
push
(
'0'
+
(
msg
.
body
[
x
]
&
0xff
).
toString
(
16
).
replace
(
/^0
(\w{2})
$/gi
,
'$1'
));
}
let
result
=
null
;
if
(
msg
.
id
!==
TRANSFER_FILE
)
Logger
.
debug
(
'jensen'
,
'receive'
,
'recv: '
+
cname
+
', seq: '
+
msg
.
sequence
+
', data bytes: '
+
msg
.
body
?.
byteLength
+
', data: '
+
heading
.
join
(
' '
)
);
try
{
result
=
decodeMessage
(
bview
,
0
,
block
.
byteLength
);
}
catch
(
err
)
{
console
.
error
(
'ci decode'
,
err
);
let
handler
=
Jensen
.
handlers
[
msg
.
id
];
let
r
=
handler
(
msg
,
self
);
if
(
r
)
trigger
(
r
,
msg
.
id
);
}
catch
(
e
)
{
trigger
(
e
);
Logger
.
error
(
'jensen'
,
'receive'
,
'recv: '
+
COMMAND_NAMES
[
msg
.
id
]
+
', seq: '
+
msg
.
sequence
+
', error: '
+
String
(
e
));
}
sendNext
();
const
msg
=
result
.
message
;
return
result
&&
msg
.
id
===
TRANSFER_FILE
?
msg
.
body
:
null
;
}
const
tryDecode
=
function
()
{
// 一个容器,比单独任意一个小包要大一点儿,好像还差一点儿
let
stime
=
new
Date
();
let
buff
=
new
ArrayBuffer
(
RECV_BUFF_SIZE
*
2
);
let
bview
=
new
Uint8Array
(
buff
);
// buff中实际使用的字节数,有效字节数
let
buffLength
=
0
;
let
crash
=
false
;
for
(
let
i
=
0
,
l
=
blocks
.
length
;
i
<
l
;
i
++
)
{
let
block
=
blocks
.
shift
();
// 把block加到buff的最末尾
for
(
let
k
=
0
;
k
<
block
.
byteLength
;
k
++
)
{
bview
[
k
+
buffLength
]
=
block
.
getInt8
(
k
);
}
buffLength
+=
block
.
byteLength
;
let
startIndex
=
0
;
while
(
true
)
{
let
rst
=
null
;
try
{
rst
=
decodeMessage
(
bview
,
startIndex
,
buffLength
);
}
catch
(
e
)
{
crash
=
true
;
break
;
}
if
(
rst
==
null
)
{
break
;
}
startIndex
+=
rst
.
length
;
let
msg
=
rst
.
message
;
// WARN: 接下来怎么整
let
cname
=
msg
.
id
===
FACTORY_RESET
?
'factory-reset'
:
COMMAND_NAMES
[
msg
.
id
];
let
heading
=
[];
for
(
let
x
=
0
;
x
<
msg
.
body
?.
byteLength
&&
x
<
32
;
x
++
)
{
heading
.
push
(
'0'
+
(
msg
.
body
[
x
]
&
0xff
).
toString
(
16
).
replace
(
/^0
(\w{2})
$/gi
,
'$1'
));
}
if
(
msg
.
id
!==
TRANSFER_FILE
)
Logger
.
debug
(
'jensen'
,
'receive'
,
'recv: '
+
cname
+
', seq: '
+
msg
.
sequence
+
', data bytes: '
+
msg
.
body
?.
byteLength
+
', data: '
+
heading
.
join
(
' '
),
);
try
{
let
handler
=
Jensen
.
handlers
[
msg
.
id
];
let
r
=
handler
(
msg
,
self
);
if
(
r
)
trigger
(
r
,
msg
.
id
);
}
catch
(
e
)
{
trigger
(
e
);
Logger
.
error
(
'jensen'
,
'receive'
,
'recv: '
+
COMMAND_NAMES
[
msg
.
id
]
+
', seq: '
+
msg
.
sequence
+
', error: '
+
String
(
e
),
);
}
sendNext
();
}
// 是否已经崩溃了?
if
(
crash
)
{
// cmd-5-42
// 5是msgid
let
msgid
=
parseInt
(
current
.
replace
(
/^cmd-
(\d
+
)
-
(\d
+
)
$/gi
,
'$1'
));
try
{
let
handler
=
Jensen
.
handlers
[
msgid
];
handler
(
null
,
self
);
}
catch
(
e
)
{
trigger
(
e
);
Logger
.
error
(
'jensen'
,
'decode'
,
'decode error: '
+
String
(
e
));
}
trigger
(
null
,
msgid
);
blocks
.
length
=
0
;
break
;
}
// WARN: 需要把剩余的字节数挪到最前面去
// startIndex已经抵达最后的位置,startIndex -> buffLength就是需要移到最前面去的字节内容了
for
(
let
k
=
0
,
bs
=
buffLength
-
startIndex
;
k
<
bs
;
k
++
)
{
bview
[
k
]
=
bview
[
k
+
startIndex
];
}
buffLength
=
buffLength
-
startIndex
;
}
// 是否已经崩溃了?
if
(
crash
)
{
// cmd-5-42
// 5是msgid
let
msgid
=
parseInt
(
current
.
replace
(
/^cmd-
(\d
+
)
-
(\d
+
)
$/gi
,
'$1'
));
try
{
let
handler
=
Jensen
.
handlers
[
msgid
];
handler
(
null
,
self
);
}
catch
(
e
)
{
trigger
(
e
);
Logger
.
error
(
'jensen'
,
'decode'
,
'decode error: '
+
String
(
e
));
}
console
.
error
(
'Decode: '
+
(
new
Date
().
getTime
()
-
stime
.
getTime
())
+
'ms'
);
};
trigger
(
null
,
msgid
);
blocks
.
length
=
0
;
break
;
}
// WARN: 需要把剩余的字节数挪到最前面去
// startIndex已经抵达最后的位置,startIndex -> buffLength就是需要移到最前面去的字节内容了
for
(
let
k
=
0
,
bs
=
buffLength
-
startIndex
;
k
<
bs
;
k
++
)
{
bview
[
k
]
=
bview
[
k
+
startIndex
];
}
buffLength
=
buffLength
-
startIndex
;
}
console
.
error
(
'Decode: '
+
(
new
Date
().
getTime
()
-
stime
.
getTime
())
+
'ms'
);
};
const
decodeMessage
=
function
(
dataView
,
startIndex
,
buffLength
)
{
let
dataLen
=
buffLength
-
startIndex
;
if
(
dataLen
<
12
)
return
null
;
if
(
dataView
[
startIndex
+
0
]
!==
0x12
||
dataView
[
startIndex
+
1
]
!==
0x34
)
throw
new
Error
(
'invalid header'
);
// 2 字节的指令id
let
idx
=
2
;
// let cmdid = this.nextShort(idx);
let
cmdid
=
read_int
(
dataView
[
startIndex
+
idx
],
dataView
[
startIndex
+
idx
+
1
]);
idx
+=
2
;
let
sequeue
=
read_int
(
dataView
[
startIndex
+
idx
+
0
],
dataView
[
startIndex
+
idx
+
1
],
dataView
[
startIndex
+
idx
+
2
],
dataView
[
startIndex
+
idx
+
3
],
);
idx
+=
4
;
let
len
=
read_int
(
dataView
[
startIndex
+
idx
+
0
],
dataView
[
startIndex
+
idx
+
1
],
dataView
[
startIndex
+
idx
+
2
],
dataView
[
startIndex
+
idx
+
3
],
);
let
padding
=
(
len
>>
24
)
&
0xff
;
len
=
len
&
0xffffff
;
idx
+=
4
;
// 需要去除的字节数
var
cutLen
=
0
;
// 数据还没有完全准备好
if
(
dataLen
<
12
+
len
+
padding
)
return
null
;
// 去掉header部分
// 下面这一行做什么用的?
// for (let i = 0; i < 12; i++) this.buffer[i + cutLen];
cutLen
+=
12
;
// 取走body部分
// 数据体部分
// let body = new Uint8Array(new ArrayBuffer(len));
// for (let i = 0; i < len; i++) body.push(this.buffer[i + cutLen]);
let
body
=
dataView
.
slice
(
startIndex
+
cutLen
,
startIndex
+
cutLen
+
len
);
cutLen
+=
len
;
// 干掉补上来的数据
// 下面这一行做什么用的?
// for (let i = 0; i < padding; i++) this.buffer[i + cutLen];
cutLen
+=
padding
;
// self.buffer = self.buffer.slice(cutLen);
return
{
message
:
new
Message
(
cmdid
,
sequeue
,
body
),
length
:
cutLen
};
};
const
decodeMessage
=
function
(
dataView
,
startIndex
,
buffLength
)
{
let
dataLen
=
buffLength
-
startIndex
;
if
(
dataLen
<
12
)
return
null
;
if
(
dataView
[
startIndex
+
0
]
!==
0x12
||
dataView
[
startIndex
+
1
]
!==
0x34
)
throw
new
Error
(
'invalid header'
);
// 2 字节的指令id
let
idx
=
2
;
// let cmdid = this.nextShort(idx);
let
cmdid
=
read_int
(
dataView
[
startIndex
+
idx
],
dataView
[
startIndex
+
idx
+
1
]);
idx
+=
2
;
let
sequeue
=
read_int
(
dataView
[
startIndex
+
idx
+
0
],
dataView
[
startIndex
+
idx
+
1
],
dataView
[
startIndex
+
idx
+
2
],
dataView
[
startIndex
+
idx
+
3
]
);
idx
+=
4
;
let
len
=
read_int
(
dataView
[
startIndex
+
idx
+
0
],
dataView
[
startIndex
+
idx
+
1
],
dataView
[
startIndex
+
idx
+
2
],
dataView
[
startIndex
+
idx
+
3
]
);
let
padding
=
(
len
>>
24
)
&
0xff
;
len
=
len
&
0xffffff
;
idx
+=
4
;
// 需要去除的字节数
var
cutLen
=
0
;
// 数据还没有完全准备好
if
(
dataLen
<
12
+
len
+
padding
)
return
null
;
// 去掉header部分
// 下面这一行做什么用的?
// for (let i = 0; i < 12; i++) this.buffer[i + cutLen];
cutLen
+=
12
;
// 取走body部分
// 数据体部分
// let body = new Uint8Array(new ArrayBuffer(len));
// for (let i = 0; i < len; i++) body.push(this.buffer[i + cutLen]);
let
body
=
dataView
.
slice
(
startIndex
+
cutLen
,
startIndex
+
cutLen
+
len
);
cutLen
+=
len
;
// 干掉补上来的数据
// 下面这一行做什么用的?
// for (let i = 0; i < padding; i++) this.buffer[i + cutLen];
cutLen
+=
padding
;
// self.buffer = self.buffer.slice(cutLen);
return
{
message
:
new
Message
(
cmdid
,
sequeue
,
body
),
length
:
cutLen
};
};
this
.
to_bcd
=
function
(
str
)
{
let
x
=
[];
for
(
let
i
=
0
;
i
<
str
.
length
;
i
+=
2
)
{
let
h
=
(
str
.
charCodeAt
(
i
)
-
48
)
&
0xff
;
let
l
=
(
str
.
charCodeAt
(
i
+
1
)
-
48
)
&
0xff
;
x
.
push
((
h
<<
4
)
|
l
);
}
return
x
;
};
this
.
to_bcd
=
function
(
str
)
{
let
x
=
[];
for
(
let
i
=
0
;
i
<
str
.
length
;
i
+=
2
)
{
let
h
=
(
str
.
charCodeAt
(
i
)
-
48
)
&
0xff
;
let
l
=
(
str
.
charCodeAt
(
i
+
1
)
-
48
)
&
0xff
;
x
.
push
((
h
<<
4
)
|
l
);
}
return
x
;
};
this
.
from_bcd
=
function
()
{
let
str
=
''
;
for
(
let
i
=
0
;
i
<
arguments
.
length
;
i
++
)
{
let
v
=
arguments
[
i
]
&
0xff
;
str
+=
(
v
>>
4
)
&
0x0f
;
str
+=
v
&
0x0f
;
}
return
str
;
};
this
.
from_bcd
=
function
()
{
let
str
=
''
;
for
(
let
i
=
0
;
i
<
arguments
.
length
;
i
++
)
{
let
v
=
arguments
[
i
]
&
0xff
;
str
+=
(
v
>>
4
)
&
0x0f
;
str
+=
v
&
0x0f
;
}
return
str
;
};
}
function
Command
(
id
)
{
this
.
command
=
id
;
this
.
msgBody
=
[];
this
.
index
=
0
;
this
.
expireTime
=
0
;
this
.
timeout
=
0
;
this
.
body
=
function
(
data
)
{
this
.
msgBody
=
data
;
return
this
;
};
this
.
expireAfter
=
function
(
seconds
)
{
this
.
expireTime
=
new
Date
().
getTime
()
+
seconds
*
1000
;
};
this
.
sequence
=
function
(
seq
)
{
this
.
index
=
seq
;
return
this
;
};
this
.
make
=
function
()
{
let
msg
=
new
Uint8Array
(
2
+
2
+
4
+
4
+
this
.
msgBody
.
length
);
let
idx
=
0
;
// msg header
msg
[
idx
++
]
=
0x12
;
msg
[
idx
++
]
=
0x34
;
// msg command id
msg
[
idx
++
]
=
(
this
.
command
>>
8
)
&
0xff
;
msg
[
idx
++
]
=
(
this
.
command
>>
0
)
&
0xff
;
// msg sequence id
msg
[
idx
++
]
=
(
this
.
index
>>
24
)
&
0xff
;
msg
[
idx
++
]
=
(
this
.
index
>>
16
)
&
0xff
;
msg
[
idx
++
]
=
(
this
.
index
>>
8
)
&
0xff
;
msg
[
idx
++
]
=
(
this
.
index
>>
0
)
&
0xff
;
// msg body length
let
len
=
this
.
msgBody
.
length
;
msg
[
idx
++
]
=
(
len
>>
24
)
&
0xff
;
msg
[
idx
++
]
=
(
len
>>
16
)
&
0xff
;
msg
[
idx
++
]
=
(
len
>>
8
)
&
0xff
;
msg
[
idx
++
]
=
(
len
>>
0
)
&
0xff
;
// msg body
for
(
let
i
=
0
;
i
<
this
.
msgBody
.
length
;
i
++
)
msg
[
idx
++
]
=
this
.
msgBody
[
i
]
&
0xff
;
return
msg
;
};
this
.
command
=
id
;
this
.
msgBody
=
[];
this
.
index
=
0
;
this
.
expireTime
=
0
;
this
.
timeout
=
0
;
this
.
body
=
function
(
data
)
{
this
.
msgBody
=
data
;
return
this
;
};
this
.
expireAfter
=
function
(
seconds
)
{
this
.
expireTime
=
new
Date
().
getTime
()
+
seconds
*
1000
;
};
this
.
sequence
=
function
(
seq
)
{
this
.
index
=
seq
;
return
this
;
};
this
.
make
=
function
()
{
let
msg
=
new
Uint8Array
(
2
+
2
+
4
+
4
+
this
.
msgBody
.
length
);
let
idx
=
0
;
// msg header
msg
[
idx
++
]
=
0x12
;
msg
[
idx
++
]
=
0x34
;
// msg command id
msg
[
idx
++
]
=
(
this
.
command
>>
8
)
&
0xff
;
msg
[
idx
++
]
=
(
this
.
command
>>
0
)
&
0xff
;
// msg sequence id
msg
[
idx
++
]
=
(
this
.
index
>>
24
)
&
0xff
;
msg
[
idx
++
]
=
(
this
.
index
>>
16
)
&
0xff
;
msg
[
idx
++
]
=
(
this
.
index
>>
8
)
&
0xff
;
msg
[
idx
++
]
=
(
this
.
index
>>
0
)
&
0xff
;
// msg body length
let
len
=
this
.
msgBody
.
length
;
msg
[
idx
++
]
=
(
len
>>
24
)
&
0xff
;
msg
[
idx
++
]
=
(
len
>>
16
)
&
0xff
;
msg
[
idx
++
]
=
(
len
>>
8
)
&
0xff
;
msg
[
idx
++
]
=
(
len
>>
0
)
&
0xff
;
// msg body
for
(
let
i
=
0
;
i
<
this
.
msgBody
.
length
;
i
++
)
msg
[
idx
++
]
=
this
.
msgBody
[
i
]
&
0xff
;
return
msg
;
};
}
function
Message
(
id
,
sequence
,
body
)
{
this
.
id
=
id
;
this
.
sequence
=
sequence
;
this
.
body
=
body
;
this
.
id
=
id
;
this
.
sequence
=
sequence
;
this
.
body
=
body
;
}
/**
...
...
@@ -562,496 +546,500 @@ function Message(id, sequence, body) {
* @param {*} handler callback function for response processing, return `non-undefined` means command ended
*/
Jensen
.
registerHandler
=
function
(
cmdid
,
handler
)
{
if
(
typeof
Jensen
.
handlers
==
'undefined'
)
Jensen
.
handlers
=
{};
Jensen
.
handlers
[
cmdid
]
=
handler
;
if
(
typeof
Jensen
.
handlers
==
'undefined'
)
Jensen
.
handlers
=
{};
Jensen
.
handlers
[
cmdid
]
=
handler
;
};
Jensen
.
prototype
.
getDeviceInfo
=
async
function
(
seconds
)
{
return
this
.
send
(
new
Command
(
QUERY_DEVICE_INFO
),
seconds
);
return
this
.
send
(
new
Command
(
QUERY_DEVICE_INFO
),
seconds
);
};
Jensen
.
prototype
.
getTime
=
async
function
(
seconds
)
{
return
this
.
send
(
new
Command
(
QUERY_DEVICE_TIME
),
seconds
);
return
this
.
send
(
new
Command
(
QUERY_DEVICE_TIME
),
seconds
);
};
Jensen
.
prototype
.
getFileCount
=
async
function
(
seconds
)
{
return
this
.
send
(
new
Command
(
QUERY_FILE_COUNT
),
seconds
);
return
this
.
send
(
new
Command
(
QUERY_FILE_COUNT
),
seconds
);
};
Jensen
.
prototype
.
factoryReset
=
async
function
(
seconds
)
{
if
(
this
.
versionNumber
<
327705
)
return
null
;
return
this
.
send
(
new
Command
(
FACTORY_RESET
),
seconds
);
if
(
this
.
versionNumber
<
327705
)
return
null
;
return
this
.
send
(
new
Command
(
FACTORY_RESET
),
seconds
);
};
Jensen
.
prototype
.
restoreFactorySettings
=
async
function
(
seconds
)
{
if
(
this
.
model
===
'hidock-h1e'
&&
this
.
versionNumber
<
393476
)
return
null
;
if
(
this
.
model
===
'hidock-h1'
&&
this
.
versionNumber
<
327944
)
return
null
;
return
this
.
send
(
new
Command
(
RESTORE_FACTORY_SETTINGS
).
body
([
0x01
,
0x02
,
0x03
,
0x04
]),
seconds
);
if
(
this
.
model
===
'hidock-h1e'
&&
this
.
versionNumber
<
393476
)
return
null
;
if
(
this
.
model
===
'hidock-h1'
&&
this
.
versionNumber
<
327944
)
return
null
;
return
this
.
send
(
new
Command
(
RESTORE_FACTORY_SETTINGS
).
body
([
0x01
,
0x02
,
0x03
,
0x04
]),
seconds
);
};
Jensen
.
prototype
.
listFiles
=
async
function
()
{
let
tag
=
'filelist'
;
if
(
this
[
tag
]
!=
null
)
return
null
;
let
fc
=
null
;
if
(
typeof
this
.
versionNumber
==
'undefined'
||
this
.
versionNumber
<=
327722
)
{
fc
=
await
this
.
getFileCount
(
5
);
if
(
fc
==
null
)
return
null
;
let
tag
=
'filelist'
;
if
(
this
[
tag
]
!=
null
)
return
null
;
let
fc
=
null
;
if
(
typeof
this
.
versionNumber
==
'undefined'
||
this
.
versionNumber
<=
327722
)
{
fc
=
await
this
.
getFileCount
(
5
);
if
(
fc
==
null
)
return
null
;
}
if
(
fc
&&
fc
.
count
==
0
)
return
null
;
let
self
=
this
;
// let tag = 'data_' + new Date().getTime();
this
[
tag
]
=
[];
Jensen
.
registerHandler
(
QUERY_FILE_LIST
,
(
msg
,
jensen
)
=>
{
if
(
msg
.
body
.
length
==
0
)
{
jensen
[
tag
]
=
null
;
return
[];
}
jensen
[
tag
].
push
(
msg
.
body
);
let
data
=
[];
let
files
=
[];
let
fcount
=
-
1
;
let
start
=
0
;
for
(
let
i
=
0
;
i
<
jensen
[
tag
].
length
;
i
++
)
{
for
(
let
k
=
0
;
k
<
jensen
[
tag
][
i
].
length
;
k
++
)
data
.
push
(
jensen
[
tag
][
i
][
k
]);
}
if
((
data
[
0
]
&
0xff
)
==
0xff
&&
(
data
[
1
]
&
0xff
)
==
0xff
)
{
fcount
=
((
data
[
2
]
&
0xff
)
<<
24
)
|
((
data
[
3
]
&
0xff
)
<<
16
)
|
((
data
[
4
]
&
0xff
)
<<
8
)
|
(
data
[
5
]
&
0xff
);
start
+=
6
;
}
let
fnpad
=
function
(
v
)
{
return
v
>
9
?
v
:
'0'
+
v
;
};
for
(
let
i
=
start
;
i
<
data
.
length
;
)
{
let
len
=
0
;
let
fname
=
[];
if
(
i
+
4
>=
data
.
length
)
break
;
let
ver
=
data
[
i
++
]
&
0xff
;
let
nameLen
=
((
data
[
i
++
]
&
0xff
)
<<
16
)
|
((
data
[
i
++
]
&
0xff
)
<<
8
)
|
(
data
[
i
++
]
&
0xff
);
for
(
let
k
=
0
;
k
<
nameLen
&&
i
<
data
.
length
;
k
++
)
{
let
c
=
data
[
i
++
]
&
0xff
;
if
(
c
>
0
)
fname
.
push
(
String
.
fromCharCode
(
c
));
}
// 4 + nameLen + 4 + 6 + 16
if
(
i
+
4
+
6
+
16
>
data
.
length
)
{
break
;
}
let
flen
=
((
data
[
i
++
]
&
0xff
)
<<
24
)
|
((
data
[
i
++
]
&
0xff
)
<<
16
)
|
((
data
[
i
++
]
&
0xff
)
<<
8
)
|
(
data
[
i
++
]
&
0xff
);
i
+=
6
;
let
sign
=
[];
for
(
let
k
=
0
;
k
<
16
;
k
++
,
i
++
)
{
let
h
=
(
data
[
i
]
&
0xff
).
toString
(
16
);
sign
.
push
(
h
.
length
==
1
?
'0'
+
h
:
h
);
}
let
ftime
=
fname
.
join
(
''
);
let
duration
=
0
;
if
(
ftime
.
match
(
/^
\d{14}
REC
\d
+
\.
wav$/gi
))
{
ftime
=
ftime
.
replace
(
/^
(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})
REC.*$/gi
,
'$1-$2-$3 $4:$5:$6'
);
ftime
=
new
Date
(
ftime
);
duration
=
flen
/
32
;
}
else
if
(
ftime
.
match
(
/^
(\d{2})?(\d{2})(\w{3})(\d{2})
-
(\d{2})(\d{2})(\d{2})
-.*
\.
hda$/gi
))
{
// 2024Mar19-110932-Rec00.hda
ftime
=
ftime
.
replace
(
/^
(\d{2})?(\d{2})(\w{3})(\d{2})
-
(\d{2})(\d{2})(\d{2})
-.*
\.
hda$/gi
,
'20$2 $3 $4 $5:$6:$7'
);
ftime
=
new
Date
(
ftime
);
duration
=
(
flen
/
32
)
*
4
;
}
else
{
ftime
=
null
;
}
if
(
ver
==
1
)
{
duration
=
duration
*
2
;
}
let
createDate
=
''
;
let
createTime
=
''
;
if
(
ftime
)
{
createDate
=
ftime
.
getFullYear
()
+
'/'
+
fnpad
(
ftime
.
getMonth
()
+
1
)
+
'/'
+
fnpad
(
ftime
.
getDate
());
createTime
=
fnpad
(
ftime
.
getHours
())
+
':'
+
fnpad
(
ftime
.
getMinutes
())
+
':'
+
fnpad
(
ftime
.
getSeconds
());
}
files
.
push
({
name
:
fname
.
join
(
''
),
createDate
:
createDate
,
createTime
:
createTime
,
time
:
ftime
,
duration
:
duration
,
length
:
flen
,
signature
:
sign
.
join
(
''
)
});
}
// if (fcount == -1 && (fc))
// 如果没有判断数量的依据
if
(
fcount
==
-
1
)
{
// return [];
}
if
((
fc
&&
files
.
length
>=
fc
.
count
)
||
(
fcount
>
-
1
&&
files
.
length
>=
fcount
))
{
// delete jensen[tag];
jensen
[
tag
]
=
null
;
return
files
.
filter
((
f
)
=>
{
return
Boolean
(
f
.
time
);
});
}
});
if
(
fc
&&
fc
.
count
==
0
)
return
null
;
let
self
=
this
;
// let tag = 'data_' + new Date().getTime();
this
[
tag
]
=
[];
Jensen
.
registerHandler
(
QUERY_FILE_LIST
,
(
msg
,
jensen
)
=>
{
if
(
msg
.
body
.
length
==
0
)
{
jensen
[
tag
]
=
null
;
return
[];
}
jensen
[
tag
].
push
(
msg
.
body
);
let
data
=
[];
let
files
=
[];
let
fcount
=
-
1
;
let
start
=
0
;
for
(
let
i
=
0
;
i
<
jensen
[
tag
].
length
;
i
++
)
{
for
(
let
k
=
0
;
k
<
jensen
[
tag
][
i
].
length
;
k
++
)
data
.
push
(
jensen
[
tag
][
i
][
k
]);
}
if
((
data
[
0
]
&
0xff
)
==
0xff
&&
(
data
[
1
]
&
0xff
)
==
0xff
)
{
fcount
=
((
data
[
2
]
&
0xff
)
<<
24
)
|
((
data
[
3
]
&
0xff
)
<<
16
)
|
((
data
[
4
]
&
0xff
)
<<
8
)
|
(
data
[
5
]
&
0xff
);
start
+=
6
;
}
let
fnpad
=
function
(
v
)
{
return
v
>
9
?
v
:
'0'
+
v
;
};
for
(
let
i
=
start
;
i
<
data
.
length
;)
{
let
len
=
0
;
let
fname
=
[];
if
(
i
+
4
>=
data
.
length
)
break
;
let
ver
=
data
[
i
++
]
&
0xff
;
let
nameLen
=
((
data
[
i
++
]
&
0xff
)
<<
16
)
|
((
data
[
i
++
]
&
0xff
)
<<
8
)
|
(
data
[
i
++
]
&
0xff
);
for
(
let
k
=
0
;
k
<
nameLen
&&
i
<
data
.
length
;
k
++
)
{
let
c
=
data
[
i
++
]
&
0xff
;
if
(
c
>
0
)
fname
.
push
(
String
.
fromCharCode
(
c
));
}
// 4 + nameLen + 4 + 6 + 16
if
(
i
+
4
+
6
+
16
>
data
.
length
)
{
break
;
}
let
flen
=
((
data
[
i
++
]
&
0xff
)
<<
24
)
|
((
data
[
i
++
]
&
0xff
)
<<
16
)
|
((
data
[
i
++
]
&
0xff
)
<<
8
)
|
(
data
[
i
++
]
&
0xff
);
i
+=
6
;
let
sign
=
[];
for
(
let
k
=
0
;
k
<
16
;
k
++
,
i
++
)
{
let
h
=
(
data
[
i
]
&
0xff
).
toString
(
16
);
sign
.
push
(
h
.
length
==
1
?
'0'
+
h
:
h
);
}
let
ftime
=
fname
.
join
(
''
);
let
duration
=
0
;
if
(
ftime
.
match
(
/^
\d{14}
REC
\d
+
\.
wav$/gi
))
{
ftime
=
ftime
.
replace
(
/^
(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})
REC.*$/gi
,
'$1-$2-$3 $4:$5:$6'
);
ftime
=
new
Date
(
ftime
);
duration
=
flen
/
32
;
}
else
if
(
ftime
.
match
(
/^
(\d{2})?(\d{2})(\w{3})(\d{2})
-
(\d{2})(\d{2})(\d{2})
-.*
\.
hda$/gi
))
{
// 2024Mar19-110932-Rec00.hda
ftime
=
ftime
.
replace
(
/^
(\d{2})?(\d{2})(\w{3})(\d{2})
-
(\d{2})(\d{2})(\d{2})
-.*
\.
hda$/gi
,
'20$2 $3 $4 $5:$6:$7'
);
ftime
=
new
Date
(
ftime
);
duration
=
(
flen
/
32
)
*
4
;
}
else
{
ftime
=
null
;
}
if
(
ver
==
1
)
{
duration
=
duration
*
2
;
}
let
createDate
=
''
;
let
createTime
=
''
;
if
(
ftime
)
{
createDate
=
ftime
.
getFullYear
()
+
'/'
+
fnpad
(
ftime
.
getMonth
()
+
1
)
+
'/'
+
fnpad
(
ftime
.
getDate
());
createTime
=
fnpad
(
ftime
.
getHours
())
+
':'
+
fnpad
(
ftime
.
getMinutes
())
+
':'
+
fnpad
(
ftime
.
getSeconds
());
}
files
.
push
({
name
:
fname
.
join
(
''
),
createDate
:
createDate
,
createTime
:
createTime
,
time
:
ftime
,
duration
:
duration
,
length
:
flen
,
signature
:
sign
.
join
(
''
),
});
}
// if (fcount == -1 && (fc))
// 如果没有判断数量的依据
if
(
fcount
==
-
1
)
{
// return [];
}
if
((
fc
&&
files
.
length
>=
fc
.
count
)
||
(
fcount
>
-
1
&&
files
.
length
>=
fcount
))
{
// delete jensen[tag];
jensen
[
tag
]
=
null
;
return
files
.
filter
((
f
)
=>
{
return
Boolean
(
f
.
time
);
});
}
});
return
this
.
send
(
new
Command
(
QUERY_FILE_LIST
));
return
this
.
send
(
new
Command
(
QUERY_FILE_LIST
));
};
Jensen
.
prototype
.
deleteFile
=
async
function
(
filename
,
seconds
)
{
let
fname
=
[];
for
(
let
i
=
0
;
i
<
filename
.
length
;
i
++
)
fname
.
push
(
filename
.
charCodeAt
(
i
));
return
this
.
send
(
new
Command
(
DELETE_FILE
).
body
(
fname
),
seconds
);
let
fname
=
[];
for
(
let
i
=
0
;
i
<
filename
.
length
;
i
++
)
fname
.
push
(
filename
.
charCodeAt
(
i
));
return
this
.
send
(
new
Command
(
DELETE_FILE
).
body
(
fname
),
seconds
);
};
Jensen
.
prototype
.
setTime
=
async
function
(
time
,
seconds
)
{
let
str
=
time
.
getFullYear
()
+
'-0'
+
(
time
.
getMonth
()
+
1
)
+
'-0'
+
time
.
getDate
()
+
'-0'
+
time
.
getHours
()
+
'-0'
+
time
.
getMinutes
()
+
'-0'
+
time
.
getSeconds
();
str
=
str
.
replace
(
/
(\d{4})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})
/gi
,
'$1$2$3$4$5$6'
);
return
this
.
send
(
new
Command
(
SET_DEVICE_TIME
).
body
(
this
.
to_bcd
(
str
)),
seconds
);
let
str
=
time
.
getFullYear
()
+
'-0'
+
(
time
.
getMonth
()
+
1
)
+
'-0'
+
time
.
getDate
()
+
'-0'
+
time
.
getHours
()
+
'-0'
+
time
.
getMinutes
()
+
'-0'
+
time
.
getSeconds
();
str
=
str
.
replace
(
/
(\d{4})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})
/gi
,
'$1$2$3$4$5$6'
);
return
this
.
send
(
new
Command
(
SET_DEVICE_TIME
).
body
(
this
.
to_bcd
(
str
)),
seconds
);
};
Jensen
.
prototype
.
getFile
=
async
function
(
filename
,
length
,
ondata
,
onprogress
)
{
if
(
typeof
length
!=
'number'
)
throw
new
Error
(
'parameter `length` required'
);
if
(
length
<=
0
)
throw
new
Error
(
'parameter `length` must greater than zero'
);
Logger
.
info
(
'jensen'
,
'getFile'
,
`file download start. filename:
${
filename
}
, length:
${
length
}
`
);
let
fname
=
[];
for
(
let
i
=
0
;
i
<
filename
.
length
;
i
++
)
fname
.
push
(
filename
.
charCodeAt
(
i
));
let
wakeLock
=
null
;
function
visibilitychange
()
{
let
audio
=
document
.
getElementById
(
'test_audio'
);
if
(
!
audio
)
{
audio
=
document
.
createElement
(
'audio'
);
audio
.
id
=
'test_audio'
audio
.
src
=
'https://audionotes.hidock.com/test/test.aac'
;
audio
.
loop
=
true
;
audio
.
controls
=
false
;
audio
.
autoplay
=
true
;
audio
.
muted
=
true
;
document
.
body
.
appendChild
(
audio
);
}
if
(
document
.
visibilityState
===
'hidden'
)
{
console
.
log
(
'Page is hidden'
);
audio
.
play
();
}
else
{
audio
.
pause
();
console
.
log
(
'Page is visible'
);
wakeLock
&&
wakeLock
.
release
();
}
if
(
typeof
length
!=
'number'
)
throw
new
Error
(
'parameter `length` required'
);
if
(
length
<=
0
)
throw
new
Error
(
'parameter `length` must greater than zero'
);
Logger
.
info
(
'jensen'
,
'getFile'
,
`file download start. filename:
${
filename
}
, length:
${
length
}
`
);
let
fname
=
[];
for
(
let
i
=
0
;
i
<
filename
.
length
;
i
++
)
fname
.
push
(
filename
.
charCodeAt
(
i
));
let
wakeLock
=
null
;
function
visibilitychange
()
{
let
audio
=
document
.
getElementById
(
'test_audio'
);
if
(
!
audio
)
{
audio
=
document
.
createElement
(
'audio'
);
audio
.
id
=
'test_audio'
;
audio
.
src
=
'https://audionotes.hidock.com/test/test.aac'
;
audio
.
loop
=
true
;
audio
.
controls
=
false
;
audio
.
autoplay
=
true
;
audio
.
muted
=
true
;
document
.
body
.
appendChild
(
audio
);
}
if
(
'wakeLock'
in
navigator
)
{
try
{
wakeLock
=
await
navigator
.
wakeLock
.
request
(
'screen'
);
console
.
log
(
'Wake lock activated'
);
}
catch
(
err
)
{
console
.
error
(
'Failed to acquire wake lock:'
,
err
);
}
if
(
document
.
visibilityState
===
'hidden'
)
{
console
.
log
(
'Page is hidden'
);
audio
.
play
();
}
else
{
audio
.
pause
();
console
.
log
(
'Page is visible'
);
wakeLock
&&
wakeLock
.
release
();
}
function
clearEventAndTask
()
{
const
audio
=
document
.
getElementById
(
'test_audio'
);
audio
&&
audio
.
remove
();
wakeLock
&&
wakeLock
.
release
();
console
.
log
(
'Clear event and task.'
);
}
if
(
'wakeLock'
in
navigator
)
{
try
{
wakeLock
=
await
navigator
.
wakeLock
.
request
(
'screen'
);
console
.
log
(
'Wake lock activated'
);
}
catch
(
err
)
{
console
.
error
(
'Failed to acquire wake lock:'
,
err
);
}
visibilitychange
();
document
.
addEventListener
(
'visibilitychange'
,
visibilitychange
);
let
flen
=
0
;
let
handler
=
(
msg
)
=>
{
if
(
msg
!=
null
)
{
flen
+=
msg
.
body
.
length
||
msg
.
body
.
byteLength
;
ondata
(
msg
.
body
);
Logger
.
info
(
'jensen'
,
'getFile length'
,
`
${
length
}
${
flen
}
`
)
if
(
flen
>=
length
)
{
document
.
removeEventListener
(
'visibilitychange'
,
visibilitychange
);
Logger
.
info
(
'jensen'
,
'getFile'
,
'file download finish.'
)
clearEventAndTask
();
// return OK indicates all file blocks received
return
'OK'
;
}
}
else
{
document
.
removeEventListener
(
'visibilitychange'
,
visibilitychange
);
clearEventAndTask
();
Logger
.
info
(
'jensen'
,
'getFile'
,
'file download fail.'
)
ondata
(
'fail'
);
}
};
this
.
onreceive
=
onprogress
;
Jensen
.
registerHandler
(
TRANSFER_FILE
,
handler
);
this
.
send
(
new
Command
(
TRANSFER_FILE
).
body
(
fname
));
}
function
clearEventAndTask
()
{
const
audio
=
document
.
getElementById
(
'test_audio'
);
audio
&&
audio
.
remove
();
wakeLock
&&
wakeLock
.
release
();
console
.
log
(
'Clear event and task.'
);
}
visibilitychange
();
document
.
addEventListener
(
'visibilitychange'
,
visibilitychange
);
let
flen
=
0
;
let
handler
=
(
msg
)
=>
{
if
(
msg
!=
null
)
{
flen
+=
msg
.
body
.
length
||
msg
.
body
.
byteLength
;
ondata
(
msg
.
body
);
Logger
.
info
(
'jensen'
,
'getFile length'
,
`
${
length
}
${
flen
}
`
);
if
(
flen
>=
length
)
{
document
.
removeEventListener
(
'visibilitychange'
,
visibilitychange
);
Logger
.
info
(
'jensen'
,
'getFile'
,
'file download finish.'
);
clearEventAndTask
();
// return OK indicates all file blocks received
return
'OK'
;
}
}
else
{
document
.
removeEventListener
(
'visibilitychange'
,
visibilitychange
);
clearEventAndTask
();
Logger
.
info
(
'jensen'
,
'getFile'
,
'file download fail.'
);
ondata
(
'fail'
);
}
};
this
.
onreceive
=
onprogress
;
Jensen
.
registerHandler
(
TRANSFER_FILE
,
handler
);
this
.
send
(
new
Command
(
TRANSFER_FILE
).
body
(
fname
));
};
Jensen
.
prototype
.
requestFirmwareUpgrade
=
async
function
(
versionNumber
,
fileSize
,
seconds
)
{
let
data
=
[];
data
[
0
]
=
(
versionNumber
>>
24
)
&
0xff
;
data
[
1
]
=
(
versionNumber
>>
16
)
&
0xff
;
data
[
2
]
=
(
versionNumber
>>
8
)
&
0xff
;
data
[
3
]
=
(
versionNumber
>>
0
)
&
0xff
;
data
[
4
]
=
(
fileSize
>>
24
)
&
0xff
;
data
[
5
]
=
(
fileSize
>>
16
)
&
0xff
;
data
[
6
]
=
(
fileSize
>>
8
)
&
0xff
;
data
[
7
]
=
(
fileSize
>>
0
)
&
0xff
;
return
this
.
send
(
new
Command
(
REQUEST_FIRMWARE_UPGRADE
).
body
(
data
),
seconds
);
let
data
=
[];
data
[
0
]
=
(
versionNumber
>>
24
)
&
0xff
;
data
[
1
]
=
(
versionNumber
>>
16
)
&
0xff
;
data
[
2
]
=
(
versionNumber
>>
8
)
&
0xff
;
data
[
3
]
=
(
versionNumber
>>
0
)
&
0xff
;
data
[
4
]
=
(
fileSize
>>
24
)
&
0xff
;
data
[
5
]
=
(
fileSize
>>
16
)
&
0xff
;
data
[
6
]
=
(
fileSize
>>
8
)
&
0xff
;
data
[
7
]
=
(
fileSize
>>
0
)
&
0xff
;
return
this
.
send
(
new
Command
(
REQUEST_FIRMWARE_UPGRADE
).
body
(
data
),
seconds
);
};
Jensen
.
prototype
.
uploadFirmware
=
async
function
(
data
,
seconds
,
onprogress
)
{
return
this
.
send
(
new
Command
(
FIRMWARE_UPLOAD
).
body
(
data
),
seconds
,
onprogress
);
return
this
.
send
(
new
Command
(
FIRMWARE_UPLOAD
).
body
(
data
),
seconds
,
onprogress
);
};
Jensen
.
prototype
.
beginBNC
=
async
function
(
seconds
)
{
return
this
.
send
(
new
Command
(
BNC_DEMO_TEST
).
body
([
0x01
]),
seconds
);
return
this
.
send
(
new
Command
(
BNC_DEMO_TEST
).
body
([
0x01
]),
seconds
);
};
Jensen
.
prototype
.
endBNC
=
async
function
(
seconds
)
{
return
this
.
send
(
new
Command
(
BNC_DEMO_TEST
).
body
([
0x00
]),
seconds
);
return
this
.
send
(
new
Command
(
BNC_DEMO_TEST
).
body
([
0x00
]),
seconds
);
};
Jensen
.
prototype
.
getSettings
=
async
function
(
seconds
)
{
if
(
this
.
versionNumber
<
327714
)
{
return
{
autoRecord
:
false
,
autoPlay
:
false
};
}
return
this
.
send
(
new
Command
(
GET_SETTINGS
),
seconds
);
if
(
this
.
versionNumber
<
327714
)
{
return
{
autoRecord
:
false
,
autoPlay
:
false
};
}
return
this
.
send
(
new
Command
(
GET_SETTINGS
),
seconds
);
};
Jensen
.
prototype
.
setAutoRecord
=
function
(
enable
,
seconds
)
{
if
(
this
.
versionNumber
<
327714
)
return
{
result
:
false
};
return
this
.
send
(
new
Command
(
SET_SETTINGS
).
body
([
0
,
0
,
0
,
enable
?
1
:
2
]),
seconds
);
if
(
this
.
versionNumber
<
327714
)
return
{
result
:
false
};
return
this
.
send
(
new
Command
(
SET_SETTINGS
).
body
([
0
,
0
,
0
,
enable
?
1
:
2
]),
seconds
);
};
Jensen
.
prototype
.
setAutoPlay
=
function
(
enable
,
seconds
)
{
if
(
this
.
versionNumber
<
327714
)
return
{
result
:
false
};
return
this
.
send
(
new
Command
(
SET_SETTINGS
).
body
([
0
,
0
,
0
,
0
,
0
,
0
,
0
,
enable
?
1
:
2
,
]),
seconds
);
if
(
this
.
versionNumber
<
327714
)
return
{
result
:
false
};
return
this
.
send
(
new
Command
(
SET_SETTINGS
).
body
([
0
,
0
,
0
,
0
,
0
,
0
,
0
,
enable
?
1
:
2
]),
seconds
);
};
Jensen
.
prototype
.
setNotification
=
function
(
enable
,
seconds
)
{
if
(
this
.
versionNumber
<
327714
)
return
{
result
:
false
};
return
this
.
send
(
new
Command
(
SET_SETTINGS
).
body
([
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
enable
?
1
:
2
]),
seconds
);
if
(
this
.
versionNumber
<
327714
)
return
{
result
:
false
};
return
this
.
send
(
new
Command
(
SET_SETTINGS
).
body
([
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
enable
?
1
:
2
]),
seconds
);
};
Jensen
.
prototype
.
setBluetoothPromptPlay
=
function
(
enable
,
seconds
)
{
// h1e 6.1.4 393476
// h1 5.1.4 327940
if
(
this
.
model
===
'hidock-h1e'
&&
this
.
versionNumber
<
393476
)
return
{
result
:
false
}
if
(
this
.
model
===
'hidock-h1'
&&
this
.
versionNumber
<
327940
)
return
{
result
:
false
}
return
this
.
send
(
new
Command
(
SET_SETTINGS
).
body
([
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
enable
?
2
:
1
]),
seconds
);
}
// h1e 6.1.4 393476
// h1 5.1.4 327940
if
(
this
.
model
===
'hidock-h1e'
&&
this
.
versionNumber
<
393476
)
return
{
result
:
false
};
if
(
this
.
model
===
'hidock-h1'
&&
this
.
versionNumber
<
327940
)
return
{
result
:
false
};
return
this
.
send
(
new
Command
(
SET_SETTINGS
).
body
([
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
,
enable
?
2
:
1
]),
seconds
);
}
;
Jensen
.
prototype
.
getCardInfo
=
function
(
seconds
)
{
if
(
this
.
versionNumber
<
327733
)
return
null
;
return
this
.
send
(
new
Command
(
READ_CARD_INFO
),
seconds
);
if
(
this
.
versionNumber
<
327733
)
return
null
;
return
this
.
send
(
new
Command
(
READ_CARD_INFO
),
seconds
);
};
Jensen
.
prototype
.
formatCard
=
function
(
seconds
)
{
if
(
this
.
versionNumber
<
327733
)
return
null
;
return
this
.
send
(
new
Command
(
FORMAT_CARD
).
body
([
0x01
,
0x02
,
0x03
,
0x04
]),
seconds
);
if
(
this
.
versionNumber
<
327733
)
return
null
;
return
this
.
send
(
new
Command
(
FORMAT_CARD
).
body
([
0x01
,
0x02
,
0x03
,
0x04
]),
seconds
);
};
Jensen
.
prototype
.
getRecordingFile
=
function
(
seconds
)
{
if
(
this
.
versionNumber
<
327733
)
return
null
;
return
this
.
send
(
new
Command
(
GET_RECORDING_FILE
),
seconds
);
if
(
this
.
versionNumber
<
327733
)
return
null
;
return
this
.
send
(
new
Command
(
GET_RECORDING_FILE
),
seconds
);
};
Jensen
.
prototype
.
recordTestStart
=
async
function
(
type
,
seconds
)
{
return
this
.
send
(
new
Command
(
0xf008
).
body
([
type
]),
seconds
);
return
this
.
send
(
new
Command
(
0xf008
).
body
([
type
]),
seconds
);
};
Jensen
.
prototype
.
recordTestEnd
=
async
function
(
type
,
seconds
)
{
return
this
.
send
(
new
Command
(
0xf009
).
body
([
type
]),
seconds
);
return
this
.
send
(
new
Command
(
0xf009
).
body
([
type
]),
seconds
);
};
Jensen
.
prototype
.
test
=
async
function
(
seconds
)
{
return
this
.
send
(
new
Command
(
DEVICE_MSG_TEST
),
seconds
);
return
this
.
send
(
new
Command
(
DEVICE_MSG_TEST
),
seconds
);
};
Jensen
.
prototype
.
getFileBlock
=
async
function
(
filename
,
length
,
ondata
)
{
if
(
typeof
(
length
)
!=
'number'
)
throw
new
Error
(
'parameter `length` required'
);
if
(
length
<=
0
)
throw
new
Error
(
'parameter `length` must greater than zero'
);
if
(
this
.
fileLength
>
0
)
return
null
;
let
data
=
[];
data
.
push
((
length
>>
24
)
&
0xff
);
data
.
push
((
length
>>
16
)
&
0xff
);
data
.
push
((
length
>>
8
)
&
0xff
);
data
.
push
((
length
>>
0
)
&
0xff
);
for
(
let
i
=
0
;
i
<
filename
.
length
;
i
++
)
data
.
push
(
filename
.
charCodeAt
(
i
));
this
.
onFileRecvHandler
=
ondata
;
this
.
fileLength
=
length
;
this
.
fileReadBytes
=
0
;
return
this
.
send
(
new
Command
(
GET_FILE_BLOCK
).
body
(
data
));
}
if
(
typeof
length
!=
'number'
)
throw
new
Error
(
'parameter `length` required'
);
if
(
length
<=
0
)
throw
new
Error
(
'parameter `length` must greater than zero'
);
if
(
this
.
fileLength
>
0
)
return
null
;
let
data
=
[];
data
.
push
((
length
>>
24
)
&
0xff
);
data
.
push
((
length
>>
16
)
&
0xff
);
data
.
push
((
length
>>
8
)
&
0xff
);
data
.
push
((
length
>>
0
)
&
0xff
);
for
(
let
i
=
0
;
i
<
filename
.
length
;
i
++
)
data
.
push
(
filename
.
charCodeAt
(
i
));
this
.
onFileRecvHandler
=
ondata
;
this
.
fileLength
=
length
;
this
.
fileReadBytes
=
0
;
return
this
.
send
(
new
Command
(
GET_FILE_BLOCK
).
body
(
data
));
}
;
Jensen
.
prototype
.
writeSerialNumber
=
async
function
(
sn
)
{
let
data
=
[];
for
(
let
i
=
0
;
i
<
sn
.
length
;
i
++
)
{
data
.
push
(
sn
.
charCodeAt
(
i
));
}
return
this
.
send
(
new
Command
(
TEST_SN_WRITE
).
body
(
data
));
}
let
data
=
[];
for
(
let
i
=
0
;
i
<
sn
.
length
;
i
++
)
{
data
.
push
(
sn
.
charCodeAt
(
i
));
}
return
this
.
send
(
new
Command
(
TEST_SN_WRITE
).
body
(
data
));
}
;
const
commonMessageParser
=
(
msg
)
=>
{
return
{
result
:
msg
.
body
[
0
]
===
0x00
?
'success'
:
'failed'
};
return
{
result
:
msg
.
body
[
0
]
===
0x00
?
'success'
:
'failed'
};
};
Jensen
.
prototype
.
sendScheduleInfo
=
function
(
info
)
{
const
startDate
=
this
.
to_bcd
(
getTimeStr
(
info
.
startDate
));
const
endDate
=
this
.
to_bcd
(
getTimeStr
(
info
.
endDate
));
const
keyAnswer
=
[
3
,
7
,
4
,
0
,
0
,
0
,
0
,
0
];
const
keyHangup
=
[
3
,
7
,
5
,
0
,
0
,
0
,
0
,
0
];
const
keyReject
=
[
3
,
7
,
6
,
0
,
0
,
0
,
0
,
0
];
const
keyMicMute
=
[
3
,
7
,
7
,
0
,
0
,
0
,
0
,
0
];
const
body
=
[...
startDate
,
...
endDate
,
0
,
0
,
...
keyAnswer
,
...
keyHangup
,
...
keyReject
,
...
keyMicMute
];
console
.
log
(
'send schedule info'
,
info
,
body
);
return
this
.
send
(
new
Command
(
SCHEDULE_INFO
).
body
(
body
));
};
let
codes
=
new
Array
(
33
).
fill
(
0
);
if
(
shortcutKeys
[
info
.
platform
]
&&
shortcutKeys
[
info
.
platform
][
info
.
os
])
{
codes
=
shortcutKeys
[
info
.
platform
][
info
.
os
];
}
let
startDate
=
new
Array
(
7
).
fill
(
0
);
let
endDate
=
new
Array
(
7
).
fill
(
0
);
if
(
info
.
startDate
&&
info
.
endDate
)
{
startDate
=
this
.
to_bcd
(
getTimeStr
(
info
.
startDate
));
endDate
=
this
.
to_bcd
(
getTimeStr
(
info
.
endDate
));
}
const
reserved
=
0x00
;
// 预留
const
body
=
[...
startDate
,
...
endDate
,
0x00
,
...
codes
];
console
.
log
(
'send schedule info'
,
info
,
body
);
return
this
.
send
(
new
Command
(
SCHEDULE_INFO
).
body
(
body
));
};
Jensen
.
registerHandler
(
SET_DEVICE_TIME
,
commonMessageParser
);
Jensen
.
registerHandler
(
BNC_DEMO_TEST
,
commonMessageParser
);
Jensen
.
registerHandler
(
DELETE_FILE
,
(
msg
)
=>
{
let
rst
=
'failed'
;
if
(
msg
.
body
[
0
]
===
0x00
)
rst
=
'success'
;
else
if
(
msg
.
body
[
0
]
===
0x01
)
rst
=
'not-exists'
;
else
if
(
msg
.
body
[
0
]
===
0x02
)
rst
=
'failed'
;
return
{
result
:
rst
};
let
rst
=
'failed'
;
if
(
msg
.
body
[
0
]
===
0x00
)
rst
=
'success'
;
else
if
(
msg
.
body
[
0
]
===
0x01
)
rst
=
'not-exists'
;
else
if
(
msg
.
body
[
0
]
===
0x02
)
rst
=
'failed'
;
return
{
result
:
rst
};
});
Jensen
.
registerHandler
(
QUERY_DEVICE_INFO
,
(
msg
,
jensen
)
=>
{
let
vc
=
[],
vn
=
0
;
let
sn
=
[];
for
(
let
i
=
0
;
i
<
4
;
i
++
)
{
let
b
=
msg
.
body
[
i
]
&
0xff
;
if
(
i
>
0
)
{
vc
.
push
(
String
(
b
));
}
vn
=
vn
|
(
b
<<
((
4
-
i
-
1
)
*
8
));
}
for
(
let
i
=
0
;
i
<
16
;
i
++
)
{
let
chr
=
msg
.
body
[
i
+
4
];
if
(
chr
>
0
)
sn
.
push
(
String
.
fromCharCode
(
chr
));
let
vc
=
[],
vn
=
0
;
let
sn
=
[];
for
(
let
i
=
0
;
i
<
4
;
i
++
)
{
let
b
=
msg
.
body
[
i
]
&
0xff
;
if
(
i
>
0
)
{
vc
.
push
(
String
(
b
));
}
jensen
.
versionCode
=
vc
.
join
(
'.'
);
jensen
.
versionNumber
=
vn
;
sn
=
sn
.
join
(
''
);
jensen
.
serialNumber
=
sn
;
return
{
versionCode
:
vc
.
join
(
'.'
),
versionNumber
:
vn
,
sn
:
sn
,
};
vn
=
vn
|
(
b
<<
((
4
-
i
-
1
)
*
8
));
}
for
(
let
i
=
0
;
i
<
16
;
i
++
)
{
let
chr
=
msg
.
body
[
i
+
4
];
if
(
chr
>
0
)
sn
.
push
(
String
.
fromCharCode
(
chr
));
}
jensen
.
versionCode
=
vc
.
join
(
'.'
);
jensen
.
versionNumber
=
vn
;
sn
=
sn
.
join
(
''
);
jensen
.
serialNumber
=
sn
;
return
{
versionCode
:
vc
.
join
(
'.'
),
versionNumber
:
vn
,
sn
:
sn
};
});
Jensen
.
registerHandler
(
QUERY_DEVICE_TIME
,
(
msg
,
jensen
)
=>
{
let
time
=
jensen
.
from_bcd
(
msg
.
body
[
0
]
&
0xff
,
msg
.
body
[
1
]
&
0xff
,
msg
.
body
[
2
]
&
0xff
,
msg
.
body
[
3
]
&
0xff
,
msg
.
body
[
4
]
&
0xff
,
msg
.
body
[
5
]
&
0xff
,
msg
.
body
[
6
]
&
0xff
,
);
return
{
time
:
time
===
'00000000000000'
?
'unknown'
:
time
.
replace
(
/^
(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})
$/gi
,
'$1-$2-$3 $4:$5:$6'
),
};
let
time
=
jensen
.
from_bcd
(
msg
.
body
[
0
]
&
0xff
,
msg
.
body
[
1
]
&
0xff
,
msg
.
body
[
2
]
&
0xff
,
msg
.
body
[
3
]
&
0xff
,
msg
.
body
[
4
]
&
0xff
,
msg
.
body
[
5
]
&
0xff
,
msg
.
body
[
6
]
&
0xff
);
return
{
time
:
time
===
'00000000000000'
?
'unknown'
:
time
.
replace
(
/^
(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})
$/gi
,
'$1-$2-$3 $4:$5:$6'
)
};
});
Jensen
.
registerHandler
(
QUERY_FILE_COUNT
,
(
msg
)
=>
{
if
(
msg
.
body
.
length
===
0
)
return
{
count
:
0
};
let
c
=
0
;
for
(
let
i
=
0
;
i
<
4
;
i
++
)
{
let
b
=
msg
.
body
[
i
]
&
0xff
;
c
=
c
|
(
b
<<
((
4
-
i
-
1
)
*
8
));
}
return
{
count
:
c
};
if
(
msg
.
body
.
length
===
0
)
return
{
count
:
0
};
let
c
=
0
;
for
(
let
i
=
0
;
i
<
4
;
i
++
)
{
let
b
=
msg
.
body
[
i
]
&
0xff
;
c
=
c
|
(
b
<<
((
4
-
i
-
1
)
*
8
));
}
return
{
count
:
c
};
});
Jensen
.
registerHandler
(
GET_SETTINGS
,
(
msg
)
=>
{
let
r1
=
msg
.
body
[
3
];
let
r2
=
msg
.
body
[
7
];
let
r4
=
msg
.
body
[
15
];
let
rst
=
{
autoRecord
:
r1
===
1
,
autoPlay
:
r2
===
1
,
bluetoothTone
:
!
(
r4
===
1
)
};
if
(
msg
.
body
.
length
>=
12
)
{
let
r3
=
msg
.
body
[
11
]
===
1
;
rst
[
'notification'
]
=
r3
;
}
return
rst
;
let
r1
=
msg
.
body
[
3
];
let
r2
=
msg
.
body
[
7
];
let
r4
=
msg
.
body
[
15
];
let
rst
=
{
autoRecord
:
r1
===
1
,
autoPlay
:
r2
===
1
,
bluetoothTone
:
!
(
r4
===
1
)
};
if
(
msg
.
body
.
length
>=
12
)
{
let
r3
=
msg
.
body
[
11
]
===
1
;
rst
[
'notification'
]
=
r3
;
}
return
rst
;
});
Jensen
.
registerHandler
(
SET_SETTINGS
,
commonMessageParser
);
Jensen
.
registerHandler
(
FACTORY_RESET
,
commonMessageParser
);
Jensen
.
registerHandler
(
RESTORE_FACTORY_SETTINGS
,
commonMessageParser
);
Jensen
.
registerHandler
(
REQUEST_FIRMWARE_UPGRADE
,
(
msg
)
=>
{
let
rst
=
''
;
let
c
=
msg
.
body
[
0
];
if
(
c
===
0x00
)
rst
=
'accepted'
;
if
(
c
===
0x01
)
rst
=
'wrong-version'
;
if
(
c
===
0x02
)
rst
=
'busy'
;
if
(
c
===
0x03
)
return
'unknown'
;
return
{
result
:
rst
};
let
rst
=
''
;
let
c
=
msg
.
body
[
0
];
if
(
c
===
0x00
)
rst
=
'accepted'
;
if
(
c
===
0x01
)
rst
=
'wrong-version'
;
if
(
c
===
0x02
)
rst
=
'busy'
;
if
(
c
===
0x03
)
return
'unknown'
;
return
{
result
:
rst
};
});
Jensen
.
registerHandler
(
FIRMWARE_UPLOAD
,
(
msg
)
=>
{
let
c
=
msg
.
body
[
0
];
return
{
result
:
c
===
0x00
?
'success'
:
'failed'
};
let
c
=
msg
.
body
[
0
];
return
{
result
:
c
===
0x00
?
'success'
:
'failed'
};
});
Jensen
.
registerHandler
(
READ_CARD_INFO
,
(
msg
)
=>
{
let
i
=
0
;
let
used
=
((
msg
.
body
[
i
++
]
&
0xff
)
<<
24
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
16
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
i
++
]
&
0xff
);
let
capacity
=
((
msg
.
body
[
i
++
]
&
0xff
)
<<
24
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
16
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
i
++
]
&
0xff
);
let
status
=
((
msg
.
body
[
i
++
]
&
0xff
)
<<
24
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
16
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
i
++
]
&
0xff
);
let
i
=
0
;
let
used
=
((
msg
.
body
[
i
++
]
&
0xff
)
<<
24
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
16
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
i
++
]
&
0xff
);
let
capacity
=
((
msg
.
body
[
i
++
]
&
0xff
)
<<
24
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
16
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
i
++
]
&
0xff
);
let
status
=
((
msg
.
body
[
i
++
]
&
0xff
)
<<
24
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
16
)
|
((
msg
.
body
[
i
++
]
&
0xff
)
<<
8
)
|
(
msg
.
body
[
i
++
]
&
0xff
);
return
{
used
:
used
,
capacity
:
capacity
,
status
:
status
.
toString
(
16
)
};
return
{
used
:
used
,
capacity
:
capacity
,
status
:
status
.
toString
(
16
)
};
});
Jensen
.
registerHandler
(
FORMAT_CARD
,
commonMessageParser
);
Jensen
.
registerHandler
(
GET_RECORDING_FILE
,
(
msg
)
=>
{
if
(
msg
.
body
==
null
||
msg
.
body
.
length
===
0
)
return
{
recording
:
null
};
else
{
let
fname
=
[];
for
(
var
i
=
0
;
i
<
msg
.
body
.
length
;
i
++
)
{
fname
.
push
(
String
.
fromCharCode
(
msg
.
body
[
i
]));
}
let
fnpad
=
function
(
v
)
{
return
v
>
9
?
v
:
'0'
+
v
;
};
let
ftime
=
fname
.
join
(
''
);
if
(
ftime
.
match
(
/^
\d{14}
REC
\d
+
\.
wav$/gi
))
{
ftime
=
ftime
.
replace
(
/^
(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})
REC.*$/gi
,
'$1-$2-$3 $4:$5:$6'
);
ftime
=
new
Date
(
ftime
);
}
else
if
(
ftime
.
match
(
/^
(\d{2})?(\d{2})(\w{3})(\d{2})
-
(\d{2})(\d{2})(\d{2})
-.*
\.
hda$/gi
))
{
// 2024Mar19-110932-Rec00.hda
ftime
=
ftime
.
replace
(
/^
(\d{2})?(\d{2})(\w{3})(\d{2})
-
(\d{2})(\d{2})(\d{2})
-.*
\.
hda$/gi
,
'20$2 $3 $4 $5:$6:$7'
);
ftime
=
new
Date
(
ftime
);
}
else
{
ftime
=
null
;
}
let
createDate
=
''
;
let
createTime
=
''
;
if
(
ftime
)
{
createDate
=
ftime
.
getFullYear
()
+
'/'
+
fnpad
(
ftime
.
getMonth
()
+
1
)
+
'/'
+
fnpad
(
ftime
.
getDate
());
createTime
=
fnpad
(
ftime
.
getHours
())
+
':'
+
fnpad
(
ftime
.
getMinutes
())
+
':'
+
fnpad
(
ftime
.
getSeconds
());
}
return
{
recording
:
fname
.
join
(
''
),
name
:
fname
.
join
(
''
),
createDate
:
createDate
,
createTime
:
createTime
,
time
:
ftime
,
duration
:
0
,
length
:
0
,
signature
:
'0'
.
repeat
(
32
),
};
if
(
msg
.
body
==
null
||
msg
.
body
.
length
===
0
)
return
{
recording
:
null
};
else
{
let
fname
=
[];
for
(
var
i
=
0
;
i
<
msg
.
body
.
length
;
i
++
)
{
fname
.
push
(
String
.
fromCharCode
(
msg
.
body
[
i
]));
}
let
fnpad
=
function
(
v
)
{
return
v
>
9
?
v
:
'0'
+
v
;
};
let
ftime
=
fname
.
join
(
''
);
if
(
ftime
.
match
(
/^
\d{14}
REC
\d
+
\.
wav$/gi
))
{
ftime
=
ftime
.
replace
(
/^
(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})
REC.*$/gi
,
'$1-$2-$3 $4:$5:$6'
);
ftime
=
new
Date
(
ftime
);
}
else
if
(
ftime
.
match
(
/^
(\d{2})?(\d{2})(\w{3})(\d{2})
-
(\d{2})(\d{2})(\d{2})
-.*
\.
hda$/gi
))
{
// 2024Mar19-110932-Rec00.hda
ftime
=
ftime
.
replace
(
/^
(\d{2})?(\d{2})(\w{3})(\d{2})
-
(\d{2})(\d{2})(\d{2})
-.*
\.
hda$/gi
,
'20$2 $3 $4 $5:$6:$7'
);
ftime
=
new
Date
(
ftime
);
}
else
{
ftime
=
null
;
}
let
createDate
=
''
;
let
createTime
=
''
;
if
(
ftime
)
{
createDate
=
ftime
.
getFullYear
()
+
'/'
+
fnpad
(
ftime
.
getMonth
()
+
1
)
+
'/'
+
fnpad
(
ftime
.
getDate
());
createTime
=
fnpad
(
ftime
.
getHours
())
+
':'
+
fnpad
(
ftime
.
getMinutes
())
+
':'
+
fnpad
(
ftime
.
getSeconds
());
}
return
{
recording
:
fname
.
join
(
''
),
name
:
fname
.
join
(
''
),
createDate
:
createDate
,
createTime
:
createTime
,
time
:
ftime
,
duration
:
0
,
length
:
0
,
signature
:
'0'
.
repeat
(
32
)
};
}
});
Jensen
.
registerHandler
(
RECORD_TEST_START
,
commonMessageParser
);
Jensen
.
registerHandler
(
RECORD_TEST_END
,
commonMessageParser
);
Jensen
.
registerHandler
(
DEVICE_MSG_TEST
,
commonMessageParser
);
Jensen
.
registerHandler
(
GET_FILE_BLOCK
,
commonMessageParser
);
Jensen
.
registerHandler
(
TEST_SN_WRITE
,
commonMessageParser
)
Jensen
.
registerHandler
(
SCHEDULE_INFO
,
commonMessageParser
)
Jensen
.
registerHandler
(
TEST_SN_WRITE
,
commonMessageParser
);
Jensen
.
registerHandler
(
SCHEDULE_INFO
,
commonMessageParser
);
export
{
Jensen
};
src/utils/utils.ts
View file @
fdfb03b7
const
Level
=
{
debug
:
"debug"
,
info
:
"info"
,
error
:
"error"
,
debug
:
'debug'
,
info
:
'info'
,
error
:
'error'
};
export
const
Logger
=
{
...
...
@@ -22,7 +22,7 @@ export const Logger = {
module
,
procedure
,
message
:
String
(
message
),
time
:
new
Date
().
getTime
()
,
time
:
new
Date
().
getTime
()
};
this
.
messages
.
push
(
log
);
if
(
this
.
consoleOutput
)
{
...
...
@@ -33,22 +33,20 @@ export const Logger = {
_print
(
log
)
{
let
time
=
new
Date
(
log
.
time
);
console
.
info
(
"["
+
(
log
.
level
===
"error"
?
"x"
:
"*"
)
+
"]["
+
'['
+
(
log
.
level
===
'error'
?
'x'
:
'*'
)
+
']['
+
time
.
toLocaleString
()
+
"]("
+
']('
+
log
.
module
+
" - "
+
' - '
+
log
.
procedure
+
") "
+
log
.
message
,
') '
+
log
.
message
);
},
filter
(
module
,
procedure
)
{
return
this
.
messages
.
filter
(
(
i
)
=>
i
.
module
===
module
&&
i
.
procedure
===
procedure
,
);
return
this
.
messages
.
filter
((
i
)
=>
i
.
module
===
module
&&
i
.
procedure
===
procedure
);
},
enableConsoleOutput
()
{
this
.
consoleOutput
=
true
;
...
...
@@ -71,25 +69,250 @@ export const Logger = {
}
return
true
;
});
}
,
}
};
export
const
getTimeStr
=
(
date
:
Date
)
=>
{
let
str
=
date
.
getFullYear
()
+
"-0"
+
'-0'
+
(
date
.
getMonth
()
+
1
)
+
"-0"
+
'-0'
+
date
.
getDate
()
+
"-0"
+
'-0'
+
date
.
getHours
()
+
"-0"
+
'-0'
+
date
.
getMinutes
()
+
"-0"
+
'-0'
+
date
.
getSeconds
();
str
=
str
.
replace
(
/
(\d{4})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})
/gi
,
"$1$2$3$4$5$6"
,
);
str
=
str
.
replace
(
/
(\d{4})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})\-
0*
(\d{2})
/gi
,
'$1$2$3$4$5$6'
);
return
str
;
};
const
keyMap
:
{
[
key
:
string
]:
number
}
=
{
A
:
0x04
,
B
:
0x05
,
C
:
0x06
,
D
:
0x07
,
E
:
0x08
,
F
:
0x09
,
G
:
0x0a
,
H
:
0x0b
,
I
:
0x0c
,
J
:
0x0d
,
K
:
0x0e
,
L
:
0x0f
,
M
:
0x10
,
N
:
0x11
,
O
:
0x12
,
P
:
0x13
,
Q
:
0x14
,
R
:
0x15
,
S
:
0x16
,
T
:
0x17
,
U
:
0x18
,
V
:
0x19
,
W
:
0x1a
,
X
:
0x1b
,
Y
:
0x1c
,
Z
:
0x1b
,
ENTER
:
0x28
,
ESCAPE
:
0x29
,
SPACE
:
0x2c
};
const
HotKeyBuilder
=
{
control
:
false
,
shift
:
false
,
alt
:
false
,
guiKey
:
false
,
keys
:
[],
withControl
:
()
=>
{
HotKeyBuilder
.
control
=
true
;
return
HotKeyBuilder
;
},
withShift
:
()
=>
{
HotKeyBuilder
.
shift
=
true
;
return
HotKeyBuilder
;
},
withAlt
:
()
=>
{
HotKeyBuilder
.
alt
=
true
;
return
HotKeyBuilder
;
},
withGuiKey
:
()
=>
{
HotKeyBuilder
.
guiKey
=
true
;
return
HotKeyBuilder
;
},
withKey
:
(
key
:
string
)
=>
{
if
(
HotKeyBuilder
.
keys
.
length
>=
2
)
throw
new
Error
(
'exceed max key bindings'
);
HotKeyBuilder
.
keys
.
push
(
HotKeyBuilder
.
__mapping
(
key
));
return
HotKeyBuilder
;
},
__mapping
:
(
key
:
string
)
=>
{
return
keyMap
[
key
];
},
build
:
()
=>
{
let
key1
=
0
;
if
(
HotKeyBuilder
.
control
)
key1
|=
0x01
<<
0
;
if
(
HotKeyBuilder
.
shift
)
key1
|=
0x01
<<
1
;
if
(
HotKeyBuilder
.
alt
)
key1
|=
0x01
<<
2
;
if
(
HotKeyBuilder
.
guiKey
)
key1
|=
0x01
<<
3
;
let
codes
=
[
0x03
,
key1
,
HotKeyBuilder
.
keys
.
length
?
HotKeyBuilder
.
keys
[
0
]
:
0x00
,
HotKeyBuilder
.
keys
.
length
>
1
?
HotKeyBuilder
.
keys
[
1
]
:
0x00
,
0x00
,
0x00
,
0x00
,
0x00
];
HotKeyBuilder
.
control
=
false
;
HotKeyBuilder
.
shift
=
false
;
HotKeyBuilder
.
alt
=
false
;
HotKeyBuilder
.
guiKey
=
false
;
HotKeyBuilder
.
keys
=
[];
return
codes
;
}
};
const
enterKeyCode
=
(
answer
:
0
|
1
=
0
,
hangup
:
0
|
1
=
0
,
reject
:
0
|
1
=
0
,
micMute
:
0
|
1
=
0
)
=>
{
let
code
=
0
;
if
(
answer
)
code
|=
0x01
<<
0
;
if
(
hangup
)
code
|=
0x01
<<
1
;
if
(
reject
)
code
|=
0x01
<<
2
;
if
(
micMute
)
code
|=
0x01
<<
3
;
return
code
;
};
const
emptyCodes
=
[
0
,
0
,
0
,
0
,
0
,
0
,
0
,
0
];
export
const
shortcutKeys
=
{
Zoom
:
{
Windows
:
[
enterKeyCode
(
0
,
1
),
...
emptyCodes
,
HotKeyBuilder
.
withAlt
().
withKey
(
'Q'
).
build
(),
...
emptyCodes
,
HotKeyBuilder
.
withAlt
().
withKey
(
'A'
).
build
()
],
Mac
:
[
enterKeyCode
(
0
,
1
),
...
emptyCodes
,
HotKeyBuilder
.
withGuiKey
().
withKey
(
'W'
).
build
(),
...
emptyCodes
,
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'A'
).
build
()
],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
Teams
:
{
Windows
:
[
enterKeyCode
(),
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'A'
).
build
(),
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'H'
).
build
(),
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'D'
).
build
(),
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'M'
).
build
()
],
Mac
:
[
enterKeyCode
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'A'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'H'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'D'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'M'
).
build
()
],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
'Google Meetings'
:
{
Windows
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
HotKeyBuilder
.
withControl
().
withKey
(
'D'
).
build
()],
Mac
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
HotKeyBuilder
.
withGuiKey
().
withKey
(
'D'
).
build
()],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
Webex
:
{
Windows
:
[
enterKeyCode
(),
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'C'
).
build
(),
HotKeyBuilder
.
withControl
().
withKey
(
'L'
).
build
(),
HotKeyBuilder
.
withControl
().
withKey
(
'D'
).
build
(),
HotKeyBuilder
.
withControl
().
withKey
(
'M'
).
build
()
],
Mac
:
[
enterKeyCode
(),
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'C'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withKey
(
'L'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'D'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'M'
).
build
()
],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
Feishu
:
{
Windows
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'D'
).
build
()],
Mac
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'D'
).
build
()],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
Lark
:
{
Windows
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'D'
).
build
()],
Mac
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'D'
).
build
()],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
WeChat
:
{
Windows
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
],
Mac
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
Line
:
{
Windows
:
[
enterKeyCode
(
0
,
1
,
1
),
...
emptyCodes
,
HotKeyBuilder
.
withKey
(
'ESCAPE'
).
build
(),
HotKeyBuilder
.
withKey
(
'ESCAPE'
).
build
(),
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'A'
).
build
()
],
Mac
:
[
enterKeyCode
(
0
,
1
,
1
),
...
emptyCodes
,
HotKeyBuilder
.
withKey
(
'ESCAPE'
).
build
(),
HotKeyBuilder
.
withKey
(
'ESCAPE'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'A'
).
build
()
],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
WhatsApp
:
{
Windows
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
],
Mac
:
[
enterKeyCode
(),
...
emptyCodes
,
HotKeyBuilder
.
withGuiKey
().
withKey
(
'W'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withKey
(
'W'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'M'
).
build
()
],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
Slack
:
{
Windows
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'SPACE'
).
build
()
],
Mac
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'SPACE'
).
build
()],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
},
Discord
:
{
Windows
:
[
enterKeyCode
(),
HotKeyBuilder
.
withControl
().
withKey
(
'ENTER'
).
build
(),
...
emptyCodes
,
HotKeyBuilder
.
withKey
(
'ESCAPE'
).
build
(),
HotKeyBuilder
.
withControl
().
withShift
().
withKey
(
'M'
).
build
()
],
Mac
:
[
enterKeyCode
(),
HotKeyBuilder
.
withGuiKey
().
withKey
(
'ENTER'
).
build
(),
...
emptyCodes
,
HotKeyBuilder
.
withGuiKey
().
withKey
(
'ESCAPE'
).
build
(),
HotKeyBuilder
.
withGuiKey
().
withShift
().
withKey
(
'M'
).
build
()
],
Linux
:
[
enterKeyCode
(),
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
,
...
emptyCodes
]
}
};
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