feat(device): Read only filled user configuration and fix app close on mac (#486)

* feat(device): Save user configuration length

* feat(device): Read only filled user configuration from EEPROM

* fix(agent): Close device connections and quit from app on Mac
This commit is contained in:
Róbert Kiss
2017-11-02 23:06:53 +01:00
committed by László Monda
parent fe6cd68c55
commit 0c30eccaca
5 changed files with 46 additions and 11 deletions

View File

@@ -39,6 +39,8 @@ let appService: AppService;
let sudoService: SudoService;
function createWindow() {
logger.info('[Electron Main] Create new window.');
// Create the browser window.
win = new BrowserWindow({
title: 'UHK Agent',
@@ -73,10 +75,13 @@ function createWindow() {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
logger.info('[Electron Main] win closed');
win = null;
deviceService.close();
deviceService = null;
appUpdateService = null;
appService = null;
uhkHidDeviceService.close();
uhkHidDeviceService = null;
sudoService = null;
});
@@ -96,11 +101,7 @@ app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
app.quit();
});
app.on('will-quit', () => {

View File

@@ -83,10 +83,11 @@ export class DeviceService {
try {
this.logService.debug(`[DeviceService] USB[T]: Read ${configName} size from keyboard`);
const configSize = await this.getConfigSizeFromKeyboard(property);
let configSize = await this.getConfigSizeFromKeyboard(property);
const chunkSize = 63;
let offset = 0;
let configBuffer = new Buffer(0);
let firstRead = true;
this.logService.debug(`[DeviceService] USB[T]: Read ${configName} from keyboard`);
while (offset < configSize) {
@@ -95,6 +96,11 @@ export class DeviceService {
const readBuffer = await this.device.write(writeBuffer);
configBuffer = Buffer.concat([configBuffer, new Buffer(readBuffer.slice(1, chunkSizeToRead + 1))]);
offset += chunkSizeToRead;
if (firstRead && config === UsbCommand.ReadUserConfig) {
firstRead = false;
configSize = readBuffer[3] + (readBuffer[4] << 8);
}
}
response = UhkHidDevice.convertBufferToIntArray(configBuffer);
return Promise.resolve(JSON.stringify(response));
@@ -105,6 +111,13 @@ export class DeviceService {
}
}
public close(): void {
this.connected = false;
this.pollTimer$.unsubscribe();
this.logService.info('[DeviceService] Device connection checker stopped.');
}
/**
* HID API not support device attached and detached event.
* This method check the keyboard is attached to the computer or not.

View File

@@ -10,6 +10,9 @@ export class UserConfiguration {
@assertUInt16
dataModelVersion: number;
@assertUInt16
userConfigurationLength: number;
deviceName: string;
moduleConfigurations: ModuleConfiguration[] = [];
@@ -24,6 +27,7 @@ export class UserConfiguration {
fromJsonObject(jsonObject: any): UserConfiguration {
this.dataModelVersion = jsonObject.dataModelVersion;
this.userConfigurationLength = jsonObject.userConfigurationLength;
this.deviceName = jsonObject.deviceName;
this.setDefaultDeviceName();
this.moduleConfigurations = jsonObject.moduleConfigurations.map((moduleConfiguration: any) => {
@@ -35,11 +39,13 @@ export class UserConfiguration {
return macro;
});
this.keymaps = jsonObject.keymaps.map((keymap: any) => new Keymap().fromJsonObject(keymap, this.macros));
this.recalculateConfigurationLength();
return this;
}
fromBinary(buffer: UhkBuffer): UserConfiguration {
this.dataModelVersion = buffer.readUInt16();
this.userConfigurationLength = buffer.readUInt16();
this.deviceName = buffer.readString();
this.setDefaultDeviceName();
this.moduleConfigurations = buffer.readArray<ModuleConfiguration>(uhkBuffer => {
@@ -52,12 +58,18 @@ export class UserConfiguration {
});
this.keymaps = buffer.readArray<Keymap>(uhkBuffer => new Keymap().fromBinary(uhkBuffer, this.macros));
ConfigSerializer.resolveSwitchKeymapActions(this.keymaps);
if (this.userConfigurationLength === 0) {
this.recalculateConfigurationLength();
}
return this;
}
toJsonObject(): any {
return {
dataModelVersion: this.dataModelVersion,
userConfigurationLength: this.userConfigurationLength,
deviceName: this.deviceName,
moduleConfigurations: this.moduleConfigurations.map(moduleConfiguration => moduleConfiguration.toJsonObject()),
keymaps: this.keymaps.map(keymap => keymap.toJsonObject(this.macros)),
@@ -67,6 +79,7 @@ export class UserConfiguration {
toBinary(buffer: UhkBuffer): void {
buffer.writeUInt16(this.dataModelVersion);
buffer.writeUInt16(this.userConfigurationLength);
buffer.writeString(this.deviceName);
buffer.writeArray(this.moduleConfigurations);
buffer.writeArray(this.macros);
@@ -87,6 +100,12 @@ export class UserConfiguration {
return this.macros.find(macro => macroId === macro.id);
}
recalculateConfigurationLength(){
const buffer = new UhkBuffer();
this.toBinary(buffer);
this.userConfigurationLength = buffer.offset;
}
private setDefaultDeviceName(): void {
if (!this.deviceName || this.deviceName.trim().length === 0) {
this.deviceName = 'My UHK';

View File

@@ -157,12 +157,13 @@ export class UhkHidDevice {
* Close the communication chanel with UHK Device
*/
public close(): void {
this.logService.info('[UhkHidDevice] Device communication closing.');
if (!this._device) {
return;
}
this._device.close();
this._device = null;
this.logService.info('[UhkHidDevice] Device communication closed.');
}
public async waitUntilKeyboardBusy(): Promise<void> {
@@ -196,7 +197,7 @@ export class UhkHidDevice {
private connectToDevice(): HID {
try {
const devs = devices();
this.logService.debug('[DeviceService] Available devices:', devs);
this.logService.debug('[UhkHidDevice] Available devices:', devs);
const dev = devs.find((x: Device) =>
x.vendorId === Constants.VENDOR_ID &&
@@ -204,15 +205,15 @@ export class UhkHidDevice {
((x.usagePage === 128 && x.usage === 129) || x.interface === 0));
if (!dev) {
this.logService.info('[DeviceService] UHK Device not found:');
this.logService.info('[UhkHidDevice] UHK Device not found:');
return null;
}
const device = new HID(dev.path);
this.logService.info('[DeviceService] Used device:', dev);
this.logService.info('[UhkHidDevice] Used device:', dev);
return device;
}
catch (err) {
this.logService.error('[DeviceService] Can not create device:', err);
this.logService.error('[UhkHidDevice] Can not create device:', err);
}
return null;

View File

@@ -78,6 +78,7 @@ export class UserConfigEffects {
Observable<KeymapAction | MacroAction | RenameUserConfigurationAction>)
.withLatestFrom(this.store.select(getUserConfiguration), this.store.select(getPrevUserConfiguration))
.mergeMap(([action, config, prevUserConfiguration]) => {
config.recalculateConfigurationLength();
this.dataStorageRepository.saveConfig(config);
if (action.type === KeymapActions.REMOVE || action.type === MacroActions.REMOVE) {