WebThingsIO / gateway

WebThings Gateway - a self-hosted web application for monitoring and controlling a building over the web
http://webthings.io/gateway
Mozilla Public License 2.0
2.61k stars 339 forks source link

Error launching event inside inner function: Unhandled Rejection #2196

Closed alexe100 closed 5 years ago

alexe100 commented 5 years ago

Hi Inside a device constructor I am trying to send events (just for testing and learning purposes) like this:

this.addEvent('turnedOn', {'@type': 'TurnedOnEvent', description: 'Light bulb is now on',});                             
this.eventNotify(new Event(this, "eventName"));

var parent = this;
setInterval(() => {
  parent.eventNotify(new Event(parent,"eventName"));
}, 10000);

The first call to eventNotify works without errors or warnings but the second one, inside timer handler results in:

INFO   : Unhandled Rejection
ERROR  : Error: Unable to find thing with id: timer1

It seems that internally eventNotify is trying to access device.name?! Why Unhandled Rejection?

Thank you Alex

tim-hellhake commented 5 years ago

It looks like the gateway does not know your device with the id timer1. You can see how it works here: Device -> Addon Manager

alexe100 commented 5 years ago

Hi Tim Your tip to see the sendEventNotification() implementation helped me to solve the problem. However, now both eventNotify call work without any error but event seems not reaching the Rules, dont know why.

I have created a (test) rule to send an email when event turnedOn is emited, but looking to the console log that rule is never executed which means the event neved read the runes context. Any ideas about the the source of the problem?

Thank you once again Alex

mrstegeman commented 5 years ago

@alexe100 Would you like to share your code so we can take a look?

mrstegeman commented 5 years ago

I'm guessing the issue is that you're using this.eventNotify() inside the constructor, which means you're doing it before calling adapter.handleDeviceAdded(device).

alexe100 commented 5 years ago

Sure, here it is the sample source-code:

class MyTimer extends Device
{
        constructor(adapter, manifest, timer)
        {
                super(adapter, timer.name);
                this['@context'] = 'https://iot.mozilla.org/schemas/';
                this['@type'] = ['TimerSensor'];
                this.name = manifest.display_name;
                this.description = 'SAMPLE DESC';

                //Add event for subscription to the device
                this.addEvent('turnedOn', {'@type': 'TurnedOnEvent',description: 'Ligh buld is now on',});

                //Launch this timer
                var parent=this;
                setInterval(() =>
                {
                        var e = new Event(this,"eventName");
                        parent.eventNotify(e);
                },10000)
        }
}

class MyTimerAdapter extends Adapter
{
        constructor(addonManager, manifest)
        {
                super(addonManager, MyTimerAdapter.name, manifest.name);
                addonManager.addAdapter(this);

                //Load configured timers from package.json
                const timers = manifest.moziot.config.timers;

                if (timers)
                {
                        for (const timer of timers)
                        {                                
                                const device = new MyTimer(this, manifest, timer);
                                this.handleDeviceAdded(device);
                        }
                }
        }
}

module.exports = MyTimerAdapter;

Thanks

mrstegeman commented 5 years ago

It looks like you've now removed the extra this.eventNotify() call. Are things working better?

alexe100 commented 5 years ago

No. I had 2 calls to eventNotify() as an attempt to solve the previous problem "Unhandled Rejection". That was due to: I have fconfigured two timers but I just created 1 timer thing. Creating two things solved the problem and I removed that extra.

Now, the problem is: the timers fire in the right time, the event is fired and each event carries the right context but it does not signals the configured rule:

If timer1 event "turnedOn" occurs, send a notification through Pushsafer

alexe100 commented 5 years ago

If I use a property instead of an event to fire a rule, it works, but not with the event

alexe100 commented 5 years ago

I am going to try to use the pulse add-on and create a custom add-on based on its source-code and reuse its event to see what happens...

mrstegeman commented 5 years ago

(Closing since the original issue is solved).

The problem now is this:

this.addEvent('turnedOn', {'@type': 'TurnedOnEvent',description: 'Ligh buld is now on',});

//Launch this timer
var parent=this;
setInterval(() =>
{
        var e = new Event(this,"eventName");
        parent.eventNotify(e);
},10000)

You're adding an event named turnedOn to your thing description, but then you're firing an event named eventName. The new Event() line needs to have turnedOn, rather than eventName.

alexe100 commented 5 years ago

You are right... I could not see that little thing... Now it works.

Thank you