@@ -293,6 +329,9 @@ export class MainApp extends HTMLElement {
this.bauFound = this.bauFound.bind(this);
this.requestBC = this.requestBC.bind(this);
this.bcReceived = this.bcReceived.bind(this);
+ this.sirkFound = this.sirkFound.bind(this);
+ this.pairCSIS = this.pairCSIS.bind(this);
+ this.closeCSISPair = this.closeCSISPair.bind(this);
}
initializeModels() {
@@ -366,6 +405,12 @@ export class MainApp extends HTMLElement {
const button = this.shadowRoot?.querySelector('#connect');
button?.addEventListener('click', WebUSBDeviceService.scan);
+ const pairCSISButton = this.shadowRoot?.querySelector('#paircsisbutton');
+ pairCSISButton?.addEventListener('click', this.pairCSIS);
+
+ const cancelCSISButton = this.shadowRoot?.querySelector('#cancelcsisbutton');
+ cancelCSISButton?.addEventListener('click', this.closeCSISPair);
+
const splashbox = this.shadowRoot?.querySelector('#splashbox');
WebUSBDeviceService.addEventListener('connected', () => { splashbox?.classList.add('hidden') });
WebUSBDeviceService.addEventListener('disconnected', () => { splashbox?.classList.remove('hidden') });
@@ -374,7 +419,6 @@ export class MainApp extends HTMLElement {
this.#stopScanButton = this.shadowRoot?.querySelector('#stop_scan');
this.#stopScanButton.addEventListener('click', this.sendStopScan);
- this.#stopScanButton.addEventListener('click', this.sendStopScan);
// this.#stopScanButton.disabled = true;
this.#scanSinkButton = this.shadowRoot?.querySelector('#sink_scan');
@@ -398,6 +442,8 @@ export class MainApp extends HTMLElement {
this.#model.addEventListener('scan-stopped', this.scanStopped);
this.#model.addEventListener('sink-scan-started', this.sinkScanStarted);
this.#model.addEventListener('source-scan-started', this.sourceScanStarted);
+ this.#model.addEventListener('sirk-found', this.sirkFound);
+ this.#model.addEventListener('csis-pairing-complete', this.closeCSISPair);
const activityLog = this.shadowRoot?.querySelector('#activity');
if (this.#pageState.get('log') === 'y') {
@@ -502,6 +548,51 @@ export class MainApp extends HTMLElement {
qrscannerbox?.classList.add('hidden');
}
+ sirkFound(evt) {
+ console.log("SIRK found");
+
+ const sirk = evt.detail.sirk;
+ const set_size = evt.detail.set_size;
+
+ if (window["pairedSetMembers"] > 0) {
+ return;
+ }
+
+ window["sirk"] = sirk;
+ window["set_size"] = set_size;
+
+ const csispairbox = this.shadowRoot?.querySelector('#csispairbox');
+
+ csispairbox?.classList.remove('hidden');
+ }
+
+ closeCSISPair() {
+ console.log("Close CSIS pairing query");
+
+ const csispairbox = this.shadowRoot?.querySelector('#csispairbox');
+
+ window["setPairingInProgress"] = 0;
+ csispairbox?.classList.add('hidden');
+ }
+
+ pairCSIS() {
+ console.log("Pairing coordinated set");
+
+ const csispairbox = this.shadowRoot?.querySelector('#csispairbox');
+
+ const sirk = window["sirk"];
+ const set_size = window["set_size"];
+ window["setPairingInProgress"] = 1;
+ window["pairedSetMembers"] = 1;
+
+ // Pair all already-found members first
+ this.#model.handlePrefoundSetMembers(set_size, sirk);
+
+ setTimeout(() => {
+ this.#model.findSetMembers(set_size, sirk);
+ }, 500);
+ }
+
bauFound(evt) {
const {decoded, raw} = evt.detail;
diff --git a/web/models/assistant-model.js b/web/models/assistant-model.js
index 8de64e6..04abc17 100644
--- a/web/models/assistant-model.js
+++ b/web/models/assistant-model.js
@@ -376,6 +376,18 @@ class AssistantModel extends EventTarget {
} else {
if (message.subType === MessageSubType.SINK_CONNECTED) {
sink.state = "connected";
+
+ const pairingInProgress = window["setPairingInProgress"];
+ const pairedSetMembers = window["pairedSetMembers"];
+
+ if (pairingInProgress) {
+ window["pairedSetMembers"] = pairedSetMembers + 1;
+
+ if (window["pairedSetMembers"] == window["set_size"]) {
+ this.dispatchEvent(new CustomEvent('csis-pairing-complete'));
+ }
+ }
+
this.dispatchEvent(new CustomEvent('sink-updated', {detail: { sink }}));
} else {
this.#sinks.splice(this.#sinks.indexOf(sink, 1));
@@ -472,11 +484,17 @@ class AssistantModel extends EventTarget {
])?.value;
console.log(`Set size = ${set_size}, rank = ${rank}, sirk = ${sirk}`);
+ const sink = this.#sinks.find(i => compareTypedArray(i.addr.value.addr, addr.value.addr));
- setTimeout(() => {
- // Delayed setVolume to prevent comm issue
- this.findSetMembers(set_size, sirk);
- }, 500);
+ if (sink) {
+ sink.csis = {
+ sirk,
+ rank,
+ set_size
+ };
+ }
+
+ this.dispatchEvent(new CustomEvent('sirk-found', {detail: {sirk, set_size}}));
}
handleSetMemberFound(message) {
@@ -495,11 +513,14 @@ class AssistantModel extends EventTarget {
return;
}
+ // Send Connect : Note, if the connect fails, we should rely on FW to send new "found" event
+ this.connectSink({addr});
+
console.log(`Set member = ${addr}`);
}
handleSinkConnectivityRes(message) {
- console.log(`Handle potential Error`);
+ console.log(`Handle Sink Connectivity Response`);
// TODO: Tie RES to actual call (could be another sink)
const payloadArray = ltvToTvArray(message.payload);
@@ -554,6 +575,20 @@ class AssistantModel extends EventTarget {
}
}
+ handleStartSetMemberScanRes(message) {
+ console.log("Handle Start Set Member Scan Res");
+
+ const payloadArray = ltvToTvArray(message.payload);
+
+ const err = tvArrayFindItem(payloadArray, [
+ BT_DataType.BT_DATA_ERROR_CODE
+ ])?.value;
+
+ if (err !== 0) {
+ console.log("Error code", err);
+ }
+ }
+
handleRES(message) {
console.log(`Response message with subType 0x${message.subType.toString(16)}`);
@@ -586,6 +621,10 @@ class AssistantModel extends EventTarget {
console.log('RESET response received');
this.dispatchEvent(new CustomEvent('scan-stopped'));
break;
+ case MessageSubType.START_SET_MEMBER_SCAN:
+ console.log('START_SET_MEMBER_SCAN response received');
+ this.handleStartSetMemberScanRes(message);
+ break;
default:
console.log(`Missing handler for RES subType 0x${message.subType.toString(16)}`);
}
@@ -667,7 +706,7 @@ class AssistantModel extends EventTarget {
console.log('Set indentifier found');
this.handleSetIndentifierFound(message);
break;
- case MessageSubType.SINK_SET_MEMBER_FOUND:
+ case MessageSubType.SET_MEMBER_FOUND:
console.log('Set member found');
this.handleSetMemberFound(message);
default:
@@ -1029,6 +1068,25 @@ class AssistantModel extends EventTarget {
this.#service.sendCMD(message);
}
+ handlePrefoundSetMembers(set_size, sirk) {
+ console.log("Connect to already found CSIS set members");
+
+ const connected_set_members = this.#sinks.filter(i => (i.csis && compareTypedArray(i.csis.sirk, sirk) && i.state === "connected"));
+ const unconnected_set_members = this.#sinks.filter(i => (i.csis && compareTypedArray(i.csis.sirk, sirk) && i.state ==! "connected"));
+
+ window["pairedSetMembers"] = connected_set_members.length;
+
+ // If we already discovered members that are not connected yet, connect to them now
+ unconnected_set_members.forEach( s => { this.connectSink(s); });
+
+ // In case all other members were already connected before, then we just need to send off event that we are done
+ const pairedSetMembers = window["pairedSetMembers"];
+
+ if (pairedSetMembers == set_size) {
+ this.dispatchEvent(new CustomEvent('csis-pairing-complete'));
+ }
+ }
+
findSetMembers(set_size, sirk) {
console.log("Connect CSIS set members CMD");