Skip to content

Commit

Permalink
Merge pull request #34 from peterwoj/master
Browse files Browse the repository at this point in the history
Update beta
  • Loading branch information
peterwoj authored Jun 6, 2021
2 parents febc06b + 7944b6b commit 2fd2c85
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 25 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,12 +77,15 @@ Once your configuration is in place startup Homebridge and to get your devices c

### 0.2.6

Default HomeKit type for auto discovery is now an OUTLET.

* Bug fixes
* #12 Missing 'D' from the digital pin requests
* #15 High CPU caused from failed config defaults for pollerseconds.
* #14 Additional accessory types, SLIDER is now available
* Adding HomeKit Sensors as well to relate to defined switches/sliders
* HUMIDITY_SENSOR, LIGHTBULB, OUTLET, TEMPERATURE_SENSOR
* Multiple devices would trigger a refresh on restart of Homebridge.

### 0.2.5

Expand Down
22 changes: 22 additions & 0 deletions config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,28 @@
]
}
]
},
"typeOf": {
"title": "Type Of",
"type": "string",
"oneOf": [
{
"title": "Outlet",
"enum": ["OUTLET"]
},
{
"title": "Lightbulb",
"enum": ["LIGHTBULB"]
},
{
"title": "Humidity Sensor",
"enum": ["HUMIDITY_SENSOR"]
},
{
"title": "Temperature Sensor",
"enum": ["TEMPERATURE_SENSOR"]
}
]
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/accessories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export class BlynkAccessory {
switch (typeOf) {
case HOMEKIT_TYPES.OUTLET:
serviceType = this.hap.Service.Outlet;
this.accessoryService = this.accessory.getService(this.hap.Service.Lightbulb)
this.accessoryService = this.accessory.getService(serviceType)
?? this.accessory.addService(serviceType);

this.accessoryService
Expand Down
26 changes: 17 additions & 9 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import {
{
"name": "item name",
"type": "LABEL",
"typeOf": "temperature",
"typeOf": "temperature_sensor",
"pintype": "virtual",
"pinnumber": "1",
"model": "accessory model",
Expand Down Expand Up @@ -116,7 +116,7 @@ export class BlynkDeviceConfig {
readonly manufacturer: string;
readonly discover: boolean;
readonly deviceId: number = 0;
name = "";
name = "";
widgets: BlynkWidgetBase[];

constructor(hap: HAP, log: Logging, baseUrl: string, config: Record<string, string | number | boolean | Record<string,string> | Array<Record<string,string>> >) {
Expand Down Expand Up @@ -145,8 +145,11 @@ export class BlynkDeviceConfig {

this.widgets = new Array<BlynkWidgetBase>();
if (this.discover === false) {
const accList: Array<Record<string, string|number>> = config['accessories'] as Array<Record<string,string|number>>
?? function(){ throw new Error(`Discovery is set to false and accessories were not defined.`) };
if (config['accessories'] === undefined) {
this.log.error(`Discovery is set to false and accessories were not defined for ${this.name}.`)
return;
}
const accList: Array<Record<string, string|number>> = config['accessories'] as Array<Record<string,string|number>>;
/*
{
"name": "item name",
Expand All @@ -168,19 +171,23 @@ export class BlynkDeviceConfig {
'max': acc['max'] as number,
'min': acc['min'] as number,
'value': acc['value'] as string,
'typeOf': acc['typeOf'] as string ?? HOMEKIT_TYPES.UNDEFINED
'typeOf': acc['typeOf'] as string ?? HOMEKIT_TYPES.OUTLET
};
this.log.info(`Adding accessory: ${widget.label}`);
this.addWidget(widget);
});
}
else {
this.log.warn(`Accessories were not defined and discover is set to false.`);
this.log.warn(`Accessories were not defined and discover is set to false for "${this.name}".`);
}
}
else {
this.deviceId = config['deviceId'] as number
?? function() { throw new Error('Discovery is set but missing deviceId to link with token')};
if (config['deviceId'] === undefined) {
this.log.error(`Discovery is set but missing deviceId to link with token for ${this.name}, will attempt with deviceId 0.`)
}
else {
this.deviceId = config['deviceId'] as number
}
}
}

Expand Down Expand Up @@ -239,8 +246,9 @@ export class BlynkDeviceConfig {
this.name = project.name;

project.widgets.forEach( (widget: IBlynkWidget) => {
widget.typeOf = HOMEKIT_TYPES.OUTLET;
this.addWidget(widget);
})
});
}

private async getProjectJSON(): Promise<IBlynkProject> {
Expand Down
45 changes: 34 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,25 @@ let myConfig: BlynkConfig;

class BlynkPlatform implements DynamicPlatformPlugin {
private readonly log: Logging;
// Loaded from homebridge accessory cache
private readonly accs: PlatformAccessory[] = [];

// Found in homebridge-blynk-platform plugin configuration
// or fetched from blynk-server
private plugins: BlynkAccessory[] = new Array<BlynkAccessory>();
// Accessories currently active, used to filter out what was read
// from the accessory cache
private platAccessories: PlatformAccessory[] = [];
private needToFetchConfigs = 0;
private poll: BlynkPoller;

constructor(log: Logging, config: PlatformConfig, homebridge: API) {
this.log = log;
myConfig = new BlynkConfig(homebridge.hap, this.log, config);
this.poll = new BlynkPoller(log, myConfig.pollerSeconds, []);

this.needToFetchConfigs = myConfig.devices.length;
this.isConfigurtionReady();

api.on(APIEvent.SHUTDOWN, () => {
this.log.info(`${PLATFORM_NAME} is shutting down.`);
Expand All @@ -75,15 +85,13 @@ class BlynkPlatform implements DynamicPlatformPlugin {
// Prepare a list of available accessories to
// 1. Bind Homebridge to Blynk event
// 2. Provide for poller to refresh state
const plugins: BlynkAccessory[] = new Array<BlynkAccessory>();
const platAccessories: PlatformAccessory[] = [];

myConfig.devices.forEach( (device: BlynkDeviceConfig) => {
(async() => {
// Check to see if this device needs its configuration retrieved.
if (device.discover) {
await device.readProject().catch((error) => { this.log.error(`error reading project: ${error}`) });
}
this.needToFetchConfigs--;

device.widgets.forEach( (widget: BlynkWidgetBase) => {
const plugin: BlynkAccessory = new BlynkAccessory(hap, this.log, widget);
Expand All @@ -92,38 +100,53 @@ class BlynkPlatform implements DynamicPlatformPlugin {
? `${device.token}-${widget.getId().toString()}`
: `${device.deviceId}-${device.manufacturer}-${widget.getModel()}-${widget.getPinType()}-${widget.getPinNumber()}`;
const accId = hap.uuid.generate(uuidSeed);
this.log.debug(`PlatformAccessory: identified ${plugin.name}(${widget.getTypeOf()}) - ${widget.getId()} [${accId}]`);

this.log.debug(`PlatformAccessory: identified ${plugin.name}(${widget.getTypeOf()}) - ${widget.getId()} [${accId}] seed: ${uuidSeed}`);
let haveAcc = this.accs.find(accessory => accessory.UUID === accId);
if (!haveAcc) {
haveAcc = new Accessory(plugin.name, accId);

plugin.attachAccessory(haveAcc);
api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [haveAcc]);
}
else {
plugin.attachAccessory(haveAcc);
}

platAccessories.push(haveAcc);
plugins.push(plugin);
this.platAccessories.push(haveAcc);
this.plugins.push(plugin);
});
})();
});
}

isConfigurtionReady(): void {
this.log.debug(`Checking if config is ready: waiting for -> ${this.needToFetchConfigs}`)
if (this.needToFetchConfigs <= 0) {
this.cleanUpAccessories();
}
else {
setTimeout( () => { this.isConfigurtionReady() }, 500);
}
}

cleanUpAccessories() {
// Remove any found orphans, these are caused by configuration changes
this.log.info(`Checking if accessories have been removed to clean up cache.`);
this.accs
.filter(orphan => ! platAccessories.includes(orphan))
.filter(orphan => ! this.platAccessories.includes(orphan))
.forEach(orphan => {
this.log.info(`Removing: ${orphan.displayName} - ${orphan.UUID}`);
this.log.info(`Removing control: ${orphan.displayName} - ${orphan.UUID}`);
api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [orphan])
});
this.accs.length = 0;
platAccessories.forEach( acc => this.accs.push(acc) );
this.platAccessories.forEach( acc => {
this.log.debug(`Committing defined accessory(${acc.displayName}) to cache`);
this.accs.push(acc);
});

// Start the refresh service
this.poll
.setPollerAccessoryList(plugins)
.setPollerAccessoryList(this.plugins)
.poll();
}
}
2 changes: 1 addition & 1 deletion src/poller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class BlynkPoller {
setPollerAccessoryList(accessories: BlynkAccessory[]): BlynkPoller {
this.accessories.length = 0;
this.accessories = accessories;
this.log.debug(`accessories to scan: ${accessories.length}`);
this.log.debug(`Poller will refresh setting for ${accessories.length} item(s).`);
return this;
}

Expand Down
10 changes: 7 additions & 3 deletions src/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export abstract class BlynkWidgetBase {
}

toString(): string {
return `${this.manufacturer} made a ${this.widgetType} named ${this.pinLabel} on pin ${this.pinUrlLabel}`;
return `${this.manufacturer} made a ${this.widgetType}(${this.id}) named ${this.pinLabel} on pin ${this.pinUrlLabel}`;
}
}

Expand Down Expand Up @@ -119,7 +119,7 @@ export class BlynkWidgetButton extends BlynkWidgetBase {

super.requestUrl(this.setPin());

this.log.warn(`setValue() --> value: ${value} | curValue: ${this.curValue}`);
this.log.debug(`setValue() --> value: ${value} | curValue: ${this.curValue}`);
}
getValue(): number {
try {
Expand Down Expand Up @@ -151,6 +151,10 @@ export class BlynkWidgetDimmer extends BlynkWidgetBase {
this.dimmerLow = widget['min'] as number ?? 0.0;
this.dimmerHigh = widget['max'] as number ?? 100.0;
this.dimmerCur = widget['value'] as number ?? 0;

if ( (this.typeOf === HOMEKIT_TYPES.LIGHTBULB) && (this.dimmerHigh > 100) ) {
this.dimmerHigh = 100;
}
}

getValue(): number {
Expand Down Expand Up @@ -195,7 +199,7 @@ export class BlynkWidgetDimmer extends BlynkWidgetBase {
}

super.requestUrl(this.setPin());
this.log.error(`new dimmer value: ${tempValue} from ${value} --> ${this.dimmerCur}`);
this.log.debug(`Dimmer(${this.name}) value: ${tempValue} from ${value} --> ${this.dimmerCur}`);
}

setDimmerLow(value: number): void {
Expand Down

0 comments on commit 2fd2c85

Please sign in to comment.