28 Commits
Author SHA1 Message Date
Serge Wagener 43e3fdf35f Remover "homebridge verified" until official approval 2022-03-18 08:24:17 +01:00
Serge Wagener d07d621e45 Added check for empty accessories list 2022-03-18 08:23:38 +01:00
Serge Wagener c8d117a894 Changed badge order 2022-03-17 16:45:58 +01:00
Serge Wagener 9a6c9e681d Links to 3rd party installation instructions 2022-03-16 17:41:14 +01:00
Serge Wagener 0394d789f8 Plugin now verified by homebridge dev's 2022-03-15 22:00:46 +01:00
Serge Wagener 84ed5cc74a Removed unneeded import 2022-03-15 16:40:24 +01:00
Serge Wagener 59fe9963a1 Merge branch 'master' of github.com:Foxi352/homebridge-smarthomeng 2022-03-15 16:39:23 +01:00
Serge Wagener 0beada795f Update README.md
Added fan rotation speed to doc
2022-03-15 07:38:07 +01:00
Serge Wagener e2d30353fb Update Fan.ts 2022-03-15 07:36:22 +01:00
Serge Wagener 1a2e5c051d Merge pull request #14 from thomas-kaltenbach/master
Add rotationspeed as fan charasteristics
2022-03-15 07:34:13 +01:00
Thomas Kaltenbach 5f0b025e25 Add rotationspped as charasteristics 2022-03-13 19:06:30 +01:00
Serge Wagener f4700332cc Preparing for v2.0.5 release 2022-03-08 16:51:24 +01:00
Serge Wagener 323c313f3c Code formating 2022-03-08 16:51:01 +01:00
Serge Wagener ae63f6cdee Merge pull request #13 from chester4444/master
Added GarageDoor and HumiditySensor
2022-03-08 16:27:23 +01:00
Serge Wagener bbc42dfb7e Added config section link 2022-03-08 16:24:52 +01:00
Chester c6f596e9e5 Merge branch 'master' of https://github.com/chester4444/homebridge-smarthomeng 2022-03-08 15:15:19 +01:00
Chester 3561e0c3d6 added humidity sensor 2022-03-08 15:13:53 +01:00
Chester 447e0a68ef added GarageDoor and HumiditySensor 2022-03-08 14:18:35 +01:00
Chester 6f373379ae Adding humidity sensor 2022-03-07 21:12:55 +01:00
Chester 6b46c9cdb8 Added garage door description 2022-03-07 17:11:36 +01:00
Chester 77df0609ca garage door added 2022-03-07 16:44:43 +01:00
Chester abe95f516f added garagedoor 2022-03-07 16:30:32 +01:00
Serge Wagener a3e7b85f17 Added badges to README 2022-02-20 10:45:25 +01:00
Serge Wagener ba2505853c Preparing for v2.0.4 release 2022-02-19 13:58:11 +01:00
Serge Wagener e0611aed2c Sort accessories in README alphabetically 2022-02-19 13:39:05 +01:00
Serge Wagener 9a1709591f Fixed package.json 2022-02-19 13:36:38 +01:00
Serge Wagener a03b5f787b Added SecuritySystem 2022-02-19 12:23:38 +01:00
Serge Wagener de26802e1d Corrected motion sensor example 2022-02-16 10:33:09 +01:00
9 changed files with 570 additions and 155 deletions

No files matched your search

+164 -81
View File
@@ -1,51 +1,43 @@
# homebridge-smarthomeng # homebridge-smarthomeng
[![npm](https://badgen.net/npm/v/homebridge-smarthomeng)](https://www.npmjs.com/package/homebridge-smarthomeng)
[![npm](https://badgen.net/badge/homebridge/>=1.3.5/green)](https://www.npmjs.com/package/homebridge-smarthomeng)
[![npm](https://badgen.net/npm/node/homebridge-smarthomeng)](https://www.npmjs.com/package/homebridge-smarthomeng)
[![npm](https://badgen.net/npm/dt/homebridge-smarthomeng)](https://www.npmjs.com/package/homebridge-smarthomeng)
[![npm](https://badgen.net/npm/dm/homebridge-smarthomeng)](https://www.npmjs.com/package/homebridge-smarthomeng)
**Version v2 is a complete rewrite from scratch and a breaking update.** **Version v2 is a complete rewrite from scratch and a breaking update.**
You need to adapt your `config.json` ! You need to adapt your [`config.json`](#example-configuration-file) !
## Currently supported accessories ## Currently supported accessories
This plugin currently supports the following services (and characteristics): This plugin currently supports the following services (and characteristics):
| Type | Description | | Type | Description |
|:----------------------------------------|:--------------------------------------------------------| |:-----------------------------------------|:--------------------------------------------------------|
| ContactSensor | Simple contact sensor, for example for windows | | [ContactSensor](#contact-sensor) | Simple contact sensor, for example for windows |
| [Doorbell](#doorbell) | Doorbell, sends message to devices on ring | | [Doorbell](#doorbell) | Doorbell, sends message to devices on ring |
| [Fan](#fan) | Simple on/off fan, may be extended in future | | [Fan](#fan) | Simple on/off fan, may be extended in future |
| [Lightbulb](#lightbulb) | Everything, from simple light to dimmable, RGB and RGBW | | [GarageDoor](#garage-door) | Garage door opener |
| [MotionSensor](#motionsensor) | Detects and reports motion | | [HumiditySensor](#humidity-sensor) | Humidity sensor |
| [OccupancySensor](#occupancysensor) | Detects presence in a room | | [Lightbulb](#lightbulb) | Everything, from simple light to dimmable, RGB and RGBW |
| [Outlet](#outlet) | Simple on/off wall outlet | | [MotionSensor](#motion-sensor) | Detects and reports motion |
| [TemperatureSensor](#temperaturesensor) | Temperature sensor | | [OccupancySensor](#occupancy-sensor) | Detects presence in a room |
| [Thermostat](#thermostat) | Thermostat with temperature sensor and heating state | | [Outlet](#outlet) | Simple on/off wall outlet |
| [Switch](#switch) | Simple on/off switch | | [SecuritySystem](#security-system) | Intrusion alarm system |
| [WindowCovering](#windowcovering) | Window covering (shutters, blinds, ...) | | [Switch](#switch) | Simple on/off switch |
| [TemperatureSensor](#temperature-sensor) | Temperature sensor |
| [Thermostat](#thermostat) | Thermostat with temperature sensor and heating state |
| [WindowCovering](#window-covering) | Window covering (shutters, blinds, ...) |
Other accessories are being worked on and will be added as soon as ready.
## Requirements ## Requirements
* [SmartHomeNG](https://github.com/smarthomeNG/smarthome) * [SmartHomeNG](https://github.com/smarthomeNG/smarthome)
* [homebridge](https://www.npmjs.com/package/homebridge) * [Node.js >=14.18.1](https://nodejs.org/en/)
* [Homebridge](https://homebridge.io)
## Installation ## Installation of plugin
### Install nodejs >=14.18.1
See [NodeJS](https://nodejs.org/en/) website for details depending on your OS.
### Install libavahi-compat-libdnssd-dev lib Use [Homebridge Config UI X](https://github.com/oznu/homebridge-config-ui-x#readme) or install manually using ```npm install -g homebridge-smarthomeng```
For me i needed these libraries to be installed for my homebridge to work. See their [Homepage](https://homebridge.io) for installation instructions.
Below is what i did on my Debian Bullseye installation:
sudo apt install libavahi-compat-libdnssd-dev
### Install homebridge >=1.3.5 from NPM repository
npm install -g homebridge --unsafe-perm
### Install this plugin from NPM repository
npm install -g homebridge-smarthomeng --unsafe-perm
## Configuration ## Configuration
@@ -54,13 +46,13 @@ If you already have a working homebridge installation just add the platform sect
### Platform configuration ### Platform configuration
The following parameters are available to configure the plugin as platform in homebridge. The following parameters are available to configure the plugin as platform in homebridge.
| Parameter | Possible values | Mandatory | Description | | Parameter | Possible values | Mandatory | Default | Description |
|:----------|:---------------------------------------|:----------|:----------------------------------------------------| |:----------|:---------------------------------------|:----------|:--------|:------------------------------------|
| platform | Any \<string> | Yes | Internal name of your platform | | platform | Any \<string> | Yes | | Internal name of your platform |
| name | Any \<string> | Yes | Visible name in HomeKit | | name | Any \<string> | Yes | | Visible name in HomeKit |
| host | IP address or FQDN of your SHNG server | Yes | Your SHNG host | | host | IP address or FQDN of your SHNG server | Yes | | Your SHNG host |
| port | Port \<number> | No | Listening port of websocket module. Default is 2424 | | port | Port \<number> | No | 2424 | Listening port of websocket module. |
| tls | \<boolean> | No | Should TLS encryption be used. Defaults is 'false' | | tls | \<boolean> | No | False | Should TLS encryption be used. |
#### Example configuration: #### Example configuration:
```json ```json
@@ -91,6 +83,25 @@ The following characteristics are valid for all accessories:
"model": "Motion 360 KNX", "model": "Motion 360 KNX",
} }
``` ```
### Contact sensor
This sensor shows the open / closed state of a contact (door, window, generic ...).
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description |
|:-------------|:----------------|:----------|:---------------------------------|
| ContactState | \<item> | Yes | SHNG item to monitor for contact |
#### Example:
```json
{
"type": "ContactSensor",
"name": "Window kitchen",
"ContactState": "EG.Kueche.Fenster"
}
```
### Doorbell ### Doorbell
A doorbell is an accessory that simply sends a message to all devices enrolled in the home that someone rang the doorbell. A doorbell is an accessory that simply sends a message to all devices enrolled in the home that someone rang the doorbell.
HomeKit displays a message that "This accessory is not currently supported by the Home app.". HomeKit displays a message that "This accessory is not currently supported by the Home app.".
@@ -113,9 +124,10 @@ Further investigation is needed, but for now it still works.
For now this accessory only supports turning the fan on and off. Further improvements are possible, but i don't have the needed hardware for testing. For now this accessory only supports turning the fan on and off. Further improvements are possible, but i don't have the needed hardware for testing.
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics) #### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description | | Parameter | Possible values | Mandatory | Description |
|:----------|:----------------|:----------|:---------------------------------------| |:--------------|:----------------|:----------|:------------------------------------------------|
| Active | \<item> | Yes | SHNG item to set and get the fan state | | Active | \<item> | Yes | SHNG item to set and get the fan state. |
| RotationSpeed | \<item> | No | SHNG item to set and get the fan rotation speed |
#### Example: #### Example:
@@ -127,6 +139,60 @@ For now this accessory only supports turning the fan on and off. Further improve
} }
``` ```
### Garage Door
This accessory is used for opening/closing garage doors or any other automatic gate.
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description |
|:--------------------|:----------------|:----------|:------------------------------------------------------------------|
| CurrentDoorState | \<item> | Yes | SHNG item to monitor the current door state |
| TargetDoorState | \<item> | Yes | SHNG item to monitor and set the target position |
| ObstructionDetected | \<item> | No | SHNG item to monitor if the door is blocked |
#### Additional comments
Valid values for 'CurrentDoorState':
* OPEN = 0
* CLOSED = 1
* OPENING = 2
* CLOSING = 3
* STOPPED = 4
Valid values for 'TargetDoorState':
* OPEN = 0
* CLOSED = 1
'ObstructionDetected' may be set 'true' if there is any physical problem opening/closing the door.
#### Example
```json
{
"type": "GarageDoor",
"name": "GarageRechts",
"currentdoorstate": "garage.rechts.cds",
"targetdoorstate": "garage.rechts.tds",
"obstructiondetected": "garage.rechts.od"
}
```
### Humidity sensor
This accessory shows the current relative humidity in %.
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description |
|:-------------------|:----------------|:----------|:-----------------------------------------------|
| CurrentHumidity | \<item> | Yes | SHNG item to monitor relative humidity in % |
#### Example:
```json
{
"type": "HumiditySensor",
"name": "Luftfeuchtigkeit Glashaus",
"CurrentHumidity": "Glashaus.Luftfeuchtigkeit"
}
```
### LightBulb ### LightBulb
Lightbulb can be as simple as a generic on/off light, but can also be as complex as a full RGBW led strip. Lightbulb can be as simple as a generic on/off light, but can also be as complex as a full RGBW led strip.
@@ -179,6 +245,25 @@ The above optional min and max parameters allow you to specify the neede range f
} }
``` ```
### Motion sensor
This sensor is tripped if it detects motion in a room.
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description |
|:---------------|:----------------|:----------|:--------------------------------|
| MotionDetected | \<item> | Yes | SHNG item to monitor for motion |
#### Example:
```json
{
"type": "MotionSensor",
"name": "Movement hallway",
"MotionDetected": "EG.Flur.Bewegung"
}
```
### Occupancy sensor ### Occupancy sensor
This sensor is tripped if it detects presence in a room. This sensor is tripped if it detects presence in a room.
@@ -199,39 +284,55 @@ This sensor is tripped if it detects presence in a room.
} }
``` ```
### Motion sensor
This sensor is tripped if it detects motion in a room. ### Outlet
This accessory can monitor and change the on/off state of a wall outlet. The outlet can be generic, a light, a fan, ...
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics) #### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description | | Parameter | Possible values | Mandatory | Description |
|:---------------|:----------------|:----------|:--------------------------------| |:----------|:----------------|:----------|:-------------------------------------|
| MotionDetected | \<item> | Yes | SHNG item to monitor for motion | | On | \<item> | Yes | SHNG item to switch outlet on or off |
#### Example: #### Example:
```json ```json
{ {
"type": "OccupancySensor", "type": "Outlet",
"name": "Presence bathroom", "name": "Christmas tree",
"OccupancyDetected": "EG.Flur.Bewegung" "On": "EG.Esszimmer.Steckdose"
} }
``` ```
### Contact sensor ### Security system
This sensor shows the open / closed state of a contact (door, window, generic ...). This accessory can pilote your intrusion security system. That system can be a physical one operated via SHNG, or a SHNG native logic.
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics) #### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description | | Parameter | Possible values | Mandatory | Description |
|:-------------|:----------------|:----------|:---------------------------------| |:-------------|:----------------|:----------|:-------------------------------------------------|
| ContactState | \<item> | Yes | SHNG item to monitor for contact | | CurrentState | \<item> | Yes | SHNG item to monitor for the current alarm state |
| TargetState | \<item> | Yes | SHNG item to set or get the target state |
#### Additional comments
Valid values for 'CurrentState':
* STAY_ARM = 0
* AWAY_ARM = 1
* NIGHT_ARM = 2
* DISARMED = 3
* ALARM_TRIGGERED = 4
Valid values for 'TargetState':
* STAY_ARM = 0
* AWAY_ARM = 1
* NIGHT_ARM = 2
* DISARMED = 3
#### Example: #### Example:
```json ```json
{ {
"type": "ContactSensor", "type": "SecuritySystem",
"name": "Window kitchen", "name": "Intrusion alarm",
"ContactState": "EG.Kueche.Fenster" "currentState": "Technik.Alarmanlage.Status.Ist",
"targetState": "Technik.Alarmanlage.Status.Soll"
} }
``` ```
@@ -253,26 +354,8 @@ This accessory can monitor and change the on/off state of something. It is very
} }
``` ```
### Outlet
This accessory can monitor and change the on/off state of a wall outlet. The outlet can be generic, a light, a fan, ...
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description |
|:----------|:----------------|:----------|:-------------------------------------|
| On | \<item> | Yes | SHNG item to switch outlet on or off |
#### Example:
```json
{
"type": "Outlet",
"name": "Christmas tree",
"On": "EG.Esszimmer.Steckdose"
}
```
### Temperature sensor ### Temperature sensor
This sensor show the actual temperature. This sensor shows the actual temperature.
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics) #### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
| Parameter | Possible values | Mandatory | Description | | Parameter | Possible values | Mandatory | Description |
@@ -313,7 +396,7 @@ CurrentHeatingCoolingState = 0 for OFF, 1 for HEAT and 2 for COOL
} }
``` ```
### WindowCovering ### Window covering
This accessory type can be used for shutters or blinds. Because the differnce between HomeKit and the controlling technology, for example KNX, can be significant this accessory has a lot of parameters. Luckily most are optional. This accessory type can be used for shutters or blinds. Because the differnce between HomeKit and the controlling technology, for example KNX, can be significant this accessory has a lot of parameters. Luckily most are optional.
#### Characteristics in addition to [common characteristics](#common-accessories-characteristics) #### Characteristics in addition to [common characteristics](#common-accessories-characteristics)
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "homebridge-smarthomeng", "name": "homebridge-smarthomeng",
"version": "2.0.0", "version": "2.0.4",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "homebridge-smarthomeng", "name": "homebridge-smarthomeng",
"version": "2.0.0", "version": "2.0.4",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"ws": "^8.4.2" "ws": "^8.4.2"
+4 -4
View File
@@ -2,15 +2,15 @@
"private": false, "private": false,
"displayName": "SmartHomeNG", "displayName": "SmartHomeNG",
"name": "homebridge-smarthomeng", "name": "homebridge-smarthomeng",
"version": "2.0.1", "version": "2.0.6",
"description": "A short description about what your plugin does.", "description": "SmartHomeNG plugin for Homebridge",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git://github.com/Foxi352/homebridge-smarthomeng2.git" "url": "git://github.com/Foxi352/homebridge-smarthomeng.git"
}, },
"bugs": { "bugs": {
"url": "https://github.com/Foxi352/homebridge-smarthomeng2/issues" "url": "https://github.com/Foxi352/homebridge-smarthomeng/issues"
}, },
"engines": { "engines": {
"node": ">=14.18.1", "node": ">=14.18.1",
+32 -4
View File
@@ -13,6 +13,7 @@ export class Fan implements AccessoryPlugin {
public name: string; public name: string;
private active = false; private active = false;
private rotationSpeed = 100;
constructor(private readonly platform: SmartHomeNGPlatform, private readonly accessory) { constructor(private readonly platform: SmartHomeNGPlatform, private readonly accessory) {
this.name = accessory.name; this.name = accessory.name;
@@ -22,14 +23,20 @@ export class Fan implements AccessoryPlugin {
this.deviceService.getCharacteristic(this.platform.Characteristic.Active) this.deviceService.getCharacteristic(this.platform.Characteristic.Active)
.onGet(this.getActive.bind(this)) .onGet(this.getActive.bind(this))
.onSet(this.setActive.bind(this)); .onSet(this.setActive.bind(this));
this.platform.shng.addMonitor(accessory.active, this.shngActiveCallback.bind(this));
if (accessory.rotationspeed) {
this.deviceService.getCharacteristic(this.platform.Characteristic.RotationSpeed)
.onGet(this.getRotationSpeed.bind(this))
.onSet(this.setRotationSpeed.bind(this));
this.platform.shng.addMonitor(accessory.rotationspeed, this.shngRotationSpeedCallback.bind(this));
}
this.informationService = this.informationService =
new this.platform.Service.AccessoryInformation() new this.platform.Service.AccessoryInformation()
.setCharacteristic(this.platform.Characteristic.Manufacturer, accessory.manufacturer) .setCharacteristic(this.platform.Characteristic.Manufacturer, accessory.manufacturer)
.setCharacteristic(this.platform.Characteristic.Model, accessory.model) .setCharacteristic(this.platform.Characteristic.Model, accessory.model)
.setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.active); .setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.active);
this.platform.shng.addMonitor(accessory.active, this.shngCallback.bind(this));
this.platform.log.info("Fan '%s' created!", accessory.name); this.platform.log.info("Fan '%s' created!", accessory.name);
} }
@@ -52,8 +59,19 @@ export class Fan implements AccessoryPlugin {
this.platform.shng.setItem(this.accessory.active, this.active); this.platform.shng.setItem(this.accessory.active, this.active);
} }
shngCallback(value: unknown): void { getRotationSpeed(): Nullable<CharacteristicValue> {
this.platform.log.debug('shngCallback:', this.accessory.name, '=', value, '(' + typeof value + ')'); this.platform.log.info('getRotationSpeed:', this.accessory.name, 'is currently', this.rotationSpeed);
return this.rotationSpeed;
}
setRotationSpeed(value: CharacteristicValue) {
this.rotationSpeed = value as number;
this.platform.log.info('setRotationSpeed:', this.accessory.name, 'was set to', this.rotationSpeed);
this.platform.shng.setItem(this.accessory.rotationspeed, this.rotationSpeed);
}
shngActiveCallback(value: unknown): void {
this.platform.log.debug('shngActiveCallback:', this.accessory.name, '=', value, '(' + typeof value + ')');
if (typeof value === 'boolean') { if (typeof value === 'boolean') {
this.active = value; this.active = value;
this.deviceService.updateCharacteristic(this.platform.Characteristic.Active, this.active); this.deviceService.updateCharacteristic(this.platform.Characteristic.Active, this.active);
@@ -61,4 +79,14 @@ export class Fan implements AccessoryPlugin {
this.platform.log.warn('Unknown type ', typeof value, 'received for', this.accessory.name + ':', value); this.platform.log.warn('Unknown type ', typeof value, 'received for', this.accessory.name + ':', value);
} }
} }
shngRotationSpeedCallback(value: unknown): void {
this.platform.log.debug('shngRotationSpeedCallback:', this.accessory.name, '=', value, '(' + typeof value + ')');
if (typeof value === 'number') {
this.rotationSpeed = value;
this.deviceService.updateCharacteristic(this.platform.Characteristic.RotationSpeed, this.rotationSpeed);
} else {
this.platform.log.warn('Unknown type ', typeof value, 'received for', this.accessory.name + ':', value);
}
}
} }
+130
View File
@@ -0,0 +1,130 @@
import {
AccessoryPlugin,
CharacteristicValue,
Service,
Nullable,
} from 'homebridge';
import { SmartHomeNGPlatform } from '../platform';
export class GarageDoor implements AccessoryPlugin {
private readonly deviceService: Service;
private readonly informationService: Service;
public name: string;
private targetDoorState = this.platform.Characteristic.CurrentDoorState.CLOSED;
private currentDoorState = this.platform.Characteristic.CurrentDoorState.STOPPED;
private obstructionDetected = false;
constructor(private readonly platform: SmartHomeNGPlatform, private readonly accessory) {
this.name = accessory.name;
this.deviceService = new this.platform.Service.GarageDoorOpener(accessory.name);
// create handlers for required characteristics
this.informationService =
new this.platform.Service.AccessoryInformation()
.setCharacteristic(this.platform.Characteristic.Manufacturer, accessory.manufacturer)
.setCharacteristic(this.platform.Characteristic.Model, accessory.model)
.setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.currentdoorstate);
if (accessory.currentdoorstate) {
this.platform.shng.addMonitor(accessory.currentdoorstate, this.shngCurrentDoorStateCallback.bind(this));
this.deviceService.getCharacteristic(this.platform.Characteristic.CurrentDoorState)
.onGet(this.getCurrentDoorState.bind(this))
.onSet(this.setCurrentDoorState.bind(this));
} else {
this.platform.log.error('GarageDoor: missing \"currentdoorstate\" in config.json!');
}
if (accessory.targetdoorstate) {
this.platform.shng.addMonitor(accessory.targetdoorstate, this.shngTargetDoorStateCallback.bind(this));
this.deviceService.getCharacteristic(this.platform.Characteristic.TargetDoorState)
.onGet(this.getTargetDoorState.bind(this))
.onSet(this.setTargetDoorState.bind(this));
} else {
this.platform.log.error('GarageDoor: missing \"targetdoorstate\" in config.json!');
}
if (accessory.obstructiondetected) {
this.platform.shng.addMonitor(accessory.obstructiondetected, this.shngObstructionDetectedCallback.bind(this));
this.deviceService.getCharacteristic(this.platform.Characteristic.ObstructionDetected)
.onGet(this.getObstructionDetected.bind(this))
.onSet(this.setObstructionDetected.bind(this));
}
this.platform.log.info("GarageDoor '%s' created!", accessory.name);
}
identify(): void {
this.platform.log.info('Identify!');
}
getServices(): Service[] {
return [this.informationService, this.deviceService];
}
getCurrentDoorState(): Nullable<CharacteristicValue> {
this.platform.log.info('getCurrentDoorState:', this.accessory.name, 'is currently', this.currentDoorState);
return this.currentDoorState;
}
setCurrentDoorState(value: CharacteristicValue) {
this.currentDoorState = value as number;
this.platform.log.info('setCurrentDoorState:', this.accessory.name, 'was set to', this.currentDoorState);
this.platform.shng.setItem(this.accessory.currentdoorstate, this.currentDoorState);
}
getTargetDoorState(): Nullable<CharacteristicValue> {
this.platform.log.info('getTargetDoorState:', this.accessory.name, 'is currently', this.targetDoorState);
return this.targetDoorState;
}
setTargetDoorState(value: CharacteristicValue) {
this.targetDoorState = value as number;
this.platform.log.info('setTargetDoorState:', this.accessory.name, 'was set to', this.targetDoorState);
this.platform.shng.setItem(this.accessory.targetdoorstate, this.targetDoorState);
}
getObstructionDetected(): Nullable<CharacteristicValue> {
this.platform.log.info('getObstructionDetected:', this.accessory.name, 'is currently', this.obstructionDetected);
return this.obstructionDetected;
}
setObstructionDetected(value: CharacteristicValue) {
this.obstructionDetected = value as boolean;
this.platform.log.info('setObstructionDetected:', this.accessory.name, 'was set to', this.obstructionDetected);
this.platform.shng.setItem(this.accessory.obstructiondetected, this.obstructionDetected);
}
shngCurrentDoorStateCallback(value: unknown): void {
this.platform.log.debug('shngCurrentDoorStateCallback:', this.accessory.name, '=', value, '(' + typeof value + ')');
if (typeof value === 'number') {
this.currentDoorState = value;
this.deviceService.updateCharacteristic(this.platform.Characteristic.CurrentDoorState, this.currentDoorState);
} else {
this.platform.log.warn('Unknown type ', typeof value, 'received for', this.accessory.name + ':', value);
}
}
shngTargetDoorStateCallback(value: unknown): void {
this.platform.log.debug('shngTargetDoorStateCallback:', this.accessory.name, '=', value, '(' + typeof value + ')');
if (typeof value === 'number') {
this.targetDoorState = value;
this.deviceService.updateCharacteristic(this.platform.Characteristic.TargetDoorState, this.targetDoorState);
} else {
this.platform.log.warn('Unknown type ', typeof value, 'received for', this.accessory.name + ':', value);
}
}
shngObstructionDetectedCallback(value: unknown): void {
this.platform.log.debug('shngObstructionDetectedCallback:', this.accessory.name, '=', value, '(' + typeof value + ')');
if (typeof value === 'boolean') {
this.obstructionDetected = value;
this.deviceService.updateCharacteristic(this.platform.Characteristic.ObstructionDetected, this.obstructionDetected);
} else {
this.platform.log.warn('Unknown type ', typeof value, 'received for', this.accessory.name + ':', value);
}
}
}
+59
View File
@@ -0,0 +1,59 @@
import {
AccessoryPlugin,
CharacteristicValue,
Service,
Nullable,
} from 'homebridge';
import { SmartHomeNGPlatform } from '../platform';
export class HumiditySensor implements AccessoryPlugin {
private readonly deviceService: Service;
private readonly informationService: Service;
public name: string;
private currentHumidity = 0;
constructor(private readonly platform: SmartHomeNGPlatform, private readonly accessory) {
this.name = accessory.name;
this.deviceService = new this.platform.Service.HumiditySensor(accessory.name);
// create handlers for required characteristics
this.deviceService.getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity)
.onGet(this.getCurrentHumidity.bind(this));
this.informationService =
new this.platform.Service.AccessoryInformation()
.setCharacteristic(this.platform.Characteristic.Manufacturer, accessory.manufacturer)
.setCharacteristic(this.platform.Characteristic.Model, accessory.model)
.setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.currenthumidity);
this.platform.shng.addMonitor(accessory.currenthumidity, this.shngCallback.bind(this));
this.platform.log.info('HumiditySensor', accessory.name, 'created!');
}
identify(): void {
this.platform.log.info('Identify!');
}
getServices(): Service[] {
return [this.informationService, this.deviceService];
}
getCurrentHumidity(): Nullable<CharacteristicValue> {
this.platform.log.debug('getCurrentHumidity:', this.accessory.name, '=', this.currentHumidity);
return this.currentHumidity;
}
shngCallback(value: unknown): void {
this.platform.log.debug('shngCallback:', this.accessory.name, '=', value, '(' + typeof value + ')');
if (typeof value === 'number') {
this.currentHumidity = value;
} else {
this.platform.log.warn('Unknown type', typeof value, 'received for', this.accessory.name + ':', value);
}
this.deviceService.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.currentHumidity);
}
}
+94
View File
@@ -0,0 +1,94 @@
import {
AccessoryPlugin,
CharacteristicValue,
Service,
Nullable,
} from 'homebridge';
import { SmartHomeNGPlatform } from '../platform';
export class SecuritySystem implements AccessoryPlugin {
private readonly deviceService: Service;
private readonly informationService: Service;
public name: string;
private currentState = this.platform.Characteristic.SecuritySystemCurrentState.DISARMED;
private targetState = this.platform.Characteristic.SecuritySystemTargetState.DISARM;
constructor(private readonly platform: SmartHomeNGPlatform, private readonly accessory) {
this.name = accessory.name;
this.deviceService = new this.platform.Service.SecuritySystem(accessory.name);
// create handlers for required characteristics
this.deviceService.getCharacteristic(this.platform.Characteristic.SecuritySystemCurrentState)
.onGet(this.handleSecuritySystemCurrentStateGet.bind(this));
this.deviceService.getCharacteristic(this.platform.Characteristic.SecuritySystemTargetState)
.onGet(this.handleSecuritySystemTargetStateGet.bind(this))
.onSet(this.handleSecuritySystemTargetStateSet.bind(this));
this.informationService =
new this.platform.Service.AccessoryInformation()
.setCharacteristic(this.platform.Characteristic.Manufacturer, accessory.manufacturer)
.setCharacteristic(this.platform.Characteristic.Model, accessory.model)
.setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.currentstate);
this.platform.shng.addMonitor(accessory.currentstate, this.shngCurrentStateCallback.bind(this));
this.platform.shng.addMonitor(accessory.targetState, this.shngTargetStateCallback.bind(this));
this.platform.log.info('SecuritySystem', accessory.name, 'created!');
}
identify(): void {
this.platform.log.info('Identify!');
}
getServices(): Service[] {
return [this.informationService, this.deviceService];
}
handleSecuritySystemCurrentStateGet(): Nullable<CharacteristicValue> {
this.platform.log.info(
'handleSecuritySystemCurrentStateGet:',
this.accessory.name, '=',
this.currentState,
);
return this.currentState;
}
handleSecuritySystemTargetStateGet(): Nullable<CharacteristicValue> {
this.platform.log.info(
'handleSecuritySystemTargetStateGet:', this.accessory.name,
'is currently', this.targetState,
);
return this.targetState;
}
handleSecuritySystemTargetStateSet(value: CharacteristicValue) {
this.targetState = value as number;
this.platform.log.info('handleSecuritySystemTargetStateSet:', this.accessory.name, 'was set to', this.targetState);
this.platform.shng.setItem(this.accessory.targetstate, this.targetState);
}
shngCurrentStateCallback(value: unknown): void {
this.platform.log.debug('shngCurrentStateCallback:', this.accessory.name, '=', value, '(' + typeof value + ')');
if (typeof value === 'number') {
this.currentState = value;
this.deviceService.updateCharacteristic(this.platform.Characteristic.SecuritySystemCurrentState, this.currentState);
} else {
this.platform.log.warn('Unknown type ', typeof value, 'received for', this.accessory.name + ':', value);
}
}
shngTargetStateCallback(value: unknown): void {
this.platform.log.debug('shngTargetStateCallback:', this.accessory.name, '=', value, '(' + typeof value + ')');
if (typeof value === 'number') {
this.targetState = value;
this.deviceService.updateCharacteristic(this.platform.Characteristic.SecuritySystemTargetState, this.targetState);
} else {
this.platform.log.warn('Unknown type ', typeof value, 'received for', this.accessory.name + ':', value);
}
}
}
+1 -1
View File
@@ -29,7 +29,7 @@ export class Doorbell implements AccessoryPlugin {
.setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.singlepress); .setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.singlepress);
this.platform.shng.addMonitor(accessory.contactstate, this.shngCallback.bind(this)); this.platform.shng.addMonitor(accessory.contactstate, this.shngCallback.bind(this));
this.platform.log.info('ContactSensor', accessory.name, 'created!'); this.platform.log.info('Doorbell', accessory.name, 'created!');
} }
identify(): void { identify(): void {
+84 -63
View File
@@ -9,8 +9,6 @@ import {
} from 'homebridge'; } from 'homebridge';
import { SmartHomeNG } from './SmartHomeNG'; import { SmartHomeNG } from './SmartHomeNG';
import { OccupancySensor } from './Accessories/OccupancySensor';
import { MotionSensor } from './Accessories/MotionSensor';
import { Switch } from './Accessories/Switch'; import { Switch } from './Accessories/Switch';
import { Outlet } from './Accessories/Outlet'; import { Outlet } from './Accessories/Outlet';
import { Fan } from './Accessories/Fan'; import { Fan } from './Accessories/Fan';
@@ -20,6 +18,11 @@ import { Thermostat } from './Accessories/Thermostat';
import { WindowCovering } from './Accessories/WindowCovering'; import { WindowCovering } from './Accessories/WindowCovering';
import { ContactSensor } from './Accessories/ContactSensor'; import { ContactSensor } from './Accessories/ContactSensor';
import { Doorbell } from './Accessories/Doorbell'; import { Doorbell } from './Accessories/Doorbell';
import { SecuritySystem } from './Accessories/SecuritySystem';
import { OccupancySensor } from './Accessories/OccupancySensor';
import { MotionSensor } from './Accessories/MotionSensor';
import { GarageDoor } from './Accessories/GarageDoor';
import { HumiditySensor } from './Accessories/HumiditySensor';
function uncapitalizeKeys(obj): Record<string, unknown> { function uncapitalizeKeys(obj): Record<string, unknown> {
function isObject(o: unknown): boolean { function isObject(o: unknown): boolean {
@@ -72,82 +75,100 @@ export class SmartHomeNGPlatform implements StaticPlatformPlugin {
// convert all configured accessory keys to lowercase to tolerate user case errors // convert all configured accessory keys to lowercase to tolerate user case errors
const accessories = JSON.parse(JSON.stringify(uncapitalizeKeys(this.config.accessories))); const accessories = JSON.parse(JSON.stringify(uncapitalizeKeys(this.config.accessories)));
this.log.debug(accessories);
if (Object.keys(accessories).length > 0) {
for (const accessory of accessories) {
if (!accessory.manufacturer) {
accessory.manufacturer = 'SmartHomeNG';
}
if (!accessory.model) {
accessory.model = 'SHNG Item';
}
for (const accessory of accessories) { if (accessory.type !== '') {
if (!accessory.manufacturer) { this.log.info('Parsing accessory:', accessory.name, 'of type', accessory.type);
accessory.manufacturer = 'SmartHomeNG'; // set lo lowercase to ignore user case errors
} switch (accessory.type.toLowerCase()) {
if (!accessory.model) {
accessory.model = 'SHNG Item';
}
if (accessory.type !== '') { // Presence sensor
this.log.info('Parsing accessory:', accessory.name, 'of type', accessory.type); case 'occupancysensor':
// set lo lowercase to ignore user case errors devices.push(new OccupancySensor(this, accessory));
switch (accessory.type.toLowerCase()) { break;
// Motion sensor
case 'motionsensor':
devices.push(new MotionSensor(this, accessory));
break;
// Presence sensor // Contact sensor
case 'occupancysensor': case 'contactsensor':
devices.push(new OccupancySensor(this, accessory)); devices.push(new ContactSensor(this, accessory));
break; break;
// Motion sensor
case 'motionsensor':
devices.push(new MotionSensor(this, accessory));
break;
// Contact sensor // Doorbell
case 'contactsensor': case 'doorbell':
devices.push(new ContactSensor(this, accessory)); devices.push(new Doorbell(this, accessory));
break; break;
// Doorbell // Security system
case 'doorbell': case 'securitysystem':
devices.push(new Doorbell(this, accessory)); devices.push(new SecuritySystem(this, accessory));
break; break;
// Switch // Switch
case 'switch': case 'switch':
devices.push(new Switch(this, accessory)); devices.push(new Switch(this, accessory));
break; break;
// Lightbulb // Lightbulb
case 'lightbulb': case 'lightbulb':
devices.push(new Lightbulb(this, accessory)); devices.push(new Lightbulb(this, accessory));
break; break;
// Outlet // Outlet
case 'outlet': case 'outlet':
devices.push(new Outlet(this, accessory)); devices.push(new Outlet(this, accessory));
break; break;
// Fan (uses Fanv2) // Fan (uses Fanv2)
case 'fan': case 'fan':
devices.push(new Fan(this, accessory)); devices.push(new Fan(this, accessory));
break; break;
// TemperatureSensor // Temperature sensor
case 'temperaturesensor': case 'temperaturesensor':
devices.push(new TemperatureSensor(this, accessory)); devices.push(new TemperatureSensor(this, accessory));
break; break;
// Thermostat // Thermostat
case 'thermostat': case 'thermostat':
devices.push(new Thermostat(this, accessory)); devices.push(new Thermostat(this, accessory));
break; break;
// WindowCovering // WindowCovering
case 'windowcovering': case 'windowcovering':
devices.push(new WindowCovering(this, accessory)); devices.push(new WindowCovering(this, accessory));
break; break;
// Show error for (yet ?) unsupported device // Garage door
default: case 'garagedoor':
this.log.warn('Accessory type', accessory.type, 'for', accessory.name, 'not recognized !'); devices.push(new GarageDoor(this, accessory));
break; break;
// Humidity sensor
case 'humiditysensor':
devices.push(new HumiditySensor(this, accessory));
break;
// Show error for (yet ?) unsupported device
default:
this.log.warn('Accessory type', accessory.type, 'for', accessory.name, 'not recognized !');
break;
}
} else {
this.log.warn('Ignoring accessory (no type given): ' + accessory);
} }
} else {
this.log.warn('Ignoring accessory (no type given): ' + accessory);
} }
} }
callback(devices); callback(devices);
this.log.debug('Finished building accessories list'); this.log.debug('Finished building accessories list');