Code for garagemote

Started by sparky, January 17, 2017, 07:38:31 AM

sparky

In my quest to control 2 doors from a garage mote I have ran into a road block.

Would someone be so kind to tell this newbie what I'm missing in the following lines of code please?   :-[

GarageMote : {
    label   : 'Garage Opener',
    icon : 'icon_garage.png',
    controls : { refresh1 : { states: [{ label:'Refresh1', action:'STS', icon:'refresh' }]},
                 opencls1 : { states: [{ label:'Open1!', action:'OPN', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status1'].value == 'CLOSED';}},
                                      { label:'Opening..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status1'].value == 'OPENING';}},
                                      { label:'Close1!', action:'CLS', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status1'].value == 'OPEN';}},
                                      { label:'Closing..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status1'].value == 'CLOSING';}}]
 	         refresh2 : { states: [{ label:'Refresh2', action:'STS2', icon:'refresh' }]},
		 opencls2 : { states: [{ label:'Open2!', action:'OPN2', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status2'].value == 'CLOSED';}},
                                      { label:'Opening..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status2'].value == 'OPENING';}},
                                      { label:'Close2!', action:'CLS2', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status2'].value == 'OPEN';}},
                                      { label:'Closing..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status2'].value == 'CLOSING';}}]
			}
              	}
  },


Thanks in advance..

Felix

Do you have 2 metrics called "Status1" and "Status2" ?
What are those definitions ?

sparky

I believe so;

exports.metrics = {
  //GarageMote
  //NOTE the \b word boundary is used to avoid matching "OPENING" (ie OPEN must be followed by word boundary/end of word)
  open1 : { name:'Status1', regexp:/(?:STS\:)?(OPN|OPEN)\b/i, value:'OPEN', pin:1, graph:1, logValue:2, graphOptions:{ legendLbl:'Garage door events', yaxis: {ticks:0}, colors:['#4a0'], /*lines: { lineWidth:1 }*/}},
  opening1 : { name:'Status1', regexp:/(?:STS\:)?(OPNING|OPENING)/i, value:'OPENING..', pin:1, graph:1, logValue:1 },
  closed1 : { name:'Status1', regexp:/(?:STS\:)?(CLS|CLOSED)/i, value:'CLOSED', pin:1, graphValPrefix:' Door: ', graph:1, logValue:0 },
  closing1 : { name:'Status1', regexp:/(?:STS\:)?(CLSING|CLOSING)/i, value:'CLOSING..', pin:1, graph:1, logValue:1.1 }, //1.1 to avoid a match with "OPENING"
  unknown1 : { name:'Status1', regexp:/(?:STS\:)?(UNK|UNKNOWN)/i, value:'UNKNOWN!', pin:1, graph:1, logValue:0.5 },
  open2 : { name:'Status2', regexp:/(?:STS\:)?(OPN|OPEN)\b/i, value:'OPEN', pin:1, graph:1, logValue:2, graphOptions:{ legendLbl:'Garage door events', yaxis: {ticks:0}, colors:['#4a0'], /*lines: { lineWidth:1 }*/}},
  opening2 : { name:'Status2', regexp:/(?:STS\:)?(OPNING|OPENING)/i, value:'OPENING..', pin:1, graph:1, logValue:1 },
  closed2 : { name:'Status2', regexp:/(?:STS\:)?(CLS|CLOSED)/i, value:'CLOSED', pin:1, graphValPrefix:' Door: ', graph:1, logValue:0 },
  closing2 : { name:'Status2', regexp:/(?:STS\:)?(CLSING|CLOSING)/i, value:'CLOSING..', pin:1, graph:1, logValue:1.1 }, //1.1 to avoid a match with "OPENING"
  unknown2 : { name:'Status2', regexp:/(?:STS\:)?(UNK|UNKNOWN)/i, value:'UNKNOWN!', pin:1, graph:1, logValue:0.5 },


Felix

Ok the problem is your metrics are identical apart from the labels. The script has no way of telling when a status is coming from what door.
Ie what does "OPEN" mean? is it door 1 or door 2?
The script will stop searching at the first match so your status1 will probably match first. Actually if you keep the original metrics.js that will match first.

I would start with changing all STS: to STS1 and STS2 in the 2 sets of metrics.
That should take you further.

sparky

Well something's still missing.  After restarting all I get is Waiting for socket connection

exports.metrics = {
  //GarageMote
  //NOTE the \b word boundary is used to avoid matching "OPENING" (ie OPEN must be followed by word boundary/end of word)
  open1 : { name:'Status1', regexp:/(?:STS1\:)?(OPN|OPEN)\b/i, value:'OPEN', pin:1, graph:1, logValue:2, graphOptions:{ legendLbl:'Garage door events', yaxis: {ticks:0}, colors:['#4a0'], /*lines: { lineWidth:1 }*/}},
  opening1 : { name:'Status1', regexp:/(?:STS1\:)?(OPNING|OPENING)/i, value:'OPENING..', pin:1, graph:1, logValue:1 },
  closed1 : { name:'Status1', regexp:/(?:STS1\:)?(CLS|CLOSED)/i, value:'CLOSED', pin:1, graphValPrefix:' Door: ', graph:1, logValue:0 },
  closing1 : { name:'Status1', regexp:/(?:STS1\:)?(CLSING|CLOSING)/i, value:'CLOSING..', pin:1, graph:1, logValue:1.1 }, //1.1 to avoid a match with "OPENING"
  unknown1 : { name:'Status1', regexp:/(?:STS1\:)?(UNK|UNKNOWN)/i, value:'UNKNOWN!', pin:1, graph:1, logValue:0.5 },
  open2 : { name:'Status2', regexp:/(?:STS2\:)?(OPN|OPEN)\b/i, value:'OPEN', pin:1, graph:1, logValue:2, graphOptions:{ legendLbl:'Garage door events', yaxis: {ticks:0}, colors:['#4a0'], /*lines: { lineWidth:1 }*/}},
  opening2 : { name:'Status2', regexp:/(?:STS2\:)?(OPNING|OPENING)/i, value:'OPENING..', pin:1, graph:1, logValue:1 },
  closed2 : { name:'Status2', regexp:/(?:STS2\:)?(CLS|CLOSED)/i, value:'CLOSED', pin:1, graphValPrefix:' Door: ', graph:1, logValue:0 },
  closing2 : { name:'Status2', regexp:/(?:STS2\:)?(CLSING|CLOSING)/i, value:'CLOSING..', pin:1, graph:1, logValue:1.1 }, //1.1 to avoid a match with "OPENING"
  unknown2 : { name:'Status2', regexp:/(?:STS2\:)?(UNK|UNKNOWN)/i, value:'UNKNOWN!', pin:1, graph:1, logValue:0.5 },


Possibly too many or not enough {}[], in the below code..  I just don't see it


GarageMote : {
    label   : 'Garage Opener',
    icon : 'icon_garage.png',
    controls : { refresh1 : { states: [{ label:'Refresh1', action:'STS1', icon:'refresh' }]},
                 opencls1 : { states: [{ label:'Open1!', action:'OPN', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status1'].value == 'CLOSED';}},
                                      { label:'Opening..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status1'].value == 'OPENING';}},
                                      { label:'Close1!', action:'CLS', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status1'].value == 'OPEN';}},
                                      { label:'Closing..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status1'].value == 'CLOSING';}}]
 	         refresh2 : { states: [{ label:'Refresh2', action:'STS2', icon:'refresh' }]},
		 opencls2 : { states: [{ label:'Open2!', action:'OPN2', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status2'].value == 'CLOSED';}},
                                      { label:'Opening..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status2'].value == 'OPENING';}},
                                      { label:'Close2!', action:'CLS2', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status2'].value == 'OPEN';}},
                                      { label:'Closing..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status2'].value == 'CLOSING';}}]
			}
              	}
  },


Thanks


Felix

You will have to check the gateway.sys.log for the specific error, I cannot guess what's going on.
Please use a basic code editor that will help you visually with syntax coloring and matching brackets highlighting to avoid such editing errors. Notepad++ is a decent basic choice.

sparky

Thank you Felix.  I will look at notepad++ 

Here are the errors;

/home/pi/gateway/metrics.js:226
       refresh2 : { states: [{ label:'Refresh', action:'STS2', icon:'refresh' }]}
       ^^^^^^^^
SyntaxError: Unexpected identifier
    at Module._compile (module.js:439:25)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/home/pi/gateway/logUtil.js:17:15)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
[2017-01-17T01:04:35.175Z] (sys) Starting


Felix

Ok syntax error, again make sure you close all the brackets and put all the commas.
A quick sample of what I think you will need, put this in the userMetrics/_example.js or a new file that has the same format as _example.js:


  DualGarageMote : {
    label   : 'Garage Opener (Dual)',
    icon : 'icon_garage.png',
    controls : { refresh1 : { states: [{ label:'Refresh1', action:'STS1', icon:'refresh' }]},
                 refresh2 : { states: [{ label:'Refresh2', action:'STS2', icon:'refresh' }]},
                 
                 opencls1 : { states: [{ label:'Open1!', action:'OPN1', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status1'].value == 'CLOSED';}},
                                      { label:'Opening1..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status1'].value == 'OPENING';}},
                                      { label:'Close1!', action:'CLS1', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status1'].value == 'OPEN';}},
                                      { label:'Closing1..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status1'].value == 'CLOSING';}}]
                           },
                 opencls2 : { states: [{ label:'Open2!', action:'OPN2', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status2'].value == 'CLOSED';}},
                                      { label:'Opening2..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status2'].value == 'OPENING';}},
                                      { label:'Close2!', action:'CLS2', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status2'].value == 'OPEN';}},
                                      { label:'Closing2..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status2'].value == 'CLOSING';}}]
                           }
              }
  },


Note that there are 2 sets of refresh and open/close controls. I think in reality you'd only need 1 refresh that would update both doors but you can leave 2 if that's the level of control you want.
Also note the metrics values are the same for both doors (the actual values registered). It's just important that when the metrics come IN the gateway app can differentiate between the two, which I think you already are good to go.

I encourage you to try to understand these metrics and the javascript structures behind them, rather than copy paste and hope it works, it will help you tremendously in further customizations and will be very rewarding when you try to build your own metrics.

Always put your custom metrics in a separate file under userMetrics inside a exports.metrics = { ... } object. Any new/custom metrics cannot have the same name as the ones already defined in the master metrics.js otherwise it will override them.

sparky

Quote from: Felix on January 17, 2017, 11:29:42 AM
I encourage you to try to understand these metrics and the javascript structures behind them, rather than copy paste and hope it works, it will help you tremendously in further customizations and will be very rewarding when you try to build your own metrics.

Felix,

Believe me when I tell you I'm trying to learn this anyway I can but it isn't going to happen overnight.  It's too late in the game to go back to school so reading as much as I can along with help from your forum is all I can possibly do.

I truly appreciate your help

Felix

I understand, it's quite a learning curve!
I hope it will be worth it for you, I think the project you're doing is great for learning some of these ee/cs skills that build on top of what others did already.
I will try to help along the way.

Forgot to mention - if you open Chrome's DevTools (F12) you can use the Console tab for simple debugging and code checking.
You can copy paste code there and it has syntax coloring and checking.
Mind that if you paste portions of code from the middle of metrics.js it might complain that they are not variables, so you will need an "=" instead of ":":

DualGarageMote = {
    label   : 'Garage Opener (Dual)',
    icon : 'icon_garage.png',
    controls : { refresh1 : { states: [{ label:'Refresh1', action:'STS1', icon:'refresh' }]},
                 refresh2 : { states: [{ label:'Refresh2', action:'STS2', icon:'refresh' }]},
                 
                 opencls1 : { states: [{ label:'Open1!', action:'OPN1', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status1'].value == 'CLOSED';}},
                                      { label:'Opening1..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status1'].value == 'OPENING';}},
                                      { label:'Close1!', action:'CLS1', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status1'].value == 'OPEN';}},
                                      { label:'Closing1..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status1'].value == 'CLOSING';}}]
                           },
                 opencls2 : { states: [{ label:'Open2!', action:'OPN2', icon:'arrow-u', css:'background-color:#FF9B9B;', condition:''+function(node) { return node.metrics['Status2'].value == 'CLOSED';}},
                                      { label:'Opening2..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status2'].value == 'OPENING';}},
                                      { label:'Close2!', action:'CLS2', icon:'arrow-d', css:'background-color:#9BFFBE;color:#000000', condition:''+function(node) { return node.metrics['Status2'].value == 'OPEN';}},
                                      { label:'Closing2..', action:'', icon:'forbidden', css:'background-color:#FFF000;', condition:''+function(node) { return node.metrics['Status2'].value == 'CLOSING';}}]
                           }
              }
  }

sparky

Thanks you Felix,

I did download notepad++ you mentioned and I will also try Chrome DevTools.

I tried the code you posted earlier (11:29a) and it came up although it only had Status1, only 1 refresh, and only 1 open/close.  Then all of a sudden all my other motes disappeared from the dashboard except for the garage mote which I was no longer able to go into until I rebooted.  I'm in the process of putting your original metrics.js back on and creating the userMetrics you suggested.