diff --git a/src/devices/protect-device.ts b/src/devices/protect-device.ts index 4faad70..f5ac210 100644 --- a/src/devices/protect-device.ts +++ b/src/devices/protect-device.ts @@ -3,7 +3,7 @@ * protect-device.ts: Base class for all UniFi Protect devices. */ import { API, CharacteristicValue, HAP, PlatformAccessory, Service, WithUUID } from "homebridge"; -import { HomebridgePluginLogging, acquireService, validService } from "homebridge-plugin-utils"; +import { HomebridgePluginLogging, acquireService, validService, validateName } from "homebridge-plugin-utils"; import { PROTECT_MOTION_DURATION, PROTECT_OCCUPANCY_DURATION} from "../settings.js"; import { ProtectApi, ProtectCameraConfig, ProtectEventPacket, ProtectNvrConfig } from "unifi-protect"; import { ProtectDeviceConfigTypes, ProtectReservedNames } from "../protect-types.js"; @@ -222,7 +222,7 @@ export abstract class ProtectDevice extends ProtectBase { // Sync the Protect name with HomeKit, if configured. if(this.hints.syncName) { - this.accessoryName = this.ufp.name ?? this.ufp.marketName ?? ("Unknown Device" + (this.ufp.mac ? ": " + this.ufp.mac : "")); + this.accessoryName = this.ufp.name ?? this.ufp.marketName ?? ("Unknown Device" + (this.ufp.mac ? " " + this.ufp.mac : "")); } return this.setInfo(this.accessory, this.ufp); @@ -679,12 +679,14 @@ export abstract class ProtectDevice extends ProtectBase { // Utility function to set the current accessory name of this device. public set accessoryName(name: string) { + const cleanedName = validateName(name); + // Set all the internally managed names within Homebridge to the new accessory name. - this.accessory.displayName = name; - this.accessory._associatedHAPAccessory.displayName = name; + this.accessory.displayName = cleanedName; + this.accessory._associatedHAPAccessory.displayName = cleanedName; // Set all the HomeKit-visible names. - this.accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.Name, name); + this.accessory.getService(this.hap.Service.AccessoryInformation)?.updateCharacteristic(this.hap.Characteristic.Name, cleanedName); } // Utility to return the command to set the device status indicator light. This works for cameras and sensors, but Protect lights deal with this differently. diff --git a/src/devices/protect-doorbell.ts b/src/devices/protect-doorbell.ts index aa140e5..31a7987 100644 --- a/src/devices/protect-doorbell.ts +++ b/src/devices/protect-doorbell.ts @@ -10,6 +10,7 @@ import { ProtectReservedNames, toCamelCase } from "../protect-types.js"; import { ProtectCamera } from "./protect-camera.js"; import { ProtectCameraPackage } from "./protect-camera-package.js"; import { ProtectNvr } from "../protect-nvr.js"; +import { validateName } from "homebridge-plugin-utils"; // A doorbell message entry. interface MessageInterface { @@ -196,7 +197,7 @@ export class ProtectDoorbell extends ProtectCamera { if(!packageCameraAccessory) { // We will use the NVR MAC address + ".NVRSystemInfo" to create our UUID. That should provide the guaranteed uniqueness we need. - packageCameraAccessory = new this.api.platformAccessory(this.accessoryName + " Package Camera", uuid); + packageCameraAccessory = new this.api.platformAccessory(validateName(this.accessoryName + " Package Camera"), uuid); if(!packageCameraAccessory) { diff --git a/src/devices/protect-liveviews.ts b/src/devices/protect-liveviews.ts index 0ff151e..1537c9b 100644 --- a/src/devices/protect-liveviews.ts +++ b/src/devices/protect-liveviews.ts @@ -8,6 +8,7 @@ import { ProtectBase } from "./protect-device.js"; import { ProtectNvr } from "../protect-nvr.js"; import { ProtectNvrLiveviewConfig } from "unifi-protect"; import { ProtectSecuritySystem } from "./protect-securitysystem.js"; +import { validateName } from "homebridge-plugin-utils"; export class ProtectLiveviews extends ProtectBase { @@ -84,7 +85,7 @@ export class ProtectLiveviews extends ProtectBase { if((this.securityAccessory = this.platform.accessories.find(x => x.UUID === uuid)) === undefined) { // We will use the NVR MAC address + ".Security" to create our UUID. That should provide the guaranteed uniqueness we need. - this.securityAccessory = new this.api.platformAccessory(this.ufpApi.bootstrap.nvr.name, uuid); + this.securityAccessory = new this.api.platformAccessory(validateName(this.ufpApi.bootstrap.nvr.name), uuid); // Register this accessory with homebridge and add it to the platform accessory array so we can track it. this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [ this.securityAccessory ]); @@ -184,7 +185,7 @@ export class ProtectLiveviews extends ProtectBase { if((newAccessory = this.platform.accessories.find(x => x.UUID === uuid)) === undefined) { - newAccessory = new this.api.platformAccessory(this.ufpApi.bootstrap.nvr.name + " " + viewName, uuid); + newAccessory = new this.api.platformAccessory(validateName(this.ufpApi.bootstrap.nvr.name + " " + viewName), uuid); // Register this accessory with homebridge and add it to the platform accessory array so we can track it. this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [ newAccessory ]); diff --git a/src/devices/protect-nvr-systeminfo.ts b/src/devices/protect-nvr-systeminfo.ts index 1bb0020..c3ead00 100644 --- a/src/devices/protect-nvr-systeminfo.ts +++ b/src/devices/protect-nvr-systeminfo.ts @@ -7,6 +7,7 @@ import { PlatformAccessory } from "homebridge"; import { ProtectBase } from "./protect-device.js"; import { ProtectEventPacket } from "unifi-protect"; import { ProtectNvr } from "../protect-nvr.js"; +import { validateName } from "homebridge-plugin-utils"; export class ProtectNvrSystemInfo extends ProtectBase { @@ -75,7 +76,7 @@ export class ProtectNvrSystemInfo extends ProtectBase { if(!this.accessory) { // We will use the NVR MAC address + ".NVRSystemInfo" to create our UUID. That should provide the guaranteed uniqueness we need. - this.accessory = new this.api.platformAccessory(this.nvr.ufp.name ?? this.nvr.ufp.marketName, uuid); + this.accessory = new this.api.platformAccessory(validateName(this.nvr.ufp.name ?? this.nvr.ufp.marketName), uuid); if(!this.accessory) { diff --git a/src/protect-nvr.ts b/src/protect-nvr.ts index 28de895..cc3c501 100644 --- a/src/protect-nvr.ts +++ b/src/protect-nvr.ts @@ -3,7 +3,7 @@ * protect-nvr.ts: NVR device class for UniFi Protect. */ import { API, APIEvent, HAP, PlatformAccessory } from "homebridge"; -import { HomebridgePluginLogging, MqttClient, retry, sleep } from "homebridge-plugin-utils"; +import { HomebridgePluginLogging, MqttClient, retry, sleep, validateName } from "homebridge-plugin-utils"; import { PLATFORM_NAME, PLUGIN_NAME, PROTECT_CONTROLLER_REFRESH_INTERVAL, PROTECT_CONTROLLER_RETRY_INTERVAL, PROTECT_M3U_PLAYLIST_PORT } from "./settings.js"; import { ProtectApi, ProtectCameraConfig, ProtectChimeConfig, ProtectLightConfig, ProtectNvrBootstrap, ProtectNvrConfig, ProtectSensorConfig, ProtectViewerConfig } from "unifi-protect"; @@ -341,7 +341,7 @@ export class ProtectNvr { // See if we already know about this accessory or if it's truly new. If it is new, add it to HomeKit. if((accessory = this.platform.accessories.find(x => x.UUID === uuid)) === undefined) { - accessory = new this.api.platformAccessory(device.name ?? device.marketName ?? ("Unknown Device" + (device.mac ? ": " + device.mac : "")), uuid); + accessory = new this.api.platformAccessory(validateName(device.name ?? device.marketName ?? ("Unknown Device" + (device.mac ? " " + device.mac : ""))), uuid); this.log.info("%s: Adding %s to HomeKit%s.", this.ufpApi.getDeviceName(device), device.modelKey, this.hasFeature("Device.Standalone", device) ? " as a standalone device" : "");