Commit 5ebd2b7a authored by martin hou's avatar martin hou

feat: 增加固件更新

parent be445719
...@@ -3,7 +3,7 @@ enum Level { ...@@ -3,7 +3,7 @@ enum Level {
info = 'info', info = 'info',
error = 'error', error = 'error',
} }
type Message = { export type Message = {
level: Level; level: Level;
module: string; module: string;
procedure: string; procedure: string;
...@@ -26,17 +26,17 @@ export const Logger = { ...@@ -26,17 +26,17 @@ export const Logger = {
messages: [] as Message[], messages: [] as Message[],
consoleOutput: true, consoleOutput: true,
printModule: [], printModule: [],
info(module: string, procedure: string, message: string) { info: (module: string, procedure: string, message: string) => {
this._append(Level.info, module, procedure, message); Logger._append(Level.info, module, procedure, message);
}, },
debug(module: string, procedure: string, message: string) { debug: (module: string, procedure: string, message: string) => {
this._append(Level.debug, module, procedure, message); Logger._append(Level.debug, module, procedure, message);
}, },
error(module: string, procedure: string, message: string) { error: (module: string, procedure: string, message: string) => {
this._append(Level.error, module, procedure, message); Logger._append(Level.error, module, procedure, message);
}, },
save(module: string, procedure: string, message: any) { }, save: (module: string, procedure: string, message: any) => { },
_append(level: Level, module: string, procedure: string, message: string) { _append: (level: Level, module: string, procedure: string, message: string) => {
let log = { let log = {
level, level,
module, module,
...@@ -44,13 +44,13 @@ export const Logger = { ...@@ -44,13 +44,13 @@ export const Logger = {
message: String(message), message: String(message),
time: new Date().getTime(), time: new Date().getTime(),
}; };
this.messages.push(log); Logger.messages.push(log);
if (this.consoleOutput) { if (Logger.consoleOutput) {
this._print(log); Logger._print(log);
} }
if (this.messages.length > 15000) this.messages.shift(); if (Logger.messages.length > 15000) Logger.messages.shift();
}, },
_print(log: Message) { _print: (log: Message) => {
let time = new Date(log.time); let time = new Date(log.time);
console.info( console.info(
'[' + '[' +
......
...@@ -11,6 +11,11 @@ button { ...@@ -11,6 +11,11 @@ button {
outline: none; outline: none;
border: 1px solid #ccc; border: 1px solid #ccc;
} }
button:hover
{
cursor: pointer;
border: solid 1px #999;
}
.result-container { .result-container {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
......
...@@ -3,7 +3,7 @@ import Jensen, { BluetoothDevice } from '..'; ...@@ -3,7 +3,7 @@ import Jensen, { BluetoothDevice } from '..';
import './index.css'; import './index.css';
import { Logger } from './Logger' import { Logger } from './Logger'
const jensen = new Jensen(); const jensen = new Jensen(Logger);
const firmwareVersions = [ const firmwareVersions = [
{ model: 'hidock-p1:mini', version: '2.1.0', url: 'https://jensen.test.hidock.com/firmwares/mini-2.1.0.bin' }, { model: 'hidock-p1:mini', version: '2.1.0', url: 'https://jensen.test.hidock.com/firmwares/mini-2.1.0.bin' },
{ model: 'hidock-p1', version: '1.2.18', url: 'https://jensen.test.hidock.com/firmwares/eason-1.2.18.bin' }, { model: 'hidock-p1', version: '1.2.18', url: 'https://jensen.test.hidock.com/firmwares/eason-1.2.18.bin' },
...@@ -16,6 +16,7 @@ export function Home() { ...@@ -16,6 +16,7 @@ export function Home() {
const [devices, setDevices] = useState<Jensen.BluetoothDevice[]>([]); const [devices, setDevices] = useState<Jensen.BluetoothDevice[]>([]);
const [greeting, setGreeting] = useState<string|null>(null); const [greeting, setGreeting] = useState<string|null>(null);
const [firmwares, setFirmwares] = useState<typeof firmwareVersions|null>(null); const [firmwares, setFirmwares] = useState<typeof firmwareVersions|null>(null);
const [logs, setLogs] = useState<string[]>([]);
useEffect(() => { useEffect(() => {
jensen.connect(); jensen.connect();
...@@ -35,10 +36,22 @@ export function Home() { ...@@ -35,10 +36,22 @@ export function Home() {
// console.log('onerror', e); // console.log('onerror', e);
// alert('此设备已经在其它已打开的HiNotes网页上建立连接'); // alert('此设备已经在其它已打开的HiNotes网页上建立连接');
// }; // };
setInterval(function()
{ // 创建日志更新定时器
Logger.info('hearbeat', 'tick', 'xxxx'); const logUpdateInterval = setInterval(() => {
}, 5000); // 从Logger.messages中获取最后500条记录
let last = Logger.messages.slice(-500).reverse();
// 将last转换为字符串数组
let logStr: string[] = last.map((item) => {
return `[${item.level === 'error' ? 'x' : '*'}] [${new Date(item.time).toLocaleString()}] (${item.module} - ${item.procedure}) ${item.message}`;
});
setLogs(logStr);
}, 1000);
// 清理函数
return () => {
clearInterval(logUpdateInterval);
};
}, []); }, []);
const getFilePart = () => { const getFilePart = () => {
...@@ -121,7 +134,14 @@ export function Home() { ...@@ -121,7 +134,14 @@ export function Home() {
const getTime = async () => { const getTime = async () => {
let time = await jensen.getTime(); let time = await jensen.getTime();
alert(JSON.stringify(time)); // alert(JSON.stringify(time));
Logger.info('jensen', 'getTime', 'Time: ' + JSON.stringify(time));
}
const info = async () => {
let info = await jensen.getDeviceInfo();
// alert(JSON.stringify(info));
Logger.info('jensen', 'info', 'Device Info: ' + JSON.stringify(info));
} }
const listFiles = async () => { const listFiles = async () => {
...@@ -134,7 +154,8 @@ export function Home() { ...@@ -134,7 +154,8 @@ export function Home() {
const getBluetoothStatus = async () => { const getBluetoothStatus = async () => {
let info = await jensen.getBluetoothStatus(); let info = await jensen.getBluetoothStatus();
alert(JSON.stringify(info)); // alert(JSON.stringify(info));
Logger.info('jensen', 'getBluetoothStatus', 'Bluetooth: ' + JSON.stringify(info));
} }
const readFilePartial = async() => { const readFilePartial = async() => {
...@@ -197,7 +218,8 @@ export function Home() { ...@@ -197,7 +218,8 @@ export function Home() {
const batteryStatus = async () => { const batteryStatus = async () => {
let status = await jensen.getBatteryStatus(5); let status = await jensen.getBatteryStatus(5);
alert(JSON.stringify(status)); // alert(JSON.stringify(status));
Logger.info('jensen', 'batteryStatus', 'Battery: ' + JSON.stringify(status));
} }
let filename = ''; let filename = '';
...@@ -306,16 +328,29 @@ export function Home() { ...@@ -306,16 +328,29 @@ export function Home() {
return; return;
} }
Logger.info('jensen', 'ota', 'firmware download start');
let xhr = new XMLHttpRequest(); let xhr = new XMLHttpRequest();
xhr.open('GET', url); xhr.open('GET', url);
xhr.responseType = 'arraybuffer'; xhr.responseType = 'arraybuffer';
xhr.onload = function(e) { xhr.onload = function(e) {
if (this.status != 200) return alert('Http Error: ' + this.status); if (this.status != 200) return alert('Http Error: ' + this.status);
Logger.info('jensen', 'ota', 'firmware download complete');
Logger.info('jensen', 'ota', 'firmware upgrade start');
jensen.requestFirmwareUpgrade(versionNumber, this.response.byteLength, 30).then((info) => { jensen.requestFirmwareUpgrade(versionNumber, this.response.byteLength, 30).then((info) => {
Logger.info('jensen', 'ota', 'firmware upgrade: ' + JSON.stringify(info));
if (info.result == 'accepted') { if (info.result == 'accepted') {
// alert('firmware upgrade accepted'); // alert('firmware upgrade accepted');
Logger.info('jensen', 'ota', 'firmware transfer start');
jensen.uploadFirmware(Array.from(new Uint8Array(this.response)), 30).then((info) => { jensen.uploadFirmware(Array.from(new Uint8Array(this.response)), 30).then((info) => {
alert(JSON.stringify(info)); if (info == null)
{
Logger.info('jensen', 'ota', 'firmware transfer timedout');
}
else
{
Logger.info('jensen', 'ota', 'firmware transfer complete: ' + JSON.stringify(info));
Logger.info('jensen', 'ota', 'please wait for the firmware upgrade to complete');
}
}); });
} }
else else
...@@ -331,6 +366,7 @@ export function Home() { ...@@ -331,6 +366,7 @@ export function Home() {
<> <>
<div style={{ display: 'flex', flexDirection: 'row', gap: '16px', padding: '16px', alignItems: 'center', flexWrap: 'wrap' }}> <div style={{ display: 'flex', flexDirection: 'row', gap: '16px', padding: '16px', alignItems: 'center', flexWrap: 'wrap' }}>
<button onClick={connect}>Connect</button> <button onClick={connect}>Connect</button>
<button onClick={info}>Info</button>
<button onClick={getTime}>Get Time</button> <button onClick={getTime}>Get Time</button>
<button onClick={listFiles}>List Files</button> <button onClick={listFiles}>List Files</button>
<button onClick={transferFile}>Transfer</button> <button onClick={transferFile}>Transfer</button>
...@@ -387,9 +423,7 @@ export function Home() { ...@@ -387,9 +423,7 @@ export function Home() {
</div> </div>
</div> </div>
<div className="log-container"> <div className="log-container">
<textarea id="log" style={{ width: '100%', height: '100%' }}>{Logger.messages.slice(-400).reverse().map((item) => { <textarea id="log" style={{ width: '100%', height: '100%' }} value={logs.join('\n')} readOnly />
return `${item.level} ${item.module} ${item.procedure} ${item.message}\n`;
}).join('')}</textarea>
</div> </div>
</div> </div>
</> </>
......
...@@ -7,16 +7,16 @@ const level = { ...@@ -7,16 +7,16 @@ const level = {
export const Logger = { export const Logger = {
messages: [], messages: [],
consoleOutput: true, consoleOutput: true,
info(module, procedure, message) { info: (module, procedure, message) => {
this._append(level.info, module, procedure, message); Logger._append(level.info, module, procedure, message);
}, },
debug(module, procedure, message) { debug: (module, procedure, message) => {
this._append(level.debug, module, procedure, message); Logger._append(level.debug, module, procedure, message);
}, },
error(module, procedure, message) { error: (module, procedure, message) => {
this._append(level.error, module, procedure, message); Logger._append(level.error, module, procedure, message);
}, },
_append(level, module, procedure, message) { _append: (level, module, procedure, message) => {
const log = { const log = {
level, level,
module, module,
...@@ -24,28 +24,28 @@ export const Logger = { ...@@ -24,28 +24,28 @@ export const Logger = {
message: message, message: message,
time: new Date().getTime() time: new Date().getTime()
}; };
this.messages.push(log); Logger.messages.push(log);
if (this.consoleOutput) this._print(log); if (Logger.consoleOutput) Logger._print(log);
if (this.messages.length > 15000) this.messages.shift(); if (Logger.messages.length > 15000) Logger.messages.shift();
}, },
_print(log) { _print: (log) => {
let time = new Date(log.time); let time = new Date(log.time);
console.info(`[${log.level === 'error' ? 'x' : '*'}][${time.toLocaleString()}](${log.module} - ${log.procedure}) ${log.message}`); console.info(`[${log.level === 'error' ? 'x' : '*'}][${time.toLocaleString()}](${log.module} - ${log.procedure}) ${log.message}`);
}, },
filter(module, procedure) { filter: (module, procedure) => {
return this.messages.filter((i) => i.module === module && i.procedure === procedure); return Logger.messages.filter((i) => i.module === module && i.procedure === procedure);
}, },
enableConsoleOutput() { enableConsoleOutput: () => {
this.consoleOutput = true; Logger.consoleOutput = true;
}, },
disableConsoleOutput() { disableConsoleOutput: () => {
this.consoleOutput = false; Logger.consoleOutput = false;
}, },
peek(rows) { peek: (rows) => {
return this.messages.slice(-rows); return Logger.messages.slice(-rows);
}, },
search(module, procedure, keyword) { search: (module, procedure, keyword) => {
return this.messages.filter((i) => { return Logger.messages.filter((i) => {
let r = i.module === module; let r = i.module === module;
if (!r) return false; if (!r) return false;
if (procedure) { if (procedure) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment