Skip to content

Commit

Permalink
Merge pull request entrylabs#379 from entrylabs/issue/12090
Browse files Browse the repository at this point in the history
ESP32 보드 펌웨어 플래시
  • Loading branch information
wodnjs6512 authored Sep 9, 2020
2 parents e4c24f4 + 84dbb0d commit af46f0d
Show file tree
Hide file tree
Showing 11 changed files with 218 additions and 97 deletions.
9 changes: 9 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"printWidth": 100,
"tabWidth": 4,
"singleQuote": true,
"trailingComma": "es5",
"bracketSpacing": true,
"semi": true,
"arrowParens": "always"
}
Binary file added app/firmwares/codewiz.bin
Binary file not shown.
Binary file added app/firmwares/esptool
Binary file not shown.
Binary file added app/firmwares/esptool.exe
Binary file not shown.
Binary file added app/firmwares/examples/esp32/codewiz.bin
Binary file not shown.
31 changes: 31 additions & 0 deletions app/firmwares/examples/esp32/codewiz.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"id": "011201",
"name": {
"en": "CodeWiz",
"ko": "코드위즈"
},
"category": "board",
"platform": ["win32", "darwin"],
"icon": "codewiz.png",
"module": "codeino.js",
"url": "http://www.codable.co.kr",
"email": "[email protected]",
"video": "https://goo.gl/cZaYCH",
"reconnect": true,
"selectPort": true,
"firmware": {
"type": "esp32",
"offset": "0x10000",
"name": "codewiz"
},
"firmwareBaudRate": 921600,
"hardware": {
"type": "serial",
"control": "slave",
"duration": 32,
"vendor": ["wch.cn", "FTDI"],
"baudRate": 921600,
"firmwarecheck": false,
"advertise": 2000
}
}
Binary file added app/firmwares/examples/esp32/codewiz.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
78 changes: 64 additions & 14 deletions app/src/main/core/serial/flasher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,45 @@ const platform = process.platform;
class Flasher {
private flasherProcess?: ChildProcess;

private _flashArduino(firmware: IFirmwareInfo, port: string, options: { baudRate?: number; MCUType?: string; }): Promise<any[]> {
private _flashESP(
firmware: IESP32TypeFirmware,
port: string,
options: {
baudRate?: number;
MCUType?: string;
}
): Promise<any[]> {
return new Promise((resolve) => {
const cmd = [
platform === 'darwin' ? './esptool' : 'esptool.exe',
` --port ${port}`,
' --before default_reset',
' --after hard_reset write_flash',
` ${firmware.offset}`,
' codewiz.bin',
].join('');

logger.info(`ESP board firmware requested.\nparameter is ${cmd}`);
this.flasherProcess = exec(
cmd,
{
cwd: directoryPaths.firmware(),
},
(...args) => {
resolve(args);
}
);
});
}

private _flashArduino(
firmware: IFirmwareInfo,
port: string,
options: {
baudRate?: number;
MCUType?: string;
}
): Promise<any[]> {
return new Promise((resolve) => {
const baudRate = options.baudRate || '115200';
const MCUType = options.MCUType || ' m328p';
Expand Down Expand Up @@ -51,18 +89,18 @@ class Flasher {
'.hex":i -C',
avrConf,
' -carduino -D',
];
].join('');

logger.info(`arduino board firmware requested.\nparameter is ${cmd.join('')}`);
logger.info(`arduino board firmware requested.\nparameter is ${cmd}`);

this.flasherProcess = exec(
cmd.join(''),
cmd,
{
cwd: directoryPaths.firmware(),
},
(...args) => {
resolve(args);
},
}
);
});
}
Expand All @@ -82,22 +120,34 @@ class Flasher {
// TODO 파일 없을 시 에러 처리
logger.info('copy style firmware upload requested');
logger.info(`${firmwareDirectory} to ${destFirmwarePath}`);
fileUtils.copyFile(targetFirmwarePath, destFirmwarePath).then(async () => {
if (firmware.afterDelay) {
await new Promise((resolve) => setTimeout(resolve, firmware.afterDelay));
}
resolve([]);
}).catch((err) => {
reject([err]);
});
fileUtils
.copyFile(targetFirmwarePath, destFirmwarePath)
.then(async () => {
if (firmware.afterDelay) {
await new Promise((resolve) => setTimeout(resolve, firmware.afterDelay));
}
resolve([]);
})
.catch((err) => {
reject([err]);
});
});
}

flash(firmware: IFirmwareInfo, port: string, options: { baudRate?: number; MCUType?: string; }): Promise<any[]> {
flash(
firmware: IFirmwareInfo,
port: string,
options: {
baudRate?: number;
MCUType?: string;
}
): Promise<any[]> {
if (typeof firmware === 'string') {
return this._flashArduino(firmware, port, options);
} else if ((firmware as ICopyTypeFirmware).type === 'copy') {
return this._flashCopy(firmware as ICopyTypeFirmware);
} else if ((firmware as IESP32TypeFirmware).type === 'esp32') {
return this._flashESP(firmware as IESP32TypeFirmware, port, options);
} else {
return Promise.reject(new Error());
}
Expand Down
96 changes: 58 additions & 38 deletions app/src/main/mainRouter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,11 @@ class MainRouter {
return global.sharedObject.roomIds || [];
}

constructor(mainWindow: BrowserWindow, entryServer: IEntryServer, options: {rootAppPath?: string}) {
constructor(
mainWindow: BrowserWindow,
entryServer: IEntryServer,
options: { rootAppPath?: string }
) {
global.$ = require('lodash');
if (options.rootAppPath) {
directoryPaths.setRootAppPath(options.rootAppPath);
Expand Down Expand Up @@ -94,7 +98,8 @@ class MainRouter {
*/
flashFirmware(firmwareName: IFirmwareInfo): Promise<IFirmwareInfo> {
logger.info(`firmware flash requested. firmwareName: ${firmwareName}`);
const connectorSerialPort = this.connector && (this.connector as SerialConnector).serialPort;
const connectorSerialPort =
this.connector && (this.connector as SerialConnector).serialPort;
// firmware type 이 copy 인 경우는 시리얼포트를 경유하지 않으므로 체크하지 않는다.
// 그러나 config 은 필요하다.
if (
Expand All @@ -113,40 +118,45 @@ class MainRouter {

this.stopScan({ saveSelectedPort: true }); // 서버 통신 중지, 시리얼포트 연결 해제

const flashFunction: () => Promise<IFirmwareInfo> = () => new Promise((resolve, reject) => {
setTimeout(() => {
if (!lastSerialPortCOMPort) {
return reject(new Error('COM Port is not selected'));
}

//연결 해제 완료시간까지 잠시 대기 후 로직 수행한다.
this.flasher.flash(firmware, lastSerialPortCOMPort, { baudRate, MCUType })
.then(([error, ...args]) => {
if (error) {
rendererConsole.log('flashError', error);
if (error === 'exit') {
// 에러 메세지 없이 프로세스 종료
reject(new Error());
} else if (++this.firmwareTryCount <= maxFlashTryCount) {
setTimeout(() => {
flashFunction().then(resolve);
}, 100);
const flashFunction: () => Promise<IFirmwareInfo> = () =>
new Promise((resolve, reject) => {
setTimeout(() => {
if (!lastSerialPortCOMPort) {
return reject(new Error('COM Port is not selected'));
}

//연결 해제 완료시간까지 잠시 대기 후 로직 수행한다.
this.flasher
.flash(firmware, lastSerialPortCOMPort, { baudRate, MCUType })
.then(([error, ...args]) => {
if (error) {
rendererConsole.log('flashError', error);
if (error === 'exit') {
// 에러 메세지 없이 프로세스 종료
reject(new Error());
} else if (++this.firmwareTryCount <= maxFlashTryCount) {
setTimeout(() => {
flashFunction().then(resolve);
}, 100);
} else {
console.log(error);
reject(new Error('Failed Firmware Upload'));
}
} else {
reject(new Error('Failed Firmware Upload'));
logger.info('firmware flash success');
resolve(firmware);
}
} else {
logger.info('firmware flash success');
resolve(firmware);
}
})
.catch(reject);
}, 500);
});
})
.catch(reject);
}, 500);
});

// 에러가 발생하거나, 정상종료가 되어도 일단 startScan 을 재시작한다.
return flashFunction();
} else {
logger.warn(`[${firmwareName}] Hardware Device Is Not Connected. config: ${this.config}`);
logger.warn(
`[${firmwareName}] Hardware Device Is Not Connected. config: ${this.config}`
);
return Promise.reject(new Error('Hardware Device Is Not Connected'));
}
}
Expand Down Expand Up @@ -222,12 +232,18 @@ class MainRouter {
this.scanner = this.scannerManager.getScanner(type);
if (this.scanner) {
const moduleFilePath = directoryPaths.modules();
this.hwModule = nativeNodeRequire(path.join(moduleFilePath, config.module)) as IHardwareModule;
this.hwModule = nativeNodeRequire(
path.join(moduleFilePath, config.module)
) as IHardwareModule;
this.sendState(HardwareStatement.scan);
this.scanner.stopScan();
const connector = await this.scanner.startScan(this.hwModule, this.config);
if (connector) {
logger.info(`[Device Info] ${config.id} | ${config?.name?.ko || config?.name?.en || 'noname'}`);
logger.info(
`[Device Info] ${config.id} | ${
config?.name?.ko || config?.name?.en || 'noname'
}`
);
this.connector = connector;
connector.setRouter(this);
this._connect(connector);
Expand All @@ -252,7 +268,9 @@ class MainRouter {

stopScan(option?: { saveSelectedPort?: boolean }) {
const { saveSelectedPort = false } = option || {};
logger.info(`scan stopped. selectedPort will be ${saveSelectedPort ? 'saved' : 'undefined'}`);
logger.info(
`scan stopped. selectedPort will be ${saveSelectedPort ? 'saved' : 'undefined'}`
);

this.server && this.server.disconnectHardware();
this.scanner && this.scanner.stopScan();
Expand Down Expand Up @@ -366,7 +384,7 @@ class MainRouter {
}

// 엔트리 측에서 데이터를 받아온 경우 전달
handleServerData({ data }: { data: any; }) {
handleServerData({ data }: { data: any }) {
if (!this.hwModule || !this.handler || !this.config) {
logger.warn('hardware is not connected but entry server data is received');
return;
Expand Down Expand Up @@ -413,17 +431,19 @@ class MainRouter {
}

setConnector(connector: any) {
logger.verbose('mainRouter\'s connector is set');
logger.verbose("mainRouter's connector is set");
this.connector = connector;
}

/**
*
* @param option {Object=} true 인 경우, 포트선택했던 내역을 지우지 않는다.
*/
close(option?: { saveSelectedPort?: boolean, saveConfig?: boolean }) {
close(option?: { saveSelectedPort?: boolean; saveConfig?: boolean }) {
const { saveSelectedPort = false, saveConfig = false } = option || {};
logger.info(`scan stopped. selectedPort will be ${saveSelectedPort ? 'saved' : 'undefined'}`);
logger.info(
`scan stopped. selectedPort will be ${saveSelectedPort ? 'saved' : 'undefined'}`
);

this.server?.disconnectHardware();
this.stopScan(option);
Expand All @@ -437,7 +457,7 @@ class MainRouter {
if (!saveSelectedPort) {
this.selectedPort = undefined;
}
};
}

executeDriver(driverPath: string) {
if (!this.config) {
Expand Down
Loading

0 comments on commit af46f0d

Please sign in to comment.