diff --git a/packages/uhk-common/src/models/device-connection-state.ts b/packages/uhk-common/src/models/device-connection-state.ts index 3310dfed..a366ef56 100644 --- a/packages/uhk-common/src/models/device-connection-state.ts +++ b/packages/uhk-common/src/models/device-connection-state.ts @@ -6,6 +6,8 @@ import { UhkDeviceProduct } from './uhk-products.js'; export interface DeviceConnectionState { bleAddress?: string; + // UHK80 connected via bluetooth + bleDeviceConnected: boolean; isPairedWithDongle?: boolean; connectedDevice?: UhkDeviceProduct; dongle: Dongle; @@ -13,6 +15,7 @@ export interface DeviceConnectionState { hasPermission: boolean; bootloaderActive: boolean; isMacroStatusDirty: boolean; + leftHalfDetected: boolean; /** * True if more than 1 UHK device connected. */ diff --git a/packages/uhk-common/src/models/uhk-products.ts b/packages/uhk-common/src/models/uhk-products.ts index a7dbbaf3..5c093bec 100644 --- a/packages/uhk-common/src/models/uhk-products.ts +++ b/packages/uhk-common/src/models/uhk-products.ts @@ -6,6 +6,7 @@ import { UHK_MODULE_IDS, UHK_MODULE_IDS_TYPE } from './uhk-module-ids.js'; export const UHK_VENDOR_ID_OLD = 0x1D50; // decimal 7504 export const UHK_VENDOR_ID = 0x37A8; // decimal 14248 +export const UHK_BLE_MIN_PRODUCT_iD = 0x8000; // decimal 32768 export interface VidPidPair { vid: number; diff --git a/packages/uhk-usb/src/uhk-hid-device.ts b/packages/uhk-usb/src/uhk-hid-device.ts index 8b9c3ef7..1c99ad02 100644 --- a/packages/uhk-usb/src/uhk-hid-device.ts +++ b/packages/uhk-usb/src/uhk-hid-device.ts @@ -21,9 +21,11 @@ import { RightSlotModules, UdevRulesInfo, UhkBuffer, + UHK_BLE_MIN_PRODUCT_iD, UHK_DONGLE, UHK_80_DEVICE, UHK_80_DEVICE_LEFT, + UHK_VENDOR_ID, } from 'uhk-common'; import { DevicePropertyIds, @@ -316,6 +318,7 @@ export class UhkHidDevice { const devs = await this.getUhkDevices(); const result: DeviceConnectionState = { bootloaderActive: false, + bleDeviceConnected: false, communicationInterfaceAvailable: false, dongle: { bootloaderActive: false, @@ -332,6 +335,7 @@ export class UhkHidDevice { }, hardwareModules: {}, isMacroStatusDirty: false, + leftHalfDetected: false, multiDevice: await getNumberOfConnectedDevices(this.options) > 1, udevRulesInfo: await this.getUdevInfoAsync(), }; @@ -373,9 +377,16 @@ export class UhkHidDevice { if (isUhkCommunicationInterface(dev)) { result.communicationInterfaceAvailable = true; - } else if (isBootloader(dev)) { + } + else if (isBootloader(dev)) { result.bootloaderActive = true; } + else if (dev.vendorId === UHK_VENDOR_ID && dev.productId >= UHK_BLE_MIN_PRODUCT_iD) { + result.bleDeviceConnected = true; + } + else if (UHK_80_DEVICE_LEFT.keyboard.some(vidPid => dev.vendorId === vidPid.vid && dev.productId === vidPid.pid)) { + result.leftHalfDetected = true; + } } if (isDongleCommunicationDevice(dev)) { diff --git a/packages/uhk-web/src/app/components/missing-device/missing-device.component.html b/packages/uhk-web/src/app/components/missing-device/missing-device.component.html index bd23401f..4f7609af 100644 --- a/packages/uhk-web/src/app/components/missing-device/missing-device.component.html +++ b/packages/uhk-web/src/app/components/missing-device/missing-device.component.html @@ -1,3 +1,4 @@ diff --git a/packages/uhk-web/src/app/components/uhk-message/uhk-message.component.html b/packages/uhk-web/src/app/components/uhk-message/uhk-message.component.html index 2120ad18..3fe18cb5 100644 --- a/packages/uhk-web/src/app/components/uhk-message/uhk-message.component.html +++ b/packages/uhk-web/src/app/components/uhk-message/uhk-message.component.html @@ -7,5 +7,6 @@

{{ header }}

{{ subtitle }}

{{ subtitle }}
+

{{ description }}

diff --git a/packages/uhk-web/src/app/components/uhk-message/uhk-message.component.ts b/packages/uhk-web/src/app/components/uhk-message/uhk-message.component.ts index 42757d7a..a81dddb3 100644 --- a/packages/uhk-web/src/app/components/uhk-message/uhk-message.component.ts +++ b/packages/uhk-web/src/app/components/uhk-message/uhk-message.component.ts @@ -7,6 +7,7 @@ import { Component, Input, ChangeDetectionStrategy } from '@angular/core'; changeDetection: ChangeDetectionStrategy.OnPush }) export class UhkMessageComponent { + @Input() description: string; @Input() header: string; @Input() subtitle: string; @Input() rotateLogo = false; diff --git a/packages/uhk-web/src/app/models/missing-device-state.ts b/packages/uhk-web/src/app/models/missing-device-state.ts index fd6e436a..7efa0b83 100644 --- a/packages/uhk-web/src/app/models/missing-device-state.ts +++ b/packages/uhk-web/src/app/models/missing-device-state.ts @@ -1,4 +1,5 @@ export interface MissingDeviceState { header: string; subtitle: string; + description?: string; } diff --git a/packages/uhk-web/src/app/store/reducers/device.ts b/packages/uhk-web/src/app/store/reducers/device.ts index 726be43f..28f1c952 100644 --- a/packages/uhk-web/src/app/store/reducers/device.ts +++ b/packages/uhk-web/src/app/store/reducers/device.ts @@ -27,6 +27,7 @@ import { getSaveToKeyboardButtonState, initProgressButtonState, ProgressButtonSt export interface State { bleAddress?: string; + bleDeviceConnected: boolean; dongle?: Dongle; isKeyboardLayoutChanging: boolean; isPairedWithDongle?: boolean; @@ -36,6 +37,7 @@ export interface State { deviceConnectionStateLoaded: boolean; keyboardHalvesAlwaysJoined: boolean; leftHalfBootloaderActive: boolean; + leftHalfDetected: boolean; multiDevice: boolean; communicationInterfaceAvailable: boolean; saveToKeyboard: ProgressButtonState; @@ -54,12 +56,14 @@ export interface State { } export const initialState: State = { + bleDeviceConnected: false, isKeyboardLayoutChanging: false, hasPermission: true, bootloaderActive: false, deviceConnectionStateLoaded: false, keyboardHalvesAlwaysJoined: false, leftHalfBootloaderActive: false, + leftHalfDetected: false, multiDevice: false, communicationInterfaceAvailable: true, saveToKeyboard: initProgressButtonState, @@ -124,15 +128,17 @@ export function reducer(state = initialState, action: Action): State { return { ...state, bleAddress: data.bleAddress, + bleDeviceConnected: data.bleDeviceConnected, dongle: data.dongle, isPairedWithDongle: data.isPairedWithDongle, connectedDevice: data.connectedDevice, deviceConnectionStateLoaded: true, - leftHalfBootloaderActive: data.leftHalfBootloaderActive, hasPermission: data.hasPermission, communicationInterfaceAvailable: data.communicationInterfaceAvailable, bootloaderActive: data.bootloaderActive, halvesInfo: data.halvesInfo, + leftHalfBootloaderActive: data.leftHalfBootloaderActive, + leftHalfDetected: data.leftHalfDetected, modules: data.hardwareModules, multiDevice: data.multiDevice, udevRuleInfo: data.udevRulesInfo, @@ -292,6 +298,29 @@ export const getMissingDeviceState = (state: State): MissingDeviceState => { }; } + if (!state.connectedDevice) { + if (state.bleDeviceConnected) { + return { + header: 'UHK 80 connected via BLE', + subtitle: 'Disconnect BLE and connect your UHK via its right USB port!' + }; + } + + if (state.dongle?.serialNumber) { + return { + header: 'Dongle connected', + subtitle: 'Please connect the UHK right half via USB cable!' + }; + } + + if (state.leftHalfDetected) { + return { + header: 'UHK 80 left half connected', + subtitle: 'Please connect the right half instead!' + }; + } + } + if (state.connectedDevice && !state.communicationInterfaceAvailable) { return { header: 'Cannot find your UHK', @@ -300,6 +329,7 @@ export const getMissingDeviceState = (state: State): MissingDeviceState => { } return { + description: 'If you have a UHK 80, connect its right half via USB, and ensure it\'s not connected to a dongle or BLE host!', header: 'Cannot find your UHK', subtitle: 'Please plug it in!' };