Skip to content

Commit

Permalink
Update accessory name once device model is known
Browse files Browse the repository at this point in the history
  • Loading branch information
gormanb committed Dec 22, 2022
1 parent fa006b5 commit 1fe0073
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 30 deletions.
34 changes: 20 additions & 14 deletions src/connectorAccessory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,6 @@ export class ConnectorAccessory {
this.client = new ConnectorHubClient(
this.platform.config, this.accessory.context.device, this.hubToken);

// Set the accessory information to be displayed in Homekit.
this.setAccessoryInformation();

// Get the WindowCovering service if it exists, otherwise create one.
this.wcService =
this.accessory.getService(this.platform.Service.WindowCovering) ||
Expand All @@ -51,12 +48,6 @@ export class ConnectorAccessory {
this.accessory.getService(this.platform.Service.Battery) ||
this.accessory.addService(this.platform.Service.Battery);

// Set the service name. This is the default name displayed by Homekit.
this.wcService.setCharacteristic(
this.platform.Characteristic.Name, accessory.displayName);
this.batteryService.setCharacteristic(
this.platform.Characteristic.Name, `${accessory.displayName} Battery`);

// Initialize the device state and set up a periodic refresh.
this.updateDeviceStatus();
setInterval(
Expand All @@ -74,16 +65,31 @@ export class ConnectorAccessory {
}

// Update the device information displayed in Homekit.
setAccessoryInformation(modelNum = 0, manufacturer = 'Dooya') {
setAccessoryInformation(deviceState: ReadDeviceAck) {
const Characteristic = this.platform.Characteristic;
const deviceInfo = this.accessory.context.device;

// Update the accessory display name, in case it wasn't set already.
this.accessory.displayName =
helpers.makeDeviceName(deviceInfo.devNum, deviceState.data.type);
this.platform.api.updatePlatformAccessories([this.accessory]);

// Set the service names. These are the default names displayed by Homekit.
this.wcService.setCharacteristic(
Characteristic.Name, this.accessory.displayName);
this.batteryService.setCharacteristic(
Characteristic.Name, `${this.accessory.displayName} Battery`);

// Update default accessory name and additional information in Homekit.
this.accessory.getService(this.platform.Service.AccessoryInformation)!
.setCharacteristic(Characteristic.Manufacturer, manufacturer)
.setCharacteristic(Characteristic.Name, this.accessory.displayName)
.setCharacteristic(Characteristic.Manufacturer, 'Dooya')
.setCharacteristic(Characteristic.SerialNumber, deviceInfo.mac)
.setCharacteristic(
Characteristic.FirmwareRevision, deviceInfo.fwVersion)
.setCharacteristic(
Characteristic.Model, helpers.getDeviceModel(modelNum));
Characteristic.Model,
helpers.getDeviceModel(deviceState.data.type));
}

/**
Expand Down Expand Up @@ -111,9 +117,9 @@ export class ConnectorAccessory {
this.usesBinaryState = (newState.data.currentPosition === undefined);
this.currentState = helpers.sanitizeDeviceState(newState);

// If this is the first time we've read the device, update the model type.
// The first time we read the device, we update the accessory details.
if (!this.lastState) {
this.setAccessoryInformation(newState.data.type);
this.setAccessoryInformation(newState);
}

// We extract 'lastPos' as below because lastState will be undefined on the
Expand Down
14 changes: 7 additions & 7 deletions src/connectorhub/connector-hub-constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,14 @@ export const deviceModels = [
'Day & Night Blinds',
'Dimming Blinds',
'Curtain',
'Curtain (Open Left)',
'Curtain (Open Right)',
'Curtain Left',
'Curtain Right',
];

export const wirelessModes = [
'Uni-Directional',
'Bi-Directional',
'Bi-Directional (with mechanical limits)',
'Bi-Directional, Mechanical Limits',
'Other',
];

Expand All @@ -58,8 +58,8 @@ export const voltageModes = ['AC Motor', 'DC Motor'];
// Discrete states that the devices can be in.
export const stateModes = [
'Not at any limit',
'Top-limit',
'Bottom-limit',
'Limits detected',
'3rd limit detected',
'Top Limit',
'Bottom Limit',
'Limits Detected',
'3rd Limit Detected',
];
18 changes: 18 additions & 0 deletions src/connectorhub/connector-hub-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ import {Log} from '../util/log';
import * as hubapi from './connector-hub-api';
import * as consts from './connector-hub-constants';

//
// Special types used internally by the plugin.
//

// This augmented type is not part of the Hub API.
export interface ExtendedDeviceInfo extends hubapi.DeviceInfo {
devNum: number;
fwVersion: string;
}

//
// Helpers which facilitate communication with the hub.
//
Expand All @@ -23,6 +33,10 @@ export function computeAccessToken({connectorKey, hubToken}): string {
return aesjs.utils.hex.fromBytes(tokenEnc).toUpperCase();
}

export function resolveIP(ip?: string): string {
return (ip || consts.kMulticastIp);
}

export function makeMsgId(): string {
// The ID is the current timestamp with all non-numeric chars removed.
return (new Date()).toJSON().replaceAll(/\D/g, '');
Expand Down Expand Up @@ -124,6 +138,10 @@ export function getDeviceModel(type: number): string {
return consts.deviceModels[type] || 'Unidentified Device';
}

export function makeDeviceName(devNum: number, type: number): string {
return `${getDeviceModel(type)} #${devNum}`;
}

// Estimate battery charge percentage from reported voltage.
// Calculation uses thresholds defined by the Connector app.
export function getBatteryPercent(batteryLevel: number): number {
Expand Down
10 changes: 5 additions & 5 deletions src/connectorhub/connectorHubClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,19 +56,19 @@ export class ConnectorHubClient {
private readonly deviceInfo: hubapi.DeviceInfo,
private readonly hubToken: string,
) {
this.sendIp = (this.config.hubIp || consts.kMulticastIp);
this.sendIp = helpers.resolveIP(this.config.hubIp);
this.accessToken = helpers.computeAccessToken(
{connectorKey: this.config.connectorKey, hubToken: this.hubToken});
}

public static getDeviceList(ip?: string): Promise<DeviceResponse> {
const sendIp = (ip || consts.kMulticastIp);
return sendCommand(helpers.makeGetDeviceListRequest(), sendIp);
return sendCommand(
helpers.makeGetDeviceListRequest(), helpers.resolveIP(ip));
}

public getDeviceState(): Promise<DeviceResponse> {
const command = helpers.makeReadDeviceRequest(this.deviceInfo);
return sendCommand(command, this.sendIp);
return sendCommand(
helpers.makeReadDeviceRequest(this.deviceInfo), this.sendIp);
}

private setOpenCloseState(op: hubapi.DeviceOpCode): Promise<DeviceResponse> {
Expand Down
13 changes: 9 additions & 4 deletions src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {isIPv4} from 'net';

import {ConnectorAccessory} from './connectorAccessory';
import {GetDeviceListAck} from './connectorhub/connector-hub-api';
import {ExtendedDeviceInfo} from './connectorhub/connector-hub-helpers';
import {ConnectorHubClient} from './connectorhub/connectorHubClient';
import {PLATFORM_NAME, PLUGIN_NAME} from './settings';
import {Log} from './util/log';
Expand Down Expand Up @@ -100,12 +101,16 @@ export class ConnectorHubPlatform implements DynamicPlatformPlugin {
Log.debug('Discovered devices:', response);

// Iterate over the discovered devices and register each of them.
// Skip index 0 since that entry always refers to the hub itself.
for (let devNum = 1; devNum < response.data.length; ++devNum) {
// Augment the basic device information with additional details.
const deviceInfo: ExtendedDeviceInfo = Object.assign(
{devNum: devNum, fwVersion: response.fwVersion},
response.data[devNum]);

// Generate a unique id for the accessory from its MAC address.
const device =
Object.assign({fwVersion: response.fwVersion}, response.data[devNum]);
const uuid = this.api.hap.uuid.generate(deviceInfo.mac);
const defaultDisplayName = `Connector Device ${devNum}`;
const uuid = this.api.hap.uuid.generate(device.mac);

// See if an accessory with the same uuid already exists.
let accessory =
Expand All @@ -124,7 +129,7 @@ export class ConnectorHubPlatform implements DynamicPlatformPlugin {
}

// Make sure the accessory stays in sync with any device config changes.
accessory.context.device = device;
accessory.context.device = deviceInfo;
this.api.updatePlatformAccessories([accessory]);

// Create the accessory handler for this accessory.
Expand Down

0 comments on commit 1fe0073

Please sign in to comment.