snowdd1 / homebridge-knx

KNX platform shim for homebridge
https://github.com/nfarina/homebridge
GNU General Public License v2.0
97 stars 55 forks source link

this.myAPI.getGlobalValue in Service Handler creates TypeError #122

Closed Luigi01W closed 4 years ago

Luigi01W commented 6 years ago

Hello, I created a custom Service Handler for 2 sprinkler valves in the garden. I want to allow only 1 of 2 to be active at the same time and therefore, when the onHKValueChange method is called with "Active" in the device, I want to check the "InUse" characteristics of the other device with this.myAPI.getGlobalValue. Unfortunately I receive a TypeError as shown in the log below. Can someone give me a hint please what could be wrong? Thank you very much in advance!

Handler Code:

/* Pflanzenbewaesserung.js
 * 
 * 
 */
/* jshint esversion: 6, strict: true, node: true */

'use strict';
/**
 * @type {HandlerPattern}
 */
var HandlerPattern = require('./handlerpattern.js');
var log = require('debug')('Pflanzenbewaesserung');

/**
 * @class   
 * @extends HandlerPattern
 */
class Pflanzenbewaesserung extends HandlerPattern {
    constructor(knxAPI) {
        super(knxAPI); // call the super constructor first. Always.
        this.HKValveTypeSet = undefined; // flag for ValveType was set
        this.HKSetDuration = undefined; // stores the Duration
    }

    /****
     * onKNXValueChange is invoked if a Bus value for one of the bound addresses is received
     * 
     */
    onKNXValueChange(field, oldValue, knxValue) {
        // console.log('INFO: on KNX value change (' + field + ", old="+ oldValue + ", new="+ knxValue + ")");

        if (!this.HKValveTypeSet)
        {
            // set initial values on startup
            this.myAPI.setValue("InUse", 0);
            this.myAPI.setValue("Active", 0);
            this.myAPI.setValue("ValveType", this.myAPI.getLocalConstant("ValveType"));
            console.log('INFO: Initial ValueType, InUse, Active set on HK');
            this.HKValveTypeSet = true;
        }       
        if (!this.HKSetDuration)
        {
            // set the initial duration from constant value
            this.HKSetDuration = this.myAPI.getLocalConstant("DefaultDuration");
            // this.myAPI.setValue("SetDuration",this.HKSetDuration);
            // console.log('INFO: SetDuration set on HK');
        }

        switch (field)
        {               
            case "Bewaesserung":
                if (knxValue == 1) {
                    // KNX Bewaesserung=1 will only be triggered if watering is not locked (rain etc.)
                    // if KNX Bewaesserung=1 set HK InUse=1 and Active=1
                    this.myAPI.setValue("InUse", 1);
                    this.myAPI.setValue("Active", 1);
                    console.log('INFO: on KNX value change Bewaesserung=1 > set InUse=1 and Active=1 on HK');

                    // Timer for Duration                   
                    console.log('INFO: start timer with '+ this.HKSetDuration + "sec.");
                    var that = this;
                    if (this.timer) clearTimeout(this.timer);
                    // this.myAPI.setValue("RemainingDuration",that.HKSetDuration);
                    this.timer = setTimeout(function () {
                        // end of Timer event
                        that.myAPI.knxWrite("Bewaesserung", 0, "DPT1");
                        that.myAPI.setValue("InUse", 0);
                        that.myAPI.setValue("Active", 0);
                        console.log('INFO: end of Timer > write Bewaesserung=0 to KNX and set InUse=0 and Active=0 on HK');
                        },this.HKSetDuration*1000); // timer needs miliseconds = seconds*1000 
                    return true;    

                } else {

                    console.log('INFO: Bewaesserung RemainingDuration=' + this.myAPI.getValue("RemainingDuration"));
                    // if KNX Bewaesserung is 0 > set InUse=0 and Active=0 on HK
                    this.myAPI.setValue("InUse", 0);
                    this.myAPI.setValue("Active", 0);
                    console.log('INFO: on KNX value change Bewaesserung=0 > set InUse=0, Active=0 on HK');
                }                       
                break;
        }
        return true;
    } // onBusValueChange

    /****
     * onHKValueChange is invoked if HomeKit is changing characteristic values
     * 
     */
    onHKValueChange(field, oldValue, newValue) {
        // console.log('INFO: on HK value change (' + field + ", old="+ oldValue + ", new="+ newValue + ")");

        switch (field)
        {
            case "Active":              
                if (newValue == 1)
                {
                    if (this.myAPI.getGlobalValue("Rasenbewaesserung", "Rasenbewaesserung", "InUse") == 0)
                    {   
                        // If other Bewaeseerung is not InUse > write Bewaesserung=1 to KNX
                        this.myAPI.knxWrite("Bewaesserung", 1, "DPT1");
                        console.log('INFO: on HK value change Active=1 > write Bewaesserung=1 to KNX');
                    } 
                    else {
                        this.myAPI.setValue("Active", 0);
                        console.log('INFO: on HK value change Active=1 > change back to Active=0 because other Bewaesserung is already running');
                    }
                    return true;
                }               
                if (newValue == 0)
                {
                    // If HK Active=0 switch Bewaesserung off
                    this.myAPI.knxWrite("Bewaesserung", 0, "DPT1");
                    console.log('INFO: on HK value change Active=0 > write Bewaesserung=0 to KNX');
                    return true;
                }
                break;

            case "SetDuration":
                // HK sets a duration and store in HKSetDuration
                this.HKSetDuration = newValue;
                console.log('INFO: on HK value change SetDuration=' + newValue + " received");
                break;

            case "RemainingDuration":
                console.log('INFO: on HK value change RemainingDuration=' + newValue + " received");    
                break;
        }
        return true;
    } // onHKValueChange
} // class  
module.exports= Pflanzenbewaesserung;

Definitions of the 2 devices in knx_config.json:

{
            "DeviceName": "Rasenbewaesserung",
            "Services": [
                {
                    "ServiceType": "Valve",
                    "ServiceName": "Rasenbewaesserung",
                    "Handler": "Rasenbewaesserung",
                    "Characteristics": [
                        {
                            "Type": "Active"
                        },
                        {
                            "Type": "ValveType"
                        },
                        {
                            "Type": "InUse"
                        },
                        {
                            "Type": "SetDuration"
                        },
                        {
                            "Type": "RemainingDuration"
                        }
                    ],
                    "KNXObjects": [
                        {
                            "Type": "Bewaesserung",
                            "Set": "0/4/0",
                            "Listen": "0/4/3",
                            "DPT": "DPT1"
                        }
                    ],
                    "KNXReadRequests": [
                        "0/4/3"
                    ],
                    "LocalConstants": {
                        "ValveType": 1,
                        "DefaultDuration": 600
                    },
                    "subtype": "SUB_2ffe2e2d-5ac3-4a94-87a8-702f4e85837a"
                }
            ],
            "UUID": "635f1b89-384b-4e4d-a9c4-ffc04f12a976"
        },
        {
            "DeviceName": "Pflanzenbewaesserung",
            "Services": [
                {
                    "ServiceType": "Valve",
                    "ServiceName": "Pflanzenbewaesserung",
                    "Handler": "Pflanzenbewaesserung",
                    "Characteristics": [
                        {
                            "Type": "Active"
                        },
                        {
                            "Type": "ValveType"
                        },
                        {
                            "Type": "InUse"
                        },
                        {
                            "Type": "SetDuration"
                        },
                        {
                            "Type": "RemainingDuration"
                        }
                    ],
                    "KNXObjects": [
                        {
                            "Type": "Bewaesserung",
                            "Set": "0/4/1",
                            "Listen": "0/4/4",
                            "DPT": "DPT1"
                        }
                    ],
                    "KNXReadRequests": [
                        "0/4/4"
                    ],
                    "LocalConstants": {
                        "ValveType": 1,
                        "DefaultDuration": 600
                    },
                    "subtype": "SUB_88904e4b-c9e4-48e3-a94a-6da792c29be2"
                }
            ],
            "UUID": "ae1e6591-a73a-4fa1-addf-5e14e5fd5e5d"
        }

Error in homebridge.log:

/homebridge/node_modules/homebridge-knx/lib/customServiceAPI.js:191
        for (var iDevice = 0; iDevice < this.service.globs.devices.length; iDevice++) {
                                                     ^
TypeError: Cannot read property 'globs' of undefined
    at customServiceAPI.getGlobalValue (/homebridge/node_modules/homebridge-knx/lib/customServiceAPI.js:191:48)
    at Pflanzenbewaesserung.onHKValueChange (/homebridge/node_modules/homebridge-knx/lib/addins/Pflanzenbewaesserung.js:98:21)
    at customServiceAPI.homekitEventCatcher (/homebridge/node_modules/homebridge-knx/lib/customServiceAPI.js:299:18)
    at CharacteristicKNX.<anonymous> (/homebridge/node_modules/homebridge-knx/lib/characteristic-knx.js:135:36)
    at emitMany (events.js:147:13)
    at Characteristic.emit (events.js:224:7)
    at Characteristic.setValue (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Characteristic.js:320:10)
    at Bridge.<anonymous> (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:871:22)
    at Array.forEach (<anonymous>)
    at Bridge.Accessory._handleSetCharacteristics (/usr/local/lib/node_modules/homebridge/node_modules/hap-nodejs/lib/Accessory.js:811:8)
snowdd1 commented 6 years ago

That's a bug.

snowdd1 commented 6 years ago

Uploaded fixed version, please report test results.

snowdd1 commented 4 years ago

Stale. I assume it's fixed.