1
0

4 کامیت‌ها 90c728a2be ... 6634f66820

نویسنده SHA1 پیام تاریخ
  JDierkse 6634f66820 Add SmokeDetectorAccessory 11 ماه پیش
  JDierkse 99bd9361cd Add ThermostatAccessory 11 ماه پیش
  JDierkse 2620420ed5 Add LowBattery and Active states to wireless sensors 11 ماه پیش
  JDierkse e9459044a0 Update Accessories 11 ماه پیش

+ 4 - 14
activityAccessory.ts

@@ -23,9 +23,9 @@ export class activityAccessory extends accessory {
 								typeId: device.id,
 								uniqueId: "Activity." + device.id,
 								deviceName: device.name,
-								switchable: device.switchable,
-								dimmable: "true",
-								detailedType: device.type
+								switchable: "false",
+								dimmable: "false",
+								detailedType: ""
 							}
 							activityDevices.push(object)
 						}
@@ -49,22 +49,12 @@ export class activityAccessory extends accessory {
 			.setCharacteristic(this.platform.Characteristic.Model, 'Domotica-Activity')
 			.setCharacteristic(this.platform.Characteristic.SerialNumber, '08000' + accessory.context.device.typeId)
 
-//*
 		this.service = this.accessory.getService(this.platform.Service.Switch) || this.accessory.addService(this.platform.Service.Switch)
 
 		this.service.getCharacteristic(this.platform.Characteristic.On)
 			.onGet(this.getOn.bind(this))
 			.onSet(this.setOn.bind(this));
-/*/
-		this.service = this.accessory.getService(this.platform.Service.StatefulProgrammableSwitch) || this.accessory.addService(this.platform.Service.StatefulProgrammableSwitch)
 
-		this.service.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchEvent)
-			.onGet(this.getOn.bind(this));
-
-		this.service.getCharacteristic(this.platform.Characteristic.ProgrammableSwitchOutputState)
-			.onGet(this.getOn.bind(this))
-			.onSet(this.setOn.bind(this));
-//*/
 		this.setName(accessory.context.device.deviceName)
 	}
 
@@ -85,7 +75,7 @@ export class activityAccessory extends accessory {
 
 	async setOn(value: CharacteristicValue) {
 		// http://$domoticaIP/external/WebUpdate.php?data=Activity/$id/
-		httpRequest("http://" + this.platform.config.hostname + '/external/WebUpdate.php?data=Activity/' + this.accessory.context.device.typeId + '/')
+		httpRequest("http://" + 'administration-container:8080' + '/external/WebUpdate.php?data=Activity/' + this.accessory.context.device.typeId + '/')
 			.catch((error) => {
 				this.platform.log.debug('activityAccessory::setOn Error ->' + error)
 			})

+ 11 - 9
cameraAccessory.ts

@@ -89,16 +89,18 @@ export class cameraAccessory extends accessory {
 			.then((response) => {
 				const devices = JSON.parse(response.body)
 
-				for (const device of devices.camera) {
-					if (device.id == this.accessory.context.device.typeId) {
-						if (device.motionstate == 'absent') {
-							this.state.Motion = false
-						} else { // present
-							this.state.Motion = true
+				if (devices.hasOwnProperty('camera')) {
+					for (const device of devices.camera) {
+						if (device.id == this.accessory.context.device.typeId) {
+							if (device.motionstate == 'absent') {
+								this.state.Motion = false
+							} else { // present
+								this.state.Motion = true
+							}
+							return this.state.Motion
+							this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.state.Motion)
+							break
 						}
-						return this.state.Motion
-						this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.state.Motion)
-						break
 					}
 				}
 			})

+ 60 - 41
doorWindowSensorAccessory.ts

@@ -9,7 +9,9 @@ export class doorWindowSensorAccessory extends accessory {
 	private service: Service
 
 	private state = {
-		Position: this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED
+		ContactSensorState: this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED,
+		LowBattery: false,
+		Active: false
 	}
 
 	static async discoverDevices(platform: domoticaPlatform): Promise<device[]> {
@@ -61,16 +63,13 @@ export class doorWindowSensorAccessory extends accessory {
 
 		this.service.getCharacteristic(this.platform.Characteristic.ContactSensorState)
 			.onGet(this.getContactSensorState.bind(this));
-/*
-		this.service.getCharacteristic(this.platform.Characteristic.CurrentPosition)
-			.onGet(this.getCurrentPosition.bind(this));
 
-		this.service.getCharacteristic(this.platform.Characteristic.PositionState)
-			.onGet(this.getPositionState.bind(this));
+		this.service.getCharacteristic(this.platform.Characteristic.StatusLowBattery)
+			.onGet(this.getLowBattery.bind(this))
+		
+		this.service.getCharacteristic(this.platform.Characteristic.StatusActive)
+			.onGet(this.getActive.bind(this))
 
-		this.service.getCharacteristic(this.platform.Characteristic.TargetPosition)
-			.onGet(this.getTargetPosition.bind(this))
-*/
 		this.setName(accessory.context.device.deviceName)
 		this.update()
 	}
@@ -82,14 +81,27 @@ export class doorWindowSensorAccessory extends accessory {
 	setValue(key, value) {
 		if (key == "state" && value != "") {
 			if (value == "Off") {
-				this.state.Position = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED
+				this.state.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED
 			} else {
-				this.state.Position = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
+				this.state.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
 			}
-/*
-			this.service.updateCharacteristic(this.platform.Characteristic.CurrentPosition, this.state.Position)
-			this.service.updateCharacteristic(this.platform.Characteristic.TargetPosition, this.state.Position)
-*/
+			this.service.updateCharacteristic(this.platform.Characteristic.ContactSensorState, this.state.ContactSensorState)
+		}
+		else if (key == "battery" && value != "") {
+			if (value < 25) {
+				this.state.LowBattery = true
+			} else {
+				this.state.LowBattery = false
+			}
+			this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+		}
+		else if (key == "online" && value != "") {
+			if (value == "false") {
+				this.state.Active = false
+			} else {
+				this.state.Active = true
+			}
+			this.service.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
 		}
 	}
 
@@ -103,18 +115,33 @@ export class doorWindowSensorAccessory extends accessory {
 			.then((response) => {
 				const devices = JSON.parse(response.body)
 
-				for (const device of devices.doorwindow) {
-					if (device.id == this.accessory.context.device.typeId) {
-						if (device.state == 'closed') {
-							this.state.Position = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED
-						} else { // open
-							this.state.Position = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
+				if (devices.hasOwnProperty('doorwindow')) {
+					for (const device of devices.doorwindow) {
+						if (device.id == this.accessory.context.device.typeId) {
+							if (device.state == 'closed') {
+								this.state.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_DETECTED
+							} else { // open
+								this.state.ContactSensorState = this.platform.Characteristic.ContactSensorState.CONTACT_NOT_DETECTED
+							}
+
+							if (device.battery < 25) {
+								this.state.LowBattery = true
+							} else {
+								this.state.LowBattery = false
+							}
+
+							if (device.online == "false") {
+								this.state.Active = false
+							} else {
+								this.state.Active = true
+							}
+
+							this.service.updateCharacteristic(this.platform.Characteristic.ContactSensorState, this.state.ContactSensorState)
+							this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+							this.service.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+
+							break
 						}
-/*
-						this.service.updateCharacteristic(this.platform.Characteristic.CurrentPosition, this.state.Position)
-						this.service.updateCharacteristic(this.platform.Characteristic.TargetPosition, this.state.Position)
-*/
-						break
 					}
 				}
 			})
@@ -122,24 +149,16 @@ export class doorWindowSensorAccessory extends accessory {
 				this.platform.log.debug('doorWindowSensorAccessory::update Error ->' + error)
 			})
 	}
-/*
-	getCurrentPosition(): CharacteristicValue {
-		return this.state.Position
-	}
 
-	getPositionState(): CharacteristicValue {
-		return this.platform.Characteristic.PositionState.STOPPED;
+	getContactSensorState(): CharacteristicValue {
+		return this.state.ContactSensorState
 	}
 
-	getTargetPosition(): CharacteristicValue {
-		return this.state.Position
+	getLowBattery(): CharacteristicValue {
+		return this.state.LowBattery
 	}
 
-	getPosition(): CharacteristicValue {
-		return this.state.Position
-	}
-*/
-	getContactSensorState(): CharacteristicValue {
-		return this.state.Position
+	getActive(): CharacteristicValue {
+		return this.state.Active
 	}
-}
+}

+ 67 - 9
environmentSensorAccessory.ts

@@ -11,7 +11,9 @@ export class environmentSensorAccessory extends accessory {
 
 	private state = {
 		Temperature: 0,
-		Humidity: 0
+		Humidity: 0,
+		LowBattery: false,
+		Active: false
 	}
 
 	static async discoverDevices(platform: domoticaPlatform): Promise<device[]> {
@@ -63,6 +65,16 @@ export class environmentSensorAccessory extends accessory {
 		this.serviceHumidity.getCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity)
 			.onGet(this.getHumidity.bind(this))
 
+		this.serviceTemperature.getCharacteristic(this.platform.Characteristic.StatusLowBattery)
+			.onGet(this.getLowBattery.bind(this))
+		this.serviceHumidity.getCharacteristic(this.platform.Characteristic.StatusLowBattery)
+			.onGet(this.getLowBattery.bind(this))
+
+		this.serviceTemperature.getCharacteristic(this.platform.Characteristic.StatusActive)
+			.onGet(this.getActive.bind(this))
+		this.serviceHumidity.getCharacteristic(this.platform.Characteristic.StatusActive)
+			.onGet(this.getActive.bind(this))
+
 		this.setName(accessory.context.device.deviceName)
 		this.update()
 	}
@@ -77,10 +89,28 @@ export class environmentSensorAccessory extends accessory {
 			this.state.Temperature = value / 100
 			this.serviceTemperature.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.state.Temperature)
 		}
-		if (key == "humidity" && value != "") {
+		else if (key == "humidity" && value != "") {
 			this.state.Humidity = value / 100
 			this.serviceHumidity.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.state.Humidity)
 		}
+		else if (key == "battery" && value != "") {
+			if (value < 25) {
+				this.state.LowBattery = true
+			} else {
+				this.state.LowBattery = false
+			}
+			this.serviceTemperature.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+			this.serviceHumidity.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+		}
+		else if (key == "online" && value != "") {
+			if (value == "false") {
+				this.state.Active = false
+			} else {
+				this.state.Active = true
+			}
+			this.serviceTemperature.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+			this.serviceHumidity.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+		}
 	}
 
 	update() {
@@ -93,13 +123,33 @@ export class environmentSensorAccessory extends accessory {
 			.then((response) => {
 				const devices = JSON.parse(response.body)
 
-				for (const device of devices.environment) {
-					if (device.id == this.accessory.context.device.typeId) {
-						this.state.Temperature = device.temperature
-						this.state.Humidity = device.humidity
-						this.serviceTemperature.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.state.Temperature)
-						this.serviceHumidity.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.state.Humidity)
-						break
+				if (devices.hasOwnProperty('environment')) {
+					for (const device of devices.environment) {
+						if (device.id == this.accessory.context.device.typeId) {
+							this.state.Temperature = device.temperature
+							this.state.Humidity = device.humidity
+
+							if (device.battery < 25) {
+								this.state.LowBattery = true
+							} else {
+								this.state.LowBattery = false
+							}
+
+							if (device.online == "false") {
+								this.state.Active = false
+							} else {
+								this.state.Active = true
+							}
+
+							this.serviceTemperature.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.state.Temperature)
+							this.serviceHumidity.updateCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity, this.state.Humidity)
+							this.serviceTemperature.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+							this.serviceTemperature.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+							this.serviceHumidity.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+							this.serviceHumidity.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+
+							break
+						}
 					}
 				}
 			})
@@ -115,4 +165,12 @@ export class environmentSensorAccessory extends accessory {
 	getHumidity(): CharacteristicValue {
 		return this.state.Humidity
 	}
+
+	getLowBattery(): CharacteristicValue {
+		return this.state.LowBattery
+	}
+
+	getActive(): CharacteristicValue {
+		return this.state.Active
+	}
 }

+ 5 - 0
httpServer.ts

@@ -59,6 +59,11 @@ export class httpServer {
 					}
 				}
 
+				if (type == "Toon") {
+					type = "Thermostat"
+				}
+
+
 				var foundAccessory
 
 				for (const accessory of this.platform.accessories) {

+ 17 - 15
klikAanKlikUitAccessory.ts

@@ -94,21 +94,23 @@ export class klikAanKlikUitAccessory extends accessory {
 			.then((response) => {
 				const devices = JSON.parse(response.body)
 
-				for (const device of devices.klikaanklikuit) {
-					if (device.id == this.accessory.context.device.typeId) {
-						if (device.state == 'on') {
-							this.state.On = true
-						} else {
-							this.state.On = false
-						}
-						this.service.updateCharacteristic(this.platform.Characteristic.On, this.state.On)
+				if (devices.hasOwnProperty('klikaanklikuit')) {
+					for (const device of devices.klikaanklikuit) {
+						if (device.id == this.accessory.context.device.typeId) {
+							if (device.state == 'on') {
+								this.state.On = true
+							} else {
+								this.state.On = false
+							}
+							this.service.updateCharacteristic(this.platform.Characteristic.On, this.state.On)
 
-						if (device.dimmable != 'false') { // WTF?
-							this.state.Brightness = device.dimLevel;
-							this.service.updateCharacteristic(this.platform.Characteristic.Brightness, this.state.Brightness)
-						}
+							if (device.dimmable != 'false') { // WTF?
+								this.state.Brightness = device.dimLevel;
+								this.service.updateCharacteristic(this.platform.Characteristic.Brightness, this.state.Brightness)
+							}
 
-						break
+							break
+						}
 					}
 				}
 			})
@@ -121,7 +123,7 @@ export class klikAanKlikUitAccessory extends accessory {
 		this.state.On = value as boolean
 
 		// http://$domoticaIP/external/WebUpdate.php?data=KlikAanKlikUit/$id/$state/
-		httpRequest("http://" + this.platform.config.hostname + '/external/WebUpdate.php?data=KlikAanKlikUit/' + this.accessory.context.device.typeId + '/' + (this.state.On? '1': '0') + '/')
+		httpRequest("http://" + 'administration-container:8080' + '/external/WebUpdate.php?data=KlikAanKlikUit/' + this.accessory.context.device.typeId + '/' + (this.state.On? '1': '0') + '/')
 			.catch((error) => {
 				this.platform.log.debug('klikAanKlikUitAccessory::setOn Error ->' + error)
 			})
@@ -135,7 +137,7 @@ export class klikAanKlikUitAccessory extends accessory {
 		this.state.Brightness = value as number
 
 		// http://$domoticaIP/external/WebUpdate.php?data=KlikAanKlikUit/$id/$state/$dimLevel
-		httpRequest("http://" + this.platform.config.hostname + '/external/WebUpdate.php?data=KlikAanKlikUit/' + this.accessory.context.device.typeId + '//' + this.state.Brightness)
+		httpRequest("http://" + 'administration-container:8080' + '/external/WebUpdate.php?data=KlikAanKlikUit/' + this.accessory.context.device.typeId + '//' + this.state.Brightness)
 			.catch((error) => {
 				this.platform.log.debug('klikAanKlikUitAccessory::setBrightness Error ->' + error)
 			})

+ 60 - 11
motionSensorAccessory.ts

@@ -9,7 +9,9 @@ export class motionSensorAccessory extends accessory {
 	private service: Service
 
 	private state = {
-		Motion: false
+		Motion: false,
+		LowBattery: false,
+		Active: false
 	}
 
 	static async discoverDevices(platform: domoticaPlatform): Promise<device[]> {
@@ -58,6 +60,12 @@ export class motionSensorAccessory extends accessory {
 		this.service.getCharacteristic(this.platform.Characteristic.MotionDetected)
 			.onGet(this.getState.bind(this));
 
+		this.service.getCharacteristic(this.platform.Characteristic.StatusLowBattery)
+			.onGet(this.getLowBattery.bind(this))
+		
+		this.service.getCharacteristic(this.platform.Characteristic.StatusActive)
+			.onGet(this.getActive.bind(this))
+
 		this.setName(accessory.context.device.deviceName)
 		this.update()
 	}
@@ -75,6 +83,22 @@ export class motionSensorAccessory extends accessory {
 			}
 			this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.state.Motion)
 		}
+		else if (key == "battery" && value != "") {
+			if (value < 25) {
+				this.state.LowBattery = true
+			} else {
+				this.state.LowBattery = false
+			}
+			this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+		}
+		else if (key == "online" && value != "") {
+			if (value == "false") {
+				this.state.Active = false
+			} else {
+				this.state.Active = true
+			}
+			this.service.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+		}
 	}
 
 	update() {
@@ -87,16 +111,33 @@ export class motionSensorAccessory extends accessory {
 			.then((response) => {
 				const devices = JSON.parse(response.body)
 
-				for (const device of devices.motion) {
-					if (device.id == this.accessory.context.device.typeId) {
-						if (device.state == 'absent') {
-							this.state.Motion = false
-						} else { // present
-							this.state.Motion = true	
+				if (devices.hasOwnProperty('motion')) {
+					for (const device of devices.motion) {
+						if (device.id == this.accessory.context.device.typeId) {
+							if (device.state == 'absent') {
+								this.state.Motion = false
+							} else { // present
+								this.state.Motion = true	
+							}
+
+							if (device.battery < 25) {
+								this.state.LowBattery = true
+							} else {
+								this.state.LowBattery = false
+							}
+
+							if (device.online == "false") {
+								this.state.Active = false
+							} else {
+								this.state.Active = true
+							}
+
+							this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.state.Motion)
+							this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+							this.service.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+
+							break
 						}
-						return this.state.Motion
-						this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, this.state.Motion)
-						break
 					}
 				}
 			})
@@ -108,4 +149,12 @@ export class motionSensorAccessory extends accessory {
 	getState(): CharacteristicValue {
 		return this.state.Motion
 	}
-}
+
+	getLowBattery(): CharacteristicValue {
+		return this.state.LowBattery
+	}
+
+	getActive(): CharacteristicValue {
+		return this.state.Active
+	}
+}

+ 54 - 9
platform.ts

@@ -11,7 +11,10 @@ import { environmentSensorAccessory } from './environmentSensorAccessory'
 import { doorWindowSensorAccessory } from './doorWindowSensorAccessory'
 import { motionSensorAccessory } from './motionSensorAccessory'
 import { cameraAccessory } from './cameraAccessory'
-import { activityAccessory } from './activityAccessory'
+//import { activityAccessory } from './activityAccessory'
+import { thermostatAccessory } from './thermostatAccessory'
+import { smokeDetectorAccessory } from './smokeDetectorAccessory'
+import { securitySystemAccessory } from './securitySystemAccessory'
 import { httpServer } from './httpServer'
 
 export class domoticaPlatform implements DynamicPlatformPlugin {
@@ -113,14 +116,44 @@ export class domoticaPlatform implements DynamicPlatformPlugin {
 				this.log.debug('cameraAccessory.discoverDevices Error ->' + error)
 			})
 
-		this.discoveryStarted('activityAccessory')
-		activityAccessory.discoverDevices(this)
+//		this.discoveryStarted('activityAccessory')
+//		activityAccessory.discoverDevices(this)
+//			.then((devices) => {
+//				this.processDiscoveredDevices(devices)
+//				this.discoveryCompleted('activityAccessory')
+//			})
+//			.catch((error) => {
+//				this.log.debug('activityAccessory.discoverDevices Error ->' + error)
+//			})
+
+		this.discoveryStarted('thermostatAccessory')
+		thermostatAccessory.discoverDevices(this)
+			.then((devices) => {
+				this.processDiscoveredDevices(devices)
+				this.discoveryCompleted('thermostatAccessory')
+			})
+			.catch((error) => {
+				this.log.debug('thermostatAccessory.discoverDevices Error ->' + error)
+			})
+
+		this.discoveryStarted('smokeDetectorAccessory')
+		smokeDetectorAccessory.discoverDevices(this)
+			.then((devices) => {
+				this.processDiscoveredDevices(devices)
+				this.discoveryCompleted('smokeDetectorAccessory')
+			})
+			.catch((error) => {
+				this.log.debug('smokeDetectorAccessory.discoverDevices Error ->' + error)
+			})
+
+		this.discoveryStarted('securitySystemAccessory')
+		securitySystemAccessory.discoverDevices(this)
 			.then((devices) => {
 				this.processDiscoveredDevices(devices)
-				this.discoveryCompleted('activityAccessory')
+				this.discoveryCompleted('securitySystemAccessory')
 			})
 			.catch((error) => {
-				this.log.debug('activityAccessory.discoverDevices Error ->' + error)
+				this.log.debug('securitySystemAccessory.discoverDevices Error ->' + error)
 			})
 	}
 
@@ -154,8 +187,14 @@ export class domoticaPlatform implements DynamicPlatformPlugin {
 					this.accessories.push(new motionSensorAccessory(this, existingAccessory))
 				} else if (existingAccessory.context.device.type == 'Camera') {
 					this.accessories.push(new cameraAccessory(this, existingAccessory))
-				} else if (existingAccessory.context.device.type == 'Activity') {
-					this.accessories.push(new activityAccessory(this, existingAccessory))
+//				} else if (existingAccessory.context.device.type == 'Activity') {
+//					this.accessories.push(new activityAccessory(this, existingAccessory))
+				} else if (existingAccessory.context.device.type == 'Thermostat') {
+					this.accessories.push(new thermostatAccessory(this, existingAccessory))
+				} else if (existingAccessory.context.device.type == 'SmokeDetector') {
+					this.accessories.push(new smokeDetectorAccessory(this, existingAccessory))
+				} else if (existingAccessory.context.device.type == 'SecuritySystem') {
+					this.accessories.push(new securitySystemAccessory(this, existingAccessory))
 				}
 			} else {
 				this.log.info('+ ' + device.type + ': ' + device.deviceName)
@@ -177,8 +216,14 @@ export class domoticaPlatform implements DynamicPlatformPlugin {
 					this.accessories.push(new motionSensorAccessory(this, accessory))
 				} else if (accessory.context.device.type == 'Camera') {
 					this.accessories.push(new cameraAccessory(this, accessory))
-				} else if (accessory.context.device.type == 'Activity') {
-					this.accessories.push(new activityAccessory(this, accessory))
+//				} else if (accessory.context.device.type == 'Activity') {
+//					this.accessories.push(new activityAccessory(this, accessory))
+				} else if (accessory.context.device.type == 'Thermostat') {
+					this.accessories.push(new thermostatAccessory(this, accessory))
+				} else if (accessory.context.device.type == 'SmokeDetector') {
+					this.accessories.push(new smokeDetectorAccessory(this, accessory))
+				} else if (accessory.context.device.type == 'SecuritySystem') {
+					this.accessories.push(new securitySystemAccessory(this, accessory))
 				}
 
 				this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory])

+ 11 - 9
powerSocketAccessory.ts

@@ -94,15 +94,17 @@ export class powerSocketAccessory extends accessory {
 			.then((response) => {
 				const devices = JSON.parse(response.body)
 
-				for (const device of devices.powersocket) {
-					if (device.id == this.accessory.context.device.typeId) {
-						if (device.state == 'on') {
-							this.state.On = true
-						} else {
-							this.state.On = false
+				if (devices.hasOwnProperty('powersocket')) {
+					for (const device of devices.powersocket) {
+						if (device.id == this.accessory.context.device.typeId) {
+							if (device.state == 'on') {
+								this.state.On = true
+							} else {
+								this.state.On = false
+							}
+							this.service.updateCharacteristic(this.platform.Characteristic.On, this.state.On)
+							break
 						}
-						this.service.updateCharacteristic(this.platform.Characteristic.On, this.state.On)
-						break
 					}
 				}
 			})
@@ -115,7 +117,7 @@ export class powerSocketAccessory extends accessory {
 		this.state.On = value as boolean
 
 		// http://$domoticaIP/external/WebUpdate.php?data=PowerSocket/$id/$state/
-		httpRequest("http://" + this.platform.config.hostname + '/external/WebUpdate.php?data=PowerSocket/' + this.accessory.context.device.typeId + '/' + (this.state.On? '1': '0') + '/')
+		httpRequest("http://" + 'administration-container:8080' + '/external/WebUpdate.php?data=PowerSocket/' + this.accessory.context.device.typeId + '/' + (this.state.On? '1': '0') + '/')
 			.catch((error) => {
 				this.platform.log.debug('powerSocketAccessory::setOn Error ->' + error)
 			})

+ 16 - 14
powerSwitchAccessory.ts

@@ -100,20 +100,22 @@ export class powerSwitchAccessory extends accessory {
 			.then((response) => {
 				const devices = JSON.parse(response.body)
 
-				for (const device of devices.powerswitch) {
-					if (device.id == this.accessory.context.device.typeId) {
-						if (device.state == 'on') {
-							this.state.On = true
-						} else {
-							this.state.On = false
-						}
-						this.service.updateCharacteristic(this.platform.Characteristic.On, this.state.On)
+				if (devices.hasOwnProperty('powerswitch')) {
+					for (const device of devices.powerswitch) {
+						if (device.id == this.accessory.context.device.typeId) {
+							if (device.state == 'on') {
+								this.state.On = true
+							} else {
+								this.state.On = false
+							}
+							this.service.updateCharacteristic(this.platform.Characteristic.On, this.state.On)
 
-						if (device.dimmable != 'false') { // WTF?
-							this.state.Brightness = device.dimlevel;
-							this.service.updateCharacteristic(this.platform.Characteristic.Brightness, this.state.Brightness)
+							if (device.dimmable != 'false') { // WTF?
+								this.state.Brightness = device.dimlevel;
+								this.service.updateCharacteristic(this.platform.Characteristic.Brightness, this.state.Brightness)
+							}
+							break
 						}
-						break
 					}
 				}
 			})
@@ -126,7 +128,7 @@ export class powerSwitchAccessory extends accessory {
 		this.state.On = value as boolean
 
 		// http://$domoticaIP/external/WebUpdate.php?data=PowerSwitch/$id/$state/
-		httpRequest("http://" + this.platform.config.hostname + '/external/WebUpdate.php?data=PowerSwitch/' + this.accessory.context.device.typeId + '/' + (this.state.On? '1': '0') + '/')
+		httpRequest("http://" + 'administration-container:8080' + '/external/WebUpdate.php?data=PowerSwitch/' + this.accessory.context.device.typeId + '/' + (this.state.On? '1': '0') + '/')
 			.catch((error) => {
 				this.platform.log.debug('powerSwitchAccessory::setOn Error ->' + error)
 			})
@@ -140,7 +142,7 @@ export class powerSwitchAccessory extends accessory {
 		this.state.Brightness = value as number
 
 		// http://$domoticaIP/external/WebUpdate.php?data=PowerSwitch/$id/$state/$dimLevel
-		httpRequest("http://" + this.platform.config.hostname + '/external/WebUpdate.php?data=PowerSwitch/' + this.accessory.context.device.typeId + '//' + this.state.Brightness)
+		httpRequest("http://" + 'administration-container:8080' + '/external/WebUpdate.php?data=PowerSwitch/' + this.accessory.context.device.typeId + '///' + this.state.Brightness)
 			.catch((error) => {
 				this.platform.log.debug('powerSwitchAccessory::setBrightness Error ->' + error)
 			})

+ 160 - 0
smokeDetectorAccessory.ts

@@ -0,0 +1,160 @@
+import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge'
+
+import { accessory } from './accessory'
+import { device } from './device'
+import { httpRequest, response } from './httpPromise'
+import { domoticaPlatform } from './platform'
+
+export class smokeDetectorAccessory extends accessory {
+	private service: Service
+
+    private state = {
+		SmokeDetected: false,
+		Tampered: false, // TODO
+		LowBattery: false,
+		Active: false
+	}
+
+	static async discoverDevices(platform: domoticaPlatform): Promise<device[]> {
+		return new Promise((resolve, reject) => {
+			let smokedetectorDevices: device[] = []
+
+			httpRequest("http://" + platform.config.hostname + ':' + platform.config.port + '/API/inventory/smokedetector')
+				.then((response) => {
+					let devices = JSON.parse(response.body)
+
+					for (const device of devices) {
+						if (device.enabled == "true") {
+							let object: device = {
+								type: "SmokeDetector",
+								typeId: device.id,
+								uniqueId: "SmokeDetector." + device.id,
+								deviceName: device.name,
+								switchable: "false",
+								dimmable: "false",
+								detailedType: device.type
+							}
+							smokedetectorDevices.push(object)
+						}
+					}
+				
+					resolve(smokedetectorDevices)
+				})
+				.catch((error) => {
+					reject('smokeDetectorAccessory::discoverDevices Error ->' + error)
+				})
+		})
+	}
+
+	constructor(
+		private readonly platform: domoticaPlatform,
+		private readonly accessory: PlatformAccessory,
+	) {
+		super("SmokeDetector", accessory.context.device.typeId)
+		this.accessory.getService(this.platform.Service.AccessoryInformation)!
+			.setCharacteristic(this.platform.Characteristic.Manufacturer, 'SmokeDetector')
+			.setCharacteristic(this.platform.Characteristic.Model, 'ZSDR-850')
+			.setCharacteristic(this.platform.Characteristic.SerialNumber, '10000' + accessory.context.device.typeId)
+
+		this.service = this.accessory.getService(this.platform.Service.SmokeSensor) || this.accessory.addService(this.platform.Service.SmokeSensor)
+
+		this.service.getCharacteristic(this.platform.Characteristic.SmokeDetected)
+			.onGet(this.getSmokeDetected.bind(this))
+		
+		this.service.getCharacteristic(this.platform.Characteristic.StatusLowBattery)
+			.onGet(this.getLowBattery.bind(this))
+
+		this.service.getCharacteristic(this.platform.Characteristic.StatusActive)
+			.onGet(this.getActive.bind(this))
+
+		this.setName(accessory.context.device.deviceName)
+		this.update()
+	}
+
+	setName(name) {
+		this.service.setCharacteristic(this.platform.Characteristic.Name, name)
+	}
+
+	setValue(key, value) {
+		if (key == "state" && value != "") {
+			if (value == "smoke") {
+				this.state.SmokeDetected = true
+			} else {
+				this.state.SmokeDetected = false
+			}
+			this.service.updateCharacteristic(this.platform.Characteristic.SmokeDetected, this.state.SmokeDetected)
+		}
+		else if (key == "battery" && value != "") {
+			if (value < 25) {
+				this.state.LowBattery = true
+			} else {
+				this.state.LowBattery = false
+			}
+			this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+		}
+		else if (key == "online" && value != "") {
+			if (value == "false") {
+				this.state.Active = false
+			} else {
+				this.state.Active = true
+			}
+			this.service.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+		}
+	}
+
+	update() {
+		const data = JSON.stringify([{
+			type: 'smokedetector',
+			query: 'state'
+		}])
+
+ 		httpRequest("http://" + this.platform.config.hostname + ':' + this.platform.config.port + '/API/Status', data)
+			.then((response) => {
+				const devices = JSON.parse(response.body)
+
+				if (devices.hasOwnProperty('smokedetector')) {
+					for (const device of devices.smokedetector) {
+						if (device.id == this.accessory.context.device.typeId) {
+							if (device.state == 'smoke') {
+								this.state.SmokeDetected = true
+							} else {
+								this.state.SmokeDetected = false
+							}
+							if (device.battery < 25) {
+								this.state.LowBattery = true
+							} else {
+								this.state.LowBattery = false
+							}
+
+							if (device.online == "false") {
+								this.state.Active = false
+							} else {
+								this.state.Active = true
+							}
+
+							this.service.updateCharacteristic(this.platform.Characteristic.SmokeDetected, this.state.SmokeDetected)
+							this.service.updateCharacteristic(this.platform.Characteristic.StatusLowBattery, this.state.LowBattery)
+							this.service.updateCharacteristic(this.platform.Characteristic.StatusActive, this.state.Active)
+
+							break
+						}
+					}
+				}
+			})
+			.catch((error) => {
+				this.platform.log.debug('smokeDetectorAccessory::update Error ->' + error)
+			})
+	}
+
+	getSmokeDetected(): CharacteristicValue {
+		return this.state.SmokeDetected
+	}
+
+	getLowBattery(): CharacteristicValue {
+		return this.state.LowBattery
+	}
+
+	getActive(): CharacteristicValue {
+		return this.state.Active
+	}
+}

+ 208 - 0
thermostatAccessory.ts

@@ -0,0 +1,208 @@
+import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge'
+
+import { accessory } from './accessory'
+import { device } from './device'
+import { httpRequest, response } from './httpPromise'
+import { domoticaPlatform } from './platform'
+
+export class thermostatAccessory extends accessory {
+	private service: Service
+
+	private state = {
+		CurrentHeatingCoolingState: 0,
+		TargetHeatingCoolingState: 0,
+		CurrentTemperature: 0.0,
+		TargetTemperature: 10.0,
+		TemperatureDisplayUnits: 0
+	}
+
+	static async discoverDevices(platform: domoticaPlatform): Promise<device[]> {
+		return new Promise((resolve, reject) => {
+			let thermostatDevices: device[] = []
+
+			httpRequest("http://" + platform.config.hostname + ':' + platform.config.port + '/API/inventory/toonthermostat')
+				.then((response) => {
+					let devices = JSON.parse(response.body)
+
+					for (const device of devices) {
+						if (device.enabled == "true") {
+							let object: device = {
+								type: "Thermostat",
+								typeId: device.id,
+								uniqueId: "Thermostat." + device.id,
+								deviceName: device.name,
+								switchable: "false",
+								dimmable: "false",
+								detailedType: ""
+							}
+							thermostatDevices.push(object)
+						}
+					}
+
+					resolve(thermostatDevices)
+				})
+				.catch((error) => {
+					reject('thermostatAccessory::discoverDevices Error ->' + error)
+				})
+		})
+	}
+
+	constructor(
+		private readonly platform: domoticaPlatform,
+		private readonly accessory: PlatformAccessory,
+	) {
+		// https://developers.homebridge.io/#/service/Thermostat
+		super("Thermostat", accessory.context.device.typeId)
+
+		this.accessory.getService(this.platform.Service.AccessoryInformation)!
+			.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Thermostat')
+			.setCharacteristic(this.platform.Characteristic.Model, 'Domotica-Thermostat')
+			.setCharacteristic(this.platform.Characteristic.SerialNumber, '09000' + accessory.context.device.typeId)
+
+		this.service = this.accessory.getService(this.platform.Service.Thermostat) || this.accessory.addService(this.platform.Service.Thermostat)
+
+		this.service.getCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState)
+			.onGet(this.getCurrentHeatingCoolingState.bind(this));
+
+		this.service.getCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState)
+			.onGet(this.getTargetHeatingCoolingState.bind(this));
+			//.onSet(this.setTargetHeatingCoolingState.bind(this));
+
+		this.service.getCharacteristic(this.platform.Characteristic.CurrentTemperature)
+			.onGet(this.getCurrentTemperature.bind(this));
+
+		this.service.getCharacteristic(this.platform.Characteristic.TargetTemperature)
+			.onGet(this.getTargetTemperature.bind(this))
+			.onSet(this.setTargetTemperature.bind(this));
+
+		this.service.getCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits)
+			.onGet(this.getTemperatureDisplayUnits.bind(this));
+			//.onSet(this.setTemperatureDisplayUnits.bind(this));
+	
+		this.setName(accessory.context.device.deviceName)
+		this.update()
+	}
+
+	setName(name) {
+		this.service.setCharacteristic(this.platform.Characteristic.Name, name)
+	}
+
+	setValue(key, value) {
+		if (key == "burnerState" && value != "") {
+			if (value == 'Off') {
+				this.state.CurrentHeatingCoolingState = this.platform.Characteristic.CurrentHeatingCoolingState.OFF
+				this.state.TargetHeatingCoolingState = this.platform.Characteristic.CurrentHeatingCoolingState.OFF
+				
+			} else {
+				this.state.CurrentHeatingCoolingState = this.platform.Characteristic.CurrentHeatingCoolingState.HEAT
+				this.state.TargetHeatingCoolingState = this.platform.Characteristic.CurrentHeatingCoolingState.HEAT
+			}
+			this.service.updateCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState, this.state.CurrentHeatingCoolingState)
+			this.service.updateCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState, this.state.TargetHeatingCoolingState)
+		} else if (key == "currentSetPoint" && value != "") {
+			this.state.TargetTemperature = value / 100
+			this.service.updateCharacteristic(this.platform.Characteristic.TargetTemperature, this.state.TargetTemperature)
+		} else if (key == "currentTemperature" && value != "") {
+			this.state.CurrentTemperature = value / 100
+			this.service.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.state.CurrentTemperature)
+		}
+	}
+
+	update() {
+		// curl -X POST "http://192.168.101.100:8080/API/Status" -d '[{"type": "toonthermostat", "query": "state"}]'
+		// {"toonthermostat":
+		//	[{"burnerlevel":"low",
+		//	  "burnerstate":"heater",
+		//	  "currentsetpoint":"1800",
+		//	  "currenttemperature":"1805",
+		//	  "device_id":"113",
+		//	  "id":"1",
+		//	  "name":"Toon",
+		//	  "programstate":"off",
+		//	  "temperaturestate":"Home"}]}
+
+		const data = JSON.stringify([{
+			type: 'toonthermostat',
+			query: 'state'
+		}])
+
+		httpRequest("http://" + this.platform.config.hostname + ':' + this.platform.config.port + '/API/Status', data)
+			.then((response) => {
+				const devices = JSON.parse(response.body)
+
+				if (devices.hasOwnProperty('toonthermostat')) {
+					for (const device of devices.toonthermostat) {
+						if (device.id == this.accessory.context.device.typeId) {
+							if (device.burnerstate == 'off') {
+								this.state.CurrentHeatingCoolingState = this.platform.Characteristic.CurrentHeatingCoolingState.OFF
+								this.state.TargetHeatingCoolingState = this.platform.Characteristic.CurrentHeatingCoolingState.OFF
+							} else {
+								this.state.CurrentHeatingCoolingState = this.platform.Characteristic.CurrentHeatingCoolingState.HEAT
+								this.state.TargetHeatingCoolingState = this.platform.Characteristic.CurrentHeatingCoolingState.HEAT
+							}
+
+							this.state.CurrentTemperature = device.currenttemperature / 100
+							this.state.TargetTemperature = device.currentsetpoint / 100
+
+							this.state.TemperatureDisplayUnits = this.platform.Characteristic.TemperatureDisplayUnits.CELSIUS
+
+							this.service.updateCharacteristic(this.platform.Characteristic.CurrentHeatingCoolingState, this.state.CurrentHeatingCoolingState)
+							this.service.updateCharacteristic(this.platform.Characteristic.TargetHeatingCoolingState, this.state.TargetHeatingCoolingState)
+							this.service.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, this.state.CurrentTemperature)
+							this.service.updateCharacteristic(this.platform.Characteristic.TargetTemperature, this.state.TargetTemperature)
+							this.service.updateCharacteristic(this.platform.Characteristic.TemperatureDisplayUnits, this.state.TemperatureDisplayUnits)
+							
+							break
+						}
+					}
+				}
+			})
+			.catch((error) => {
+				this.platform.log.debug('thermostatAccessory::update Error ->' + error)
+			})
+	}
+
+	getCurrentHeatingCoolingState(): CharacteristicValue {
+		// https://developers.homebridge.io/#/characteristic/CurrentHeatingCoolingState
+		return this.state.CurrentHeatingCoolingState
+	}
+
+	getTargetHeatingCoolingState(): CharacteristicValue {
+		// https://developers.homebridge.io/#/characteristic/TargetHeatingCoolingState
+		return this.state.TargetHeatingCoolingState
+	}
+
+	setTargetHeatingCoolingState(value) {
+		// https://developers.homebridge.io/#/characteristic/TargetHeatingCoolingState
+	}
+
+	getCurrentTemperature(): CharacteristicValue {
+		// https://developers.homebridge.io/#/characteristic/CurrentTemperature
+		return this.state.CurrentTemperature
+	}
+
+	getTargetTemperature(): CharacteristicValue {
+		// https://developers.homebridge.io/#/characteristic/TargetTemperature
+		return this.state.TargetTemperature
+	}
+
+	async setTargetTemperature(value) {
+		// https://developers.homebridge.io/#/characteristic/TargetTemperature
+		this.state.TargetTemperature = value
+
+		// http://$domoticaIP/external/WebUpdate.php?data=Toon/$id/
+		httpRequest("http://" + 'administration-container:8080' + '/external/WebUpdate.php?data=Toon/' + this.accessory.context.device.typeId + '///' + (this.state.TargetTemperature * 100))
+			.catch((error) => {
+				this.platform.log.debug('thermostatAccessory::setOn Error ->' + error)
+			})
+	}
+
+	getTemperatureDisplayUnits(): CharacteristicValue {
+		// https://developers.homebridge.io/#/characteristic/TemperatureDisplayUnits
+		return this.state.TemperatureDisplayUnits
+	}
+
+	setTemperatureDisplayUnits(value) {
+		// https://developers.homebridge.io/#/characteristic/TemperatureDisplayUnits
+	}
+}