feat(device): Read user config from eeprom (#413)
* feat(device): Read user config from eeprom * read data from eeprom * fix user config serialization * fix device connected detection * not allow override default config is eeprom is empty * add error handling to eeprom parsing * colorize log output * add USB[T] feature * add class name to USB[T] log * remove redundant error log msg * Add USB[T] to Apply user config
This commit is contained in:
committed by
László Monda
parent
d621b1e5e6
commit
96e968729d
@@ -18,9 +18,11 @@ import { UhkHidDeviceService } from './uhk-hid-device.service';
|
|||||||
* UHK USB Communications command. All communication package should have start with a command code.
|
* UHK USB Communications command. All communication package should have start with a command code.
|
||||||
*/
|
*/
|
||||||
enum Command {
|
enum Command {
|
||||||
|
GetProperty = 0,
|
||||||
UploadConfig = 8,
|
UploadConfig = 8,
|
||||||
ApplyConfig = 9,
|
ApplyConfig = 9,
|
||||||
LaunchEepromTransfer = 12,
|
LaunchEepromTransfer = 12,
|
||||||
|
ReadUserConfig = 15,
|
||||||
GetKeyboardState = 16
|
GetKeyboardState = 16
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,6 +33,15 @@ enum EepromTransfer {
|
|||||||
WriteUserConfig = 3
|
WriteUserConfig = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum SystemPropertyIds {
|
||||||
|
UsbProtocolVersion = 0,
|
||||||
|
BridgeProtocolVersion = 1,
|
||||||
|
DataModelVersion = 2,
|
||||||
|
FirmwareVersion = 3,
|
||||||
|
HardwareConfigSize = 4,
|
||||||
|
UserConfigSize = 5
|
||||||
|
}
|
||||||
|
|
||||||
const snooze = ms => new Promise(resolve => setTimeout(resolve, ms));
|
const snooze = ms => new Promise(resolve => setTimeout(resolve, ms));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,6 +49,7 @@ const snooze = ms => new Promise(resolve => setTimeout(resolve, ms));
|
|||||||
* Functionality:
|
* Functionality:
|
||||||
* - Detect device is connected or not
|
* - Detect device is connected or not
|
||||||
* - Send UserConfiguration to the UHK Device
|
* - Send UserConfiguration to the UHK Device
|
||||||
|
* - Read UserConfiguration from the UHK Device
|
||||||
*/
|
*/
|
||||||
export class DeviceService {
|
export class DeviceService {
|
||||||
private pollTimer$: Subscription;
|
private pollTimer$: Subscription;
|
||||||
@@ -48,6 +60,7 @@ export class DeviceService {
|
|||||||
private device: UhkHidDeviceService) {
|
private device: UhkHidDeviceService) {
|
||||||
this.pollUhkDevice();
|
this.pollUhkDevice();
|
||||||
ipcMain.on(IpcEvents.device.saveUserConfiguration, this.saveUserConfiguration.bind(this));
|
ipcMain.on(IpcEvents.device.saveUserConfiguration, this.saveUserConfiguration.bind(this));
|
||||||
|
ipcMain.on(IpcEvents.device.loadUserConfiguration, this.loadUserConfiguration.bind(this));
|
||||||
logService.debug('[DeviceService] init success');
|
logService.debug('[DeviceService] init success');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,6 +72,38 @@ export class DeviceService {
|
|||||||
return this.connected;
|
return this.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return with the actual UserConfiguration from UHK Device
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async loadUserConfiguration(event: Electron.Event): Promise<void> {
|
||||||
|
let response = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.logService.debug('[DeviceService] USB[T]: Read user configuration size from keyboard');
|
||||||
|
const configSize = await this.getUserConfigSizeFromKeyboard();
|
||||||
|
const chunkSize = 63;
|
||||||
|
let offset = 0;
|
||||||
|
let configBuffer = new Buffer(0);
|
||||||
|
|
||||||
|
this.logService.debug('[DeviceService] USB[T]: Read user configuration from keyboard');
|
||||||
|
while (offset < configSize) {
|
||||||
|
const chunkSizeToRead = Math.min(chunkSize, configSize - offset);
|
||||||
|
const writeBuffer = Buffer.from([Command.ReadUserConfig, chunkSizeToRead, offset & 0xff, offset >> 8]);
|
||||||
|
const readBuffer = await this.device.write(writeBuffer);
|
||||||
|
configBuffer = Buffer.concat([configBuffer, new Buffer(readBuffer.slice(1, chunkSizeToRead + 1))]);
|
||||||
|
offset += chunkSizeToRead;
|
||||||
|
}
|
||||||
|
response = UhkHidDeviceService.convertBufferToIntArray(configBuffer);
|
||||||
|
} catch (error) {
|
||||||
|
this.logService.error('[DeviceService] getUserConfigFromEeprom error', error);
|
||||||
|
} finally {
|
||||||
|
this.device.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
event.sender.send(IpcEvents.device.loadUserConfigurationReply, JSON.stringify(response));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* HID API not support device attached and detached event.
|
* HID API not support device attached and detached event.
|
||||||
* This method check the keyboard is attached to the computer or not.
|
* This method check the keyboard is attached to the computer or not.
|
||||||
@@ -76,25 +121,38 @@ export class DeviceService {
|
|||||||
.do((connected: boolean) => {
|
.do((connected: boolean) => {
|
||||||
this.connected = connected;
|
this.connected = connected;
|
||||||
this.win.webContents.send(IpcEvents.device.deviceConnectionStateChanged, connected);
|
this.win.webContents.send(IpcEvents.device.deviceConnectionStateChanged, connected);
|
||||||
this.logService.info(`Device connection state changed to: ${connected}`);
|
this.logService.info(`[DeviceService] Device connection state changed to: ${connected}`);
|
||||||
})
|
})
|
||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the UserConfiguration size from the UHK Device
|
||||||
|
* @returns {Promise<number>}
|
||||||
|
*/
|
||||||
|
private async getUserConfigSizeFromKeyboard(): Promise<number> {
|
||||||
|
const buffer = await this.device.write(new Buffer([Command.GetProperty, SystemPropertyIds.UserConfigSize]));
|
||||||
|
const configSize = buffer[1] + (buffer[2] << 8);
|
||||||
|
this.logService.debug('[DeviceService] User config size:', configSize);
|
||||||
|
return configSize;
|
||||||
|
}
|
||||||
|
|
||||||
private async saveUserConfiguration(event: Electron.Event, json: string): Promise<void> {
|
private async saveUserConfiguration(event: Electron.Event, json: string): Promise<void> {
|
||||||
const response = new IpcResponse();
|
const response = new IpcResponse();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.sendUserConfigToKeyboard(json);
|
this.logService.debug('[DeviceService] USB[T]: Write user configuration to keyboard');
|
||||||
|
await this.sendUserConfigToKeyboard(json);
|
||||||
|
this.logService.debug('[DeviceService] USB[T]: Write user configuration to EEPROM');
|
||||||
await this.writeUserConfigToEeprom();
|
await this.writeUserConfigToEeprom();
|
||||||
this.device.close();
|
|
||||||
|
|
||||||
response.success = true;
|
response.success = true;
|
||||||
this.logService.info('transferring finished');
|
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
this.logService.error('[DeviceService] Transferring error', error);
|
this.logService.error('[DeviceService] Transferring error', error);
|
||||||
response.error = {message: error.message};
|
response.error = {message: error.message};
|
||||||
|
} finally {
|
||||||
|
this.device.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
event.sender.send(IpcEvents.device.saveUserConfigurationReply, response);
|
event.sender.send(IpcEvents.device.saveUserConfigurationReply, response);
|
||||||
@@ -114,19 +172,14 @@ export class DeviceService {
|
|||||||
for (const fragment of fragments) {
|
for (const fragment of fragments) {
|
||||||
await this.device.write(fragment);
|
await this.device.write(fragment);
|
||||||
}
|
}
|
||||||
|
this.logService.debug('[DeviceService] USB[T]: Apply user configuration to keyboard');
|
||||||
const applyBuffer = new Buffer([Command.ApplyConfig]);
|
const applyBuffer = new Buffer([Command.ApplyConfig]);
|
||||||
await this.device.write(applyBuffer);
|
await this.device.write(applyBuffer);
|
||||||
this.logService.info('[DeviceService] Transferring finished');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async writeUserConfigToEeprom(): Promise<void> {
|
private async writeUserConfigToEeprom(): Promise<void> {
|
||||||
this.logService.info('[DeviceService] Start write user configuration to eeprom');
|
await this.device.write(new Buffer([Command.LaunchEepromTransfer, EepromTransfer.WriteUserConfig]));
|
||||||
|
|
||||||
const buffer = await this.device.write(new Buffer([Command.LaunchEepromTransfer, EepromTransfer.WriteUserConfig]));
|
|
||||||
await this.waitUntilKeyboardBusy();
|
await this.waitUntilKeyboardBusy();
|
||||||
|
|
||||||
this.logService.info('[DeviceService] End write user configuration to eeprom');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async waitUntilKeyboardBusy(): Promise<void> {
|
private async waitUntilKeyboardBusy(): Promise<void> {
|
||||||
|
|||||||
@@ -6,6 +6,17 @@ import { Constants, LogService } from 'uhk-common';
|
|||||||
* HID API wrapper to support unified logging and async write
|
* HID API wrapper to support unified logging and async write
|
||||||
*/
|
*/
|
||||||
export class UhkHidDeviceService {
|
export class UhkHidDeviceService {
|
||||||
|
/**
|
||||||
|
* Convert the Buffer to number[]
|
||||||
|
* @param {Buffer} buffer
|
||||||
|
* @returns {number[]}
|
||||||
|
* @private
|
||||||
|
* @static
|
||||||
|
*/
|
||||||
|
public static convertBufferToIntArray(buffer: Buffer): number[] {
|
||||||
|
return Array.prototype.slice.call(buffer, 0);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the communication package that will send over USB and
|
* Create the communication package that will send over USB and
|
||||||
* - add usb report code as 1st byte
|
* - add usb report code as 1st byte
|
||||||
@@ -32,17 +43,6 @@ export class UhkHidDeviceService {
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the Buffer to number[]
|
|
||||||
* @param {Buffer} buffer
|
|
||||||
* @returns {number[]}
|
|
||||||
* @private
|
|
||||||
* @static
|
|
||||||
*/
|
|
||||||
private static convertBufferToIntArray(buffer: Buffer): number[] {
|
|
||||||
return Array.prototype.slice.call(buffer, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert buffer to space separated hexadecimal string
|
* Convert buffer to space separated hexadecimal string
|
||||||
* @param {Buffer} buffer
|
* @param {Buffer} buffer
|
||||||
@@ -109,7 +109,7 @@ export class UhkHidDeviceService {
|
|||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
const logString = UhkHidDeviceService.bufferToString(receivedData);
|
const logString = UhkHidDeviceService.bufferToString(receivedData);
|
||||||
this.logService.debug('[UhkHidDevice] Transfer UHK ===> Agent: ', logString);
|
this.logService.debug('[UhkHidDevice] USB[R]:', logString);
|
||||||
|
|
||||||
if (receivedData[0] !== 0) {
|
if (receivedData[0] !== 0) {
|
||||||
return reject(new Error(`Communications error with UHK. Response code: ${receivedData[0]}`));
|
return reject(new Error(`Communications error with UHK. Response code: ${receivedData[0]}`));
|
||||||
@@ -119,7 +119,7 @@ export class UhkHidDeviceService {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const sendData = UhkHidDeviceService.getTransferData(buffer);
|
const sendData = UhkHidDeviceService.getTransferData(buffer);
|
||||||
this.logService.debug('[UhkHidDevice] Transfer Agent ===> UHK: ', UhkHidDeviceService.bufferToString(sendData));
|
this.logService.debug('[UhkHidDevice] USB[W]:', UhkHidDeviceService.bufferToString(sendData));
|
||||||
device.write(sendData);
|
device.write(sendData);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ class Device {
|
|||||||
public static readonly deviceConnectionStateChanged = 'device-connection-state-changed';
|
public static readonly deviceConnectionStateChanged = 'device-connection-state-changed';
|
||||||
public static readonly saveUserConfiguration = 'device-save-user-configuration';
|
public static readonly saveUserConfiguration = 'device-save-user-configuration';
|
||||||
public static readonly saveUserConfigurationReply = 'device-save-user-configuration-reply';
|
public static readonly saveUserConfigurationReply = 'device-save-user-configuration-reply';
|
||||||
|
public static readonly loadUserConfiguration = 'device-load-user-configuration';
|
||||||
|
public static readonly loadUserConfigurationReply = 'device-load-user-configuration-reply';
|
||||||
}
|
}
|
||||||
|
|
||||||
export class IpcEvents {
|
export class IpcEvents {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
SaveConfigurationReplyAction,
|
SaveConfigurationReplyAction,
|
||||||
SetPrivilegeOnLinuxReplyAction
|
SetPrivilegeOnLinuxReplyAction
|
||||||
} from '../store/actions/device';
|
} from '../store/actions/device';
|
||||||
|
import { LoadUserConfigFromDeviceReplyAction } from '../store/actions/user-config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeviceRendererService {
|
export class DeviceRendererService {
|
||||||
@@ -28,6 +29,10 @@ export class DeviceRendererService {
|
|||||||
this.ipcRenderer.send(IpcEvents.device.saveUserConfiguration, JSON.stringify(buffer));
|
this.ipcRenderer.send(IpcEvents.device.saveUserConfiguration, JSON.stringify(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadUserConfiguration(): void {
|
||||||
|
this.ipcRenderer.send(IpcEvents.device.loadUserConfiguration);
|
||||||
|
}
|
||||||
|
|
||||||
private registerEvents(): void {
|
private registerEvents(): void {
|
||||||
this.ipcRenderer.on(IpcEvents.device.deviceConnectionStateChanged, (event: string, arg: boolean) => {
|
this.ipcRenderer.on(IpcEvents.device.deviceConnectionStateChanged, (event: string, arg: boolean) => {
|
||||||
this.dispachStoreAction(new ConnectionStateChangedAction(arg));
|
this.dispachStoreAction(new ConnectionStateChangedAction(arg));
|
||||||
@@ -40,6 +45,10 @@ export class DeviceRendererService {
|
|||||||
this.ipcRenderer.on(IpcEvents.device.saveUserConfigurationReply, (event: string, response: IpcResponse) => {
|
this.ipcRenderer.on(IpcEvents.device.saveUserConfigurationReply, (event: string, response: IpcResponse) => {
|
||||||
this.dispachStoreAction(new SaveConfigurationReplyAction(response));
|
this.dispachStoreAction(new SaveConfigurationReplyAction(response));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.ipcRenderer.on(IpcEvents.device.loadUserConfigurationReply, (event: string, response: string) => {
|
||||||
|
this.dispachStoreAction(new LoadUserConfigFromDeviceReplyAction(JSON.parse(response)));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private dispachStoreAction(action: Action): void {
|
private dispachStoreAction(action: Action): void {
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ const PREFIX = '[user-config] ';
|
|||||||
// tslint:disable-next-line:variable-name
|
// tslint:disable-next-line:variable-name
|
||||||
export const ActionTypes = {
|
export const ActionTypes = {
|
||||||
LOAD_USER_CONFIG: type(PREFIX + 'Load User Config'),
|
LOAD_USER_CONFIG: type(PREFIX + 'Load User Config'),
|
||||||
|
LOAD_USER_CONFIG_FROM_DEVICE: type(PREFIX + 'Load User Config from Device'),
|
||||||
|
LOAD_USER_CONFIG_FROM_DEVICE_REPLY: type(PREFIX + 'Load User Config from Device reply'),
|
||||||
LOAD_USER_CONFIG_SUCCESS: type(PREFIX + 'Load User Config Success'),
|
LOAD_USER_CONFIG_SUCCESS: type(PREFIX + 'Load User Config Success'),
|
||||||
SAVE_USER_CONFIG_SUCCESS: type(PREFIX + 'Save User Config Success')
|
SAVE_USER_CONFIG_SUCCESS: type(PREFIX + 'Save User Config Success')
|
||||||
};
|
};
|
||||||
@@ -16,6 +18,16 @@ export class LoadUserConfigAction implements Action {
|
|||||||
type = ActionTypes.LOAD_USER_CONFIG;
|
type = ActionTypes.LOAD_USER_CONFIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class LoadUserConfigFromDeviceAction implements Action {
|
||||||
|
type = ActionTypes.LOAD_USER_CONFIG_FROM_DEVICE;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class LoadUserConfigFromDeviceReplyAction implements Action {
|
||||||
|
type = ActionTypes.LOAD_USER_CONFIG_FROM_DEVICE_REPLY;
|
||||||
|
|
||||||
|
constructor(public payload: Array<number>) { }
|
||||||
|
}
|
||||||
|
|
||||||
export class LoadUserConfigSuccessAction implements Action {
|
export class LoadUserConfigSuccessAction implements Action {
|
||||||
type = ActionTypes.LOAD_USER_CONFIG_SUCCESS;
|
type = ActionTypes.LOAD_USER_CONFIG_SUCCESS;
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ export class ApplicationEffects {
|
|||||||
this.logService.info('Renderer appStart effect end');
|
this.logService.info('Renderer appStart effect end');
|
||||||
});
|
});
|
||||||
|
|
||||||
@Effect({ dispatch: false })
|
@Effect({dispatch: false})
|
||||||
showNotification$: Observable<Action> = this.actions$
|
showNotification$: Observable<Action> = this.actions$
|
||||||
.ofType(ActionTypes.APP_SHOW_NOTIFICATION)
|
.ofType(ActionTypes.APP_SHOW_NOTIFICATION)
|
||||||
.map(toPayload)
|
.map(toPayload)
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ import 'rxjs/add/operator/withLatestFrom';
|
|||||||
import { NotificationType, IpcResponse } from 'uhk-common';
|
import { NotificationType, IpcResponse } from 'uhk-common';
|
||||||
import {
|
import {
|
||||||
ActionTypes,
|
ActionTypes,
|
||||||
ConnectionStateChangedAction, HideSaveToKeyboardButton,
|
ConnectionStateChangedAction,
|
||||||
|
HideSaveToKeyboardButton,
|
||||||
PermissionStateChangedAction,
|
PermissionStateChangedAction,
|
||||||
SaveToKeyboardSuccessAction,
|
SaveToKeyboardSuccessAction,
|
||||||
SaveToKeyboardSuccessFailed
|
SaveToKeyboardSuccessFailed
|
||||||
@@ -25,10 +26,11 @@ import { ShowNotificationAction } from '../actions/app';
|
|||||||
import { AppState } from '../index';
|
import { AppState } from '../index';
|
||||||
import { UserConfiguration } from '../../config-serializer/config-items/user-configuration';
|
import { UserConfiguration } from '../../config-serializer/config-items/user-configuration';
|
||||||
import { UhkBuffer } from '../../config-serializer/uhk-buffer';
|
import { UhkBuffer } from '../../config-serializer/uhk-buffer';
|
||||||
|
import { LoadUserConfigFromDeviceAction } from '../actions/user-config';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class DeviceEffects {
|
export class DeviceEffects {
|
||||||
@Effect({dispatch: false})
|
@Effect()
|
||||||
deviceConnectionStateChange$: Observable<Action> = this.actions$
|
deviceConnectionStateChange$: Observable<Action> = this.actions$
|
||||||
.ofType(ActionTypes.CONNECTION_STATE_CHANGED)
|
.ofType(ActionTypes.CONNECTION_STATE_CHANGED)
|
||||||
.map(toPayload)
|
.map(toPayload)
|
||||||
@@ -39,6 +41,13 @@ export class DeviceEffects {
|
|||||||
else {
|
else {
|
||||||
this.router.navigate(['/detection']);
|
this.router.navigate(['/detection']);
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.switchMap((connected: boolean) => {
|
||||||
|
if (connected) {
|
||||||
|
return Observable.of(new LoadUserConfigFromDeviceAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
return Observable.empty();
|
||||||
});
|
});
|
||||||
|
|
||||||
@Effect({dispatch: false})
|
@Effect({dispatch: false})
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import 'rxjs/add/operator/withLatestFrom';
|
|||||||
import 'rxjs/add/operator/mergeMap';
|
import 'rxjs/add/operator/mergeMap';
|
||||||
import 'rxjs/add/observable/of';
|
import 'rxjs/add/observable/of';
|
||||||
|
|
||||||
import { NotificationType } from 'uhk-common';
|
import { LogService, NotificationType } from 'uhk-common';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
ActionTypes,
|
ActionTypes,
|
||||||
@@ -29,6 +29,8 @@ import { MacroActions } from '../actions/macro';
|
|||||||
import { UndoUserConfigData } from '../../models/undo-user-config-data';
|
import { UndoUserConfigData } from '../../models/undo-user-config-data';
|
||||||
import { ShowNotificationAction, DismissUndoNotificationAction } from '../actions/app';
|
import { ShowNotificationAction, DismissUndoNotificationAction } from '../actions/app';
|
||||||
import { ShowSaveToKeyboardButtonAction } from '../actions/device';
|
import { ShowSaveToKeyboardButtonAction } from '../actions/device';
|
||||||
|
import { DeviceRendererService } from '../../services/device-renderer.service';
|
||||||
|
import { UhkBuffer } from '../../config-serializer/uhk-buffer';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class UserConfigEffects {
|
export class UserConfigEffects {
|
||||||
@@ -86,10 +88,46 @@ export class UserConfigEffects {
|
|||||||
return [new LoadUserConfigSuccessAction(config), go(payload.path)];
|
return [new LoadUserConfigSuccessAction(config), go(payload.path)];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@Effect({dispatch: false}) loadUserConfigFromDevice$ = this.actions$
|
||||||
|
.ofType(ActionTypes.LOAD_USER_CONFIG_FROM_DEVICE)
|
||||||
|
.do(() => this.deviceRendererService.loadUserConfiguration());
|
||||||
|
|
||||||
|
@Effect() loadUserConfigFromDeviceReply$ = this.actions$
|
||||||
|
.ofType(ActionTypes.LOAD_USER_CONFIG_FROM_DEVICE_REPLY)
|
||||||
|
.map(action => action.payload)
|
||||||
|
.switchMap((data: Array<number>) => {
|
||||||
|
try {
|
||||||
|
let userConfig;
|
||||||
|
if (data.length > 0) {
|
||||||
|
const uhkBuffer = new UhkBuffer();
|
||||||
|
let hasNonZeroValue = false;
|
||||||
|
for (const num of data) {
|
||||||
|
if (num > 0) {
|
||||||
|
hasNonZeroValue = true;
|
||||||
|
}
|
||||||
|
uhkBuffer.writeUInt8(num);
|
||||||
|
}
|
||||||
|
uhkBuffer.offset = 0;
|
||||||
|
userConfig = new UserConfiguration();
|
||||||
|
userConfig.fromBinary(uhkBuffer);
|
||||||
|
|
||||||
|
if (hasNonZeroValue) {
|
||||||
|
return Observable.of(new LoadUserConfigSuccessAction(userConfig));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
this.logService.error('Eeprom parse error:', err);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Observable.empty();
|
||||||
|
});
|
||||||
|
|
||||||
constructor(private actions$: Actions,
|
constructor(private actions$: Actions,
|
||||||
private dataStorageRepository: DataStorageRepositoryService,
|
private dataStorageRepository: DataStorageRepositoryService,
|
||||||
private store: Store<AppState>,
|
private store: Store<AppState>,
|
||||||
private defaultUserConfigurationService: DefaultUserConfigurationService) {
|
private defaultUserConfigurationService: DefaultUserConfigurationService,
|
||||||
|
private deviceRendererService: DeviceRendererService,
|
||||||
|
private logService: LogService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private getUserConfiguration() {
|
private getUserConfiguration() {
|
||||||
|
|||||||
@@ -13,13 +13,15 @@ export interface State {
|
|||||||
navigationCountAfterNotification: number;
|
navigationCountAfterNotification: number;
|
||||||
prevUserConfig?: UserConfiguration;
|
prevUserConfig?: UserConfiguration;
|
||||||
runningInElectron: boolean;
|
runningInElectron: boolean;
|
||||||
|
userConfigLoading: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState: State = {
|
const initialState: State = {
|
||||||
started: false,
|
started: false,
|
||||||
showAddonMenu: false,
|
showAddonMenu: false,
|
||||||
navigationCountAfterNotification: 0,
|
navigationCountAfterNotification: 0,
|
||||||
runningInElectron: runInElectron()
|
runningInElectron: runInElectron(),
|
||||||
|
userConfigLoading: true
|
||||||
};
|
};
|
||||||
|
|
||||||
export function reducer(state = initialState, action: Action) {
|
export function reducer(state = initialState, action: Action) {
|
||||||
@@ -76,7 +78,16 @@ export function reducer(state = initialState, action: Action) {
|
|||||||
case UserConfigActionTypes.SAVE_USER_CONFIG_SUCCESS: {
|
case UserConfigActionTypes.SAVE_USER_CONFIG_SUCCESS: {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
prevUserConfig: action.payload
|
prevUserConfig: action.payload,
|
||||||
|
userConfigLoading: false
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
case UserConfigActionTypes.LOAD_USER_CONFIG_FROM_DEVICE:
|
||||||
|
case UserConfigActionTypes.LOAD_USER_CONFIG: {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
userConfigLoading: true
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,10 +4,27 @@ import * as util from 'util';
|
|||||||
|
|
||||||
import { LogService } from 'uhk-common';
|
import { LogService } from 'uhk-common';
|
||||||
|
|
||||||
|
const transferRegExp = /USB\[T]:/;
|
||||||
|
const writeRegExp = /USB\[W]:/;
|
||||||
|
const readRegExp = /USB\[R]: 00/;
|
||||||
|
const errorRegExp = /(?:(USB\[R]: ([^0]|0[^0])))/;
|
||||||
|
|
||||||
// https://github.com/megahertz/electron-log/issues/44
|
// https://github.com/megahertz/electron-log/issues/44
|
||||||
// console.debug starting with Chromium 58 this method is a no-op on Chromium browsers.
|
// console.debug starting with Chromium 58 this method is a no-op on Chromium browsers.
|
||||||
if (console.debug) {
|
if (console.debug) {
|
||||||
console.debug = console.log;
|
console.debug = (...args: any[]): void => {
|
||||||
|
if (writeRegExp.test(args[0])) {
|
||||||
|
console.log('%c' + args[0], 'color:blue');
|
||||||
|
} else if (readRegExp.test(args[0])) {
|
||||||
|
console.log('%c' + args[0], 'color:green');
|
||||||
|
} else if (errorRegExp.test(args[0])) {
|
||||||
|
console.log('%c' + args[0], 'color:red');
|
||||||
|
}else if (transferRegExp.test(args[0])) {
|
||||||
|
console.log('%c' + args[0], 'color:orange');
|
||||||
|
} else {
|
||||||
|
console.log(...args);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,7 +38,7 @@ if (console.debug) {
|
|||||||
*/
|
*/
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ElectronLogService implements LogService {
|
export class ElectronLogService implements LogService {
|
||||||
private static getErrorText(args: any) {
|
public static getErrorText(args: any) {
|
||||||
return util.inspect(args);
|
return util.inspect(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ while(offset < configSize) {
|
|||||||
const usbCommand = isHardwareConfig ? uhk.usbCommands.readHardwareConfig : uhk.usbCommands.readUserConfig;
|
const usbCommand = isHardwareConfig ? uhk.usbCommands.readHardwareConfig : uhk.usbCommands.readUserConfig;
|
||||||
chunkSizeToRead = Math.min(chunkSize, configSize - offset);
|
chunkSizeToRead = Math.min(chunkSize, configSize - offset);
|
||||||
buffer = Buffer.from([usbCommand, chunkSizeToRead, offset & 0xff, offset >> 8]);
|
buffer = Buffer.from([usbCommand, chunkSizeToRead, offset & 0xff, offset >> 8]);
|
||||||
|
console.log('write to keyboard', uhk.bufferToString(buffer));
|
||||||
device.write(uhk.getTransferData(buffer));
|
device.write(uhk.getTransferData(buffer));
|
||||||
buffer = Buffer.from(device.readSync());
|
buffer = Buffer.from(device.readSync());
|
||||||
console.log('read-config-chunk', uhk.bufferToString(buffer));
|
console.log('read-config-chunk', uhk.bufferToString(buffer));
|
||||||
|
|||||||
Reference in New Issue
Block a user