Show scanner name in the Bluetooth Advertisement Monitor (#23926)

This commit is contained in:
J. Nick Koston 2025-01-28 13:07:16 -10:00 committed by GitHub
parent cbdb7406ad
commit cc8869b9f9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 81 additions and 10 deletions

View File

@ -19,6 +19,15 @@ export interface BluetoothDeviceData extends DataTableRowData {
tx_power: number;
}
export interface BluetoothScannerDetails {
source: string;
connectable: boolean;
name: string;
adapter: string;
}
export type BluetoothScannersDetails = Record<string, BluetoothScannerDetails>;
interface BluetoothRemoveDeviceData {
address: string;
}
@ -29,6 +38,11 @@ interface BluetoothAdvertisementSubscriptionMessage {
remove?: BluetoothRemoveDeviceData[];
}
interface BluetoothScannersDetailsSubscriptionMessage {
add?: BluetoothScannerDetails[];
remove?: BluetoothScannerDetails[];
}
export interface BluetoothAllocationsData {
source: string;
slots: number;
@ -36,6 +50,43 @@ export interface BluetoothAllocationsData {
allocated: string[];
}
export const subscribeBluetoothScannersDetailsUpdates = (
conn: Connection,
store: Store<BluetoothScannersDetails>
): Promise<UnsubscribeFunc> =>
conn.subscribeMessage<BluetoothScannersDetailsSubscriptionMessage>(
(event) => {
const data = { ...(store.state || {}) };
if (event.add) {
for (const device_data of event.add) {
data[device_data.source] = device_data;
}
}
if (event.remove) {
for (const device_data of event.remove) {
delete data[device_data.source];
}
}
store.setState(data, true);
},
{
type: `bluetooth/subscribe_scanner_details`,
}
);
export const subscribeBluetoothScannersDetails = (
conn: Connection,
callbackFunction: (bluetoothScannersDetails: BluetoothScannersDetails) => void
) =>
createCollection<BluetoothScannersDetails>(
"_bluetoothScannerDetails",
() => Promise.resolve<BluetoothScannersDetails>({}), // empty hash as initial state
subscribeBluetoothScannersDetailsUpdates,
conn,
callbackFunction
);
const subscribeBluetoothAdvertisementsUpdates = (
conn: Connection,
store: Store<BluetoothDeviceData[]>

View File

@ -14,9 +14,14 @@ import "../../../../../components/ha-icon-button";
import "../../../../../layouts/hass-tabs-subpage-data-table";
import { haStyle } from "../../../../../resources/styles";
import type { HomeAssistant, Route } from "../../../../../types";
import type { BluetoothDeviceData } from "../../../../../data/bluetooth";
import { subscribeBluetoothAdvertisements } from "../../../../../data/bluetooth";
import type {
BluetoothDeviceData,
BluetoothScannersDetails,
} from "../../../../../data/bluetooth";
import {
subscribeBluetoothAdvertisements,
subscribeBluetoothScannersDetails,
} from "../../../../../data/bluetooth";
import { showBluetoothDeviceInfoDialog } from "./show-dialog-bluetooth-device-info";
@customElement("bluetooth-advertisement-monitor")
@ -31,25 +36,39 @@ export class BluetoothAdvertisementMonitorPanel extends LitElement {
@state() private _data: BluetoothDeviceData[] = [];
private _unsub?: UnsubscribeFunc;
@state() private _scanners: BluetoothScannersDetails = {};
private _unsub_advertisements?: UnsubscribeFunc;
private _unsub_scanners?: UnsubscribeFunc;
public connectedCallback(): void {
super.connectedCallback();
if (this.hass) {
this._unsub = subscribeBluetoothAdvertisements(
this._unsub_advertisements = subscribeBluetoothAdvertisements(
this.hass.connection,
(data) => {
this._data = data;
}
);
this._unsub_scanners = subscribeBluetoothScannersDetails(
this.hass.connection,
(scanners) => {
this._scanners = scanners;
}
);
}
}
public disconnectedCallback() {
super.disconnectedCallback();
if (this._unsub) {
this._unsub();
this._unsub = undefined;
if (this._unsub_advertisements) {
this._unsub_advertisements();
this._unsub_advertisements = undefined;
}
if (this._unsub_scanners) {
this._unsub_scanners();
this._unsub_scanners = undefined;
}
}
@ -88,10 +107,11 @@ export class BluetoothAdvertisementMonitorPanel extends LitElement {
}
);
private _dataWithIds = memoizeOne((data) =>
private _dataWithNamedSourceAndIds = memoizeOne((data) =>
data.map((row) => ({
...row,
id: row.address,
source: this._scanners[row.source]?.name || row.source,
}))
);
@ -102,7 +122,7 @@ export class BluetoothAdvertisementMonitorPanel extends LitElement {
.narrow=${this.narrow}
.route=${this.route}
.columns=${this._columns(this.hass.localize)}
.data=${this._dataWithIds(this._data)}
.data=${this._dataWithNamedSourceAndIds(this._data)}
@row-click=${this._handleRowClicked}
clickable
></hass-tabs-subpage-data-table>