feat(config): Read / write hardware configuration area (#423)
* add write-hca.js * refactor: Move config serializer into the uhk-common package * refactor: Move getTransferBuffers into the uhk-usb package * refactor: delete obsoleted classes * build: add uhk-usb build command * refactor: move eeprom transfer to uhk-usb package * fix: Fix write-hca.js * feat: load hardware config from the device and * style: fix ts lint errors * build: fix rxjs dependency resolve * test: Add jasmine unit test framework to the tet serializer * fix(user-config): A "type": "basic", properties to the "keystroke" action types * feat(usb): set chmod+x on write-hca.js * feat(usb): Create USB logger * style: Fix type * build: Add chalk to dependencies. Chalk will colorize the output
This commit is contained in:
committed by
László Monda
parent
1122784bdb
commit
9294bede50
@@ -1,8 +1,7 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
import { type } from 'uhk-common';
|
||||
import { Notification, CommandLineArgs } from 'uhk-common';
|
||||
import { AppStartInfo } from '../../../../../uhk-common/src/models/app-start-info';
|
||||
import { AppStartInfo, HardwareConfiguration, Notification } from 'uhk-common';
|
||||
|
||||
const PREFIX = '[app] ';
|
||||
|
||||
@@ -15,7 +14,8 @@ export const ActionTypes = {
|
||||
APP_PROCESS_START_INFO: type(PREFIX + 'process start info'),
|
||||
UNDO_LAST: type(PREFIX + 'undo last action'),
|
||||
UNDO_LAST_SUCCESS: type(PREFIX + 'undo last action success'),
|
||||
DISMISS_UNDO_NOTIFICATION: type(PREFIX + 'dismiss notification action')
|
||||
DISMISS_UNDO_NOTIFICATION: type(PREFIX + 'dismiss notification action'),
|
||||
LOAD_HARDWARE_CONFIGURATION_SUCCESS: type(PREFIX + 'load hardware configuration success')
|
||||
};
|
||||
|
||||
export class AppBootsrappedAction implements Action {
|
||||
@@ -58,6 +58,12 @@ export class DismissUndoNotificationAction implements Action {
|
||||
type = ActionTypes.DISMISS_UNDO_NOTIFICATION;
|
||||
}
|
||||
|
||||
export class LoadHardwareConfigurationSuccessAction implements Action {
|
||||
type = ActionTypes.LOAD_HARDWARE_CONFIGURATION_SUCCESS;
|
||||
|
||||
constructor(public payload: HardwareConfiguration) {}
|
||||
}
|
||||
|
||||
export type Actions
|
||||
= AppStartedAction
|
||||
| AppBootsrappedAction
|
||||
@@ -66,4 +72,6 @@ export type Actions
|
||||
| ProcessAppStartInfoAction
|
||||
| UndoLastAction
|
||||
| UndoLastSuccessAction
|
||||
| DismissUndoNotificationAction;
|
||||
| DismissUndoNotificationAction
|
||||
| LoadHardwareConfigurationSuccessAction
|
||||
;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
import { KeyAction } from '../../config-serializer/config-items/key-action';
|
||||
import { Keymap } from '../../config-serializer/config-items/keymap';
|
||||
import { Macro } from '../../config-serializer/config-items/macro';
|
||||
import { KeyAction, Keymap, Macro } from 'uhk-common';
|
||||
|
||||
export namespace KeymapActions {
|
||||
export const PREFIX = '[Keymap] ';
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
import { Macro } from '../../config-serializer/config-items/macro';
|
||||
import { MacroAction } from '../../config-serializer/config-items/macro-action';
|
||||
import { Macro, MacroAction } from 'uhk-common';
|
||||
|
||||
export namespace MacroActions {
|
||||
export const PREFIX = '[Macro] ';
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
import { type } from 'uhk-common';
|
||||
import { UserConfiguration } from '../../config-serializer/config-items/user-configuration';
|
||||
import { type, UserConfiguration, ConfigurationReply } from 'uhk-common';
|
||||
|
||||
const PREFIX = '[user-config] ';
|
||||
|
||||
// tslint:disable-next-line:variable-name
|
||||
export const ActionTypes = {
|
||||
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_CONFIG_FROM_DEVICE: type(PREFIX + 'Load User Config from Device'),
|
||||
LOAD_CONFIG_FROM_DEVICE_REPLY: type(PREFIX + 'Load User Config from Device reply'),
|
||||
LOAD_USER_CONFIG_SUCCESS: type(PREFIX + 'Load User Config Success'),
|
||||
SAVE_USER_CONFIG_SUCCESS: type(PREFIX + 'Save User Config Success')
|
||||
};
|
||||
@@ -18,14 +16,14 @@ export class LoadUserConfigAction implements Action {
|
||||
type = ActionTypes.LOAD_USER_CONFIG;
|
||||
}
|
||||
|
||||
export class LoadUserConfigFromDeviceAction implements Action {
|
||||
type = ActionTypes.LOAD_USER_CONFIG_FROM_DEVICE;
|
||||
export class LoadConfigFromDeviceAction implements Action {
|
||||
type = ActionTypes.LOAD_CONFIG_FROM_DEVICE;
|
||||
}
|
||||
|
||||
export class LoadUserConfigFromDeviceReplyAction implements Action {
|
||||
type = ActionTypes.LOAD_USER_CONFIG_FROM_DEVICE_REPLY;
|
||||
export class LoadConfigFromDeviceReplyAction implements Action {
|
||||
type = ActionTypes.LOAD_CONFIG_FROM_DEVICE_REPLY;
|
||||
|
||||
constructor(public payload: Array<number>) { }
|
||||
constructor(public payload: ConfigurationReply) { }
|
||||
}
|
||||
|
||||
export class LoadUserConfigSuccessAction implements Action {
|
||||
@@ -43,4 +41,7 @@ export class SaveUserConfigSuccessAction implements Action {
|
||||
export type Actions
|
||||
= LoadUserConfigAction
|
||||
| LoadUserConfigSuccessAction
|
||||
| SaveUserConfigSuccessAction;
|
||||
| SaveUserConfigSuccessAction
|
||||
| LoadConfigFromDeviceAction
|
||||
| LoadConfigFromDeviceReplyAction
|
||||
;
|
||||
|
||||
@@ -12,7 +12,7 @@ import 'rxjs/add/operator/map';
|
||||
import 'rxjs/add/operator/mergeMap';
|
||||
import 'rxjs/add/operator/withLatestFrom';
|
||||
|
||||
import { NotificationType, IpcResponse } from 'uhk-common';
|
||||
import { NotificationType, IpcResponse, UhkBuffer, UserConfiguration } from 'uhk-common';
|
||||
import {
|
||||
ActionTypes,
|
||||
ConnectionStateChangedAction,
|
||||
@@ -24,9 +24,7 @@ import {
|
||||
import { DeviceRendererService } from '../../services/device-renderer.service';
|
||||
import { ShowNotificationAction } from '../actions/app';
|
||||
import { AppState } from '../index';
|
||||
import { UserConfiguration } from '../../config-serializer/config-items/user-configuration';
|
||||
import { UhkBuffer } from '../../config-serializer/uhk-buffer';
|
||||
import { LoadUserConfigFromDeviceAction } from '../actions/user-config';
|
||||
import { LoadConfigFromDeviceAction } from '../actions/user-config';
|
||||
|
||||
@Injectable()
|
||||
export class DeviceEffects {
|
||||
@@ -44,7 +42,7 @@ export class DeviceEffects {
|
||||
})
|
||||
.switchMap((connected: boolean) => {
|
||||
if (connected) {
|
||||
return Observable.of(new LoadUserConfigFromDeviceAction());
|
||||
return Observable.of(new LoadConfigFromDeviceAction());
|
||||
}
|
||||
|
||||
return Observable.empty();
|
||||
|
||||
@@ -12,11 +12,10 @@ import 'rxjs/add/operator/switchMap';
|
||||
import 'rxjs/add/operator/withLatestFrom';
|
||||
import 'rxjs/add/observable/of';
|
||||
|
||||
import { Keymap } from 'uhk-common';
|
||||
import { KeymapActions } from '../actions';
|
||||
import { AppState } from '../index';
|
||||
|
||||
import { Keymap } from '../../config-serializer/config-items/keymap';
|
||||
|
||||
@Injectable()
|
||||
export class KeymapEffects {
|
||||
|
||||
|
||||
@@ -11,7 +11,14 @@ import 'rxjs/add/operator/withLatestFrom';
|
||||
import 'rxjs/add/operator/mergeMap';
|
||||
import 'rxjs/add/observable/of';
|
||||
|
||||
import { LogService, NotificationType } from 'uhk-common';
|
||||
import {
|
||||
ConfigurationReply,
|
||||
HardwareConfiguration,
|
||||
LogService,
|
||||
NotificationType,
|
||||
UhkBuffer,
|
||||
UserConfiguration
|
||||
} from 'uhk-common';
|
||||
|
||||
import {
|
||||
ActionTypes,
|
||||
@@ -20,21 +27,42 @@ import {
|
||||
SaveUserConfigSuccessAction
|
||||
} from '../actions/user-config';
|
||||
|
||||
import { UserConfiguration } from '../../config-serializer/config-items/user-configuration';
|
||||
import { DataStorageRepositoryService } from '../../services/datastorage-repository.service';
|
||||
import { DefaultUserConfigurationService } from '../../services/default-user-configuration.service';
|
||||
import { AppState, getPrevUserConfiguration, getUserConfiguration } from '../index';
|
||||
import { KeymapActions } from '../actions/keymap';
|
||||
import { MacroActions } from '../actions/macro';
|
||||
import { UndoUserConfigData } from '../../models/undo-user-config-data';
|
||||
import { ShowNotificationAction, DismissUndoNotificationAction } from '../actions/app';
|
||||
import { ShowNotificationAction, DismissUndoNotificationAction, LoadHardwareConfigurationSuccessAction } from '../actions/app';
|
||||
import { ShowSaveToKeyboardButtonAction } from '../actions/device';
|
||||
import { DeviceRendererService } from '../../services/device-renderer.service';
|
||||
import { UhkBuffer } from '../../config-serializer/uhk-buffer';
|
||||
|
||||
@Injectable()
|
||||
export class UserConfigEffects {
|
||||
|
||||
private static getUserConfigFromDeviceResponse(json: string): UserConfiguration {
|
||||
const data = JSON.parse(json);
|
||||
const userConfig = new UserConfiguration();
|
||||
userConfig.fromBinary(UhkBuffer.fromArray(data));
|
||||
|
||||
if (userConfig.dataModelVersion > 0) {
|
||||
return userConfig;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static getHardwareConfigFromDeviceResponse(json: string): HardwareConfiguration {
|
||||
const data = JSON.parse(json);
|
||||
const hardwareConfig = new HardwareConfiguration();
|
||||
hardwareConfig.fromBinary(UhkBuffer.fromArray(data));
|
||||
|
||||
if (hardwareConfig.uuid > 0) {
|
||||
return hardwareConfig;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Effect() loadUserConfig$: Observable<Action> = this.actions$
|
||||
.ofType(ActionTypes.LOAD_USER_CONFIG)
|
||||
.startWith(new LoadUserConfigAction())
|
||||
@@ -88,38 +116,36 @@ export class UserConfigEffects {
|
||||
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({dispatch: false}) loadConfigFromDevice$ = this.actions$
|
||||
.ofType(ActionTypes.LOAD_CONFIG_FROM_DEVICE)
|
||||
.do(() => this.deviceRendererService.loadConfigurationFromKeyboard());
|
||||
|
||||
@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);
|
||||
@Effect() loadConfigFromDeviceReply$ = this.actions$
|
||||
.ofType(ActionTypes.LOAD_CONFIG_FROM_DEVICE_REPLY)
|
||||
.map(toPayload)
|
||||
.mergeMap((data: ConfigurationReply): any => {
|
||||
if (!data.success) {
|
||||
return [new ShowNotificationAction({
|
||||
type: NotificationType.Error,
|
||||
message: data.error
|
||||
})];
|
||||
}
|
||||
|
||||
return Observable.empty();
|
||||
try {
|
||||
const userConfig = UserConfigEffects.getUserConfigFromDeviceResponse(data.userConfiguration);
|
||||
const hardwareConfig = UserConfigEffects.getHardwareConfigFromDeviceResponse(data.hardwareConfiguration);
|
||||
|
||||
return [
|
||||
new LoadUserConfigSuccessAction(userConfig),
|
||||
new LoadHardwareConfigurationSuccessAction(hardwareConfig)
|
||||
];
|
||||
} catch (err) {
|
||||
this.logService.error('Eeprom parse error:', err);
|
||||
return [new ShowNotificationAction({
|
||||
type: NotificationType.Error,
|
||||
message: err.message
|
||||
})];
|
||||
}
|
||||
});
|
||||
|
||||
constructor(private actions$: Actions,
|
||||
@@ -147,4 +173,5 @@ export class UserConfigEffects {
|
||||
return config;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,11 +3,10 @@ import { compose } from '@ngrx/core/compose';
|
||||
import { ActionReducer, combineReducers } from '@ngrx/store';
|
||||
import { RouterState, routerReducer } from '@ngrx/router-store';
|
||||
import { storeFreeze } from 'ngrx-store-freeze';
|
||||
import { Keymap, UserConfiguration } from 'uhk-common';
|
||||
|
||||
import userConfigurationReducer from './reducers/user-configuration';
|
||||
import presetReducer from './reducers/preset';
|
||||
import { Keymap } from '../config-serializer/config-items/keymap';
|
||||
import { UserConfiguration } from '../config-serializer/config-items/user-configuration';
|
||||
import * as fromAppUpdate from './reducers/app-update.reducer';
|
||||
import * as autoUpdateSettings from './reducers/auto-update-settings';
|
||||
import * as fromApp from './reducers/app.reducer';
|
||||
@@ -53,6 +52,8 @@ export const showAddonMenu = createSelector(appState, fromApp.showAddonMenu);
|
||||
export const getUndoableNotification = createSelector(appState, fromApp.getUndoableNotification);
|
||||
export const getPrevUserConfiguration = createSelector(appState, fromApp.getPrevUserConfiguration);
|
||||
export const runningInElectron = createSelector(appState, fromApp.runningInElectron);
|
||||
export const getHardwareConfiguration = createSelector(appState, fromApp.getHardwareConfiguration);
|
||||
export const getKeyboardLayout = createSelector(appState, fromApp.getKeyboardLayout);
|
||||
|
||||
export const appUpdateState = (state: AppState) => state.appUpdate;
|
||||
export const getShowAppUpdateAvailable = createSelector(appUpdateState, fromAppUpdate.getShowAppUpdateAvailable);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { routerActions } from '@ngrx/router-store';
|
||||
import { Action } from '@ngrx/store';
|
||||
|
||||
import { runInElectron, Notification, NotificationType } from 'uhk-common';
|
||||
import { HardwareConfiguration, runInElectron, Notification, NotificationType, UserConfiguration } from 'uhk-common';
|
||||
import { ActionTypes, ShowNotificationAction } from '../actions/app';
|
||||
import { ActionTypes as UserConfigActionTypes } from '../actions/user-config';
|
||||
import { UserConfiguration } from '../../config-serializer/config-items/user-configuration';
|
||||
import { KeyboardLayout } from '../../keyboard/keyboard-layout.enum';
|
||||
|
||||
export interface State {
|
||||
started: boolean;
|
||||
@@ -13,7 +13,8 @@ export interface State {
|
||||
navigationCountAfterNotification: number;
|
||||
prevUserConfig?: UserConfiguration;
|
||||
runningInElectron: boolean;
|
||||
userConfigLoading: boolean;
|
||||
configLoading: boolean;
|
||||
hardwareConfig?: HardwareConfiguration;
|
||||
}
|
||||
|
||||
const initialState: State = {
|
||||
@@ -21,7 +22,7 @@ const initialState: State = {
|
||||
showAddonMenu: false,
|
||||
navigationCountAfterNotification: 0,
|
||||
runningInElectron: runInElectron(),
|
||||
userConfigLoading: true
|
||||
configLoading: true
|
||||
};
|
||||
|
||||
export function reducer(state = initialState, action: Action) {
|
||||
@@ -56,7 +57,7 @@ export function reducer(state = initialState, action: Action) {
|
||||
// When deleted a keymap or macro the app automaticaly navigate to other keymap, or macro, so
|
||||
// so we have to count the navigations and when reach the 2nd then remove the dialog.
|
||||
case routerActions.UPDATE_LOCATION: {
|
||||
const newState = { ...state };
|
||||
const newState = {...state};
|
||||
newState.navigationCountAfterNotification++;
|
||||
|
||||
if (newState.navigationCountAfterNotification > 1) {
|
||||
@@ -79,18 +80,24 @@ export function reducer(state = initialState, action: Action) {
|
||||
return {
|
||||
...state,
|
||||
prevUserConfig: action.payload,
|
||||
userConfigLoading: false
|
||||
configLoading: false
|
||||
};
|
||||
}
|
||||
|
||||
case UserConfigActionTypes.LOAD_USER_CONFIG_FROM_DEVICE:
|
||||
case UserConfigActionTypes.LOAD_CONFIG_FROM_DEVICE:
|
||||
case UserConfigActionTypes.LOAD_USER_CONFIG: {
|
||||
return {
|
||||
...state,
|
||||
userConfigLoading: true
|
||||
configLoading: true
|
||||
};
|
||||
}
|
||||
|
||||
case ActionTypes.LOAD_HARDWARE_CONFIGURATION_SUCCESS:
|
||||
return {
|
||||
...state,
|
||||
hardwareConfig: action.payload
|
||||
};
|
||||
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
@@ -100,3 +107,11 @@ export const showAddonMenu = (state: State) => state.showAddonMenu;
|
||||
export const getUndoableNotification = (state: State) => state.undoableNotification;
|
||||
export const getPrevUserConfiguration = (state: State) => state.prevUserConfig;
|
||||
export const runningInElectron = (state: State) => state.runningInElectron;
|
||||
export const getHardwareConfiguration = (state: State) => state.hardwareConfig;
|
||||
export const getKeyboardLayout = (state: State): KeyboardLayout => {
|
||||
if (state.hardwareConfig && state.hardwareConfig.isIso) {
|
||||
return KeyboardLayout.ISO;
|
||||
}
|
||||
|
||||
return KeyboardLayout.ANSI;
|
||||
};
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Action } from '@ngrx/store';
|
||||
import { Keymap } from 'uhk-common';
|
||||
|
||||
import { Keymap } from '../../config-serializer/config-items/keymap';
|
||||
import { KeymapActions } from '../actions/keymap';
|
||||
|
||||
const initialState: Keymap[] = [];
|
||||
|
||||
@@ -5,12 +5,7 @@ import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/observable/of';
|
||||
import 'rxjs/add/operator/map';
|
||||
|
||||
import { Helper as KeyActionHelper } from '../../config-serializer/config-items/key-action';
|
||||
import { Keymap } from '../../config-serializer/config-items/keymap';
|
||||
import { Macro } from '../../config-serializer/config-items/macro';
|
||||
import { UserConfiguration } from '../../config-serializer/config-items/user-configuration';
|
||||
import { Layer } from '../../config-serializer/config-items/layer';
|
||||
import { Module } from '../../config-serializer/config-items/module';
|
||||
import { Keymap, KeyActionHelper, Layer, Macro, Module, UserConfiguration } from 'uhk-common';
|
||||
import { KeymapActions, MacroActions } from '../actions';
|
||||
import { AppState } from '../index';
|
||||
import { ActionTypes } from '../actions/user-config';
|
||||
|
||||
Reference in New Issue
Block a user