import previous work
This commit is contained in:
parent
de50469b4e
commit
9fe684f9d0
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Disclaimer of Warranty
|
||||||
|
|
||||||
|
This Work is provided "AS IS." Any express or implied warranties, including but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the repository Creator or Contributors be liable for any direct, indirect, incidental, special, exemplary or consequential damages (including, but not limited to, procurement of substitute goods or services, loss of use, data or profits, or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this Work, even if advised of the possibility of such damage.
|
||||||
|
|
||||||
|
The User of this Work agrees to hold harmless and indemnify the repository Creator and it's Contributors, its agents and employees from every claim or liability (whether in tort or in contract), including attorney's fees, court costs, and expenses, arising in direct consequence of Recipient's use of the item, including, but not limited to, claims or liabilities made for injury to or death of personnel of User or third parties, damage to or destruction of property of User or third parties, and infringement or other violations of intellectual property or technical data rights.
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIDhDCCAmwCCQD2xSDyQCMEuTANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMC
|
||||||
|
dXMxEzARBgNVBAgMCmNhbGlmb3JuaWExCzAJBgNVBAcMAmxhMQswCQYDVQQKDAJj
|
||||||
|
bzEQMA4GA1UECwwHc2VjdGlvbjESMBAGA1UEAwwJMTI3LjAuMC4xMR8wHQYJKoZI
|
||||||
|
hvcNAQkBFhBtZUBqYWtlZG93bnMuY29tMB4XDTIyMTEyNDA3MDcxN1oXDTMyMTEy
|
||||||
|
MTA3MDcxN1owgYMxCzAJBgNVBAYTAnVzMRMwEQYDVQQIDApjYWxpZm9ybmlhMQsw
|
||||||
|
CQYDVQQHDAJsYTELMAkGA1UECgwCY28xEDAOBgNVBAsMB3NlY3Rpb24xEjAQBgNV
|
||||||
|
BAMMCTEyNy4wLjAuMTEfMB0GCSqGSIb3DQEJARYQbWVAamFrZWRvd25zLmNvbTCC
|
||||||
|
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL79eV4MifDgLHjIriewR9ri
|
||||||
|
k+vVpzgaefEs2LYtGuT2il26uxQIUBn/nNoDPtEM4F4PD0MulINEonbh5ipih1YQ
|
||||||
|
VDSZhFcdYt6nm+ew1T7kMm++y0HrhojsXiA3kpab3XzSCFqZ2o/ae3xDxjxIEq4F
|
||||||
|
XrED5h5budcCSwAez/2NS5GLTH8xHlDg1djTl+Y1h4mOwnR18PmOFP+9sOAg6ZzO
|
||||||
|
/jLbxwx+AoE0OnO/ldbvLvytdmB8k/mi79+OtS6w53jqIggvTkPK/yQss82EaWTm
|
||||||
|
XJyEJ9BTB0jcRItS0Y2ck0tRUI7QifdY8Q+exQwO0kRpyA/EtE/BK5PwMY10LnkC
|
||||||
|
AwEAATANBgkqhkiG9w0BAQsFAAOCAQEAhN2x+yfItai4ozVvdXKlvECsdlQzmKEe
|
||||||
|
aXfPuDTdYLuOBPnpPRALM9ewML2xiwX4TVGltTWIIxWubRIGyVT8RzdwYY6lOx0w
|
||||||
|
UhQz9MUK2MqJM7hAwjeEnKTMned5PTtm6Jd+HBU9o9FBEhi4LuFrFrVa2vZLzfGp
|
||||||
|
kJoq7tKFcotHEQ5aQ1OfsOwcHEBeqv+yM7RMjl1B1hlU5z0OtmOU8RLlSe5xLT9X
|
||||||
|
/m9YmrAlJwslqtBBcaAgP1TMJeCEL14ezp0Z4CFakX+1TuopqPyp5F4h97i6spER
|
||||||
|
kzH5kfp0E99OwAmooI+++CSEm+/2NQKWOEZ98qa7rLaEWp8Q6lmEAw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
|
@ -0,0 +1,178 @@
|
||||||
|
|
||||||
|
// air light 在 检查设备 => 连接设备 => 获取实例 => 判断设备类型 进行整合
|
||||||
|
// 不同类型升级提供俩个接口,通过判断设备类型分别调用不同的SDK包,再进行升级后续操作
|
||||||
|
let curGlasses = null;
|
||||||
|
const DEBUG = true;
|
||||||
|
|
||||||
|
import GlassesLight from './js_light/glasses.js';
|
||||||
|
import * as managerLight from './js_light/manager.js'
|
||||||
|
import GlassesAir from './js_air/glasses.js'
|
||||||
|
import * as managerAir from './js_air/manager.js'
|
||||||
|
|
||||||
|
// *******************
|
||||||
|
|
||||||
|
export function isNrealDevice(device) {
|
||||||
|
// 涉及俩种设备的区分协议(符合 air 和 light 俩种Nreal设备)
|
||||||
|
// console.log({
|
||||||
|
// pid_hex: device.productId.toString(16),
|
||||||
|
// pid_dec: device.productId
|
||||||
|
// })
|
||||||
|
return device.productId == 0x0423
|
||||||
|
|| device.productId == 0x573C
|
||||||
|
|| device.productId == 0x0424;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addHidListener() {
|
||||||
|
navigator.hid.onconnect = function (event) {
|
||||||
|
let device = event.device;
|
||||||
|
if (device.productId == 1059 || device.productId == 1060) {
|
||||||
|
console.log('connected',{device});
|
||||||
|
managerAir.canCommand(device).then(result => {
|
||||||
|
if (result) {
|
||||||
|
curGlasses = new GlassesAir(device);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (device.productId == 22332 || device.productId == 22336) {
|
||||||
|
managerLight.canCommand(device).then(result => {
|
||||||
|
if (result) {
|
||||||
|
curGlasses = new GlassesLight(device);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
navigator.hid.ondisconnect = function (event) {
|
||||||
|
if (curGlasses && curGlasses.device == event.device) {
|
||||||
|
curGlasses = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
window.curGlassesArray = [];
|
||||||
|
|
||||||
|
export function checkConnection() {
|
||||||
|
if (curGlasses) {
|
||||||
|
return curGlasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
return navigator.hid.getDevices().then(devices => {
|
||||||
|
// console.warn('filtering', devices);
|
||||||
|
// filters out devices that are nreal devices.
|
||||||
|
return devices.filter(isNrealDevice);
|
||||||
|
}).then(async devices => {
|
||||||
|
console.log('filtered:', devices)
|
||||||
|
|
||||||
|
for (let device of devices) {
|
||||||
|
// if(curGlasses){
|
||||||
|
// console.warn('skipping',device)
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
if (device.productId == 1059 || device.productId == 1060) {
|
||||||
|
console.log({air:device});
|
||||||
|
if (await managerAir.canCommand(device)) {
|
||||||
|
curGlasses = new GlassesAir(device);
|
||||||
|
curGlassesArray.push(curGlasses);
|
||||||
|
return curGlasses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (device.productId == 22332 || device.productId == 22336) {
|
||||||
|
if (await managerLight.canCommand(device)) {
|
||||||
|
curGlasses = new GlassesLight(device);
|
||||||
|
return curGlasses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function requestDevice() {
|
||||||
|
return navigator.hid.requestDevice({
|
||||||
|
filters: [{
|
||||||
|
vendorId: 0x0486, // ? ASUS Computers Inc. ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0483, // STMicroelectronics ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x0482, // Kyocera Corporation ?
|
||||||
|
}, {
|
||||||
|
vendorId: 0x3318, // Gleaming Reality (Wuxi) Technology Co., LTD ?
|
||||||
|
}]
|
||||||
|
}).then(async devices => {
|
||||||
|
for (let device of devices) {
|
||||||
|
if (deviceIsAir(device)) {
|
||||||
|
// can command checks isMcu
|
||||||
|
// air shows up as 3 separate HID devices
|
||||||
|
// but we only select 1 that can be commanded
|
||||||
|
// this code was originally from their activation/update page
|
||||||
|
// so, maybe devices OTHER than MCU can be communicated with via JS?
|
||||||
|
// I'm not sure yet...
|
||||||
|
if (await managerAir.canCommand(device)) {
|
||||||
|
curGlasses = new GlassesAir(device);
|
||||||
|
return curGlasses;
|
||||||
|
}
|
||||||
|
} else if (deviceIsLight(device)) {
|
||||||
|
// NOTE i don't have a Light to test with,
|
||||||
|
// so all my work is focusedd on the Air Protocol for now...
|
||||||
|
if (await managerLight.canCommand(device)) {
|
||||||
|
curGlasses = new GlassesLight(device);
|
||||||
|
return curGlasses;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function connectDevice() {
|
||||||
|
let glasses = await checkConnection();
|
||||||
|
if (glasses) {
|
||||||
|
return glasses;
|
||||||
|
}
|
||||||
|
return await requestDevice();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function disconnectDevice() {
|
||||||
|
if(curGlasses){
|
||||||
|
curGlasses._device.close()
|
||||||
|
curGlasses = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deviceIsAir(device){
|
||||||
|
// 0x423 || 0x424
|
||||||
|
return device.productId == 1059 || device.productId == 1060
|
||||||
|
}
|
||||||
|
|
||||||
|
export function deviceIsLight(device){
|
||||||
|
// 0x573C || 0x5740
|
||||||
|
return device.productId == 22332 || device.productId == 22336
|
||||||
|
}
|
||||||
|
|
||||||
|
// check glasses is air or light?
|
||||||
|
export function isAirOrLight() {
|
||||||
|
if (!curGlasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
if (deviceIsAir(curGlasses.device)) {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
if (deviceIsLight(curGlasses.device)) {
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
export function hexStream2int8Array(captureString){
|
||||||
|
return new Uint8Array(captureString.match(/.{1,2}/g).map((b)=>{
|
||||||
|
// console.log(b);
|
||||||
|
return b //.parseInt(16)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parseHexString(captureString){
|
||||||
|
return glasses.protocol.parse_rsp(hexStream2int8Array(captureString))
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
curGlasses
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,535 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<style>
|
||||||
|
html,body {
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
#imu, #imu-labels {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
#imu {
|
||||||
|
display: block;
|
||||||
|
position: relative;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#imu-bars {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
height: 300px;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
#imu-bars .bar {
|
||||||
|
width: 24px;
|
||||||
|
background: blue;
|
||||||
|
margin: 0 7px 0 0;
|
||||||
|
|
||||||
|
min-height: 1px;
|
||||||
|
}
|
||||||
|
#imu-bars .bar.bar-gap {
|
||||||
|
margin-right: 39px;
|
||||||
|
}
|
||||||
|
#sparklines {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#sparklines .sparkline-wrapper {
|
||||||
|
float: left;
|
||||||
|
width: 500px;
|
||||||
|
height: 50px;
|
||||||
|
margin-right: 10px;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
#sparklines .sparkline-label {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
background: black;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
#sparklines .sparkline {
|
||||||
|
width: 500px;
|
||||||
|
background: beige;
|
||||||
|
/* border: 1px solid blue;*/
|
||||||
|
height: 50px;
|
||||||
|
min-width: 500px;
|
||||||
|
min-height: 50px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sparkline {
|
||||||
|
stroke: transparent;
|
||||||
|
fill: blue;
|
||||||
|
}
|
||||||
|
/*.sparkline--line {
|
||||||
|
stroke: red;
|
||||||
|
}
|
||||||
|
.sparkline--fill {
|
||||||
|
fill: blue;
|
||||||
|
}*/
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="noSupportHid"></div>
|
||||||
|
<div id="connect"><button>connect</button></div>
|
||||||
|
<div id="disconnect" onclick="disconnectDevices()"><button>disconnect</button></div>
|
||||||
|
<div id="hadConnect"></div>
|
||||||
|
<div id="sn"></div>
|
||||||
|
<div id="firmwareMcu"></div>
|
||||||
|
<div id="firmwareDp"></div>
|
||||||
|
<!-- <div id="getBrightness" onclick="window.getBrightness()"><button>get brightness</button></div> -->
|
||||||
|
<!-- <div id="setBrightness" onclick="window.setBrightness()"><button>set brightness</button></div> -->
|
||||||
|
<input type="range" min="1" max="8" step="1" value="8"
|
||||||
|
name="brightness"
|
||||||
|
oninput="window.updateBrightness(event)">
|
||||||
|
<!-- <label for="brightness">set brightness to: <span class="req-brightness-value"></span> </label> -->
|
||||||
|
<div>current brightness: <span class="current-brightness">?</span></div>
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<div id="imu-labels"></div>
|
||||||
|
<div id="imu"></div>
|
||||||
|
<div id="imu-bars"></div>
|
||||||
|
<div id="sparklines"></div>
|
||||||
|
|
||||||
|
|
||||||
|
<hr/>
|
||||||
|
<div id="output"></div>
|
||||||
|
|
||||||
|
<script type="module">
|
||||||
|
|
||||||
|
// if(!header){
|
||||||
|
// window.location.href = 'https://www-uat.nreal.cn/support/activationGlasses/'
|
||||||
|
// }
|
||||||
|
|
||||||
|
import * as Manager from './js_air/manager.js';
|
||||||
|
import * as Common from './common.js';
|
||||||
|
//import * as GA from '../addGa.js';
|
||||||
|
import http from "../tools/http.js"
|
||||||
|
// import downloadfiles from "../tools/downloadfile.js"
|
||||||
|
|
||||||
|
const hidFilters = [
|
||||||
|
{ 'vendorId': 0x3318 }, // NReal Vendor ID, Gleaming Reality?
|
||||||
|
];
|
||||||
|
|
||||||
|
let binFile = null;
|
||||||
|
let currentGlass = null;
|
||||||
|
|
||||||
|
window.Manager = Manager;
|
||||||
|
|
||||||
|
|
||||||
|
// UI Stuff / todo remake in vue or something
|
||||||
|
// let brightness_out = document.querySelector('[name="brightness"]').value;
|
||||||
|
|
||||||
|
window.updateBrightness = function(event) {
|
||||||
|
//console.log(event);
|
||||||
|
let value = event.target.value;
|
||||||
|
console.log(value);
|
||||||
|
// document.querySelector('.req-brightness-value').innerHTML = value;
|
||||||
|
// brightness_out = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
async function upgradeMcu() {
|
||||||
|
if (binFile == null) {
|
||||||
|
alert('Please select the firmware file or redownload it. ')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let version = await Manager.getFirmwareVersionInMcu();
|
||||||
|
if (version == null) {
|
||||||
|
alert("The device is not connected, please connect the glasses");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let result;
|
||||||
|
http.get({ url: `/nebula/v1/isc/admin/device/version/check?deviceType=2&country=2&fileType=10¤tFileName=air_${version}.bin`, timeout: 1000 }, async function (err, res) {
|
||||||
|
if (err) {
|
||||||
|
alert('Error. Please refresh and try again.')
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (res.data.isLatest) {
|
||||||
|
document.getElementById('alreadyLast').innerText = "Your MCU firmware is the latest. There's no update available."
|
||||||
|
document.getElementById('alreadyLast').style.display = 'block'
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
document.getElementById('upgradeDp').disabled = true;
|
||||||
|
let data = await binFile.arrayBuffer();
|
||||||
|
// document.getElementById('tip').style.display = 'block'
|
||||||
|
document.getElementById('upgradeMcu').style.display = 'none'
|
||||||
|
document.getElementById('progress').style.display = 'block'
|
||||||
|
result = await Manager.upgradeInMcu(await binFile.arrayBuffer());
|
||||||
|
if (result) {
|
||||||
|
// document.getElementById('tip').style.display = 'none'
|
||||||
|
document.getElementById('outputMcu').style.display = 'block'
|
||||||
|
let mcuTimer = setInterval(async () => {
|
||||||
|
if (Common.curGlasses) {
|
||||||
|
Manager.getFirmwareVersionInMcu().then(lastVersion => {
|
||||||
|
document.getElementById('latestVersionMcu').style.display = 'block';
|
||||||
|
document.getElementById('latestVersionMcu').innerText = lastVersion ? `Current MCU firmware version is: ${lastVersion}` : ''
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('err', err)
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
clearInterval(mcuTimer);
|
||||||
|
mcuTimer = null;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
document.getElementById('fail').style.display = 'block'
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
document.getElementById('upgradeDp').disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function upgradeInDp() {
|
||||||
|
if (binFile == null) {
|
||||||
|
alert('Please select the firmware file or redownload it. ')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
document.getElementById('alreadyLastDp').style.display = 'none'
|
||||||
|
document.getElementById('outputdp').style.display = 'none'
|
||||||
|
let dpVersion = await Manager.isNeedUpgradeInDp();
|
||||||
|
console.log('dpVersion', dpVersion)
|
||||||
|
if (dpVersion == null) {
|
||||||
|
alert("The device is not connected, please connect the glasses");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!dpVersion) {
|
||||||
|
document.getElementById('alreadyLastDp').innerText = "Your DP firmware is the latest. There's no update available."
|
||||||
|
document.getElementById('alreadyLastDp').style.display = 'block'
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('tipdp').style.display = 'block'
|
||||||
|
document.getElementById('upgradeDp').style.display = 'none'
|
||||||
|
document.getElementById('progressDp').style.display = 'block'
|
||||||
|
let result;
|
||||||
|
result = await Manager.upgradeInDp();
|
||||||
|
if (result) {
|
||||||
|
document.getElementById('outputdp').style.display = 'block'
|
||||||
|
let dpTimer = setInterval(async () => {
|
||||||
|
if (Common.curGlasses) {
|
||||||
|
Manager.getFirmwareVersionInDp()
|
||||||
|
.then(lastVersion => {
|
||||||
|
document.getElementById('latestVersionDp').style.display = 'block';
|
||||||
|
document.getElementById('latestVersionDp').innerText = lastVersion ? `Current DP firmware version is: ${lastVersion}` : '';
|
||||||
|
})
|
||||||
|
.catch(err => { console.log(err) })
|
||||||
|
.finally(() => {
|
||||||
|
clearInterval(dpTimer)
|
||||||
|
dpTimer = null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
document.getElementById('progressDp').style.display = 'none';
|
||||||
|
document.getElementById('faildp').style.display = 'block'
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function upgradeDsp() {
|
||||||
|
if (binFile == null) {
|
||||||
|
alert('Please select the firmware file or redownload it. ')
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 拿到文件的版本号
|
||||||
|
let version = binFile.name.slice(4, 9)
|
||||||
|
let flag = await Manager.isNeedUpgradeInDsp(version);
|
||||||
|
if (flag == null) {
|
||||||
|
alert("Please connect glasses first!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (flag != 1) {
|
||||||
|
alert("Already the latest version!");
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let data = await binFile.arrayBuffer();
|
||||||
|
|
||||||
|
let result = await Manager.upgradeInDsp(await binFile.arrayBuffer());
|
||||||
|
// let timer = setInterval(() => {
|
||||||
|
// setOutput((Manager.current/Manager.total) * 100 + '%')
|
||||||
|
// if(Manager.current == Manager.total){
|
||||||
|
// clearInterval(timer)
|
||||||
|
// setOutput(result)
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
// setOutput((Manager.current/Manager.total) * 100 + '%')
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// function downloadFile() {
|
||||||
|
// http.get({ url: `/nebula/v1/isc/admin/device/version/check?deviceType=2&country=2&fileType=10¤tFileName=isLatest`, timeout: 1000 }, function (err, result) {
|
||||||
|
// if (err) {
|
||||||
|
// alert("download failed")
|
||||||
|
// } else {
|
||||||
|
// const url = result.data.uri
|
||||||
|
// downloadfiles(url)
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
async function isLastest(ver) {
|
||||||
|
http.get({ url: `/nebula/v1/isc/admin/device/version/check?deviceType=2&country=2&fileType=10¤tFileName=air_${ver}`, timeout: 1000 }, function (err, result) {
|
||||||
|
if (err) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
return result.data.isLatest
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取文件名
|
||||||
|
// function fileNameFromHeader (disposition) {
|
||||||
|
// let result = null;
|
||||||
|
// if (disposition && /filename=.*/ig.test(disposition)) {
|
||||||
|
// result = disposition.match(/filename=.*/ig);
|
||||||
|
// return decodeURI(result[0].split('=')[1]);
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function selectbin() {
|
||||||
|
// return Manager.selectBinFile().then(file => {
|
||||||
|
// var reg = /07.[1-2].[0-9]{2}.[0-9]{3}_[0-9]{8}/g;
|
||||||
|
// if (reg.test(file.name)) {
|
||||||
|
// binFile = file;
|
||||||
|
// document.getElementById('binfile').value = file.name;
|
||||||
|
|
||||||
|
// } else {
|
||||||
|
// document.getElementById('binfile').value = " "
|
||||||
|
// window.alert("Please select the firmware file or redownload it. ")
|
||||||
|
// binFile = null
|
||||||
|
|
||||||
|
// }
|
||||||
|
// return binFile;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
function connect() {
|
||||||
|
Common.connectDevice().then(async glasses => {
|
||||||
|
if (glasses) {
|
||||||
|
document.getElementById('hadConnect').style.display = 'block'
|
||||||
|
document.getElementById('connect').style.opacity = '0'
|
||||||
|
document.getElementById('firmwareMcu').innerText = 'Current glasses version is : ' + await firmwareMcu()
|
||||||
|
|
||||||
|
document.getElementById('firmwareDp').innerText = 'Current DP version is : ' + await firmwareDp()
|
||||||
|
|
||||||
|
document.getElementById('sn').innerText = 'SN:' + await getSN()
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
// document.getElementById('sn').innerHTML = getSN()
|
||||||
|
// document.getElementById('version').innerText = '版本号' + firmwareMcu()
|
||||||
|
setOutput('glasses : ' + glasses.toString());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function firmwareMcu() {
|
||||||
|
return Manager.getFirmwareVersionInMcu().then(version => {
|
||||||
|
// setOutput('firmware : ' + version);
|
||||||
|
return version
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function firmwareDp() {
|
||||||
|
return Manager.getFirmwareVersionInDp().then(version => {
|
||||||
|
// setOutput('firmware : ' + version);
|
||||||
|
return version
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSN() {
|
||||||
|
return Manager.getSN().then(version => {
|
||||||
|
// setOutput('SN : ' + version);
|
||||||
|
return version
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function JumpToApp() {
|
||||||
|
Manager.boot2App().then(result => {
|
||||||
|
setOutput('jump to app : ' + result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function serial() {
|
||||||
|
Manager.getSerialPort().then(version => {
|
||||||
|
setOutput('serial port: ' + version.serialNumber);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function deactivate() {
|
||||||
|
Manager.deactivate().then(result => {
|
||||||
|
setOutput('deactivate ' + result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// function activate() {
|
||||||
|
// let nowTime = new Date().getTime()
|
||||||
|
// Manager.activate(nowTime).then(async result => {
|
||||||
|
// if (result) {
|
||||||
|
// let sn = await getSN()
|
||||||
|
// const data = {
|
||||||
|
// sn,
|
||||||
|
// timestamp: nowTime,
|
||||||
|
// deviceType: 'Air_OTA'
|
||||||
|
// }
|
||||||
|
// document.getElementById('activeted').style.display = 'block'
|
||||||
|
// document.getElementById('activate').style.opacity = '0'
|
||||||
|
// } else {
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
//上传测井数据表到服务器数据库
|
||||||
|
// function PostToServer(data) {
|
||||||
|
// var httpRequest = new XMLHttpRequest();//第一步:建立所需的对象
|
||||||
|
// httpRequest.open("POST", "https://app-uat-api-cn.nreal.work/api/user-profile/v1/rest/device-activation/activate", true); //调用AddDataToServer
|
||||||
|
// httpRequest.setRequestHeader("Content-Type", "application/json"); //设置请求头信息
|
||||||
|
// // httpRequest.setRequestHeader("Authorization", header); //设置请求头信息
|
||||||
|
// httpRequest.setRequestHeader("Authorization", header); //设置请求头信息
|
||||||
|
// httpRequest.send(JSON.stringify(data)); //设置为发送给服务器数据
|
||||||
|
// }
|
||||||
|
|
||||||
|
window.setOutput = function(output) {
|
||||||
|
document.getElementById('output').innerText = output + '<br/>' + document.getElementById('output').innerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.getBrightness = function() {
|
||||||
|
Manager.getBrightness().then(brightness => {
|
||||||
|
setOutput('brightness : ' + brightness);
|
||||||
|
|
||||||
|
document.querySelector('.current-brightness').innerText = brightness;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.setBrightness = function() {
|
||||||
|
let brightness = document.querySelector('.brightness').value;
|
||||||
|
Manager.setBrightness(parseInt(brightness)-1).then(result => {
|
||||||
|
setOutput('set brightness : ' + result);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onBrightnessChanged = function(new_value) {
|
||||||
|
document.querySelector('[name="brightness"]').value = new_value;
|
||||||
|
document.querySelector('.current-brightness').innerText = new_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.disconnectDevices = () => {
|
||||||
|
window.curGlassesArray.map(g=>{
|
||||||
|
g._device.close();
|
||||||
|
g._device.forget();
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
window.endpoints = [];
|
||||||
|
|
||||||
|
window.listUsbEndpoints = () => {
|
||||||
|
window.endpoints = [];
|
||||||
|
// list usb endpoints
|
||||||
|
navigator.usb.requestDevice({filters:[]}).then((device)=>{
|
||||||
|
window.usb_device = device;
|
||||||
|
|
||||||
|
//usb_device.configurations[0].interfaces[1].alternates[1].endpoints[0]
|
||||||
|
|
||||||
|
for(let configuration of device.configurations){
|
||||||
|
|
||||||
|
for(let _interface of configuration.interfaces){
|
||||||
|
|
||||||
|
for(let alternate of _interface?.alternates ?? []){
|
||||||
|
|
||||||
|
for(let endpoint of alternate.endpoints){
|
||||||
|
|
||||||
|
window.endpoints.push(endpoint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.table(window.endpoints);
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
window.sparkline_elements = [];
|
||||||
|
|
||||||
|
window.onload = async () => {
|
||||||
|
|
||||||
|
for(var i = 0; i<41; i++){
|
||||||
|
let child = document.createElement('div');
|
||||||
|
child.classList.add('bar');
|
||||||
|
if((i+1) % 4 === 0){
|
||||||
|
child.classList.add('bar-gap');
|
||||||
|
}
|
||||||
|
document.getElementById('imu-bars').append(child)
|
||||||
|
|
||||||
|
document.getElementById('imu-labels').innerHTML+= i.toString().padStart(3,'0') + ' ';
|
||||||
|
if((i+1)%4 === 0){
|
||||||
|
document.getElementById('imu-labels').innerHTML+= ' | ';
|
||||||
|
}
|
||||||
|
|
||||||
|
//<svg class="sparkline" width="100" height="30" stroke-width="0"></svg>
|
||||||
|
// const _svg = document.createElement('svg');
|
||||||
|
var svgns = "http://www.w3.org/2000/svg";
|
||||||
|
var _svg = document.createElementNS(svgns,'svg');
|
||||||
|
_svg.classList.add('sparkline')
|
||||||
|
_svg.setAttribute('width', '500')
|
||||||
|
_svg.setAttribute('height', '50')
|
||||||
|
_svg.setAttribute('stroke-width', '0')
|
||||||
|
_svg.setAttributeNS(null, 'viewBox', '0 0 500 50')
|
||||||
|
// _svg.setAttribute('viewBox', '0 0 500 50')
|
||||||
|
|
||||||
|
const _span = document.createElement('span')
|
||||||
|
_span.classList.add('sparkline-label')
|
||||||
|
_span.innerText = (i).toString().padStart(3,'0');
|
||||||
|
|
||||||
|
window.sparkline_elements.push(_svg)
|
||||||
|
|
||||||
|
const _sl_wrapper = document.createElement('div');
|
||||||
|
_sl_wrapper.classList.add('sparkline-wrapper')
|
||||||
|
_sl_wrapper.append(_span)
|
||||||
|
_sl_wrapper.append(_svg)
|
||||||
|
|
||||||
|
document.getElementById('sparklines').append(_sl_wrapper)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Manager?.hidSupported()) {
|
||||||
|
document.getElementById('noSupportHid').style.display = "block";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.Common = Common;
|
||||||
|
Common.addHidListener();
|
||||||
|
Common.checkConnection(); // see if we can re-connect
|
||||||
|
// Manager.addHidListener();
|
||||||
|
// Manager.addSerialListener();
|
||||||
|
document.getElementById('connect').onclick = connect;
|
||||||
|
//document.getElementById('getBrightness').onclick = getBrightness;
|
||||||
|
// document.getElementById('activate').onclick = activate;
|
||||||
|
// document.getElementById('downloadFile').onclick = downloadFile;
|
||||||
|
// document.getElementById('deactivate').onclick = deactivate;
|
||||||
|
// document.getElementById('firmwareMcu').onclick = firmwareMcu;
|
||||||
|
// document.getElementById('SN').onclick = getSN;
|
||||||
|
// document.getElementById('app').onclick = JumpToApp;
|
||||||
|
// document.getElementById('serial').onclick = serial;
|
||||||
|
// document.getElementById('upload').onclick = upload;
|
||||||
|
// document.getElementById('selectbin').onclick = selectbin;
|
||||||
|
// document.getElementById('upgradeMcu').onclick = upgradeMcu;
|
||||||
|
// document.getElementById('upgradeDp').onclick = upgradeInDp;
|
||||||
|
// document.getElementById('upgradeDsp').onclick = upgradeDsp;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
@ -0,0 +1,435 @@
|
||||||
|
import * as Protocol from './protocol.js';
|
||||||
|
|
||||||
|
import sparkline from '../tools/sparkline.js'
|
||||||
|
|
||||||
|
/* captures */
|
||||||
|
// TODO: move this to another folder
|
||||||
|
// import {captures} from './captures.js';
|
||||||
|
// window.captures = captures
|
||||||
|
|
||||||
|
// let values = '';
|
||||||
|
|
||||||
|
// let fourBytesToFloat = (data) => {
|
||||||
|
// // Create a buffer
|
||||||
|
// var buf = new ArrayBuffer(4);
|
||||||
|
// // Create a data view of it
|
||||||
|
// var view = new DataView(buf);
|
||||||
|
|
||||||
|
// // set bytes
|
||||||
|
// data.forEach(function (b, i) {
|
||||||
|
// view.setUint8(i, b);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// // Read the bits as a float; note that by doing this, we're implicitly
|
||||||
|
// // converting it from a 32-bit float into JavaScript's native 64-bit double
|
||||||
|
// var num = view.getFloat32(0);
|
||||||
|
// // Done
|
||||||
|
// // console.log(num);
|
||||||
|
|
||||||
|
// return num;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// captures.forEach((capture,i)=>{
|
||||||
|
// if(i<100){
|
||||||
|
// if(capture.msgId === "0 0x0" && capture.payload.split(' ').length === 41){
|
||||||
|
// // hex2dec
|
||||||
|
// // console.log(capture.payload.split(' ').map(x=>parseInt(x).toString().padStart(2,'0')))
|
||||||
|
// // const hex2dec = capture.payload.split(' ').map((x,k)=>{
|
||||||
|
// // // return x.padStart(2,'0')
|
||||||
|
// // let i = parseInt(x,16)
|
||||||
|
// // return i ? i.toString().padStart(3, '0') : ' '
|
||||||
|
// // }).join(' ');
|
||||||
|
// // values+=hex2dec+'\n';
|
||||||
|
// // console.log(hex2dec)
|
||||||
|
|
||||||
|
// // ok i think it's transmitted as a 4x4f matrix, based on
|
||||||
|
// // \NRSDK\Scripts\Utility\ConversionUtility.cs
|
||||||
|
|
||||||
|
// // convert string representation of 41 bytes to Uint8Array
|
||||||
|
// // hrm... 41 bytes is too small a payload for 16 floats would need at least 48 bytes
|
||||||
|
|
||||||
|
// let _payload = new Uint8Array(capture.payload.split(' ').map(x=>parseInt(x,16)));
|
||||||
|
|
||||||
|
// // let f0 = fourBytesToFloat(_payload.slice(0,4));
|
||||||
|
|
||||||
|
// // extract 4x4 matrix of floats from byte-string
|
||||||
|
// let _f = [];
|
||||||
|
// for(let i=0;i<4;i++){
|
||||||
|
|
||||||
|
// // push 3 4-byte floats to _f
|
||||||
|
// for(let j=0;j<3;j++){
|
||||||
|
// let bytes = _payload.slice((i*4)+j,(i*4)+j+4)
|
||||||
|
// _f.push(fourBytesToFloat(bytes))
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
// // print 4x4 visual diagram to console
|
||||||
|
|
||||||
|
// console.log(_f.map((x)=>{
|
||||||
|
// return x; //.toFixed(2)
|
||||||
|
// }).join(', \n'))
|
||||||
|
|
||||||
|
// console.log('-------')
|
||||||
|
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// console.log(values)
|
||||||
|
/* End captures */
|
||||||
|
|
||||||
|
window.sparkline_values = [];
|
||||||
|
let stop_at = Infinity;//1000;
|
||||||
|
let current = 0;
|
||||||
|
|
||||||
|
//reduce update rate
|
||||||
|
let render_every = 2;
|
||||||
|
let imu_report_current = 0;
|
||||||
|
window.max_history = 1000;
|
||||||
|
|
||||||
|
|
||||||
|
// 41-byte packets
|
||||||
|
window.fo_packets = [];
|
||||||
|
window.fo_status_min = Infinity;
|
||||||
|
window.fo_status_max = -Infinity;
|
||||||
|
window.fo_status_distribution = {};
|
||||||
|
|
||||||
|
window.i8_two_samples = [];
|
||||||
|
|
||||||
|
// non-41 byte packets
|
||||||
|
window.packets_len_distribution = {};
|
||||||
|
window.packets_status_distribution = {};
|
||||||
|
|
||||||
|
window.render_sparklines = true;
|
||||||
|
|
||||||
|
window.bar_heights = [];
|
||||||
|
let bars = [];
|
||||||
|
|
||||||
|
window.samples_for_csv = [];
|
||||||
|
window.stats_by_packet_length = {};
|
||||||
|
|
||||||
|
// set to false to disable printing output when
|
||||||
|
// mysterious msgId 0x0 is being received
|
||||||
|
window.imu_output = true;
|
||||||
|
|
||||||
|
window.logPackets = () => {
|
||||||
|
console.log('packets:',{
|
||||||
|
packets_len_distribution,
|
||||||
|
packets_status_distribution
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// window.logFOPackets = () => {
|
||||||
|
// console.table([
|
||||||
|
// {
|
||||||
|
// // 0 - 255
|
||||||
|
// min: window.fo_status_min,
|
||||||
|
// max: window.fo_status_max,
|
||||||
|
// }
|
||||||
|
// ])
|
||||||
|
// console.log(window.fo_status_distribution)
|
||||||
|
// }
|
||||||
|
|
||||||
|
export default class Glasses extends EventTarget {
|
||||||
|
constructor(device) {
|
||||||
|
console.log('constructing');
|
||||||
|
super();
|
||||||
|
this._device = device;
|
||||||
|
this._interestMsg = [];
|
||||||
|
this._reports = new Map();
|
||||||
|
this._captures = [];
|
||||||
|
// set input listener
|
||||||
|
device.oninputreport = this._handleInputReport.bind(this);
|
||||||
|
|
||||||
|
window.glasses = this;
|
||||||
|
window.glasses.protocol = Protocol;
|
||||||
|
|
||||||
|
this.setBrightness = window.Manager.setBrightness;
|
||||||
|
|
||||||
|
for(let i = 0; i<41; i++){
|
||||||
|
bars.push(document.querySelector('#imu-bars .bar:nth-child('+(i+1)+')'))
|
||||||
|
}
|
||||||
|
|
||||||
|
// this.renderSparklines();
|
||||||
|
}
|
||||||
|
|
||||||
|
renderSparklines(){
|
||||||
|
if(!window.imu_output){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.bar_heights.map((v,k)=>{
|
||||||
|
if(bars[k]){
|
||||||
|
bars[k].style.height = v+'px';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// console.log('renderSparklines');
|
||||||
|
if(window.render_sparklines){
|
||||||
|
for(const [v,k] of window.sparkline_values){
|
||||||
|
if(window.sparkline_elements[k]){
|
||||||
|
requestAnimationFrame(()=>{
|
||||||
|
sparkline(window.sparkline_elements[k],window.sparkline_values[k],{
|
||||||
|
spotRadius: 0
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// if(fo_packets.length){
|
||||||
|
requestAnimationFrame(this.renderSparklines.bind(this))
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
dumpCaptures(){
|
||||||
|
console.log(JSON.stringify(window.captures));
|
||||||
|
}
|
||||||
|
|
||||||
|
get device() { return this._device; }
|
||||||
|
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
if (!this._device.opened) {
|
||||||
|
return this._device.open();
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
_handleInputReport({ device, reportId, data }) {
|
||||||
|
const reportData = new Uint8Array(data.buffer);
|
||||||
|
let report = Protocol.parse_rsp(reportData);
|
||||||
|
if(!report){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// console.log('input',{
|
||||||
|
// reportId,
|
||||||
|
// data,
|
||||||
|
// reportData,
|
||||||
|
// report
|
||||||
|
// });
|
||||||
|
// if(device !== glasses._device){
|
||||||
|
// debugger;
|
||||||
|
// }
|
||||||
|
const packet = {
|
||||||
|
dir: 'IN',
|
||||||
|
reportId: reportId,
|
||||||
|
plen: report.payload.length,
|
||||||
|
status: report.status,
|
||||||
|
msgId: [report.msgId, '0x'+(report.msgId.toString(16))].join(' '),
|
||||||
|
key: Protocol.keyForHex(report.msgId),
|
||||||
|
payload: report.payload.map(b => b.toString(16).padStart(2, "0")).join(' '),
|
||||||
|
dec: report.payload.map(Protocol.hex2Decimal).join(' '),
|
||||||
|
string: String.fromCharCode.apply(null, report.payload),
|
||||||
|
// ascii: new TextDecoder().decode(
|
||||||
|
// new Uint8Array(
|
||||||
|
// report.payload
|
||||||
|
// )
|
||||||
|
// ).split('\x00').join(' ')
|
||||||
|
}
|
||||||
|
|
||||||
|
if(report.msgId === 0){
|
||||||
|
// console.log(report.payload.length, report.status)
|
||||||
|
imu_report_current++;
|
||||||
|
|
||||||
|
|
||||||
|
if(imu_report_current < 1000){
|
||||||
|
// // update stats by packet length
|
||||||
|
// if(!window.stats_by_packet_length[report.payload.length]){
|
||||||
|
// window.stats_by_packet_length[report.payload.length] = {
|
||||||
|
// count: 0,
|
||||||
|
// status: {
|
||||||
|
// distribution: {}
|
||||||
|
// },
|
||||||
|
// // byte_stats[pos] = {distribution: {}}
|
||||||
|
// byte_stats: {}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// window.stats_by_packet_length[report.payload.length].count++;
|
||||||
|
|
||||||
|
// if(!window.stats_by_packet_length[report.payload.length].status.distribution[report.status]){
|
||||||
|
// window.stats_by_packet_length[report.payload.length].status.distribution[report.status] = 0;
|
||||||
|
// }
|
||||||
|
// window.stats_by_packet_length[report.payload.length].status.distribution[report.status]++;
|
||||||
|
|
||||||
|
// // update stats by byte position
|
||||||
|
// for(let i = 0; i<report.payload.length; i++){
|
||||||
|
// if(!window.stats_by_packet_length[report.payload.length].byte_stats[i]){
|
||||||
|
// window.stats_by_packet_length[report.payload.length].byte_stats[i] = {
|
||||||
|
// distribution: {}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if(!window.stats_by_packet_length[report.payload.length].byte_stats[i].distribution[report.payload[i]]){
|
||||||
|
// window.stats_by_packet_length[report.payload.length].byte_stats[i].distribution[report.payload[i]] = 0;
|
||||||
|
// }
|
||||||
|
// window.stats_by_packet_length[report.payload.length].byte_stats[i].distribution[report.payload[i]]++;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// status len data
|
||||||
|
// samples_for_csv.push([report.status, report.payload.length, ...report.payload].join(','))
|
||||||
|
// if(samples_for_csv.length > 1000){
|
||||||
|
// samples_for_csv.shift();
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
if(imu_report_current === render_every && window.imu_output){
|
||||||
|
imu_report_current = 0;
|
||||||
|
|
||||||
|
// update text/bar graphs
|
||||||
|
|
||||||
|
// console.log('got report',report);
|
||||||
|
const stringified = [...report.payload].map((x,k)=>{
|
||||||
|
// return x.padStart(2,'0')
|
||||||
|
let i = x//parseInt(x)
|
||||||
|
let padded = (i).toString().padStart(3, '0');
|
||||||
|
let out = '' + (i ? padded : '___')
|
||||||
|
if((k+1)%4 === 0){
|
||||||
|
out+=' | ';
|
||||||
|
}
|
||||||
|
|
||||||
|
//console.table([packet]);
|
||||||
|
// window.packets_len_distribution[report.payload.length]
|
||||||
|
// = (window.packets_len_distribution[report.payload.length] || 0) + 1;
|
||||||
|
|
||||||
|
// window.packets_status_distribution[report.status]
|
||||||
|
// = (window.packets_status_distribution[report.status] || 0) + 1;
|
||||||
|
|
||||||
|
// update sparkline
|
||||||
|
if(current<stop_at && report.payload.length === 41){
|
||||||
|
i8_two_samples.push(report.payload[2]);
|
||||||
|
if(i8_two_samples.length > 50){
|
||||||
|
i8_two_samples.shift();
|
||||||
|
}
|
||||||
|
// fo_packets.push(report);
|
||||||
|
// if(fo_packets.length > window.max_history){
|
||||||
|
// fo_packets.shift();
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if(report.status < window.fo_status_min){
|
||||||
|
// window.fo_status_min = report.status;
|
||||||
|
// }
|
||||||
|
// if(report.status > window.fo_status_max){
|
||||||
|
// window.fo_status_max = report.status;
|
||||||
|
// }
|
||||||
|
// if(!window.fo_status_distribution[report.status]){
|
||||||
|
// window.fo_status_distribution[report.status] = 0;
|
||||||
|
// }
|
||||||
|
// window.fo_status_distribution[report.status]++;
|
||||||
|
|
||||||
|
window.bar_heights[k] = i;
|
||||||
|
|
||||||
|
if(!window.sparkline_values[k]){
|
||||||
|
window.sparkline_values[k] = [];
|
||||||
|
}
|
||||||
|
if(window.sparkline_values[k].length > window.max_history){
|
||||||
|
window.sparkline_values[k].shift();
|
||||||
|
}
|
||||||
|
|
||||||
|
// debugger;
|
||||||
|
window.sparkline_values[k].push(i);
|
||||||
|
}
|
||||||
|
return out
|
||||||
|
}).join(' ');
|
||||||
|
|
||||||
|
document.getElementById('imu').innerHTML = stringified
|
||||||
|
|
||||||
|
// debugger;
|
||||||
|
if(current < stop_at){
|
||||||
|
current++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(current>=stop_at){
|
||||||
|
// console.warn('no longer updating sparklines');
|
||||||
|
// }
|
||||||
|
// console.log('IN',report.msgId);
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
console.table([packet])
|
||||||
|
}
|
||||||
|
|
||||||
|
// console.log('IN',report.msgId);
|
||||||
|
|
||||||
|
// window.captures.push(packet)
|
||||||
|
|
||||||
|
if(report.msgId === Protocol.MESSAGES.P_BUTTON_PRESSED){
|
||||||
|
|
||||||
|
// button press payloads are 11-bits
|
||||||
|
|
||||||
|
// ┌- first 4 bytes appear to be which button is pressed
|
||||||
|
// | ┌- second 4 bytes are a associated payload
|
||||||
|
// | | ┌- haven't seen last 3 bits used yet
|
||||||
|
// 0000 0000 000
|
||||||
|
|
||||||
|
// Button IDs
|
||||||
|
// 0001 = power button
|
||||||
|
// payloads
|
||||||
|
// 0000 - turned off
|
||||||
|
// 0001 - turned on
|
||||||
|
// 0006 = brightness increase
|
||||||
|
// 0007 = brightness decrease
|
||||||
|
// payloads
|
||||||
|
// 0000 - 0007 = 8 brightness levels, 0007 being brightest
|
||||||
|
|
||||||
|
|
||||||
|
const button = report.payload[3];
|
||||||
|
const int = Protocol.brightBytes2Int(report.payload);
|
||||||
|
|
||||||
|
|
||||||
|
// if report.payload[3] ===
|
||||||
|
console.log('button pressed',
|
||||||
|
{
|
||||||
|
button,
|
||||||
|
brightness_int: int
|
||||||
|
});
|
||||||
|
window.onBrightnessChanged(int);
|
||||||
|
}
|
||||||
|
|
||||||
|
this._reports.set(report.msgId, report);
|
||||||
|
}
|
||||||
|
|
||||||
|
sendReport(msgId, payload) {
|
||||||
|
const data = new Uint8Array(payload);
|
||||||
|
const cmd = Protocol.cmd_build(msgId, data);
|
||||||
|
// console.log({
|
||||||
|
// msgId,
|
||||||
|
// payload,
|
||||||
|
// data,
|
||||||
|
// cmd
|
||||||
|
// })
|
||||||
|
|
||||||
|
console.table([{
|
||||||
|
dir: 'OUT',
|
||||||
|
msgId: [msgId, '0x'+(msgId.toString(16))].join(' '),
|
||||||
|
key: Protocol.keyForHex(msgId),
|
||||||
|
payload: data.join(' '),
|
||||||
|
cmd: cmd.map(b => b.toString(16).padStart(2, "0")).join(' ')
|
||||||
|
}])
|
||||||
|
this._device.sendReport(0x00, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendReportTimeout(msgId, payload = [], timeout = 1000) {
|
||||||
|
this.sendReport(msgId, payload);
|
||||||
|
const time = new Date().getTime();
|
||||||
|
while ((new Date().getTime() - time) < timeout) {
|
||||||
|
if (this._reports.has(msgId)) {
|
||||||
|
let report = this._reports.get(msgId);
|
||||||
|
this._reports.delete(msgId);
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 10));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
async isMcu() {
|
||||||
|
const report = await this.sendReportTimeout(Protocol.MESSAGES.R_ACTIVATION_TIME);
|
||||||
|
return report != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `<Glasses deviceName=${this._device.productName} vid=${this._device.vendorId} pid=${this._device.vendorId}>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,567 @@
|
||||||
|
|
||||||
|
import Glasses from './glasses.js';
|
||||||
|
import * as Protocol from './protocol.js';
|
||||||
|
import * as common from './../common.js'
|
||||||
|
|
||||||
|
|
||||||
|
// let devices = [];
|
||||||
|
const DEBUG = true;
|
||||||
|
// progress bar
|
||||||
|
let current
|
||||||
|
let total
|
||||||
|
// DP progress
|
||||||
|
let dpCurrent
|
||||||
|
// DSP progress
|
||||||
|
let DspSecond
|
||||||
|
let DspThrid
|
||||||
|
|
||||||
|
/** check browser whether hid support */
|
||||||
|
// todo move to common
|
||||||
|
export function hidSupported() {
|
||||||
|
return !(navigator.hid === undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check glasses is open?
|
||||||
|
// note we filter out things that arent the master control unit
|
||||||
|
export function canCommand(device) {
|
||||||
|
if (device) {
|
||||||
|
let glasses = new Glasses(device);
|
||||||
|
return glasses.connect().then(() => {
|
||||||
|
return glasses.isMcu();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getGlasses() {
|
||||||
|
return common.curGlasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function hasActivated() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
let activationReport = await glasses.sendReportTimeout(Protocol.MESSAGES.R_ACTIVATION_TIME);
|
||||||
|
|
||||||
|
if (reportSuccess(activationReport) && activationReport.payload.length > 0) {
|
||||||
|
let time = Protocol.bytes2Time(activationReport.payload);
|
||||||
|
return time > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// /** activate the glasses */
|
||||||
|
// export async function activate(timeStamp) {
|
||||||
|
|
||||||
|
// let glasses = await common.connectDevice();
|
||||||
|
// if (!glasses) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// // hardcode value = 300
|
||||||
|
// // 3C 4B 46 52 54 41 01
|
||||||
|
// const time = Protocol.time2Bytes(timeStamp);
|
||||||
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.W_ACTIVATION_TIME, time)
|
||||||
|
// .then(report => {
|
||||||
|
// return reportSuccess;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /** deactivate the glasses */
|
||||||
|
// export async function deactivate() {
|
||||||
|
// let glasses = await common.connectDevice();
|
||||||
|
// if (!glasses) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.W_CANCEL_ACTIVATION)
|
||||||
|
// .then(report => {
|
||||||
|
// return reportSuccess;
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Conversion from decimal to hexadecimal
|
||||||
|
function Decimal2Hex(value) {
|
||||||
|
if (value.toString(16).length == 1) {
|
||||||
|
return ('0x0' + value.toString(16))
|
||||||
|
} else {
|
||||||
|
return ('0x' + value.toString(16))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read firmware MCU version*/
|
||||||
|
export async function getFirmwareVersionInMcu() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_MCU_APP_FW_VERSION)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read firmware DP version*/
|
||||||
|
export async function getFirmwareVersionInDp() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_DP7911_FW_VERSION)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read firmware DSP version*/
|
||||||
|
export async function getFirmwareVersionInDsp() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_DSP_VERSION)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameters required for the progress bar
|
||||||
|
// function progress(cur, all) {
|
||||||
|
// current = cur
|
||||||
|
// total = all
|
||||||
|
// document.getElementById('progress').innerText = parseInt((current / total) * 100) + 1 + '%'
|
||||||
|
// }
|
||||||
|
|
||||||
|
// function progressInDp(cur) {
|
||||||
|
// current = cur
|
||||||
|
// document.getElementById('progressDp').innerText = current + '%'
|
||||||
|
// }
|
||||||
|
|
||||||
|
// export async function selectBinFile() {
|
||||||
|
// const pickerOpts = {
|
||||||
|
// types: [
|
||||||
|
// {
|
||||||
|
// description: 'firmware image',
|
||||||
|
// accept: {
|
||||||
|
// 'bin/*': ['.bin']
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// excludeAcceptAllOption: true,
|
||||||
|
// multiple: false
|
||||||
|
// };
|
||||||
|
|
||||||
|
// let filePaths = await window.showOpenFilePicker(pickerOpts);
|
||||||
|
// if (filePaths.length > 0) {
|
||||||
|
// return filePaths[0].getFile();
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
function isBootDevice(device) {
|
||||||
|
return device.vendorId === Protocol.NREAL_VENDOR_ID
|
||||||
|
&& device.productId === Protocol.BOOT_PRODUCT_ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function waitBootDevice() {
|
||||||
|
let devices = await navigator.hid.getDevices().then(devices => {
|
||||||
|
return devices.filter(isBootDevice);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (devices.length > 0) {
|
||||||
|
return devices[0];
|
||||||
|
}
|
||||||
|
// await requestDevice()
|
||||||
|
|
||||||
|
await navigator.hid.requestDevice({
|
||||||
|
filters: [{ vendorId: Protocol.NREAL_VENDOR_ID, productId: Protocol.NREAL_BOOT_PRODUCT_ID }]
|
||||||
|
});
|
||||||
|
const time = new Date().getTime();
|
||||||
|
while ((new Date().getTime() - time) < 2000) {
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 20));
|
||||||
|
devices = await navigator.hid.getDevices().then(devices => {
|
||||||
|
return devices.filter(isBootDevice);
|
||||||
|
});
|
||||||
|
if (devices.length > 0) {
|
||||||
|
return devices[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// export async function upgradeInMcu(data) {
|
||||||
|
// let glasses = await common.connectDevice();
|
||||||
|
// if (!glasses) {
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_PREPARE)
|
||||||
|
// .then(report => {
|
||||||
|
// if (reportSuccess(report)) {
|
||||||
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.W_MCU_APP_JUMP_TO_BOOT);
|
||||||
|
// }
|
||||||
|
// }).then(async (report) => {
|
||||||
|
// if (reportSuccess(report)) {
|
||||||
|
// let device = await waitBootDevice();
|
||||||
|
// if (await canCommand(device)) {
|
||||||
|
// return sendFirmwareInMcu(new Glasses(device), data);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
export function Asc2Hex(value) {
|
||||||
|
return ('0x' + value.charCodeAt().toString(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** need to upgrade firmware DSP version? */
|
||||||
|
// export async function isNeedUpgradeInDsp(version) {
|
||||||
|
// let glasses = await common.connectDevice();
|
||||||
|
// if (!glasses) {
|
||||||
|
// return 'not found device';
|
||||||
|
// }
|
||||||
|
// let HexVersion = version.split('').map((item, index) => {
|
||||||
|
// return Asc2Hex(item)
|
||||||
|
// })
|
||||||
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.R_IS_NEED_UPGRADE_DSP_FW, HexVersion)
|
||||||
|
// .then(report => {
|
||||||
|
// if (reportSuccess(report)) {
|
||||||
|
// return report.payload[0]
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
|
||||||
|
export async function upgradeInDsp(data) {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return sendFirmwareInDsp(glasses, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** need to upgrade firmware DP version? */
|
||||||
|
export async function isNeedUpgradeInDp() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_DP7911_FW_IS_UPDATE)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return report.payload[0]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function upgradeInDp() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 添加眼镜休眠时间
|
||||||
|
const time = Protocol.time2Bytes('600');
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_SLEEP_TIME, time)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DP)
|
||||||
|
.then(async report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
// wait for air dp upgrade completed
|
||||||
|
while(!glasses._reports.has(27661) && common.curGlasses){
|
||||||
|
await sleep(500)
|
||||||
|
dpCurrent = glasses._reports.get(27660) ? glasses._reports.get(27660).status : 0
|
||||||
|
progressInDp(dpCurrent)
|
||||||
|
}
|
||||||
|
|
||||||
|
return glasses._reports.get(27661) ? glasses._reports.get(27661).status == 0 : false
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function sendFirmwareInMcu(bootDevice, data) {
|
||||||
|
|
||||||
|
let ofs = 0;
|
||||||
|
const firstPackLen = 24;
|
||||||
|
const fwLen = data.byteLength;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let report = await bootDevice.sendReportTimeout(
|
||||||
|
Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_START,
|
||||||
|
data.slice(ofs, ofs + firstPackLen));
|
||||||
|
if (!reportSuccess(report)) {
|
||||||
|
console.error('send fw data failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ofs += firstPackLen;
|
||||||
|
|
||||||
|
while (ofs < fwLen) {
|
||||||
|
progress(ofs, fwLen)
|
||||||
|
if ((ofs + 42) > fwLen) {
|
||||||
|
report = await bootDevice.sendReportTimeout(
|
||||||
|
Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_TRANSMIT,
|
||||||
|
data.slice(ofs, fwLen));
|
||||||
|
if (!reportSuccess(report)) {
|
||||||
|
console.error('send fw data failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
report = await bootDevice.sendReportTimeout(
|
||||||
|
Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_TRANSMIT,
|
||||||
|
data.slice(ofs, ofs + 42));
|
||||||
|
|
||||||
|
if (!reportSuccess(report)) {
|
||||||
|
console.error('send fw data failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ofs += 42;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send finish */
|
||||||
|
report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_MCU_APP_FW_FINISH);
|
||||||
|
// if (!reportSuccess(report)) {
|
||||||
|
// console.error('send fw data failed');
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
/* jump to app */
|
||||||
|
report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_BOOT_JUMP_TO_APP);
|
||||||
|
// if (!reportSuccess(report)) {
|
||||||
|
// console.error('send fw data failed');
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Send the command to upgrade the DP
|
||||||
|
// report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DP);
|
||||||
|
|
||||||
|
|
||||||
|
current = 0
|
||||||
|
total = 0
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function sendFirmwareInDsp(glasses, data) {
|
||||||
|
|
||||||
|
let ofs = 0;
|
||||||
|
let sendBufferLength = 0
|
||||||
|
const firstPackLen = 24;
|
||||||
|
const fwLen = data.byteLength;
|
||||||
|
|
||||||
|
|
||||||
|
// prepare upgrade dsp
|
||||||
|
await glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DSP_APP_FW_PREPARE);
|
||||||
|
|
||||||
|
// wait for air dsp upgrade boot
|
||||||
|
while (!glasses._reports.has(27663)) {
|
||||||
|
await sleep(100)
|
||||||
|
}
|
||||||
|
|
||||||
|
// await sleep(30000)
|
||||||
|
|
||||||
|
let report = await glasses.sendReportTimeout(
|
||||||
|
Protocol.MESSAGES.W_UPDATE_DSP_APP_FW_START,
|
||||||
|
data.slice(ofs, ofs + firstPackLen));
|
||||||
|
if (!reportSuccess(report)) {
|
||||||
|
console.error('send fw data failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ofs += firstPackLen;
|
||||||
|
|
||||||
|
while (ofs < fwLen) {
|
||||||
|
if ((ofs + 42) <= fwLen) {
|
||||||
|
progress(ofs, fwLen)
|
||||||
|
}
|
||||||
|
if ((ofs + 42) > fwLen) {
|
||||||
|
report = await glasses.sendReportTimeout(
|
||||||
|
Protocol.MESSAGES.W_UPDATE_DSP_APP_FW_TRANSMIT,
|
||||||
|
data.slice(ofs, fwLen));
|
||||||
|
if (!reportSuccess(report)) {
|
||||||
|
console.error('send fw data failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最后一包4K发送
|
||||||
|
|
||||||
|
// air DSP one package write finish, wait a while
|
||||||
|
// while(!glasses._reports.has(27662)){
|
||||||
|
// await sleep(100)
|
||||||
|
// }
|
||||||
|
// glasses._reports.delete(27662)
|
||||||
|
await sleep(300)
|
||||||
|
|
||||||
|
sendBufferLength = 0
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
report = await glasses.sendReportTimeout(
|
||||||
|
Protocol.MESSAGES.W_UPDATE_DSP_APP_FW_TRANSMIT,
|
||||||
|
data.slice(ofs, ofs + 42));
|
||||||
|
|
||||||
|
|
||||||
|
if (!reportSuccess(report)) {
|
||||||
|
console.error('send fw data failed');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ofs += 42;
|
||||||
|
sendBufferLength += 42
|
||||||
|
|
||||||
|
if (sendBufferLength >= 4096) {
|
||||||
|
// 等待4K包传完回送消息
|
||||||
|
|
||||||
|
// air DSP one package write finish, wait a while
|
||||||
|
while (!(glasses._reports.has(27662) && (glasses._reports.get(27662).status == 0 || glasses._reports.get(27662).status == 1))) {
|
||||||
|
// while(!glasses._reports.has(27662)){
|
||||||
|
await sleep(100)
|
||||||
|
}
|
||||||
|
glasses._reports.delete(27662)
|
||||||
|
|
||||||
|
// await sleep(300)
|
||||||
|
|
||||||
|
|
||||||
|
sendBufferLength -= 4096
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send finish */
|
||||||
|
report = await glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DSP_APP_FW_FINISH);
|
||||||
|
// if (!reportSuccess(report)) {
|
||||||
|
// console.error('send fw data failed');
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
// dsp write bin ==> first 100%
|
||||||
|
progress(ofs,fwLen)
|
||||||
|
/* Check whether the upgrade is complete */
|
||||||
|
// air DSP judge for flash&boot
|
||||||
|
// 删除之前刷新boot的过程,dsp重新刷新
|
||||||
|
glasses._reports.delete(27664)
|
||||||
|
while(!(glasses._reports.has(27664) && (glasses._reports.get(27664).status == 100))){
|
||||||
|
if(common.curGlasses){
|
||||||
|
await sleep(100)
|
||||||
|
DspSecond = glasses._reports.has(27664) ? glasses._reports.get(27664).status : 0
|
||||||
|
}else{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DspSecond = 100
|
||||||
|
|
||||||
|
while(!(glasses._reports.has(27667) && (glasses._reports.get(27667).status == 100))){
|
||||||
|
if(common.curGlasses){
|
||||||
|
await sleep(100)
|
||||||
|
DspThrid = glasses._reports.has(27667) ? glasses._reports.get(27667).status : 0
|
||||||
|
}else{
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DspThrid = 100
|
||||||
|
|
||||||
|
while (!(glasses._reports.has(27668) && (glasses._reports.get(27668).status == 0))) {
|
||||||
|
await sleep(100)
|
||||||
|
}
|
||||||
|
|
||||||
|
// report = await glasses.sendReportTimeout(Protocol.MESSAGES.E_DSP_UPDATE_ENDING);
|
||||||
|
|
||||||
|
current = 0
|
||||||
|
total = 0
|
||||||
|
DspSecond = 0
|
||||||
|
DspThrid = 0
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay synchronization program execution
|
||||||
|
function sleep(delay) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, delay))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** read air glasses SN*/
|
||||||
|
export async function getSN() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_GLASSID)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read air glassess Brightness */
|
||||||
|
export async function getBrightness() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
// what's the chance the getBrightness is the same as setBrightness?
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_BRIGHTNESS)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return report.payload;
|
||||||
|
// return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** write air glassess Brightness */
|
||||||
|
export async function setBrightness(brightness_int) {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
const payload = Protocol.brightInt2Bytes(brightness_int-1);
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_BRIGHTNESS, payload)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess(report)) {
|
||||||
|
return report.payload;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// export async function isAirOrLight(){
|
||||||
|
// let glasses = await common.connectDevice();
|
||||||
|
// if (!glasses) {
|
||||||
|
// return 'not found device';
|
||||||
|
// }
|
||||||
|
// if(glasses.device.productId == 1059 || glasses.device.productId == 1060){
|
||||||
|
// return 1
|
||||||
|
// }
|
||||||
|
// if(glasses.device.productId == 22332 || glasses.device.productId == 22336){
|
||||||
|
// return 2
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
function reportSuccess(report) {
|
||||||
|
return report && report.status === 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
current,
|
||||||
|
total,
|
||||||
|
dpCurrent
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,377 @@
|
||||||
|
|
||||||
|
const HEAD = 0xfd;
|
||||||
|
const MSG_ID_OFS = 15;
|
||||||
|
const PAYLOAD_OFS = 22;
|
||||||
|
const LEN_OFS = 5;
|
||||||
|
const CRC_OFS = 1;
|
||||||
|
const TS_OFS = 7;
|
||||||
|
const RESERVED_OFS = 17;
|
||||||
|
|
||||||
|
|
||||||
|
export const NREAL_VENDOR_ID = 0x3318;
|
||||||
|
export const BOOT_PRODUCT_ID = 0x0423;
|
||||||
|
|
||||||
|
|
||||||
|
export const MESSAGES = {
|
||||||
|
W_CANCEL_ACTIVATION: 0x19,
|
||||||
|
R_MCU_APP_FW_VERSION: 0x26,//MCU APP FW version.
|
||||||
|
R_GLASSID: 0x15,//MCU APP FW version.
|
||||||
|
// R_DSP_APP_FW_VERSION: 0x21,//DSP APP FW version.
|
||||||
|
R_DP7911_FW_VERSION: 0x16,//DP APP FW version.
|
||||||
|
R_ACTIVATION_TIME: 0x29,//Read activation time
|
||||||
|
W_ACTIVATION_TIME: 0x2A,//Write activation time
|
||||||
|
W_SLEEP_TIME: 0x1E,//Write unsleep time
|
||||||
|
|
||||||
|
// R_IS_NEED_UPGRADE_DSP_FW: 0x49,//Check whether the DSP needs to be upgraded.
|
||||||
|
// W_FORCE_UPGRADE_DSP_FW: 0x69,//Force upgrade DSP.
|
||||||
|
R_DSP_VERSION: 0x18,//DSP APP FW version.
|
||||||
|
W_UPDATE_DSP_APP_FW_PREPARE: 0x45, //(Implemented in APP)
|
||||||
|
W_UPDATE_DSP_APP_FW_START: 0x46, //(Implemented in APP)
|
||||||
|
W_UPDATE_DSP_APP_FW_TRANSMIT: 0x47, //(Implemented in APP)
|
||||||
|
E_DSP_ONE_PACKGE_WRITE_FINISH: 0x6C0E, //(check 4K as one package send)
|
||||||
|
W_UPDATE_DSP_APP_FW_FINISH: 0x48, //(Implemented in APP)
|
||||||
|
E_DSP_UPDATE_ENDING: 0x6C11, //whether the upgrade is complete.
|
||||||
|
E_DSP_UPDATE_PROGRES: 0x6C10, //before upgrade dsp, air for update dsp boot
|
||||||
|
|
||||||
|
W_UPDATE_MCU_APP_FW_PREPARE: 0x3E,//Preparations for mcu app fw upgrade
|
||||||
|
W_UPDATE_MCU_APP_FW_START: 0x3F, //(Implemented in Boot)
|
||||||
|
W_UPDATE_MCU_APP_FW_TRANSMIT: 0x40, //(Implemented in Boot)
|
||||||
|
W_UPDATE_MCU_APP_FW_FINISH: 0x41, //(Implemented in Boot)
|
||||||
|
W_BOOT_JUMP_TO_APP: 0x42, //(Implemented in Boot)
|
||||||
|
W_MCU_APP_JUMP_TO_BOOT: 0x44,
|
||||||
|
R_DP7911_FW_IS_UPDATE:0x3C,
|
||||||
|
W_UPDATE_DP: 0x3D,
|
||||||
|
|
||||||
|
|
||||||
|
W_BOOT_UPDATE_MODE: 0x1100,
|
||||||
|
W_BOOT_UPDATE_CONFIRM: 0x1101,
|
||||||
|
W_BOOT_UPDATE_PREPARE: 0x1102,
|
||||||
|
|
||||||
|
W_BOOT_UPDATE_START: 0x1103,
|
||||||
|
W_BOOT_UPDATE_TRANSMIT: 0x1104,
|
||||||
|
W_BOOT_UPDATE_FINISH: 0x1105,
|
||||||
|
|
||||||
|
// P_ = pushed from device
|
||||||
|
|
||||||
|
// 11-bit payload
|
||||||
|
P_BUTTON_PRESSED: 0x6C05,
|
||||||
|
|
||||||
|
// appear to fire every 5 seconds with payload = 0
|
||||||
|
P_UKNOWN_HEARTBEAT: 0x6c02,
|
||||||
|
P_UKNOWN_HEARTBEAT_2: 0x6c12
|
||||||
|
};
|
||||||
|
|
||||||
|
export function keyForHex(hex){
|
||||||
|
for (let key in MESSAGES) {
|
||||||
|
if (MESSAGES[key] == hex) {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function listKnownCommands(){
|
||||||
|
let data = [];
|
||||||
|
Object.keys(MESSAGES).map((key)=>{
|
||||||
|
|
||||||
|
|
||||||
|
data.push({
|
||||||
|
key,
|
||||||
|
hex:'0x'+MESSAGES[key].toString(16),
|
||||||
|
dec:MESSAGES[key]
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('air commands:');
|
||||||
|
console.table(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const crc32_table = [
|
||||||
|
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||||
|
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||||
|
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
||||||
|
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||||
|
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
|
||||||
|
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||||
|
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
|
||||||
|
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||||
|
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
||||||
|
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||||
|
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
|
||||||
|
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||||
|
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
|
||||||
|
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||||
|
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
||||||
|
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||||
|
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
|
||||||
|
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||||
|
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
|
||||||
|
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||||
|
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||||
|
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||||
|
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
|
||||||
|
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||||
|
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
|
||||||
|
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||||
|
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
||||||
|
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||||
|
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
|
||||||
|
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||||
|
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
|
||||||
|
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||||
|
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
|
||||||
|
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||||
|
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
|
||||||
|
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||||
|
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
|
||||||
|
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||||
|
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
|
||||||
|
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||||
|
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
|
||||||
|
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||||
|
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
|
||||||
|
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||||
|
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
||||||
|
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||||
|
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
|
||||||
|
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||||
|
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
|
||||||
|
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||||
|
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
|
||||||
|
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||||
|
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
|
||||||
|
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||||
|
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
|
||||||
|
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||||
|
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
|
||||||
|
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||||
|
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
|
||||||
|
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||||
|
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
|
||||||
|
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||||
|
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||||
|
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
function cmd_crc(buf, len) {
|
||||||
|
let CRC32_data = 0xFFFFFFFF;
|
||||||
|
for (let i = 0; i != len; ++i) {
|
||||||
|
let t = (CRC32_data ^ buf[i]) & 0xFF;
|
||||||
|
CRC32_data = ((CRC32_data >> 8) & 0xFFFFFF) ^ crc32_table[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
return ~CRC32_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function cmd_build(msgId, payload) {
|
||||||
|
let crc = 0;
|
||||||
|
let buff = new Uint8Array(64);
|
||||||
|
buff[0] = HEAD;
|
||||||
|
|
||||||
|
// memset(buff + TS_OFS, 0, 8);
|
||||||
|
// memset(buff + RESERVED_OFS, 0, 5);
|
||||||
|
|
||||||
|
buff[MSG_ID_OFS] = (msgId >> 0) & 0xff;
|
||||||
|
buff[MSG_ID_OFS + 1] = (msgId >> 8) & 0xff;
|
||||||
|
|
||||||
|
let len = /*LEN*/2 + /*TS*/8 + /*MSG_ID*/2 + /*RESERVED*/5;
|
||||||
|
|
||||||
|
if (payload != null && payload.length > 0) {
|
||||||
|
buff.set(payload, PAYLOAD_OFS);
|
||||||
|
len += payload.length;
|
||||||
|
}
|
||||||
|
buff[LEN_OFS] = (len) & 0xff;
|
||||||
|
buff[LEN_OFS + 1] = (len >> 8) & 0xff;
|
||||||
|
|
||||||
|
crc = cmd_crc(buff.slice(LEN_OFS), len);
|
||||||
|
buff[CRC_OFS] = (crc >> 0) & 0xff;
|
||||||
|
buff[CRC_OFS + 1] = (crc >> 8) & 0xff;
|
||||||
|
buff[CRC_OFS + 2] = (crc >> 16) & 0xff;
|
||||||
|
buff[CRC_OFS + 3] = (crc >> 24) & 0xff;
|
||||||
|
return buff;
|
||||||
|
};
|
||||||
|
|
||||||
|
function get_msgId(response) {
|
||||||
|
let msgId = (response[15]) | (response[16] << 8);
|
||||||
|
return msgId;
|
||||||
|
};
|
||||||
|
|
||||||
|
function get_status_byte(response) {
|
||||||
|
return response[22];
|
||||||
|
};
|
||||||
|
|
||||||
|
window.unparsed = [];
|
||||||
|
|
||||||
|
// 4-bytes to 32-bit float
|
||||||
|
function four_bytes_to_float(byte_array){
|
||||||
|
var data = byte_array; // [64, 226, 157, 10];
|
||||||
|
|
||||||
|
// Create a buffer
|
||||||
|
var buf = new ArrayBuffer(4);
|
||||||
|
// Create a data view of it
|
||||||
|
var view = new DataView(buf);
|
||||||
|
|
||||||
|
// set bytes
|
||||||
|
data.forEach(function (b, i) {
|
||||||
|
view.setUint8(i, b);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Read the bits as a float; note that by doing this, we're implicitly
|
||||||
|
// converting it from a 32-bit float into JavaScript's native 64-bit double
|
||||||
|
var num = view.getFloat32(0);
|
||||||
|
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function parse_rsp(rsp) {
|
||||||
|
let result = {
|
||||||
|
msgId: -1,
|
||||||
|
status: 0,
|
||||||
|
payload: new Uint8Array()
|
||||||
|
};
|
||||||
|
|
||||||
|
if(rsp[0] !== HEAD){
|
||||||
|
// console.warn('HEAD mismatch', rsp[0]);
|
||||||
|
// console.warn([...rsp].map(x => x.toString(16).padStart(2,'0')).join(' '));
|
||||||
|
if(window.unparsed.length<1000){
|
||||||
|
window.unparsed.push([...rsp].map(x => x.toString(16).padStart(2,'0')).join(','))
|
||||||
|
|
||||||
|
// extract 16 32-bit,4-byte floats from 64 bytes
|
||||||
|
// NOPE
|
||||||
|
// window.unparsed.push([
|
||||||
|
// [
|
||||||
|
// four_bytes_to_float(rsp.slice(0,4)),
|
||||||
|
// four_bytes_to_float(rsp.slice(4,8)),
|
||||||
|
// four_bytes_to_float(rsp.slice(8,12)),
|
||||||
|
// four_bytes_to_float(rsp.slice(12,16)),
|
||||||
|
// ],
|
||||||
|
// [
|
||||||
|
// four_bytes_to_float(rsp.slice(16,20)),
|
||||||
|
// four_bytes_to_float(rsp.slice(20,24)),
|
||||||
|
// four_bytes_to_float(rsp.slice(24,28)),
|
||||||
|
// four_bytes_to_float(rsp.slice(28,32)),
|
||||||
|
// ],
|
||||||
|
// [
|
||||||
|
// four_bytes_to_float(rsp.slice(32,36)),
|
||||||
|
// four_bytes_to_float(rsp.slice(36,40)),
|
||||||
|
// four_bytes_to_float(rsp.slice(40,44)),
|
||||||
|
// four_bytes_to_float(rsp.slice(44,48)),
|
||||||
|
// ],
|
||||||
|
// [
|
||||||
|
// four_bytes_to_float(rsp.slice(48,52)),
|
||||||
|
// four_bytes_to_float(rsp.slice(52,56)),
|
||||||
|
// four_bytes_to_float(rsp.slice(56,60)),
|
||||||
|
// four_bytes_to_float(rsp.slice(60,64)),
|
||||||
|
// ]
|
||||||
|
// ])
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
tried assuming the entire payload was 4x4 32-bit numbers,
|
||||||
|
but some of these values are way out there, so it's not
|
||||||
|
close but not quite
|
||||||
|
|
||||||
|
[2.3931767537309237e-38, 262153.6875, 1.7935222607106134e-33, -1.2112571145736495e-19]
|
||||||
|
[1.6100218705859986e-40, -1.0015453862283195e+36, 7.89323398984883e-39, 0]
|
||||||
|
[7.068319291428253e-38, -2.0569895575965996e-38, 4.316160146187087e+34, 3.6734198463196485e-40]
|
||||||
|
[4164320, 8.664825968624503e-22, -3.881952544155522e-34, 0]
|
||||||
|
*/
|
||||||
|
|
||||||
|
return;
|
||||||
|
// debugger
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsp == null || rsp.length < 1) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.msgId = get_msgId(rsp);
|
||||||
|
result.status = get_status_byte(rsp);
|
||||||
|
|
||||||
|
|
||||||
|
let packet_len = (rsp[5]) | (rsp[6] << 8);
|
||||||
|
if (packet_len < 18) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
packet_len = packet_len - 17 - 1;/* len, ts, msgid, reserve, status*/
|
||||||
|
result.payload = rsp.slice(PAYLOAD_OFS + 1, PAYLOAD_OFS + 1 + packet_len);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// todo: learn bitshifts/bitmasks and stuff instead of writing it out
|
||||||
|
// export const brightness_map = [
|
||||||
|
// // 3: 6 = increase (3= button id)
|
||||||
|
// // 7 = decrease
|
||||||
|
// // 7: intensity 0-7
|
||||||
|
// // 0 0 0 4 - 0 0 0 8 - 0 0 0
|
||||||
|
// "0 0 0 6 0 0 0 0 0 0 0", // dimmest
|
||||||
|
// "0 0 0 6 0 0 0 1 0 0 0",
|
||||||
|
// "0 0 0 6 0 0 0 2 0 0 0",
|
||||||
|
// "0 0 0 6 0 0 0 3 0 0 0",
|
||||||
|
// "0 0 0 6 0 0 0 4 0 0 0",
|
||||||
|
// "0 0 0 6 0 0 0 5 0 0 0",
|
||||||
|
// "0 0 0 6 0 0 0 6 0 0 0",
|
||||||
|
// "0 0 0 6 0 0 0 7 0 0 0", // brightest
|
||||||
|
// ]
|
||||||
|
|
||||||
|
// arg brightness_int 1-8, 8 being the brightest
|
||||||
|
export function brightInt2Bytes(brightness_int) {
|
||||||
|
// const req_bright = brightness_map[parseInt(brightness_int)-1];
|
||||||
|
// const byte_arr = new Uint8Array(req_bright.split(' ').map(x => parseInt(x)));
|
||||||
|
// return byte_arr
|
||||||
|
return new Uint8Array(['0' + brightness_int]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// arg Uint8Array, returns string
|
||||||
|
export function brightBytes2Int(bright_byte_arr) {
|
||||||
|
return bright_byte_arr[7] + 1;
|
||||||
|
//return brightness_map.indexOf(bright_byte_arr.join(' ')) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function bytes2Time(bytes) {
|
||||||
|
let time = '';
|
||||||
|
for (let i = bytes.byteLength - 1; i >= 0; i--) {
|
||||||
|
if(i > 3){
|
||||||
|
time += bytes[i].toString(2)
|
||||||
|
}else{
|
||||||
|
time += bytes[i].toString(2)
|
||||||
|
// time += bytes[i] << (i * 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return time;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function hex2Decimal(byte){
|
||||||
|
return parseInt(byte, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function time2Bytes(timeStamp){
|
||||||
|
let arr = new Uint8Array(8)
|
||||||
|
let len = Math.floor((Number(timeStamp).toString(2).length) / 8)
|
||||||
|
let longN = parseInt(Number(timeStamp).toString(2).substring(0,Number(timeStamp).toString(2).length - 32), 2)
|
||||||
|
for (let i = len; i >= 0; i--) {
|
||||||
|
if(i > 3){
|
||||||
|
arr[i] = ((longN >>> ((i - 4) * 8)) & 0xFF);
|
||||||
|
}else{
|
||||||
|
arr[i] = ((timeStamp >>> (i * 8)) & 0xFF);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Formats an 8-bit integer |value| in hexadecimal with leading zeros.
|
||||||
|
export function hex8(value) {
|
||||||
|
return ('0x' + value.toString(16)).substring(-2).toUpperCase();
|
||||||
|
};
|
||||||
|
export function bytes2String(buffer) {
|
||||||
|
let bufferString = '';
|
||||||
|
for (let byte of buffer)
|
||||||
|
bufferString += ' ' + hex8(byte);
|
||||||
|
return bufferString;
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,37 @@
|
||||||
|
digraph G {
|
||||||
|
NRSessionManager -> NRSubsystemManager
|
||||||
|
|
||||||
|
NRSubsystemManager -> NRDeviceSubsystem
|
||||||
|
|
||||||
|
NRDeviceSubsystem -> m_NativeGlassesController
|
||||||
|
NRDeviceSubsystem -> m_NativeHMD
|
||||||
|
|
||||||
|
m_NativeGlassesController -> GetTempratureLevel
|
||||||
|
|
||||||
|
NRSessionManager -> TrackingSubSystem
|
||||||
|
|
||||||
|
TrackingSubSystem -> InitTrackingMode
|
||||||
|
TrackingSubSystem -> _tss_Start
|
||||||
|
TrackingSubSystem -> Recenter
|
||||||
|
|
||||||
|
NRRenderer
|
||||||
|
|
||||||
|
TrackableFactory -> _tf_Start
|
||||||
|
|
||||||
|
NRTrackingModeChangedListener
|
||||||
|
|
||||||
|
NRDebugger -> Log
|
||||||
|
|
||||||
|
NRKernel -> NRDevice -> NRDevice_init
|
||||||
|
NRKernalUpdater
|
||||||
|
NRNotificationListener
|
||||||
|
NRKernel -> GlassesTemperatureLevel
|
||||||
|
NRKernel -> AsyncTaskExecuter
|
||||||
|
|
||||||
|
NRSessionManager -> CreateSession -> NRDevice_init
|
||||||
|
NRSessionManager -> AutoAdaptSessionConfig
|
||||||
|
|
||||||
|
NativeAPI -> NativeInterface
|
||||||
|
NativeAPI -> Configration -> UpdateConfig
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,90 @@
|
||||||
|
import * as Protocol from './protocol.js';
|
||||||
|
import * as ProtocolYmodem from './protocolYmodem.js';
|
||||||
|
|
||||||
|
|
||||||
|
export default class Glasses extends EventTarget {
|
||||||
|
constructor(device) {
|
||||||
|
super();
|
||||||
|
this._device = device;
|
||||||
|
this._interestMsg = [];
|
||||||
|
this._reports = new Map();
|
||||||
|
// set input listener
|
||||||
|
device.oninputreport = this._handleInputReport.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
get device() { return this._device; }
|
||||||
|
|
||||||
|
|
||||||
|
connect() {
|
||||||
|
if (!this._device.opened) {
|
||||||
|
return this._device.open();
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Information parsing to distinguish between connect and upgrade
|
||||||
|
_handleInputReport({ device, reportId, data }) {
|
||||||
|
const reportData = new Uint8Array(data.buffer);
|
||||||
|
// Different parsing modes by protocol
|
||||||
|
let report = Protocol.parse_rsp(reportData);
|
||||||
|
this._reports.set(report.msgId, report);
|
||||||
|
}
|
||||||
|
|
||||||
|
// light connect
|
||||||
|
sendReport(msgId, payload, option) {
|
||||||
|
const data = new Uint8Array(payload);
|
||||||
|
const cmd = Protocol.cmd_build(msgId, data, option);
|
||||||
|
this._device.sendReport(0x00, cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
async sendReportTimeout(msgId, payload = [], option, timeout = 3000) {
|
||||||
|
this.sendReport(msgId, payload, option);
|
||||||
|
const time = new Date().getTime();
|
||||||
|
while ((new Date().getTime() - time) < timeout) {
|
||||||
|
if (this._reports.has(msgId)) {
|
||||||
|
let report = this._reports.get(msgId);
|
||||||
|
this._reports.delete(msgId);
|
||||||
|
return report;
|
||||||
|
}
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 10));
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// light upgrade
|
||||||
|
//#region
|
||||||
|
// sendReportUpgrade(msgId, payload) {
|
||||||
|
// const data = new Uint8Array(payload);
|
||||||
|
// const cmd = Protocol.cmd_build(msgId, data);
|
||||||
|
// this._device.controlTransferOut(0x00, cmd);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// async sendReportTimeoutUpgrade(msgId, payload = [], timeout = 2000) {
|
||||||
|
// this.sendReportUpgrade(msgId, payload);
|
||||||
|
// const time = new Date().getTime();
|
||||||
|
// // console.log('sendReportTimeout', Protocol.hex8(msgId), payload);
|
||||||
|
// while ((new Date().getTime() - time) < timeout) {
|
||||||
|
// if (this._reports.has(msgId)) {
|
||||||
|
// let report = this._reports.get(msgId);
|
||||||
|
// // console.log('sendReportTimeout recv', report);
|
||||||
|
// this._reports.delete(msgId);
|
||||||
|
// return report;
|
||||||
|
// }
|
||||||
|
// await new Promise(resolve => setTimeout(resolve, 20));
|
||||||
|
// }
|
||||||
|
// return null;
|
||||||
|
// }
|
||||||
|
//#endregion
|
||||||
|
|
||||||
|
async isMcu() {
|
||||||
|
const report = await this.sendReportTimeout(Protocol.MESSAGES.R_ACTIVATION_TIME);
|
||||||
|
return report != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `<Glasses deviceName=${this._device.productName} vid=${this._device.vendorId} pid=${this._device.vendorId}>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,462 @@
|
||||||
|
|
||||||
|
import Glasses from './glasses.js';
|
||||||
|
import * as Protocol from './protocol.js';
|
||||||
|
import * as ProtocolYmodem from './protocolYmodem.js';
|
||||||
|
import * as common from './../common.js'
|
||||||
|
|
||||||
|
// let devices = [];
|
||||||
|
const DEBUG = true;
|
||||||
|
// progress bar
|
||||||
|
let current
|
||||||
|
let total
|
||||||
|
|
||||||
|
/** check browser whether hid support */
|
||||||
|
// todo move to common
|
||||||
|
export function hidSupported() {
|
||||||
|
return !(navigator.hid === undefined);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** check browser whether serial support */
|
||||||
|
// export function serialSupported() {
|
||||||
|
// return !(navigator.serial === undefined);
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// check glasses is open?
|
||||||
|
export function canCommand(device) {
|
||||||
|
if (device) {
|
||||||
|
let glasses = new Glasses(device);
|
||||||
|
return glasses.connect().then(() => {
|
||||||
|
return glasses.isMcu();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getGlasses() {
|
||||||
|
return common.curGlasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function hasActivated(glasses) {
|
||||||
|
let activationReport = await glasses.sendReportTimeout(Protocol.MESSAGES.R_ACTIVATION_TIME);
|
||||||
|
|
||||||
|
if (!reportSuccess(activationReport) && activationReport.payload.length > 0) {
|
||||||
|
let time = Protocol.bytes2Time(activationReport.payload);
|
||||||
|
return time > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** activate the glasses */
|
||||||
|
export async function activate(timeStamp, flag) {
|
||||||
|
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// if (await hasActivated(glasses)) {
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// hardcode value = 300
|
||||||
|
// const time = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2C, 0x01]);
|
||||||
|
let time
|
||||||
|
if (flag == 1) {
|
||||||
|
time = new Uint8Array([0xff, 0xff]);
|
||||||
|
} else {
|
||||||
|
let timeHex = Number(timeStamp).toString(16)
|
||||||
|
time = new Uint8Array(timeHex.toString().length);
|
||||||
|
for (let i = 0; i < timeHex.toString().length; i++) {
|
||||||
|
time[i] = Asc2Hex(timeHex.toString().slice(i, i + 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_ACTIVATION_TIME, time, 1)
|
||||||
|
.then(report => {
|
||||||
|
return reportSuccess;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** deactivate the glasses */
|
||||||
|
export async function deactivate() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 时间清除
|
||||||
|
activate('ff', 1)
|
||||||
|
|
||||||
|
const deactiveMessage = new Uint8Array([0x31]);
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_CANCEL_ACTIVATION, deactiveMessage, 1)
|
||||||
|
.then(report => {
|
||||||
|
return reportSuccess(report);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conversion from decimal to hexadecimal
|
||||||
|
function Asc2Hex(value) {
|
||||||
|
return ('0x' + value.charCodeAt().toString(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read firmware version MCU*/
|
||||||
|
export async function getFirmwareVersionInMcu() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_MCU_APP_FW_VERSION)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess) {
|
||||||
|
return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read firmware version AUDIO*/
|
||||||
|
export async function getFirmwareVersionInAudio() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_AUDIO_APP_FW_VERSION)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess) {
|
||||||
|
return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** read firmware version OV580*/
|
||||||
|
export async function getFirmwareVersionInOv580() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_OV580_APP_FW_VERSION)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess) {
|
||||||
|
return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export async function selectBinFile() {
|
||||||
|
const pickerOpts = {
|
||||||
|
types: [
|
||||||
|
{
|
||||||
|
description: 'firmware image',
|
||||||
|
accept: {
|
||||||
|
'bin/*': ['.bin']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
excludeAcceptAllOption: true,
|
||||||
|
multiple: false
|
||||||
|
};
|
||||||
|
|
||||||
|
let filePaths = await window.showOpenFilePicker(pickerOpts);
|
||||||
|
if (filePaths.length > 0) {
|
||||||
|
return filePaths[0].getFile();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// function isBootDevice(device) {
|
||||||
|
// return device.vendorId === ProtocolYmodem.NREAL_VENDOR_ID
|
||||||
|
// && device.productId === ProtocolYmodem.BOOT_PRODUCT_ID;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 通过hid识别设备
|
||||||
|
// async function waitBootDevice() {
|
||||||
|
// let devices = await navigator.hid.getDevices().then(devices => {
|
||||||
|
// return devices.filter(isBootDevice);
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (devices.length > 0) {
|
||||||
|
// return devices[0];
|
||||||
|
// }
|
||||||
|
// navigator.hid.requestDevice({
|
||||||
|
// filters: [{ vendorId: Protocol.NREAL_VENDOR_ID, productId: Protocol.BOOT_PRODUCT_ID }]
|
||||||
|
// });
|
||||||
|
// const time = new Date().getTime();
|
||||||
|
// while ((new Date().getTime() - time) < 2000) {
|
||||||
|
// await new Promise(resolve => setTimeout(resolve, 20));
|
||||||
|
// devices = await navigator.hid.getDevices().then(devices => {
|
||||||
|
// return devices.filter(isBootDevice);
|
||||||
|
// });
|
||||||
|
// if (devices.length > 0) {
|
||||||
|
// return devices[0];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
export async function getSerialPort() {
|
||||||
|
if ('serial' in navigator) {
|
||||||
|
console.log('当前浏览器支持serial')
|
||||||
|
}
|
||||||
|
return navigator.serial.requestPort({
|
||||||
|
filters: [{ usbVendorId: ProtocolYmodem.NREAL_VENDOR_ID, usbProductId: ProtocolYmodem.BOOT_PRODUCT_ID }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// NREAL GLASSES
|
||||||
|
// function isBootport(port){
|
||||||
|
// return port.serialNumber === "00000000001A"
|
||||||
|
// }
|
||||||
|
|
||||||
|
// 通过USB虚拟串口识别
|
||||||
|
async function waitSerialPort() {
|
||||||
|
let port = await navigator.serial.getPorts().then(port => {
|
||||||
|
return port;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (port.length > 0) {
|
||||||
|
return port[0];
|
||||||
|
}
|
||||||
|
// MCU + AUDIO + 580
|
||||||
|
|
||||||
|
// Prompt user to select any serial port.
|
||||||
|
port = await getSerialPort()
|
||||||
|
|
||||||
|
return port
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function upgradeInMcuForSerial(data){
|
||||||
|
let port = await waitSerialPort();
|
||||||
|
// let device = await waitBootDevice();
|
||||||
|
if (port) {
|
||||||
|
// open serial port
|
||||||
|
await port.open({ baudRate: 115200 }); //串口波特率
|
||||||
|
return sendFirmwareInMcu(port, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export async function upgradeInMcu(data) {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_MCU_SUPER_B_JUMP_TO_A)
|
||||||
|
// .then(report => {
|
||||||
|
// if (reportSuccess) {
|
||||||
|
// return glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_MCU_SUPER_A_FW_START);
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
.then(async (report) => {
|
||||||
|
if (reportSuccess) {
|
||||||
|
let port = await waitSerialPort();
|
||||||
|
// let device = await waitBootDevice();
|
||||||
|
if (port) {
|
||||||
|
// open serial port
|
||||||
|
await port.open({ baudRate: 115200 }); //串口波特率
|
||||||
|
return sendFirmwareInMcu(port, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delay synchronization program execution
|
||||||
|
function sleep(delay) {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, delay))
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function upgradeInDp() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// upgrade DP
|
||||||
|
if (DEBUG) console.log("send fw to upgrade the DP");
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.W_UPDATE_DP, [], 1)
|
||||||
|
.then(async report => {
|
||||||
|
if (!reportSuccess(report)) {
|
||||||
|
if (glasses._reports.has(68)) {
|
||||||
|
glasses._reports.delete(68)
|
||||||
|
}
|
||||||
|
// wait for light dp upgrade completed
|
||||||
|
while (!glasses._reports.has(68)) {
|
||||||
|
await sleep(500)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return glasses._reports.get(68).payload[0] == 49
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// check glasses is air or light?
|
||||||
|
// export async function isAirOrLight(){
|
||||||
|
// let glasses = await common.connectDevice();
|
||||||
|
// if (!glasses) {
|
||||||
|
// return 'not found device';
|
||||||
|
// }
|
||||||
|
// if(glasses.device.productId == 1059 || glasses.device.productId == 1060){
|
||||||
|
// return 1
|
||||||
|
// }
|
||||||
|
// if(glasses.device.productId == 22332 || glasses.device.productId == 22336){
|
||||||
|
// return 2
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Listening for serial port response
|
||||||
|
async function listenSerial(reader, port) {
|
||||||
|
while (port.readable) {
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
const { value, done } = await reader.read();
|
||||||
|
if (value) {
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
// TODO: Handle non-fatal read error.
|
||||||
|
// console.log(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parameters required for the progress bar
|
||||||
|
function progress(cur, all) {
|
||||||
|
current = cur
|
||||||
|
total = all
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function sendFirmwareInMcu(port, data) {
|
||||||
|
|
||||||
|
data = new Uint8Array(data)
|
||||||
|
let ofs = 0;
|
||||||
|
const firstPackLen = 1024;
|
||||||
|
const fwLen = data.byteLength;
|
||||||
|
|
||||||
|
|
||||||
|
const writer = port.writable.getWriter();
|
||||||
|
const reader = port.readable.getReader();
|
||||||
|
|
||||||
|
|
||||||
|
// Write upgrade command
|
||||||
|
await writer.write(Protocol.cmd_build(Protocol.MESSAGES.W_UPDATE_MCU_SUPER_A_FW_START))
|
||||||
|
console.log(await listenSerial(reader, port))
|
||||||
|
|
||||||
|
// Transmission over serial port
|
||||||
|
// Ymodem
|
||||||
|
|
||||||
|
while (ofs < fwLen) {
|
||||||
|
progress(ofs, fwLen)
|
||||||
|
if ((ofs + 1024) > fwLen) {
|
||||||
|
let DATNB = ProtocolYmodem.cmd_build(data.slice(ofs, fwLen))
|
||||||
|
await writer.write(DATNB)
|
||||||
|
// console.log(await listenSerial(reader, port))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
let DATNB = ProtocolYmodem.cmd_build(data.slice(ofs, ofs + firstPackLen))
|
||||||
|
await writer.write(DATNB)
|
||||||
|
// console.log(await listenSerial(reader, port))
|
||||||
|
// .then(async (report)=>{
|
||||||
|
// while (port.readable) {
|
||||||
|
// const reader = port.readable.getReader();
|
||||||
|
|
||||||
|
// try {
|
||||||
|
// while (true) {
|
||||||
|
// const { value, done } = await reader.read();
|
||||||
|
// if (done) {
|
||||||
|
// // Allow the serial port to be closed later.
|
||||||
|
// reader.releaseLock();
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// if (value) {
|
||||||
|
// console.log(value);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// } catch (error) {
|
||||||
|
// // TODO: Handle non-fatal read error.
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
ofs += 1024;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send finish */
|
||||||
|
|
||||||
|
|
||||||
|
// if (!reportSuccess(report)) {
|
||||||
|
// console.error('send fw data failed');
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
let EOT_FIRST = ProtocolYmodem.cmd_build_EOT()
|
||||||
|
await writer.write(EOT_FIRST)
|
||||||
|
// console.log(await listenSerial(reader, port))
|
||||||
|
|
||||||
|
let EOT_SECOND = ProtocolYmodem.cmd_build_EOT()
|
||||||
|
await writer.write(EOT_SECOND)
|
||||||
|
// console.log(await listenSerial(reader, port))
|
||||||
|
|
||||||
|
// let SOH = ProtocolYmodem.cmd_build_SOH()
|
||||||
|
// await writer.write(SOH)
|
||||||
|
// console.log(await listenSerial(reader, port))
|
||||||
|
|
||||||
|
|
||||||
|
/* jump to B */
|
||||||
|
await writer.write(Protocol.cmd_build(Protocol.MESSAGES.W_MCU_SUPER_A_JUMP_TO_B))
|
||||||
|
|
||||||
|
|
||||||
|
// Send the command to upgrade the DP
|
||||||
|
// await writer.write(Protocol.cmd_build(Protocol.MESSAGES.W_UPDATE_DP, [], 1))
|
||||||
|
|
||||||
|
|
||||||
|
// report = await bootDevice.sendReportTimeout(Protocol.MESSAGES.W_MCU_SUPER_A_JUMP_TO_B);
|
||||||
|
// if (!reportSuccess(report)) {
|
||||||
|
// console.error('send fw data failed');
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// close serial port
|
||||||
|
// reader.releaseLock();
|
||||||
|
// await port.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** read Glasses SN*/
|
||||||
|
export async function getSN() {
|
||||||
|
let glasses = await common.connectDevice();
|
||||||
|
if (!glasses) {
|
||||||
|
return 'not found device';
|
||||||
|
}
|
||||||
|
return glasses.sendReportTimeout(Protocol.MESSAGES.R_GLASSID)
|
||||||
|
.then(report => {
|
||||||
|
if (reportSuccess) {
|
||||||
|
return String.fromCharCode.apply(null, report.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function reportSuccess(report) {
|
||||||
|
return (report && report.payload.length === 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
current,
|
||||||
|
total,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,249 @@
|
||||||
|
|
||||||
|
// light demo connect
|
||||||
|
const HEAD = 0x02;
|
||||||
|
const END = 0x03;
|
||||||
|
const BREAK = 0x3a;
|
||||||
|
|
||||||
|
export const NREAL_VENDOR_ID = 0x0486;
|
||||||
|
export const BOOT_PRODUCT_ID = 0x573C;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const MESSAGES = {
|
||||||
|
W_CANCEL_ACTIVATION: 0x65,
|
||||||
|
R_MCU_APP_FW_VERSION: 0x35,//MCU APP FW version.
|
||||||
|
R_AUDIO_APP_FW_VERSION: 0x35,//AUDIO APP FW version.
|
||||||
|
R_OV580_APP_FW_VERSION: 0x35,//OV580 APP FW version.
|
||||||
|
R_ACTIVATION_TIME: 0x66,//Read activation time
|
||||||
|
W_ACTIVATION_TIME: 0x66,//Write activation time
|
||||||
|
R_GLASSID: 0x43,//Read Glasses SN
|
||||||
|
R_ISNEED_ACTIVATION: 0x65,//Read whether to activate
|
||||||
|
|
||||||
|
W_MCU_SUPER_B_JUMP_TO_A: 0x38, //(Implemented in A)
|
||||||
|
W_UPDATE_MCU_SUPER_A_FW_START: 0x39, //(Implemented in A)
|
||||||
|
W_MCU_SUPER_A_JUMP_TO_B: 0x52, //(Implemented in A)
|
||||||
|
W_UPDATE_DP: 0x58,
|
||||||
|
|
||||||
|
W_BOOT_UPDATE_MODE: 0x1100,
|
||||||
|
W_BOOT_UPDATE_CONFIRM: 0x1101,
|
||||||
|
W_BOOT_UPDATE_PREPARE: 0x1102,
|
||||||
|
|
||||||
|
W_BOOT_UPDATE_START: 0x1103,
|
||||||
|
W_BOOT_UPDATE_TRANSMIT: 0x1104,
|
||||||
|
W_BOOT_UPDATE_FINISH: 0x1105,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const crc32_table = [
|
||||||
|
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
|
||||||
|
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
|
||||||
|
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
|
||||||
|
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
|
||||||
|
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
|
||||||
|
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
|
||||||
|
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
|
||||||
|
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
|
||||||
|
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
|
||||||
|
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
|
||||||
|
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
|
||||||
|
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
|
||||||
|
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
|
||||||
|
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
|
||||||
|
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
|
||||||
|
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
|
||||||
|
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
|
||||||
|
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
|
||||||
|
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
|
||||||
|
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
|
||||||
|
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
|
||||||
|
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
|
||||||
|
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
|
||||||
|
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
|
||||||
|
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
|
||||||
|
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
|
||||||
|
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
|
||||||
|
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
|
||||||
|
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
|
||||||
|
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
|
||||||
|
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
|
||||||
|
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
|
||||||
|
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
|
||||||
|
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
|
||||||
|
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
|
||||||
|
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
|
||||||
|
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
|
||||||
|
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
|
||||||
|
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
|
||||||
|
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
|
||||||
|
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
|
||||||
|
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
|
||||||
|
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
|
||||||
|
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
|
||||||
|
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
|
||||||
|
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
|
||||||
|
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
|
||||||
|
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
|
||||||
|
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
|
||||||
|
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
|
||||||
|
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
|
||||||
|
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
|
||||||
|
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
|
||||||
|
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
|
||||||
|
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
|
||||||
|
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
|
||||||
|
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
|
||||||
|
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
|
||||||
|
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
|
||||||
|
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
|
||||||
|
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
|
||||||
|
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
|
||||||
|
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
|
||||||
|
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
function cmd_crc(buf, len) {
|
||||||
|
let CRC32_data = 0xFFFFFFFF;
|
||||||
|
for (let i = 0; i != len; ++i) {
|
||||||
|
let t = (CRC32_data ^ buf[i]) & 0xFF;
|
||||||
|
CRC32_data = ((CRC32_data >> 8) & 0xFFFFFF) ^ crc32_table[t];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return ~CRC32_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function cmd_build(msgId, payload, option) {
|
||||||
|
let DATATYPE
|
||||||
|
//102:激活时间 53:软件版本 52:当前固件中的7211软件版本 72:查询视频转换芯片7211的软件版本 97:SDK1.4以及以后版本的软件版本
|
||||||
|
// 101:获取是否需要激活 67:读取眼镜SN 57:休眠命令眼镜(SET) 101:失活眼镜(test) 88:升级DP
|
||||||
|
if (msgId == 102 || msgId == 53 || msgId == 52 || msgId == 72 || msgId == 97 || msgId == 101 || msgId == 67 || msgId == 88) {
|
||||||
|
if (option == 1) {
|
||||||
|
DATATYPE = 0x31 // SET命令
|
||||||
|
} else {
|
||||||
|
DATATYPE = 0x33 // GET命令
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 56:重启到达A区 57:触发升级程序 82:重启回到B区s
|
||||||
|
if (msgId == 56 || msgId == 57 || msgId == 82) {
|
||||||
|
DATATYPE = 0x40 // 超级命令
|
||||||
|
}
|
||||||
|
let num = 0;
|
||||||
|
let crc = 0;
|
||||||
|
let buff = new Uint8Array(64);
|
||||||
|
buff[num++] = HEAD; /*head*/
|
||||||
|
buff[num++] = BREAK; /*:*/
|
||||||
|
buff[num++] = DATATYPE; /*dataType*/
|
||||||
|
buff[num++] = BREAK; /*:*/
|
||||||
|
buff[num++] = msgId; /*commandId*/
|
||||||
|
buff[num++] = BREAK; /*:*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (payload != null && payload.length > 0) {
|
||||||
|
for (let i = 0; i < payload.length; i++) {
|
||||||
|
buff[num++] = payload[i] /*data*/
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buff[num++] = 0x33; /* tmp data */
|
||||||
|
}
|
||||||
|
|
||||||
|
buff[num++] = BREAK; /*:*/
|
||||||
|
|
||||||
|
buff[num++] = 0x38 /*timeStamp*/
|
||||||
|
buff[num++] = 0x38
|
||||||
|
|
||||||
|
|
||||||
|
buff[num++] = BREAK; /*:*/
|
||||||
|
|
||||||
|
crc = cmd_crc(buff.slice(0, num), num);
|
||||||
|
buff[num++] = Asc2Hex(Hex2Decimal((crc >> 24) & 0xff)[0]);
|
||||||
|
buff[num++] = Asc2Hex(Hex2Decimal((crc >> 24) & 0xff)[1]);
|
||||||
|
buff[num++] = Asc2Hex(Hex2Decimal((crc >> 16) & 0xff)[0]);
|
||||||
|
buff[num++] = Asc2Hex(Hex2Decimal((crc >> 16) & 0xff)[1]);
|
||||||
|
buff[num++] = Asc2Hex(Hex2Decimal((crc >> 8) & 0xff)[0]);
|
||||||
|
buff[num++] = Asc2Hex(Hex2Decimal((crc >> 8) & 0xff)[1]);
|
||||||
|
buff[num++] = Asc2Hex(Hex2Decimal((crc >> 0) & 0xff)[0]);
|
||||||
|
buff[num++] = Asc2Hex(Hex2Decimal((crc >> 0) & 0xff)[1]);
|
||||||
|
|
||||||
|
buff[num++] = BREAK; /*:*/
|
||||||
|
buff[num++] = END; /*end*/
|
||||||
|
|
||||||
|
|
||||||
|
return buff;
|
||||||
|
};
|
||||||
|
|
||||||
|
function get_msgId(response) {
|
||||||
|
let msgId = response[4];
|
||||||
|
return msgId;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export function parse_rsp(rsp) {
|
||||||
|
let result = {
|
||||||
|
msgId: -1,
|
||||||
|
payload: new Uint8Array()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (rsp == null || rsp.length < 1) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.msgId = get_msgId(rsp);
|
||||||
|
|
||||||
|
let packet_len = rsp.lastIndexOf(3) + 1
|
||||||
|
if (packet_len < 22) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
packet_len = packet_len - 6 - 14;/* head, dataType, msgid, timeStamp, crc, endflag*/
|
||||||
|
result.payload = rsp.slice(6, 6 + packet_len);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// export function time2Bytes(timeStamp){
|
||||||
|
// let arr = new Uint8Array(8)
|
||||||
|
// let len = Math.floor((Number(timeStamp).toString(2).length) / 8)
|
||||||
|
// for (let i = len; i >= 0; i--) {
|
||||||
|
// arr[i] = (timeStamp >> (i * 8) & 0xFFFFFFFF);
|
||||||
|
// }
|
||||||
|
// return arr;
|
||||||
|
// }
|
||||||
|
|
||||||
|
export function bytes2Time(bytes) {
|
||||||
|
let time = '';
|
||||||
|
for (let i = 0; i < bytes.byteLength; i++) {
|
||||||
|
time += String.fromCharCode(bytes[i]);
|
||||||
|
}
|
||||||
|
time = parseInt(time, 16)
|
||||||
|
return time;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Formats an 8-bit integer |value| in hexadecimal with leading zeros.
|
||||||
|
export function hex8(value) {
|
||||||
|
return ('0x' + value.toString(16)).substring(-2).toUpperCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
function Hex2Decimal(value) {
|
||||||
|
if (value.toString(16).length == 2) {
|
||||||
|
return value.toString(16)
|
||||||
|
} else {
|
||||||
|
return '0' + value.toString(16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Asc2Hex(value) {
|
||||||
|
return ('0x' + value.charCodeAt().toString(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bytes2String(buffer) {
|
||||||
|
let bufferString = '';
|
||||||
|
for (let byte of buffer)
|
||||||
|
bufferString += ' ' + hex8(byte);
|
||||||
|
return bufferString;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
// light demo upgrade
|
||||||
|
const HEAD = 0x02;
|
||||||
|
let pn = 1; // PN
|
||||||
|
|
||||||
|
export const NREAL_VENDOR_ID = 0x0483;
|
||||||
|
export const BOOT_PRODUCT_ID = 0x5740;
|
||||||
|
|
||||||
|
|
||||||
|
export const MESSAGES = {
|
||||||
|
W_CANCEL_ACTIVATION: 0x19,
|
||||||
|
R_MCU_APP_FW_VERSION: 0x35,//MCU APP FW version.
|
||||||
|
R_ACTIVATION_TIME: 0x66,//Read activation time
|
||||||
|
W_ACTIVATION_TIME: 0x2A,//Write activation time
|
||||||
|
|
||||||
|
W_UPDATE_MCU_APP_FW_PREPARE: 0x3E,//Preparations for mcu app fw upgrade
|
||||||
|
W_UPDATE_MCU_APP_FW_START: 0x39, //(Implemented in APP A)
|
||||||
|
W_UPDATE_MCU_APP_FW_TRANSMIT: 0x40, //(Implemented in APP A)
|
||||||
|
W_UPDATE_MCU_APP_FW_FINISH: 0x41, //(Implemented in APP A)
|
||||||
|
W_BOOT_JUMP_TO_APP: 0x42, //(Implemented in APP A)
|
||||||
|
W_MCU_APP_JUMP_TO_BOOT: 0x38, //Jump into APP A
|
||||||
|
|
||||||
|
W_BOOT_UPDATE_MODE: 0x1100,
|
||||||
|
W_BOOT_UPDATE_CONFIRM: 0x1101,
|
||||||
|
W_BOOT_UPDATE_PREPARE: 0x1102,
|
||||||
|
|
||||||
|
W_BOOT_UPDATE_START: 0x1103,
|
||||||
|
W_BOOT_UPDATE_TRANSMIT: 0x1104,
|
||||||
|
W_BOOT_UPDATE_FINISH: 0x1105,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
const crc16_table = [
|
||||||
|
0, 4129, 8258, 12387, 16516, 20645, 24774, 28903, 33032, 37161, 41290, 45419, 49548, 53677,
|
||||||
|
57806, 61935, 4657, 528, 12915, 8786, 21173, 17044, 29431, 25302, 37689, 33560, 45947, 41818,
|
||||||
|
54205, 50076, 62463, 58334, 9314, 13379, 1056, 5121, 25830, 29895, 17572, 21637, 42346, 46411,
|
||||||
|
34088, 38153, 58862, 62927, 50604, 54669, 13907, 9842, 5649, 1584, 30423, 26358, 22165, 18100,
|
||||||
|
46939, 42874, 38681, 34616, 63455, 59390, 55197, 51132, 18628, 22757, 26758, 30887, 2112, 6241,
|
||||||
|
10242, 14371, 51660, 55789, 59790, 63919, 35144, 39273, 43274, 47403, 23285, 19156, 31415,
|
||||||
|
27286, 6769, 2640, 14899, 10770, 56317, 52188, 64447, 60318, 39801, 35672, 47931, 43802, 27814,
|
||||||
|
31879, 19684, 23749, 11298, 15363, 3168, 7233, 60846, 64911, 52716, 56781, 44330, 48395, 36200,
|
||||||
|
40265, 32407, 28342, 24277, 20212, 15891, 11826, 7761, 3696, 65439, 61374, 57309, 53244, 48923,
|
||||||
|
44858, 40793, 36728, 37256, 33193, 45514, 41451, 53516, 49453, 61774, 57711, 4224, 161, 12482,
|
||||||
|
8419, 20484, 16421, 28742, 24679, 33721, 37784, 41979, 46042, 49981, 54044, 58239, 62302, 689,
|
||||||
|
4752, 8947, 13010, 16949, 21012, 25207, 29270, 46570, 42443, 38312, 34185, 62830, 58703, 54572,
|
||||||
|
50445, 13538, 9411, 5280, 1153, 29798, 25671, 21540, 17413, 42971, 47098, 34713, 38840, 59231,
|
||||||
|
63358, 50973, 55100, 9939, 14066, 1681, 5808, 26199, 30326, 17941, 22068, 55628, 51565, 63758,
|
||||||
|
59695, 39368, 35305, 47498, 43435, 22596, 18533, 30726, 26663, 6336, 2273, 14466, 10403, 52093,
|
||||||
|
56156, 60223, 64286, 35833, 39896, 43963, 48026, 19061, 23124, 27191, 31254, 2801, 6864, 10931,
|
||||||
|
14994, 64814, 60687, 56684, 52557, 48554, 44427, 40424, 36297, 31782, 27655, 23652, 19525, 15522,
|
||||||
|
11395, 7392, 3265, 61215, 65342, 53085, 57212, 44955, 49082, 36825, 40952, 28183, 32310, 20053,
|
||||||
|
24180, 11923, 16050, 3793, 7920
|
||||||
|
];
|
||||||
|
|
||||||
|
|
||||||
|
function cmd_crc(buf, len) {
|
||||||
|
let CRC16_data = 0x0000;
|
||||||
|
for (let i = 0; i != len; ++i) {
|
||||||
|
let t = (CRC16_data >> 8) ^ (buf[i] & 0xFF);
|
||||||
|
CRC16_data = (CRC16_data << 8) ^ crc16_table[t];
|
||||||
|
CRC16_data = '0x' + CRC16_data.toString(16).substring(CRC16_data.toString(16).length - 4)
|
||||||
|
Hex2Decimal(CRC16_data)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return CRC16_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function cmd_build(payload) {
|
||||||
|
let num = 0;
|
||||||
|
let crc = 0;
|
||||||
|
let buff = new Uint8Array(1029);
|
||||||
|
buff[num++] = HEAD; /*head*/
|
||||||
|
|
||||||
|
if (pn > 255) {
|
||||||
|
pn = 0
|
||||||
|
}
|
||||||
|
buff[num++] = Decimal2Hex(pn); /*pn*/
|
||||||
|
buff[num++] = Decimal2Hex((~pn) >>> 0); /*xpn*/
|
||||||
|
// buff[num++] = 0x01 /*pn*/
|
||||||
|
// buff[num++] = 0xFE /*xpn*/
|
||||||
|
pn++
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if (payload != null && payload.byteLength > 0) {
|
||||||
|
for (let i = 0; i < payload.byteLength; i++) {
|
||||||
|
buff[num++] = payload[i] /*data*/
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buff[num++] = 0x33; /* tmp data */
|
||||||
|
}
|
||||||
|
|
||||||
|
crc = cmd_crc(buff.slice(3, 3 + payload.length), payload.length);
|
||||||
|
buff[num++] = (crc >> 8) & 0xff;
|
||||||
|
buff[num++] = (crc >> 0) & 0xff;
|
||||||
|
|
||||||
|
|
||||||
|
return buff;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function cmd_build_EOT() {
|
||||||
|
let num = 0;
|
||||||
|
let buff = new Uint8Array(133);
|
||||||
|
|
||||||
|
buff[num++] = 0x04
|
||||||
|
buff[num++] = 0x00
|
||||||
|
buff[num++] = 0xFF
|
||||||
|
for (let i = 0; i < 128; i++) {
|
||||||
|
buff[num++] = 0x00
|
||||||
|
}
|
||||||
|
buff[num++] = 0x00
|
||||||
|
buff[num++] = 0x00
|
||||||
|
|
||||||
|
return buff
|
||||||
|
}
|
||||||
|
|
||||||
|
export function cmd_build_SOH() {
|
||||||
|
let num = 0;
|
||||||
|
let buff = new Uint8Array(133);
|
||||||
|
|
||||||
|
buff[num++] = 0x01
|
||||||
|
buff[num++] = 0x00
|
||||||
|
buff[num++] = 0xFF
|
||||||
|
for (let i = 0; i < 128; i++) {
|
||||||
|
buff[num++] = 0x00
|
||||||
|
}
|
||||||
|
buff[num++] = 0x00
|
||||||
|
buff[num++] = 0x00
|
||||||
|
|
||||||
|
return buff
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export function bytes2Time(bytes) {
|
||||||
|
let time = 0;
|
||||||
|
for (let i = bytes.byteLength - 1; i >= 0; i--) {
|
||||||
|
time += bytes[i] << (i * 8);
|
||||||
|
}
|
||||||
|
return time;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Formats an 8-bit integer |value| in hexadecimal with leading zeros.
|
||||||
|
export function hex8(value) {
|
||||||
|
return ('0x' + value.toString(16)).substring(-2).toUpperCase();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Conversion from decimal to hexadecimal
|
||||||
|
function Decimal2Hex(value) {
|
||||||
|
if (value.toString(16).length == 1) {
|
||||||
|
return ('0x0' + value.toString(16))
|
||||||
|
} else {
|
||||||
|
return ('0x' + value.toString(16))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Conversion from hexadecimal to decimal
|
||||||
|
function Hex2Decimal(value) {
|
||||||
|
return eval(value).toString(10)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ASCII character to hexadecimal
|
||||||
|
function Asc2Hex(value) {
|
||||||
|
return ('0x' + value.charCodeAt().toString(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function bytes2String(buffer) {
|
||||||
|
let bufferString = '';
|
||||||
|
for (let byte of buffer)
|
||||||
|
bufferString += ' ' + hex8(byte);
|
||||||
|
return bufferString;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC+/XleDInw4Cx4
|
||||||
|
yK4nsEfa4pPr1ac4GnnxLNi2LRrk9opdursUCFAZ/5zaAz7RDOBeDw9DLpSDRKJ2
|
||||||
|
4eYqYodWEFQ0mYRXHWLep5vnsNU+5DJvvstB64aI7F4gN5KWm9180ghamdqP2nt8
|
||||||
|
Q8Y8SBKuBV6xA+YeW7nXAksAHs/9jUuRi0x/MR5Q4NXY05fmNYeJjsJ0dfD5jhT/
|
||||||
|
vbDgIOmczv4y28cMfgKBNDpzv5XW7y78rXZgfJP5ou/fjrUusOd46iIIL05Dyv8k
|
||||||
|
LLPNhGlk5lychCfQUwdI3ESLUtGNnJNLUVCO0In3WPEPnsUMDtJEacgPxLRPwSuT
|
||||||
|
8DGNdC55AgMBAAECggEBAJWvDIa0JwvcdZ44EZ3TX41h1HKZoROsVHO7JSEqGpDl
|
||||||
|
1C1/Yo1hsn2dwq1uq7WldNbi0KBjikuS6A1qIDyJue2uoIAU7Q5lXo6IJ/0erxI6
|
||||||
|
QHkpvB0u3OLE9UQkqcNV5vGjnp57RDtIDU2nxF6MUe+HD96F4r1aQD0NdABlJbdd
|
||||||
|
vr/THU2vfA+RbSg1Uhy2k2CS1k67wNn1qHVgZk8kwPPYOlX3x0sXpis6Ppe7fODi
|
||||||
|
e13O7YHgu9+xjjbFTqmt0xyHhX4VT0uhgTO7HrS3tGHD/yPGy+novIwbevRsT2sc
|
||||||
|
drmznOckM8Ml8JKLEUjUHuKwa5cHdTGc6SHBOfsre60CgYEA/cFwbFzb5WVx/XbD
|
||||||
|
LR3Y47IYOcEvTvNJytHZhrg04WKwwUECA3Cr1eTgx+gPcroSAN8ASsSq8r8OhQut
|
||||||
|
Sl8uBIMTL4Cd0gxtN8gKqjj7IUKZfw1S+kC/2QKg5kveHEC9g8OU4d98mgHgyWSw
|
||||||
|
suVbC1dk52TMrlDul5HAEcStSksCgYEAwK3rZBwmDcRLjxfc62IRsCvxaIy/jhWa
|
||||||
|
+gjD4k6VZwb4VTTd4TM6sLIdUhbPSjisdDnsz6hJt/6E0UKKZu7ZXMA1DDW0dP1V
|
||||||
|
AzK+POrnfIKIMStXHmVFd0SKyj1Ti2lZ65vXImOVX97uvmpVGUiztW1xlISdnr+t
|
||||||
|
llKmaK4jr8sCgYBi0N5nxG15UlzmeEYfHp1kZekbLIiwtPsKeVe9J6SoFFeCmj8f
|
||||||
|
edPgsoV6M3s4kQ8LucuSUi3D4/TSiK6N5Ky14xkoiWxr7JzneQX2LcRVumqt2FF0
|
||||||
|
1Jwg9O4VYHv5ApkKY7Jply8dhhe0NXq936TpsLnBhjZSt3+CFKb4BF/7KwKBgQCr
|
||||||
|
ymVVnMNRAvNbYatXMtkSehuDW/pudFT5GVeNLwOGGHDRh5FMeKCbajM6PZwUUPNx
|
||||||
|
rTO28hTIN+WzreA4ZjzmtXiWqkt7A2QItfVn2wkJulgzfrDuKN0GudYE+yjB4+yI
|
||||||
|
ZSorPx6vm9TBcYzuPiP8Xtgl0xe1srDSll5IdvragQKBgQDQHD1NaljMbffbQtcd
|
||||||
|
6wSJH6a8UyKvXKUzPaK8XlklJDH5GNmqy/0kgPWROZ3w6riu4XXbluRw9tlveKAO
|
||||||
|
IuOr3epJXZenLK0l6235p3Cp7CHUPWbPefNiH+DoEG7BE0VTyoUQMuS0XN+abrWv
|
||||||
|
/5qdNgzNzqy7VEO1/g0ZG2fzLw==
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* @Author: 哈库呐玛塔塔
|
||||||
|
* @Date: 2022-11-18 11:32:07
|
||||||
|
* @Descripttion:
|
||||||
|
* @LastEditors: 哈库呐玛塔塔
|
||||||
|
* @LastEditTime: 2022-11-21 14:36:15
|
||||||
|
*/
|
||||||
|
var http = {};
|
||||||
|
// var baseUrl = "https://app-test-api.nreal.work/api" // test
|
||||||
|
// var baseUrl = "https://app-uat-api.nreal.ai/api" // uat
|
||||||
|
|
||||||
|
var baseUrl = "https://app-api.nreal.ai/api" // master
|
||||||
|
http.rquest = function (option, callback) {
|
||||||
|
var url = baseUrl + option.url;
|
||||||
|
var method = option.method;
|
||||||
|
var data = option.data;
|
||||||
|
var timeout = option.timeout || 0;
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
(timeout > 0) && (xhr.timeout = timeout);
|
||||||
|
xhr.onreadystatechange = function () {
|
||||||
|
if (xhr.readyState == 4) {
|
||||||
|
if (xhr.status >= 200 && xhr.status < 400) {
|
||||||
|
var result = xhr.responseText;
|
||||||
|
try { result = JSON.parse(xhr.responseText); } catch (e) { }
|
||||||
|
callback && callback(null, result);
|
||||||
|
} else {
|
||||||
|
callback && callback('status: ' + xhr.status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.bind(this);
|
||||||
|
xhr.open(method, url, true);
|
||||||
|
if (typeof data === 'object') {
|
||||||
|
try {
|
||||||
|
data = JSON.stringify(data);
|
||||||
|
} catch (e) { }
|
||||||
|
}
|
||||||
|
xhr.send(data);
|
||||||
|
xhr.ontimeout = function () {
|
||||||
|
callback && callback('timeout');
|
||||||
|
console.log('%c连%c接%c超%c时', 'color:red', 'color:orange', 'color:purple', 'color:green');
|
||||||
|
};
|
||||||
|
};
|
||||||
|
http.get = function (url, callback) {
|
||||||
|
console.log('url', url)
|
||||||
|
var option = url.url ? url : { url: url };
|
||||||
|
option.method = 'get';
|
||||||
|
this.rquest(option, callback);
|
||||||
|
};
|
||||||
|
http.post = function (option, callback) {
|
||||||
|
option.method = 'post';
|
||||||
|
this.rquest(option, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default http
|
||||||
|
|
@ -0,0 +1,224 @@
|
||||||
|
// https://github.com/fnando/sparkline/blob/main/src/sparkline.js
|
||||||
|
function getY(max, height, diff, value) {
|
||||||
|
if (max===0) return height;
|
||||||
|
const pre_parse = (height - (value * height / max) + diff);
|
||||||
|
// console.log(pre_parse);
|
||||||
|
return parseFloat((pre_parse).toFixed(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeChildren(svg) {
|
||||||
|
[...svg.querySelectorAll("*")].forEach(element => svg.removeChild(element));
|
||||||
|
}
|
||||||
|
|
||||||
|
function defaultFetch(entry) {
|
||||||
|
return entry.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildElement(tag, attrs) {
|
||||||
|
const element = document.createElementNS("http://www.w3.org/2000/svg", tag);
|
||||||
|
|
||||||
|
for (let name in attrs) {
|
||||||
|
element.setAttribute(name, attrs[name]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return element;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function sparkline(svg, entries, options) {
|
||||||
|
removeChildren(svg);
|
||||||
|
|
||||||
|
if (entries.length <= 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
options = options || {};
|
||||||
|
|
||||||
|
if (typeof(entries[0]) === "number") {
|
||||||
|
entries = entries.map(entry => {
|
||||||
|
return {value: entry};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// This function will be called whenever the mouse moves
|
||||||
|
// over the SVG. You can use it to render something like a
|
||||||
|
// tooltip.
|
||||||
|
const onmousemove = options.onmousemove;
|
||||||
|
|
||||||
|
// This function will be called whenever the mouse leaves
|
||||||
|
// the SVG area. You can use it to hide the tooltip.
|
||||||
|
const onmouseout = options.onmouseout;
|
||||||
|
|
||||||
|
// Should we run in interactive mode? If yes, this will handle the
|
||||||
|
// cursor and spot position when moving the mouse.
|
||||||
|
const interactive = ("interactive" in options) ? options.interactive : !!onmousemove;
|
||||||
|
|
||||||
|
// Define how big should be the spot area.
|
||||||
|
const spotRadius = options.spotRadius || 2;
|
||||||
|
const spotDiameter = spotRadius * 2;
|
||||||
|
|
||||||
|
// Define how wide should be the cursor area.
|
||||||
|
const cursorWidth = options.cursorWidth || 2;
|
||||||
|
|
||||||
|
// Get the stroke width; this is used to compute the
|
||||||
|
// rendering offset.
|
||||||
|
const strokeWidth = parseFloat(svg.attributes["stroke-width"].value);
|
||||||
|
|
||||||
|
// By default, data must be formatted as an array of numbers or
|
||||||
|
// an array of objects with the value key (like `[{value: 1}]`).
|
||||||
|
// You can set a custom function to return data for a different
|
||||||
|
// data structure.
|
||||||
|
const fetch = options.fetch || defaultFetch;
|
||||||
|
|
||||||
|
// Retrieve only values, easing the find for the maximum value.
|
||||||
|
const values = entries.map(entry => fetch(entry));
|
||||||
|
|
||||||
|
// The rendering width will account for the spot size.
|
||||||
|
const width = parseFloat(svg.attributes.width.value) - spotDiameter * 2;
|
||||||
|
|
||||||
|
// Get the SVG element's full height.
|
||||||
|
// This is used
|
||||||
|
const fullHeight = parseFloat(svg.attributes.height.value);
|
||||||
|
|
||||||
|
// The rendering height accounts for stroke width and spot size.
|
||||||
|
const height = fullHeight - (strokeWidth * 2) - spotDiameter;
|
||||||
|
|
||||||
|
// The maximum value. This is used to calculate the Y coord of
|
||||||
|
// each sparkline datapoint.
|
||||||
|
const max = Math.max(...values);
|
||||||
|
|
||||||
|
// Some arbitrary value to remove the cursor and spot out of
|
||||||
|
// the viewing canvas.
|
||||||
|
const offscreen = -1000;
|
||||||
|
|
||||||
|
// Cache the last item index.
|
||||||
|
const lastItemIndex = values.length - 1;
|
||||||
|
|
||||||
|
// Calculate the X coord base step.
|
||||||
|
const offset = width / lastItemIndex;
|
||||||
|
|
||||||
|
// Hold all datapoints, which is whatever we got as the entry plus
|
||||||
|
// x/y coords and the index.
|
||||||
|
const datapoints = [];
|
||||||
|
|
||||||
|
// Hold the line coordinates.
|
||||||
|
const pathY = getY(max, height, strokeWidth + spotRadius, values[0]);
|
||||||
|
let pathCoords = `M${spotDiameter} ${pathY}`;
|
||||||
|
|
||||||
|
values.forEach((value, index) => {
|
||||||
|
const x = index * offset + spotDiameter;
|
||||||
|
const y = getY(max, height, strokeWidth + spotRadius, value);
|
||||||
|
|
||||||
|
datapoints.push(Object.assign({}, entries[index], {
|
||||||
|
index: index,
|
||||||
|
x: x,
|
||||||
|
y: y
|
||||||
|
}));
|
||||||
|
|
||||||
|
pathCoords += ` L ${x} ${y}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(pathCoords.includes("NaN")) {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
const path = buildElement("path", {
|
||||||
|
class: "sparkline--line",
|
||||||
|
d: pathCoords,
|
||||||
|
fill: "none"
|
||||||
|
});
|
||||||
|
|
||||||
|
let fillCoords = `${pathCoords} V ${fullHeight} L ${spotDiameter} ${fullHeight} Z`;
|
||||||
|
|
||||||
|
if(fillCoords.includes("NaN")) {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fill = buildElement("path", {
|
||||||
|
class: "sparkline--fill",
|
||||||
|
d: fillCoords,
|
||||||
|
stroke: "none"
|
||||||
|
});
|
||||||
|
|
||||||
|
svg.appendChild(fill);
|
||||||
|
svg.appendChild(path);
|
||||||
|
|
||||||
|
if (!interactive) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// const cursor = buildElement("line", {
|
||||||
|
// class: "sparkline--cursor",
|
||||||
|
// x1: offscreen,
|
||||||
|
// x2: offscreen,
|
||||||
|
// y1: 0,
|
||||||
|
// y2: fullHeight,
|
||||||
|
// "stroke-width": cursorWidth
|
||||||
|
// });
|
||||||
|
|
||||||
|
// const spot = buildElement("circle", {
|
||||||
|
// class: "sparkline--spot",
|
||||||
|
// cx: offscreen,
|
||||||
|
// cy: offscreen,
|
||||||
|
// r: spotRadius
|
||||||
|
// });
|
||||||
|
|
||||||
|
// svg.appendChild(cursor);
|
||||||
|
// svg.appendChild(spot);
|
||||||
|
|
||||||
|
// const interactionLayer = buildElement("rect", {
|
||||||
|
// width: svg.attributes.width.value,
|
||||||
|
// height: svg.attributes.height.value,
|
||||||
|
// style: "fill: transparent; stroke: transparent",
|
||||||
|
// class: "sparkline--interaction-layer",
|
||||||
|
// });
|
||||||
|
// svg.appendChild(interactionLayer);
|
||||||
|
|
||||||
|
// interactionLayer.addEventListener("mouseout", event => {
|
||||||
|
// cursor.setAttribute("x1", offscreen);
|
||||||
|
// cursor.setAttribute("x2", offscreen);
|
||||||
|
|
||||||
|
// spot.setAttribute("cx", offscreen);
|
||||||
|
|
||||||
|
// if (onmouseout) {
|
||||||
|
// onmouseout(event);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// interactionLayer.addEventListener("mousemove", event => {
|
||||||
|
// const mouseX = event.offsetX;
|
||||||
|
|
||||||
|
// let nextDataPoint = datapoints.find(entry => {
|
||||||
|
// return entry.x >= mouseX;
|
||||||
|
// });
|
||||||
|
|
||||||
|
// if (!nextDataPoint) {
|
||||||
|
// nextDataPoint = datapoints[lastItemIndex];
|
||||||
|
// }
|
||||||
|
|
||||||
|
// let previousDataPoint = datapoints[datapoints.indexOf(nextDataPoint) - 1];
|
||||||
|
// let currentDataPoint;
|
||||||
|
// let halfway;
|
||||||
|
|
||||||
|
// if (previousDataPoint) {
|
||||||
|
// halfway = previousDataPoint.x + ((nextDataPoint.x - previousDataPoint.x) / 2);
|
||||||
|
// currentDataPoint = mouseX >= halfway ? nextDataPoint : previousDataPoint;
|
||||||
|
// } else {
|
||||||
|
// currentDataPoint = nextDataPoint;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// const x = currentDataPoint.x;
|
||||||
|
// const y = currentDataPoint.y;
|
||||||
|
|
||||||
|
// spot.setAttribute("cx", x);
|
||||||
|
// spot.setAttribute("cy", y);
|
||||||
|
|
||||||
|
// cursor.setAttribute("x1", x);
|
||||||
|
// cursor.setAttribute("x2", x);
|
||||||
|
|
||||||
|
// if (onmousemove) {
|
||||||
|
// onmousemove(event, currentDataPoint);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
export default sparkline;
|
||||||
Loading…
Reference in New Issue