Netatmo Weather Station?

Anybody know of any updates to this? I’d love to be able to get my Netatmo to work with my Smartthings.

yes any updates? got mine all setup ! :smile:

Been waiting on this too…

They said it was coming soon like 3 weeks ago…I think STs may have to lookup the definition of “soon” lol. Hopefully soon!!

1 Like

Any updates on this @urman, @Dianoga, or @Ben?

HI, would love to try this out too!

i have mine installed, and obviously not integrated with smart things… but it actually warned me of co2 hazard, well our ceiling fire/other stuff alarms went off , but my fiance was like "prolly just dead battery, i looked at this and opened some windows

Any updates on this? @Dianoga

The code is currently in @urman’s hands. We just finished a fair amount of testing and tweaking though. Hopefully not too much longer.

:smiley:… that is all.

Ya’all should take a gander over to the Labs Section on the smart app… jus sayin :wink:

1 Like

@urman @Dianoga

Could you tell me the names of capabilities for the sound, pressure, and CO2 readings? Want to write a “Netatmo Monitor” smartapp :stuck_out_tongue:

capability "Relative Humidity Measurement"
capability “Temperature Measurement”

	attribute "carbonDioxide", "string"
	attribute "noise", "string"
	attribute "pressure", "string"

Ahhh ok, so that means i cannot subscribe to the carbon dioxide measurements?

So the measurements are all Imperial? Any way to get Metric? My Netatmo is set up for Metric.

You can subscribe to those. I just didn’t feel like typing the names.

Here you go guys. An app to monitor all that Netatmo has to offer. Try it out and let me know if you see any bugs. Should be working well though :smile: Also shared to the IDE shared apps.

definition(
    name: "Netatmo Monitor",
    namespace: "tslagle13",
    author: "Tim Slagle",
    description: "Monitor all netatmo values within a specific range.  Will notifiy you outside of a specific range only.",
    iconUrl: "http://withasideofthriftiness.com/wp-content/uploads/2013/05/netatmo-logo.jpeg",
    iconX2Url: "http://withasideofthriftiness.com/wp-content/uploads/2013/05/netatmo-logo.jpeg")

preferences {
  page(name: "selectNetatmo")
  page(name: "netatmoTemp")
  page(name: "netatmoHumidity")
  page(name: "netatmoCO")
  page(name: "netatmoNoise")
  page(name: "netatmoPressure")
  page(name: "timeIntervalInput", title: "Only during a certain time", nextPage: "Settings") {
		section {
			input "starting", "time", title: "Starting", required: false
			input "ending", "time", title: "Ending", required: false
            }
            }
  
  page( name:"Settings", title:"Settings", uninstall:true, install:true ) {
	section("Notifications") {
        input "sendPushMessageAll", "enum", title: "Bypass all notifications?", metadata:[values:["Yes","No"]], required:true
        input "frequency", "decimal", title: "Minimum time between actions (defaults to every event)", description: "Minutes", required: false
  	}
    section("More options", hideable: true, hidden: true) {
			href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : "incomplete"
			input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
				options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
			input "modes", "mode", title: "Only when mode is", multiple: true, required: false
		}
	}
}


def selectNetatmo() {
    dynamicPage(name: "selectNetatmo", title: "Netatmo Monitor", nextPage:"netatmoTemp", uninstall: true) {		
		section("Netatmo") {
			input "netatmo", "capability.temperatureMeasurement", title: "Monitor this Netatmo", required: true, multiple: false,  refreshAfterSelection:true
            input "location1", "text", title: "Where is your netatmo?(E.g. Basement)", required: true
		}   	
    }
}

def netatmoTemp() {
    dynamicPage(name: "netatmoTemp", title: "Netatmo Monitor", nextPage:"netatmoHumidity", uninstall: true) {		
		section("Temperature") {
			input "netatmoTempHigh", "number", title: "What temperature is too high? (Number)", required: false
            input "netatmoTempLow", "number", title: "What temperature is too low? (Number)", required: false
            input "sendPushMessageTemp", "enum", title: "Bypass temperature notifications?", metadata:[values:["Yes","No"]], required:true
		}	
    }
}

def netatmoHumidity() {
    dynamicPage(name: "netatmoHumidity", title: "Netatmo Monitor", nextPage:"netatmoPressure", uninstall: true) {		
		section("Humidity") {
			input "netatmoHumidityHigh", "number", title: "What humidity is too high? (Number)", required: false
            input "netatmoHumidityLow", "number", title: "What humidity is too low? (Number)", required: false
            input "sendPushMessageHumidity", "enum", title: "Bypass humidity notifications?", metadata:[values:["Yes","No"]], required:true
		}	
    }
}

def netatmoPressure() {
    dynamicPage(name: "netatmoPressure", title: "Netatmo Monitor", nextPage:"netatmoCO", uninstall: true) {		
		section("Pressure") {
			input "netatmoPressueHigh", "number", title: "What air pressure level is too high? (Number)", required: false
            input "netatmoPressueLow", "number", title: "What air pressure level is too low? (Number)", required: false
            input "sendPushMessagePressure", "enum", title: "Bypass pressure notifications?", metadata:[values:["Yes","No"]], required:true
		}	
    }
}

def netatmoCO() {
    dynamicPage(name: "netatmoCO", title: "Netatmo Monitor", nextPage:"netatmoNoise", uninstall: true) {		
		section("CO2") {
			input "netatmoCOHigh", "number", title: "What CO2 level is too high? (Number)", required: false
            input "sendPushMessageCO", "enum", title: "Bypass CO2 notifications?", metadata:[values:["Yes","No"]], required:true
		}	
    }
}

def netatmoNoise() {
    dynamicPage(name: "netatmoNoise", title: "Netatmo Monitor", nextPage:"Settings", uninstall: true) {		
		section("Noise") {
			input "netatmoNoiseHigh", "number", title: "What Noise level is too high? (Number)", required: false
            input "sendPushMessageNoise", "enum", title: "Bypass noise notifications?", metadata:[values:["Yes","No"]], required:true
		}	
    }
}

def installed(){
	go()
}

def updated(){
	unsubscribe()
    go()
}

def go(){
subscribe(netatmo, "temperature", notifyTemp)
subscribe(netatmo, "humidity", notifyHumidity)
subscribe(netatmo, "noise", notifyNoise)
subscribe(netatmo, "carbonDioxide", notifyCO)
subscribe(netatmo, "pressure", notifyPressure)
//subscribe(app, appTouch)  //Used for testing
}

def notifyTemp(evt) {
if (allOk){
if ( sendPushMessageAll != "Yes" ) {
if (frequency) {
	def lastTimeTemp = state[frequencyKeyTemp(evt)]
	if (lastTimeTemp == null || now() - lastTimeTemp >= frequency * 60000) {
    if (netatmo.latestValue("temperature") > netatmoTempHigh){
    def msg = "Netatmo detected a temperature above ${netatmoTempHigh} in ${location1}.  Current temp is ${netatmo.latestValue("temperature")}"
    	if ( sendPushMessageTemp != "Yes" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyTemp(evt)] = now()
    	}
    } 
    
    if (netatmo.latestValue("temperature") < netatmoTempLow){
    def msg = "Netatmo detected a temperature under ${netatmoTempLow} in ${location1}. Current temp is ${netatmo.latestValue("temperature")}"
    	if ( sendPushMessageTemp != "Yes" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyTemp(evt)] = now()
    	}
    } 
}
}
}
}
}

def notifyHumidity(evt){
if (allOk){
if ( sendPushMessageAll != "Yes" ) {
if (frequency) {
	def lastTimeHumidity = state[frequencyKeyHumidity(evt)]
	if (lastTimeHumidity == null || now() - lastTimeHumidity >= frequency * 60000) {
if (netatmo.latestValue("humidity") < netatmoHumidityLow){
    def msg = "Netatmo detected a humidity under ${netatmoHumidityLow} in ${location1}. Current humidity is ${netatmo.latestValue("humidity")}"
    	if ( sendPushMessageHumidity != "Yes" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyHumidity(evt)] = now()
    	}
    }
    
    if (netatmo.latestValue("humidity") > netatmoHumidityHigh){
    def msg = "Netatmo detected a humidity over ${netatmoHumidityHigh} in ${location1}. Current humidity is ${netatmo.latestValue("humidity")}"
    	if ( sendPushMessageHumidity != "Yes" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyHumidity(evt)] = now()
    	}
    }
    
}
}
}
}
}

def notifyNoise(evt){
if (allOk){
if ( sendPushMessageAll != "Yes" ) {
if (frequency) {
	def lastTimeNoise = state[frequencyKeyNoise(evt)]
	if (lastTimeNoise == null || now() - lastTimeNoise >= frequency * 60000) {
if (netatmo.latestValue("noise") > netatmoNoiseHigh){
    def msg = "Netatmo detected a noise level over ${netatmoNoiseHigh} in ${location1}. Current noise level is ${netatmo.latestValue("noise")}"
    	if ( sendPushMessageNoise != "Yes" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyNoise(evt)] = now()
    	}
    }
}
}
}
}
}

def notifyCO(evt){
if (allOk){
if ( sendPushMessageAll != "Yes" ) {
if (frequency) {
	def lastTimeCO = state[frequencyKeyCO(evt)]
	if (lastTimeCO == null || now() - lastTimeCO >= frequency * 60000) {
if (netatmo.latestValue("carbonDioxide") > netatmoCOHigh){
        def msg = "I detected a CO2 level over ${netatmoCOHigh} for ${netatmo}.  Current CO2 level is ${netatmo.latestValue("carbonDioxide")}"
    	if ( sendPushMessageCO != "Yes" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyCO(evt)] = now()
    	}
    } 
}
}
}
}
}


def notifyPressure(evt){
if (allOk){
if ( sendPushMessageAll != "Yes" ) {
if (frequency) {
	def lastTimePressure = state[frequencyKeyPressure(evt)]
	if (lastTimePressure == null || now() - lastTimeTemp >= frequency * 60000) {
if (netatmo.latestValue("pressure") > netatmoPressureHigh){
    def msg = "Netatmo detected a pressure level over ${netatmoPressureHigh} in ${location1}. Current pressure is ${netatmo.latestValue("pressure")}"
    	if ( sendPushMessagePressure != "Yes" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyPressure(evt)] = now()
    	}
    }
    
    if (netatmo.latestValue("pressure") < netatmoPressureLow){
    def msg = "Netatmo detected a pressure level under ${netatmoPressureLow} in ${location1}. Current pressure is ${netatmo.latestValue("pressure")}"
    	if ( sendPushMessagePressure != "Yes" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyPressure(evt)] = now()
    	}
    }
}
}
}
}
}


//def appTouch(evt){      //Used for testing
//log.info("test")

//if (frequency) {
//	def lastTimeTemp = state[frequencyKeyTemp(evt)]
//	if (lastTimeTemp == null || now() - lastTimeTemp >= frequency * 60000) {
//    if (netatmo.latestValue("temperature") > netatmoTempHigh){
//    def msg = "Netatmo detected a temperature above ${netatmoTempHigh} in ${location1}."
//    sendNotificationEvent(msg)
//    	if ( sendPushMessageTemp != "Yes" ) {
//        	log.info(msg)
        	
//            state[frequencyKeyTemp(evt)] = now()
//    	}
//    } 
//    
//    if (netatmo.latestValue("temperature") < netatmoTempLow){
//    def msg = "Netatmo detected a temperature under ${netatmoTempLow} in ${location1}."
//    sendNotificationEvent(msg)
//    	if ( sendPushMessageTemp != "Yes" ) {
//        	log.info(msg)
//        	
//            state[frequencyKeyTemp(evt)] = now()
//    	}
//    } 
//}
//}
//}


private frequencyKeyTemp(evt) {
	"lastActionTimeStamp"
}

private frequencyKeyHumidity(evt) {
	"lastActionTimeStamp"
}

private frequencyKeyPressure(evt) {
	"lastActionTimeStamp"
}

private frequencyKeyCO(evt) {
	"lastActionTimeStamp"
}

private frequencyKeyNoise(evt) {
	"lastActionTimeStamp"
}



private getAllOk() {
	modeOk && daysOk && timeOk
}

private getModeOk() {
	def result = !modes || modes.contains(location.mode)
	log.trace "modeOk = $result"
	result
}

private getDaysOk() {
	def result = true
	if (days) {
		def df = new java.text.SimpleDateFormat("EEEE")
		if (location.timeZone) {
			df.setTimeZone(location.timeZone)
		}
		else {
			df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
		}
		def day = df.format(new Date())
		result = days.contains(day)
	}
	log.trace "daysOk = $result"
	result
}

private getTimeOk() {
	def result = true
	if (starting && ending) {
		def currTime = now()
		def start = timeToday(starting).time
		def stop = timeToday(ending).time
		result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
	}
	log.trace "timeOk = $result"
	result
}

private hhmm(time, fmt = "h:mm a")
{
	def t = timeToday(time, location.timeZone)
	def f = new java.text.SimpleDateFormat(fmt)
	f.setTimeZone(location.timeZone ?: timeZone(time))
	f.format(t)
}

private getTimeLabel()
{
	(starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
}
// TODO - End Centralize

On somewhat of a different subject, check out this site. It hosts the history of your data and give the option to upload the data to WeatherUnderground and a few other weather data outlets.

Meteoware Plus

1 Like

Update to my code. Lots more customization!

definition(
    name: "Netatmo Monitor",
    namespace: "tslagle13",
    author: "Tim Slagle",
    description: "Monitor all netatmo values within a specific range.  Will notifiy you outside of a specific range only.",
    iconUrl: "http://withasideofthriftiness.com/wp-content/uploads/2013/05/netatmo-logo.jpeg",
    iconX2Url: "http://withasideofthriftiness.com/wp-content/uploads/2013/05/netatmo-logo.jpeg")

preferences {
  page(name: "selectNetatmo")
  page(name: "netatmoTemp")
  page(name: "netatmoHumidity")
  page(name: "netatmoCO")
  page(name: "netatmoNoise")
  page(name: "netatmoPressure")
  page(name: "timeIntervalInput", title: "Only during a certain time", nextPage: "Settings") {
		section {
			input "starting", "time", title: "Starting", required: false
			input "ending", "time", title: "Ending", required: false
            }
            }
  
  page( name:"Settings", title:"Settings", uninstall:true, install:true ) {
	section("Notifications") {
        input "sendPushMessageAll", "bool", title: "Bypass all notifications?", defaultVaule:false, required:true
        input "frequency", "decimal", title: "Minimum time between actions (defaults to every event)", description: "Minutes", required: false
  	}
    section("More options", hideable: true, hidden: true) {
			href "timeIntervalInput", title: "Only during a certain time", description: timeLabel ?: "Tap to set", state: timeLabel ? "complete" : "incomplete"
			input "days", "enum", title: "Only on certain days of the week", multiple: true, required: false,
				options: ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
			input "modes", "mode", title: "Only when mode is", multiple: true, required: false
		}
	}
}


def selectNetatmo() {
    dynamicPage(name: "selectNetatmo", title: "Netatmo Monitor", nextPage:"netatmoTemp", uninstall: true) {		
		section("Netatmo") {
			input "netatmo", "capability.temperatureMeasurement", title: "Monitor this Netatmo", required: true, multiple: false,  refreshAfterSelection:true
            input "location1", "text", title: "Where is your netatmo?(E.g. Basement)", required: true
		}   	
    }
}

def netatmoTemp() {
    dynamicPage(name: "netatmoTemp", title: "Netatmo Monitor", nextPage:"netatmoHumidity", uninstall: true) {		
		section("Temperature") {
			input "netatmoTempHigh", "number", title: "What temperature is too high? (Number)", required: false
            input "sendPushMessageTempHigh", "bool", title: "Bypass high temperature notifications?", defaultValue:true, required:true
            input "netatmoTempLow", "number", title: "What temperature is too low? (Number)", required: false
            input "sendPushMessageTemp", "bool", title: "Bypass low temperature notifications?", defaultValue:true, required:true
		}	
    }
}

def netatmoHumidity() {
    dynamicPage(name: "netatmoHumidity", title: "Netatmo Monitor", nextPage:"netatmoPressure", uninstall: true) {		
		section("Humidity") {
			input "netatmoHumidityHigh", "number", title: "What humidity is too high? (Number)", required: false
            input "sendPushMessageHumidityHigh", "bool", title: "Bypass high humidity notifications?", defaultValue:true, required:true
            input "netatmoHumidityLow", "number", title: "What humidity is too low? (Number)", required: false
            input "sendPushMessageHumidity", "bool", title: "Bypass low humidity notifications?", defaultValue:true, required:true
		}	
    }
}

def netatmoPressure() {
    dynamicPage(name: "netatmoPressure", title: "Netatmo Monitor", nextPage:"netatmoCO", uninstall: true) {		
		section("Pressure") {
			input "netatmoPressueHigh", "number", title: "What air pressure level is too high? (Number)", required: false
            input "sendPushMessagePressureHigh", "bool", title: "Bypass high pressure notifications?", defaultValue:true, required:true
            input "netatmoPressueLow", "number", title: "What air pressure level is too low? (Number)", required: false
            input "sendPushMessagePressure", "bool", title: "Bypass low pressure notifications?", defaultValue:true, required:true
		}	
    }
}

def netatmoCO() {
    dynamicPage(name: "netatmoCO", title: "Netatmo Monitor", nextPage:"netatmoNoise", uninstall: true) {		
		section("CO2") {
			input "netatmoCOHigh", "number", title: "What CO2 level is too high? (Number)", required: false
            input "sendPushMessageCO", "bool", title: "Bypass CO2 notifications?", defaultValue:true, required:true
		}	
    }
}

def netatmoNoise() {
    dynamicPage(name: "netatmoNoise", title: "Netatmo Monitor", nextPage:"Settings", uninstall: true) {		
		section("Noise") {
			input "netatmoNoiseHigh", "number", title: "What Noise level is too high? (Number)", required: false
            input "sendPushMessageNoise", "bool", title: "Bypass noise notifications?", defaultValue:true, required:true
		}	
    }
}

def installed(){
	go()
}

def updated(){
	unsubscribe()
    go()
}

def go(){
subscribe(netatmo, "temperature", notifyTemp)
subscribe(netatmo, "humidity", notifyHumidity)
subscribe(netatmo, "noise", notifyNoise)
subscribe(netatmo, "carbonDioxide", notifyCO)
subscribe(netatmo, "pressure", notifyPressure)
//subscribe(app, appTouch)  //Used for testing
}

def notifyTemp(evt) {
if (allOk){
if ( sendPushMessageAll != "On" ) {
if (frequency) {
	def lastTimeTemp = state[frequencyKeyTemp(evt)]
	if (lastTimeTemp == null || now() - lastTimeTemp >= frequency * 60000) {
    if (netatmo.latestValue("temperature") > netatmoTempHigh){
    def msg = "Netatmo detected a temperature above ${netatmoTempHigh} in ${location1}.  Current temp is ${netatmo.latestValue("temperature")}"
    	if ( sendPushMessageTempHigh != "On" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyTemp(evt)] = now()
    	}
    } 
    
    if (netatmo.latestValue("temperature") < netatmoTempLow){
    def msg = "Netatmo detected a temperature under ${netatmoTempLow} in ${location1}. Current temp is ${netatmo.latestValue("temperature")}"
    	if ( sendPushMessageTemp != "On" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyTemp(evt)] = now()
    	}
    } 
}
}
}
}
}

def notifyHumidity(evt){
if (allOk){
if ( sendPushMessageAll != "On" ) {
if (frequency) {
	def lastTimeHumidity = state[frequencyKeyHumidity(evt)]
	if (lastTimeHumidity == null || now() - lastTimeHumidity >= frequency * 60000) {
if (netatmo.latestValue("humidity") < netatmoHumidityLow){
    def msg = "Netatmo detected a humidity under ${netatmoHumidityLow} in ${location1}. Current humidity is ${netatmo.latestValue("humidity")}"
    	if ( sendPushMessageHumidityHigh != "On" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyHumidity(evt)] = now()
    	}
    }
    
    if (netatmo.latestValue("humidity") > netatmoHumidityHigh){
    def msg = "Netatmo detected a humidity over ${netatmoHumidityHigh} in ${location1}. Current humidity is ${netatmo.latestValue("humidity")}"
    	if ( sendPushMessageHumidity != "On" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyHumidity(evt)] = now()
    	}
    }
    
}
}
}
}
}

def notifyNoise(evt){
if (allOk){
if ( sendPushMessageAll != "On" ) {
if (frequency) {
	def lastTimeNoise = state[frequencyKeyNoise(evt)]
	if (lastTimeNoise == null || now() - lastTimeNoise >= frequency * 60000) {
if (netatmo.latestValue("noise") > netatmoNoiseHigh){
    def msg = "Netatmo detected a noise level over ${netatmoNoiseHigh} in ${location1}. Current noise level is ${netatmo.latestValue("noise")}"
    	if ( sendPushMessageNoise != "On" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyNoise(evt)] = now()
    	}
    }
}
}
}
}
}

def notifyCO(evt){
if (allOk){
if ( sendPushMessageAll != "On" ) {
if (frequency) {
	def lastTimeCO = state[frequencyKeyCO(evt)]
	if (lastTimeCO == null || now() - lastTimeCO >= frequency * 60000) {
if (netatmo.latestValue("carbonDioxide") > netatmoCOHigh){
        def msg = "I detected a CO2 level over ${netatmoCOHigh} for ${netatmo}.  Current CO2 level is ${netatmo.latestValue("carbonDioxide")}"
    	if ( sendPushMessageCO != "On" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyCO(evt)] = now()
    	}
    } 
}
}
}
}
}


def notifyPressure(evt){
if (allOk){
if ( sendPushMessageAll != "On" ) {
if (frequency) {
	def lastTimePressure = state[frequencyKeyPressure(evt)]
	if (lastTimePressure == null || now() - lastTimeTemp >= frequency * 60000) {
if (netatmo.latestValue("pressure") > netatmoPressureHigh){
    def msg = "Netatmo detected a pressure level over ${netatmoPressureHigh} in ${location1}. Current pressure is ${netatmo.latestValue("pressure")}"
    	if ( sendPushMessagePressureHigh != "On" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyPressure(evt)] = now()
    	}
    }
    
    if (netatmo.latestValue("pressure") < netatmoPressureLow){
    def msg = "Netatmo detected a pressure level under ${netatmoPressureLow} in ${location1}. Current pressure is ${netatmo.latestValue("pressure")}"
    	if ( sendPushMessagePressure != "On" ) {
        	log.info(msg)
        	sendPush(msg)
            state[frequencyKeyPressure(evt)] = now()
    	}
    }
}
}
}
}
}


//def appTouch(evt){      //Used for testing
//log.info("test")

//if (frequency) {
//	def lastTimeTemp = state[frequencyKeyTemp(evt)]
//	if (lastTimeTemp == null || now() - lastTimeTemp >= frequency * 60000) {
//    if (netatmo.latestValue("temperature") > netatmoTempHigh){
//    def msg = "Netatmo detected a temperature above ${netatmoTempHigh} in ${location1}."
//    sendNotificationEvent(msg)
//    	if ( sendPushMessageTemp != "Yes" ) {
//        	log.info(msg)
        	
//            state[frequencyKeyTemp(evt)] = now()
//    	}
//    } 
//    
//    if (netatmo.latestValue("temperature") < netatmoTempLow){
//    def msg = "Netatmo detected a temperature under ${netatmoTempLow} in ${location1}."
//    sendNotificationEvent(msg)
//    	if ( sendPushMessageTemp != "Yes" ) {
//        	log.info(msg)
//        	
//            state[frequencyKeyTemp(evt)] = now()
//    	}
//    } 
//}
//}
//}


private frequencyKeyTemp(evt) {
	"lastActionTimeStamp"
}

private frequencyKeyHumidity(evt) {
	"lastActionTimeStamp"
}

private frequencyKeyPressure(evt) {
	"lastActionTimeStamp"
}

private frequencyKeyCO(evt) {
	"lastActionTimeStamp"
}

private frequencyKeyNoise(evt) {
	"lastActionTimeStamp"
}



private getAllOk() {
	modeOk && daysOk && timeOk
}

private getModeOk() {
	def result = !modes || modes.contains(location.mode)
	log.trace "modeOk = $result"
	result
}

private getDaysOk() {
	def result = true
	if (days) {
		def df = new java.text.SimpleDateFormat("EEEE")
		if (location.timeZone) {
			df.setTimeZone(location.timeZone)
		}
		else {
			df.setTimeZone(TimeZone.getTimeZone("America/New_York"))
		}
		def day = df.format(new Date())
		result = days.contains(day)
	}
	log.trace "daysOk = $result"
	result
}

private getTimeOk() {
	def result = true
	if (starting && ending) {
		def currTime = now()
		def start = timeToday(starting).time
		def stop = timeToday(ending).time
		result = start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start
	}
	log.trace "timeOk = $result"
	result
}

private hhmm(time, fmt = "h:mm a")
{
	def t = timeToday(time, location.timeZone)
	def f = new java.text.SimpleDateFormat(fmt)
	f.setTimeZone(location.timeZone ?: timeZone(time))
	f.format(t)
}

private getTimeLabel()
{
	(starting && ending) ? hhmm(starting) + "-" + hhmm(ending, "h:mm a z") : ""
}
// TODO - End Centralize