From aa73f5551d96e21edfd7b427e197bc40d73c847f Mon Sep 17 00:00:00 2001 From: rtuszik Date: Sat, 2 Dec 2023 15:43:15 +0100 Subject: [PATCH] "Enhanced Device Information and Serial Number Handling - Added functionality to parse and set the model name based on serial numbers. - Included method to set 'V-Zug' as the manufacturer for all devices. - Refined JSON parsing for improved model data management. - Enhanced serial number handling for device identification in HomeKit." --- README.md | 13 +- package-lock.json | 4 +- package.json | 2 +- src/VZugAccessory.ts | 51 ++++- src/VZugPlatform.ts | 1 - src/vzugmodel.json | 474 +++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 528 insertions(+), 17 deletions(-) create mode 100644 src/vzugmodel.json diff --git a/README.md b/README.md index c84dec9..ff4bdc5 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,11 @@ Integrate your V-ZUG appliances into Apple HomeKit using this Homebridge plugin, which currently supports status monitoring via an unofficial REST API. This plugin provides a HomeKit switch to reflect the operational status of your V-ZUG appliance, allowing you to check if the device is active. + +## Features + +- **Status Monitoring**: Exposes the operational status of your V-ZUG appliances as a switch in HomeKit, showing if the device is active. + ## Installation 1. **Install Homebridge**: @@ -25,7 +30,6 @@ Add your V-ZUG appliances to your Homebridge `config.json`: "name": "DEVICE_NAME", "ip": "DEVICE_IP_ADDRESS" } - // Add more devices as needed ] } ``` @@ -48,16 +52,15 @@ Add your V-ZUG appliances to your Homebridge `config.json`: } ``` -## Current Functionality - -- **Status Monitoring**: The plugin currently exposes the operational status of your V-ZUG appliances as a switch in HomeKit, showing if the device is active. ## Supported Models - Currently tested with: - - V-Zug CombairSteamer V6000 60 + - V-Zug CombairSteamer V6000 60Y - V-Zug CombairSteamer V6000 45F +The plugin will automatically find the Model and Serial Number of your Device and populate the relevant fields for HomeKit + ## Developer's Note This is my first Homebridge plugin, primarily aimed at status monitoring for V-ZUG appliances. It's pretty basic – mainly showing the on/off status. Since it's my initial release, there might be some room for improvement. I'm open to feedback and suggestions! diff --git a/package-lock.json b/package-lock.json index e74f07a..51eafb8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "homebridge-vzug", - "version": "1.1.1", + "version": "1.2.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "homebridge-vzug", - "version": "1.1.1", + "version": "1.2.0", "license": "Apache-2.0", "dependencies": { "axios": "^1.6.2" diff --git a/package.json b/package.json index cbdf7c0..7eb8ea0 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "displayName": "Homebridge-vzug", "name": "homebridge-vzug", - "version": "1.1.1", + "version": "1.2.0", "description": "Integration of V-ZUG Appliances using unofficial python API", "license": "Apache-2.0", "repository": { diff --git a/src/VZugAccessory.ts b/src/VZugAccessory.ts index 8eb994d..192b03d 100644 --- a/src/VZugAccessory.ts +++ b/src/VZugAccessory.ts @@ -1,10 +1,12 @@ import { Service, PlatformAccessory, Logger, API } from 'homebridge'; import axios from 'axios'; import { DeviceConfig } from './VZugPlatform'; - +import * as fs from 'fs'; +import * as path from 'path'; export class VZugAccessory { private service: Service; + private models: any; // To store the model data constructor( private readonly log: Logger, @@ -12,23 +14,58 @@ export class VZugAccessory { private readonly accessory: PlatformAccessory, private readonly config: DeviceConfig, ) { - // Assuming a Switch Service for demonstration this.service = new this.api.hap.Service.Switch(accessory.displayName); - // Register handlers for the On/Off Characteristic this.service.getCharacteristic(this.api.hap.Characteristic.On) .on('get', this.handleOnGet.bind(this)) .on('set', this.handleOnSet.bind(this)); - // Add the service to the accessory this.accessory.addService(this.service); - // Set up polling to periodically fetch device status + // Load model data + this.models = JSON.parse(fs.readFileSync(path.join(__dirname, 'vzugmodel.json'), 'utf8')); + + this.setSerialNumber(); + this.setManufacturer(); + setInterval(() => { this.fetchDeviceStatus(); - }, 10000); // Poll every 10 seconds (10000 milliseconds) + }, 10000); } + async setSerialNumber() { + try { + const url = `http://${this.config.ip}/ai?command=getDeviceStatus`; + const response = await axios.get(url); + if (response.status === 200) { + const serialNumber = response.data.Serial; + const modelNumber = serialNumber.substring(0, 5); + const modelName = this.findModelName(modelNumber); + + this.accessory.getService(this.api.hap.Service.AccessoryInformation) + .setCharacteristic(this.api.hap.Characteristic.SerialNumber, serialNumber) + .setCharacteristic(this.api.hap.Characteristic.Model, modelName); + } + } catch (error) { + this.log.error('Error fetching serial number:', error instanceof Error ? error.message : 'Unknown error'); + } + } + + findModelName(modelNumber: string): string { + for (const model of this.models) { + if (model.Model.includes(modelNumber)) { + return model.Name; + } + } + return 'Unknown Model'; + } + + private setManufacturer() { + this.accessory.getService(this.api.hap.Service.AccessoryInformation) + .setCharacteristic(this.api.hap.Characteristic.Manufacturer, 'V-Zug'); + } + + async fetchDeviceStatus() { try { const url = `http://${this.config.ip}/ai?command=getDeviceStatus`; @@ -62,8 +99,6 @@ export class VZugAccessory { handleOnSet(value, callback) { // Implement logic to set the new state - // This part is device-specific and depends on available API commands - // Handle errors appropriately, similar to handleOnGet callback(null); } } \ No newline at end of file diff --git a/src/VZugPlatform.ts b/src/VZugPlatform.ts index f139b25..ee91bcd 100644 --- a/src/VZugPlatform.ts +++ b/src/VZugPlatform.ts @@ -25,7 +25,6 @@ export class VZugPlatform implements DynamicPlatformPlugin { this.api.on('didFinishLaunching', () => { this.log.debug('Executed didFinishLaunching callback'); - // Perform further operations here if necessary }); } diff --git a/src/vzugmodel.json b/src/vzugmodel.json new file mode 100644 index 0000000..08444a5 --- /dev/null +++ b/src/vzugmodel.json @@ -0,0 +1,474 @@ +[ + { + "Name": "AdoraDish V2000", + "Model": "41108, 41109" + }, + { + "Name": "AdoraDish V4000", + "Model": "41110, 41112, 41114" + }, + { + "Name": "AdoraDish V6000", + "Model": "41115, 41118, 41119, 41120, 41121, 41125" + }, + { + "Name": "AdoraDry V2000", + "Model": "12011" + }, + { + "Name": "AdoraDry V2000", + "Model": "12017" + }, + { + "Name": "AdoraDry V6000", + "Model": "12013" + }, + { + "Name": "AdoraDry V6000", + "Model": "12019" + }, + { + "Name": "AdoraWash V2000", + "Model": "11021, 11041" + }, + { + "Name": "AdoraWash V4000", + "Model": "11023, 11042" + }, + { + "Name": "AdoraWash V6000", + "Model": "11025, 11043" + }, + { + "Name": "Adorina CS", + "Model": "11018" + }, + { + "Name": "AiroClearCabinet V4000", + "Model": "64009" + }, + { + "Name": "AiroClearCabinet V4000", + "Model": "64010" + }, + { + "Name": "AiroClearCabinet V4000", + "Model": "64011" + }, + { + "Name": "AiroClearCabinet V6000", + "Model": "61058" + }, + { + "Name": "AiroClearCabinet V6000", + "Model": "61060" + }, + { + "Name": "AiroClearIsland V6000", + "Model": "63020" + }, + { + "Name": "AiroClearWall V2000 V90", + "Model": "62032" + }, + { + "Name": "AiroClearWall V4000", + "Model": "62026" + }, + { + "Name": "AiroClearWall V4000 Q120", + "Model": "62031" + }, + { + "Name": "AiroClearWall V6000", + "Model": "62028" + }, + { + "Name": "AiroClearWall V6000", + "Model": "62029" + }, + { + "Name": "CoffeeCenter V6000 45", + "Model": "25005" + }, + { + "Name": "Combair V2000 45", + "Model": "21048" + }, + { + "Name": "Combair V2000 60", + "Model": "21043" + }, + { + "Name": "Combair V4000 45", + "Model": "21049" + }, + { + "Name": "Combair V4000 45P", + "Model": "21058" + }, + { + "Name": "Combair V4000 60", + "Model": "21045" + }, + { + "Name": "Combair V4000 60P", + "Model": "21055" + }, + { + "Name": "Combair V600 60", + "Model": "21126" + }, + { + "Name": "Combair V6000 45", + "Model": "21050" + }, + { + "Name": "Combair V6000 45", + "Model": "21067" + }, + { + "Name": "Combair V6000 45P", + "Model": "21059" + }, + { + "Name": "Combair V6000 45P", + "Model": "21070" + }, + { + "Name": "Combair V6000 60", + "Model": "21047" + }, + { + "Name": "Combair V6000 60", + "Model": "21068" + }, + { + "Name": "Combair V6000 60P", + "Model": "21057" + }, + { + "Name": "Combair V6000 60P", + "Model": "21073" + }, + { + "Name": "CombairSteamer V2000 60", + "Model": "23036" + }, + { + "Name": "CombairSteamer V6000 60", + "Model": "23038" + }, + { + "Name": "CombairSteamer V6000 60", + "Model": "23049" + }, + { + "Name": "CombiCookTop V2000 I804", + "Model": "31095" + }, + { + "Name": "CombiCookTop V4000 I804", + "Model": "31096" + }, + { + "Name": "CombiCooler V4000", + "Model": "51087" + }, + { + "Name": "CombiCooler V4000 178 KNI", + "Model": "51114" + }, + { + "Name": "CombiCooler V4000 178 NI", + "Model": "51108" + }, + { + "Name": "CombiCooler V6000 Supreme", + "Model": "51096" + }, + { + "Name": "CombiMiwell V4000 45", + "Model": "24025" + }, + { + "Name": "CombiSteamer V4000 45", + "Model": "23031" + }, + { + "Name": "CombiSteamer V6000 45", + "Model": "23032" + }, + { + "Name": "CombiSteamer V6000 45", + "Model": "23043" + }, + { + "Name": "CombiSteamer V6000 45F", + "Model": "23033" + }, + { + "Name": "CombiSteamer V6000 45F", + "Model": "23045" + }, + { + "Name": "CombiSteamer V6000 45L Grand", + "Model": "23034" + }, + { + "Name": "CombiSteamer V6000 45L Grand", + "Model": "23046" + }, + { + "Name": "CombiSteamer V6000 45M PowerSteam", + "Model": "23041" + }, + { + "Name": "CombiSteamer V6000 45M PowerSteam", + "Model": "23047" + }, + { + "Name": "CookTop Teppan Yaki I40", + "Model": "31140" + }, + { + "Name": "CookTop V2000 I302", + "Model": "31160" + }, + { + "Name": "CookTop V2000 I604", + "Model": "31159" + }, + { + "Name": "CookTop V2000 I804", + "Model": "31146" + }, + { + "Name": "CookTop V4000 I302", + "Model": "31143" + }, + { + "Name": "CookTop V4000 I402", + "Model": "31144" + }, + { + "Name": "CookTop V4000 I604", + "Model": "31115" + }, + { + "Name": "CookTop V4000 I604", + "Model": "31157" + }, + { + "Name": "CookTop V4000 I704", + "Model": "31116" + }, + { + "Name": "CookTop V4000 I804", + "Model": "31158" + }, + { + "Name": "CookTop V4000 I904", + "Model": "31142" + }, + { + "Name": "CookTop V6000 A905", + "Model": "31155" + }, + { + "Name": "CookTop V6000 I705 FullFlex", + "Model": "31132" + }, + { + "Name": "CookTop V6000 I905", + "Model": "31114" + }, + { + "Name": "CookTop V6000 I906 FullFlex", + "Model": "31134" + }, + { + "Name": "Cooler V4000 178K", + "Model": "51121" + }, + { + "Name": "Cooler V4000 178K (-T)", + "Model": "51124" + }, + { + "Name": "Cooler V4000 178KG", + "Model": "51122" + }, + { + "Name": "Cooler V6000 Supreme", + "Model": "51098, 51131" + }, + { + "Name": "DF Premira SL", + "Model": "61037" + }, + { + "Name": "DF Premira SL", + "Model": "61038" + }, + { + "Name": "DFSG", + "Model": "61031" + }, + { + "Name": "DFSG", + "Model": "61033" + }, + { + "Name": "DI Premira", + "Model": "63016" + }, + { + "Name": "DIAS", + "Model": "63009" + }, + { + "Name": "DIQS10", + "Model": "63014" + }, + { + "Name": "Drawer V2000 14", + "Model": "35005" + }, + { + "Name": "DSMS downdraft hood", + "Model": "64005" + }, + { + "Name": "DSTS9 downdraft hood", + "Model": "64004" + }, + { + "Name": "DW Premira", + "Model": "62022" + }, + { + "Name": "DW Premira", + "Model": "62023" + }, + { + "Name": "DWQS", + "Model": "62019" + }, + { + "Name": "DWQS", + "Model": "62021" + }, + { + "Name": "FoodCenter V2000", + "Model": "52004" + }, + { + "Name": "Freezer V4000 178N", + "Model": "53003" + }, + { + "Name": "Freezer V4000 178N (-T)", + "Model": "53005" + }, + { + "Name": "Freezer V6000 Supreme", + "Model": "51099" + }, + { + "Name": "GAS311 dial controls", + "Model": "31073" + }, + { + "Name": "GAS321 dial controls", + "Model": "31074" + }, + { + "Name": "GAS411 multi-slider", + "Model": "31063" + }, + { + "Name": "GAS421 multi-slider", + "Model": "31064" + }, + { + "Name": "GAS641 multi-slider", + "Model": "31071" + }, + { + "Name": "GAS731 dial controls", + "Model": "31075" + }, + { + "Name": "GAS951 multi-slider", + "Model": "31072" + }, + { + "Name": "Miwell V600 38", + "Model": "24019" + }, + { + "Name": "Prestige T", + "Model": "51081" + }, + { + "Name": "RefreshButler V6000", + "Model": "14003" + }, + { + "Name": "Steamer V4000 38", + "Model": "23025" + }, + { + "Name": "Steamer V4000 45", + "Model": "23026" + }, + { + "Name": "VacuDrawer V6000 14", + "Model": "36004" + }, + { + "Name": "VacuDrawer V6000 14", + "Model": "36005" + }, + { + "Name": "WarmingDrawer V4000 14", + "Model": "34026" + }, + { + "Name": "WarmingDrawer V4000 14", + "Model": "34027" + }, + { + "Name": "WarmingDrawer V4000 22", + "Model": "34029" + }, + { + "Name": "WarmingDrawer V4000 28", + "Model": "34030" + }, + { + "Name": "WarmingDrawer V4000 31", + "Model": "34031" + }, + { + "Name": "WineCooler UCSL 60", + "Model": "51093" + }, + { + "Name": "WineCooler V4000 45", + "Model": "51113" + }, + { + "Name": "WineCooler V4000 90", + "Model": "51102" + }, + { + "Name": "WineCooler V6000", + "Model": "51095" + }, + { + "Name": "WineCooler V6000 Supreme", + "Model": "51097" + } +] \ No newline at end of file