Skip to content

Commit

Permalink
More debug logs + discard global state
Browse files Browse the repository at this point in the history
  • Loading branch information
Herlix committed Aug 16, 2024
1 parent 0fc6aef commit 7a6b982
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 74 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"displayName": "Plejd",
"name": "homebridge-plejd",
"author": "Herlix",
"version": "1.4.9",
"version": "1.5.0",
"description": "HomeKit support for the Plejd BLE platform using Homebridge",
"license": "Apache-2.0",
"type": "module",
Expand Down
125 changes: 52 additions & 73 deletions src/plejdService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,6 @@ enum PlejdCommand {
}

export class PlejdService {
private connectedPeripheral: noble.Peripheral | null = null;

private sendQueue: Buffer[] = [];
private plejdTimeout: NodeJS.Timeout | null = null;
private queueTimeout: NodeJS.Timeout | null = null;
Expand Down Expand Up @@ -64,11 +62,6 @@ export class PlejdService {
isOn: boolean,
brightness: number | null,
) => {
const addressBuffer = this.getAddressBuffer();
if (!this.storedPeripheralConnected() || !addressBuffer) {
return;
}

const payload = Buffer.from(
!brightness || brightness === 0
? identifier.toString(16).padStart(2, "0") +
Expand All @@ -85,13 +78,7 @@ export class PlejdService {
"hex",
);

const data = plejdEncodeDecode(
this.config.cryptoKey,
addressBuffer,
payload,
);

this.sendQueue.unshift(data);
this.sendQueue.unshift(payload);
};

configureBLE = () => {
Expand All @@ -103,11 +90,6 @@ export class PlejdService {
noble.on("warning", (msg: string) => {
this.log.warn("Noble warning: ", msg);
});

noble.on(
"discover",
async (peripheral) => await this.onDiscover(peripheral),
);
};

// -------------- Private -------------- \\
Expand All @@ -116,36 +98,35 @@ export class PlejdService {
this.log.info(
`Discovered | ${peripheral.advertisement.localName} | addr: ${peripheral.address} | RSSI: ${peripheral.rssi} dB`,
);
this.log.debug(`Stopping scan`);
await noble.stopScanningAsync();

if (this.storedPeripheralConnected()) {
this.tryDisconnect(this.connectedPeripheral);
}

try {
this.log.debug(`Connecting to the new peripheral`);
await peripheral.connectAsync();
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
this.log.info(
`Connected to mesh | ${peripheral.advertisement.localName} (addr: ${peripheral.address})`,
);
} catch (error) {
this.log.error(
`Connecting failed | ${peripheral.advertisement.localName} | addr: ${peripheral.address}) - err: ${error}`,
);
await this.tryDisconnect(this.connectedPeripheral);
await this.tryDisconnect(peripheral);
noble.reset();
await this.tryStartScanning();
return;
}

this.connectedPeripheral = peripheral.once("disconnect", async () => {
this.log.debug("Setting up disconnect handle");
peripheral.once("disconnect", async () => {
this.log.info("Disconnected from mesh");
await this.tryStartScanning();
});

let characteristics: noble.Characteristic[];
try {
characteristics = await this.discoverCaracteristics(peripheral);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (e: any) {
} catch (e) {
this.log.error(
"Failed to discover characteristics, disconnecting. Error:",
e,
Expand All @@ -161,11 +142,7 @@ export class PlejdService {
private discoverCaracteristics = async (
peripheral: noble.Peripheral,
): Promise<noble.Characteristic[]> => {
const addr = peripheral.address;
this.log.info(
`Connected to mesh | ${peripheral.advertisement.localName} (addr: ${addr})`,
);

this.log.debug("Discovering characteristics");
const services = [PlejdCharacteristics.Service];
const characteristicIds = [
PlejdCharacteristics.Data,
Expand All @@ -179,14 +156,15 @@ export class PlejdService {
services,
characteristicIds,
);

this.log.debug("Characteristics discovered");
return characteristics;
};

private setupDevice = async (
peripheral: noble.Peripheral,
characteristics: noble.Characteristic[],
) => {
this.log.debug("Locating relevant characteristics");
const authChar = characteristics.find(
(char) => char.uuid === PlejdCharacteristics.Auth,
);
Expand All @@ -210,28 +188,46 @@ export class PlejdService {
);
return;
}

const addressBuffer = reverseBuffer(
Buffer.from(String(peripheral.address).replace(/:/g, ""), "hex"),
);

await this.authenticate(authChar);
await this.setupCommunication(pingChar, lastDataChar, dataChar);
await this.setupCommunication(
pingChar,
lastDataChar,
dataChar,
addressBuffer,
);
};

private handleQueuedMessages = (dataChar: noble.Characteristic) => {
private handleQueuedMessages = (
dataChar: noble.Characteristic,
addressBuffer: Buffer,
) => {
if (this.queueTimeout) {
clearTimeout(this.queueTimeout);
}

this.queueTimeout = setTimeout(async () => {
const data = this.sendQueue.pop();
if (!data || !this.storedPeripheralConnected()) {
this.handleQueuedMessages(dataChar);
const payload = this.sendQueue.pop();
if (!payload) {
this.handleQueuedMessages(dataChar, addressBuffer);
return;
}

const data = plejdEncodeDecode(
this.config.cryptoKey,
addressBuffer,
payload,
);
this.log.debug(
`BLE command sent to ${this.getAddressBuffer()?.toString("hex") ?? "Unknown"} | ${data.length} bytes | ${data.toString("hex")}`,
`BLE command sent to ${addressBuffer?.toString("hex") ?? "Unknown"} | ${data.length} bytes | ${data.toString("hex")}`,
);
try {
await dataChar.writeAsync(data, false);
this.handleQueuedMessages(dataChar);
this.handleQueuedMessages(dataChar, addressBuffer);
} catch (error) {
this.sendQueue.unshift(data);
this.log.error("Failed to send data to device, will retry: ", error);
Expand Down Expand Up @@ -338,27 +334,17 @@ export class PlejdService {
pingChar: noble.Characteristic,
lastDataChar: noble.Characteristic,
dataChar: noble.Characteristic,
addressBuffer: Buffer,
) => {
this.log.debug("Setting up ping pong communication with Plejd device");
this.startPlejdPing(pingChar);
this.handleQueuedMessages(dataChar);

const addressBuffer = this.getAddressBuffer();

if (!addressBuffer) {
this.log.error(
"Failed to get address buffer",
this.connectedPeripheral?.address,
);
return;
}
this.log.debug("Starting queue handler for messages to Plejd device");
this.handleQueuedMessages(dataChar, addressBuffer);

try {
this.log.debug("Subscribing to incomming messages");
await lastDataChar.subscribeAsync();
lastDataChar.on("data", async (data, isNotification) => {
if (!this.storedPeripheralConnected()) {
await lastDataChar.unsubscribeAsync();
return;
}
await this.handleNotification(data, isNotification, addressBuffer);
});
} catch (e) {
Expand All @@ -368,47 +354,40 @@ export class PlejdService {

private authenticate = async (authChar: noble.Characteristic) => {
try {
this.log.debug("Authenticating to Plejd device");
await authChar.writeAsync(Buffer.from([0x00]), false);
const data = await authChar.readAsync();
await authChar.writeAsync(
plejdCharResp(this.config.cryptoKey, data),
false,
);
this.log.debug("Authentication successful");
} catch (e) {
this.log.error("Failed to authenticate to Plejd device", e);
}
};

private storedPeripheralConnected = () =>
this.connectedPeripheral !== null &&
this.connectedPeripheral.state === "connected";

private tryStartScanning = async () => {
try {
if (noble._state === "poweredOn") {
this.log.info("Scanning for Plejd devices");

await noble.startScanningAsync([PlejdCharacteristics.Service], false);
noble.once(
"discover",
async (peripheral) => await this.onDiscover(peripheral),
);
}
} catch (e) {
this.log.error("Failed to start scanning for Plejd devices", e);
}
};

private tryDisconnect = async (peripheral: noble.Peripheral | null) => {
private tryDisconnect = async (peripheral: noble.Peripheral) => {
try {
await peripheral?.disconnectAsync();
await peripheral.disconnectAsync();
} catch (e) {
this.log.debug("Failed to disconnect from previous peripheral", e);
}
};

private getAddressBuffer = (): Buffer | null =>
this.connectedPeripheral?.address
? reverseBuffer(
Buffer.from(
String(this.connectedPeripheral?.address).replace(/:/g, ""),
"hex",
),
)
: null;
}

0 comments on commit 7a6b982

Please sign in to comment.