Tryb wakacyjny w SmartThings

Zbliża się okres wakacji, większość z nas opuści swoje domy na dłuższy okres czasu. Tym samym musimy zabezpieczyć nasz dorobek przed niebezpieczeństwami. Dzisiaj pokażemy jak dostosować inteligenty dom SmartThings aby strzegł naszego domu oraz pozwolił nim się opiekować pod naszą nieobecność.

Po zainstalowaniu czujników dymu, CO, wody, ruchu oraz zaprogramowaniu automatyzacji Smart Home Monitor, nasz dom jest bezpieczny. Lecz dodatkowym atutem odstraszania włamywacza jest opieka nad naszym domostwem przez osoby najbliższe. Dzisiaj zaprezentuję SmartApps menedżer wakacji, która pozwala na zabezpieczenie zaworów, wyłączenie urządzeń oraz właśnie pozwala na dostęp opiekuna.

[UWAGA]: Funkcja do działania na platformie SmartThings wymagała zainstalowania niestandardowych kodów obsługi. Możliwość ta została jednak wycofana. Na chwilę obecną nie jest możliwe skonfigurowanie żadnej nowej SmartApp w aplikacji SmartThings.

Menedżer wakacyjny „ST-Vacation-Manager”

„ST-Vacation-Manager” został opublikowany na GitHub całą dokumentację możesz znaleźć tutaj. Automatycznie przełącza dom w tryb urlopowy po Twojej nieobecności i zarządza opiekunem odwiedzającego dom.

Ta aplikacja pozwala rozszerzyć SmartThings, aby skutecznie utworzyć tryb wakacyjny, który jest automatycznie uruchamiany po wybranym czasie nieobecności. Na przykład możesz chcieć wyłączyć wodę lub gaz, kiedy jesteś na wakacjach, ale możesz nie chcieć tego robić kiedy wychodzisz tylko do pracy. Vacation Manager pozwala także na opiekę nad domem, opiekę nad psem, podlewanie roślin.

Instalacja

SmartApp jest instalowany jako niestandardowa SmartApps w aplikacji mobilnej SmartThings. Dlatego aplikacja musi być najpierw zainstalowana w repozytorium SmartThings SmartApps. Szczegółową instrukcję instalowania, wraz ze screenami znajdziesz tutaj.

  1. Otwórz SmartThings IDE w przeglądarce internetowej i zaloguj się na swoje konto.
  2. Kliknij sekcję „My SmartApps” (Moje SmartApps) na pasku nawigacyjnym.
  3. Na następnej stronie, kliknij przycisk „+ Create New SmartApp” po prawej stronie.
  4. Na stronie „New SmartApp” wybierz zakładkę „Z kodu”, skopiuj kod źródłowy.„vacation-manager.groovy” z GitHub i wklej go w oknie edytora IDE.
  5. Kliknij niebieski przycisk „Create” u dołu strony. Teraz powinno się otworzyć okno edytora IDE zawierające kod SmartApp.
  6. Kliknij niebieski przycisk „Save” nad oknem edytora.
  7. Kliknij przycisk „Publish” obok niego i wybierz „For Me”. Teraz samodzielnie opublikowałeś swoją aplikację SmartApp.
Kod „ST-Vacation-Manager”

Poniżej przedstawiam spolszczony kod SmartApp. Oryginał znajduje się tutaj.

/*
 *  Vacation Manager
 *
 *  Copyright 2018 Warren Poschman
 *
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 *  in compliance with the License. You may obtain a copy of the License at:
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
 *  on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
 *  for the specific language governing permissions and limitations under the License.
 *
 */

def appVersion() {
	return "1.7"
}

/*
* Change Log:
* 2019-04-21 - (1.7) Improved and simplified vacation mode management to allow other apps/devices to trigger consistently
* 2018-02-25 - (1.6) Modified HVAC management logic to first check if thermostat supports resume since not all thermostats do
* 2018-12-22 - (1.5) Added HVAC management instead of relying on vacation routine to do it since routines cannot do a resume schedule
* 2018-11-24 - (1.4) Added logic to avoid turning off lights, valves, etc. on a sitter that is already present
* 2018-7-17  - (1.3) Improved vacation return logic and added app state tracking for better reliability
* 2018-7-12  - (1.2) Reinstated push messages for house sitter arrival/departure and made small tweaks
* 2018-7-10  - (1.1) Improved vacation mode handling, improved reliability due to latent SHM mode status
* 2018-7-9   - (1.0) Initial release
* 2018-7-8   - (0.1) Debug release
*/

definition(
    name: "Menedżer wakacji",
    namespace: "LLWarrenP",
    author: "Warren Poschman",
    description: "Automatically go into vacation mode after everyone has been gone for a set time, turn off devices, and manage a house sitter",
    category: "Safety & Security",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-NeighborhoodNetwork.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-NeighborhoodNetwork@2x.png",
    iconX3Url: "https://s3.amazonaws.com/smartapp-icons/SafetyAndSecurity/App-NeighborhoodNetwork@2x.png"
)

preferences {
    page(name: "configure")
}

def configure() {
	dynamicPage(name: "configure", title: "Vacation Manager v${appVersion()}", install: true, uninstall: true) {
		def actions = location.helloHome?.getPhrases()*.label
    	actions.sort()
		section("Kiedy wszystkie te osoby opuszczą dom na wakacjach:") {
        	paragraph "Wybierz wszyskich, który będą nieobecni przez dłuższy czas, z wyjątkiem opiekuna domu. "
			input "people", "capability.presenceSensor", multiple: true, required: true
		}
		section("Przejdź do tego trybu na wakacje") {
        	paragraph "Wybierz tryb do zmiany i jak długo przed przejściem do tego trybu i wykonywania procedur. Ustaw czas na dłuższy niż normalnie jesteś nieobecny (np. 18 godzin)"
			input "vacationMode", "mode", title: "Który tryb ?", required: true
            paragraph "Sugeruje się, aby najpierw utworzyć tryb o nazwie 'wakacje', aby śledzić różnicę między wyjazdem a urlopem"
			input "vacationTime", "decimal", title: "Po ilu godzinach ?", defaultValue: 24, range: "0..*", required: true
        	input "vacationRoutine", "enum", title: "I wykonaj tą procedurę:", required: false, options: actions
            paragraph "Należy pamiętać, że procedura wakacyjna może wykonać działania, Menedżer wakacji może je wykonać. Ta procedura zostanie wykonana, gdy wybierasz się na wakacje."
		}
		section("Wyłącz te przełączniki i zawory na wakacjach:") {
        	paragraph "Wyłączaj te urządzenia / zawory przed wyjazdem. Może to zastępować lub uzupełniać dowolną rutynę urlopową wykonaną powyżej."
			input "offDevices", "capability.switch", title: "Które przełączniki ?", multiple: true, required: false
			input "offValves", "capability.valve", title: "Które zawory ?", multiple: true, required: false
        	input "boolDevicesReturn", "bool", title: "Włącz je ponownie po powrocie ?", required: false
		}
		section("Dostosuj te termostaty podczas wakacji:") {
        	paragraph "Dostosuj ustawienia HVAC podczas wakacji. Może to zastępować lub uzupełniać dowolną rutynę urlopową wykonaną powyżej."
            input "thermostats", "capability.thermostat", title: "Jakie termostaty ?", multiple: true, required: false
			input "heatingSetpoint", "decimal", title: "Do ogrzewania ustaw termostaty na:", defaultValue: 62, range: "0..100", required: false
			input "coolingSetpoint", "decimal", title: "Do chłodzenia ustaw termostaty na:", defaultValue: 85, range: "0..100", required: false
        	input "boolResumeHVAC", "bool", title: "Czy powrócić do normalnej pracy HVAC po powrocie?", required: false
            paragraph "Uwaga: Niektóre termostaty mogą nie obsługiwać funkcji wznawiania i będą pozostawione przy nastawach urlopowych."
		}
		section("Ustawienia opiekunka w trybie wakacyjnym:") {
        	paragraph "Jeśli od czasu do czasu dom odwiedza opiekun, włącz minimalną liczbę wymaganych urządzeń, gdy są one potrzebne (woda, gaz itp.)."
            input "houseSitters", "capability.presenceSensor", title: "Jakie czujniki obecności ?", multiple: true, required: false
			paragraph "Opcjonalnie wykonaj procedurę czyszczenia, wyłączając światła, zamykając drzwi itp., Np. „Do widzenia!” rutyna. Po wykonaniu procedury wyjazdu opiekuna zostanie również uruchomiony główny tryb rutyny urlopowej."
			input "sitterArrivalRoutine", "enum", title: "Wykonaj tę procedurę przybycia:", required: false, options: actions
			input "onSitterDevices", "capability.switch", title: "Włącz te przełączniki, gdy przybędzie opiekun:", multiple: true, required: false
       		input "onSitterValves", "capability.valve", title: "Otwórz zawory, gdy nadejdzie opiekun:", multiple: true, required: false
        	input "boolOffSitterDevicesLeave", "bool", title: "Wyłącz je, kiedy odejdą?", required: false
        	input "sitterDepartureRoutine", "enum", title: "Wykonaj tę procedurę wyjazdu:", required: false, options: actions
			input "offSitterDevices", "capability.switch", title: "Wyłącz te przełączniki po wyjściu opiekuna:", multiple: true, required: false       
			input "offSitterValves", "capability.valve", title: "Zamknij te zawory po wyjściu opiekuna:", multiple: true, required: false
            input "boolSitterResumeHVAC", "bool", title: "Czy tymczasowo wznowić normalne działanie HVAC, gdy opiekun jest obecny (jeśli jest obsługiwany)?", required: false
            paragraph "Jeśli włączysz tę opcję, wybrane termostaty wznowią swój program, gdy przybędzie opiekun i wrócą do nastaw wakacyjnych, gdy odejdą."
		}
		section( "Powiadomienia" ) {
			input("recipients", "contact", title: "Wyślij powiadomienia do", required: false) {
				input "sendPushMessage", "enum", title: "Wysłać powiadomienie push?", options: ["Yes", "No"], required: false
				input "phone", "phone", title: "Wysłać wiadomość tekstową ?", required: false
			}
		}
	}
}

def installed() {
	log.debug "Installed with settings: ${settings}"
	subscribe(people, "presence", presence)
	// Assume we are not on vacation but then check just to be sure
	state[onVacation()] = "false"
    if (everyoneIsAway()) checkVacation()
    if ((location.mode == vacationMode) && (houseSitters)) subscribe(houseSitters, "presence", houseSitterPresence) 
}

def updated() {
	log.debug "Updated with settings: ${settings}"
	unsubscribe()
    // After update, check vacation status and set state machine
    if (location.mode == vacationMode) state[onVacation()] = "true"
    else state[onVacation()] = "false"
    if (everyoneIsAway() && (state[onVacation()] != "true")) checkVacation()
	subscribe(people, "presence", presence)
    if ((location.mode == vacationMode) && (houseSitters)) subscribe(houseSitters, "presence", houseSitterPresence)
}

def presence(evt) {
	log.debug "vacation manager was informed that someone's presence has changed to '${evt.value}'"
	if (evt.value == "not present") {
		if (everyoneIsAway()) {
			log.debug "vacation manager has determined that everyone is away; automatically enabling vacation mode ${vacationTime} hours from now if no one returns"
			runIn(findVacationThreshold() * 3600, checkVacation)
		}
	}
	else {
    	// Vacation is over as we have returned - return to normal operation (SHM will change state)
		if (state[onVacation()] == "true") {
            def message = "Vacation Manager has deactivated ${vacationMode} mode since someone has returned from vacation"
            log.info message
			send(message)
            }
        else log.debug "vacation manager has determined that someone has returned while not in vacation mode; resuming normal operation"
        unschedule(checkVacation)
        if (houseSitters) unsubscribe(houseSitters)
        if ((state[onVacation()] == "true") && (boolDevicesReturn)) {
        	if (offDevices) offDevices.on()
            if (offValves) offValves.open()
        }
        if ((state[onVacation()] == "true") && (thermostats && boolResumeHVAC)) resumeThermostats()
        state[onVacation()] = "false"
    }
}

def checkVacation() {
	if (everyoneIsAway()) {
		def threshold = 1000 * 3600 * findVacationThreshold() - 1000
		def awayLongEnough = people.findAll { person ->
			def presenceState = person.currentState("presence")
			if (!presenceState) {
				// This device has yet to check in and has no presence state, treat it as not away long enough
				return false
			}
			def elapsed = now() - presenceState.rawDateCreated.time
			elapsed >= threshold
		}
		log.debug "vacationmanager found ${awayLongEnough.size()} out of ${people.size()} person(s) who were away long enough"
		if (awayLongEnough.size() == people.size()) {
			def message = "Vacation Manager has activated ${vacationMode} mode since everyone has been gone for more than ${vacationTime} hours"
            log.info message
			send(message)
            state[onVacation()] = "true"
            location.helloHome?.execute(settings.vacationRoutine)
            // Let SHM settle and then put us back into vacation mode if not already
            runIn(15, setVacationMode)           
            // Turn off any devices that should be off during vacation
            if (offDevices) offDevices.off()
            if (offValves) offValves.close()
            // Adjust the thermostats
            if (thermostats) {
            	if (heatingSetpoint) thermostats.setHeatingSetpoint(heatingSetpoint)
				if (coolingSetpoint) thermostats.setCoolingSetpoint(coolingSetpoint)
            	}
            // If we have a house sitter, start looking for their arrival/departure
            if (houseSitters) subscribe(houseSitters, "presence", houseSitterPresence)
		    // If we have a sitter, check for presence (e.g. a hot handoff was made) and turn back on any devices that should be on when a house sitter is present
    		if (houseSitters) {
    			for (person in houseSitters) {
					if (person.currentPresence == "present") {
			            log.debug "turning on devices for already present house sitter"
            			if (onSitterDevices) onSitterDevices.on()
			            if (onSitterVavles) onSitterValves.open()
                        if (thermostats && boolSitterResumeHVAC) resumeThermostats()
            			if (sitterArrivalRoutine) log.debug "executing routine '${settings.sitterArrivalRoutine}' for house sitter arrival"
			            location.helloHome?.execute(settings.sitterArrivalRoutine)
						break
						}
        			}
        		}
		} else {
			log.debug "vacation manager determined not everyone has been away long enough; doing nothing"
            state[onVacation()] = "false"
		}
	} else {
    	log.debug "vacation manager determined not everyone is away; doing nothing"
        state[onVacation()] = "false"
    }
}

def houseSitterPresence(evt) {
	if (evt.value == "present") {
		send("Vacation Manager reports house sitter has arrived") 
		log.debug "house sitter has arrived during ${location.mode} mode"
		if ((state[onVacation()] == "true") || (location.mode == vacationMode)) {
			// Turn on any devices that should be on when the house sitter is present
            // This effectively pauses vacation mode for the duration of the sitter's stay
            log.debug "turning on devices for house sitter arrival"
            if (onSitterDevices) onSitterDevices.on()
            if (onSitterVavles) onSitterValves.open()
            if (thermostats && boolSitterResumeHVAC) resumeThermostats()
            if (sitterArrivalRoutine) log.debug "executing routine '${settings.sitterArrivalRoutine}' for house sitter arrival"
            location.helloHome?.execute(settings.sitterArrivalRoutine)
		}
	}
	else if (evt.value == "not present") {
		send("Vacation Manager reports house sitter has departed") 
		log.debug "house sitter has departed during ${location.mode} mode"
        if ((state[onVacation()] == "true") || (location.mode == vacationMode)) {
            // Turn off any devices that should be off when the house sitter has left
            if (boolOffSitterDevicesLeave) {
            	log.debug "turning off devices that were turned on when house sitter arrived"
            	if (onSitterDevices) onSitterDevices.off()
                if (onSitterVavles) onSitterValves.close()
            }
            log.debug "turning off selected devices after sitter has left"
            if (offSitterDevices) offSitterDevices.off()
            if (offSitterVavles) offSitterValves.close()
            if (thermostats && boolSitterResumeHVAC) {
            	if (heatingSetpoint) thermostats.setHeatingSetpoint(heatingSetpoint)
				if (coolingSetpoint) thermostats.setCoolingSetpoint(coolingSetpoint)
            	}
            if (sitterDepartureRoutine) log.debug "executing routine '${settings.sitterDepartureRoutine}' for house sitter departure"
            location.helloHome?.execute(settings.sitterDepartureRoutine)
			// Set the mode back to the vacation mode just in case the mode or some devices changed
			if (vacationRoutine) log.debug "executing routine '${settings.vacationRoutine}' for house sitter departure"
			location.helloHome?.execute(settings.vacationRoutine)
            // Allow SHM to settle and then ensure that we resume vacation mode since sitter is gone
            runIn(15, setVacationMode)
            }
    }
}

private everyoneIsAway() {
	def result = true
    // Check for residents
	for (person in people) {
		if (person.currentPresence == "present") {
			result = false
			break
		}
	}
	return result
}

private send(msg) {
	if (location.contactBookEnabled) {
        log.debug("sending notifications to: ${recipients?.size()}")
		sendNotificationToContacts(msg, recipients)
	}
	else  {
		if (sendPushMessage != "No") {
			log.debug("sending push message")
			sendPush(msg)
		}

		if (phone) {
			log.debug("sending text message")
			sendSms(phone, msg)
		}
	}
	log.debug msg
}

private findVacationThreshold() {
	(vacationTime != null && vacationTime != "") ? vacationTime : 24
}

def setVacationMode() {
	if (location.mode != vacationMode) {
    	log.debug "resetting current mode to ${vacationMode}"
        setLocationMode(vacationMode)
    }
    state[onVacation()] = "true"
}

private resumeThermostats() {
	// Checks to see if the thermostat supports the resumeProgram command and if so sends it
	thermostats.each {
    	if (it.hasCommand("resumeProgram")) it.resumeProgram() else log.debug "${it.label} does not support resume program command, leaving at vacation setpoints"
	}
}

private onVacation() {
	"onVacation"
}
Dodanie do aplikacji SmartThings
  1. Wejdź do „SmartApp”.
  2. Kliknij plus (+) i wybierz z listy „Menedżer wakacji”.
  3. Ustaw wybrane opcje w panelu konfiguracji.

Ustawienia aplikacji

Wszystkie ustawienia są dobrze udokumentowane w aplikacji, ale oto kilka najważniejszych:

Zmień na ten tryb na wakacje – po ilu godzinach? Zamiarem aplikacji jest przejście do trybu wakacyjnego po nieobecności przez okres dłuższy niż zwykle, na przykład ponad 18 godzin. Jeśli chcesz, aby tryb był aktywowany wcześniej, możesz ustawić go na niższą tolerancję, ale pamiętaj, że ma on działać po tym, jak „Smart Home Monitor” ustawia Cię jako „poza domem” i uzbroi ekosystem.

Włącz je ponownie po powrocie? wyłącz je, kiedy odejdą? Są one zaprojektowane tak, aby po prostu przełączać wszystko, co zostało ręcznie włączone w aplikacji i nie powoduje cofnięcia / ponownego wykonania żadnej procedury. Pamiętaj również, że po powrocie z wakacji „Smart Home Monitor” (zazwyczaj) przejdzie z trybu wakacyjnego do Home i (zwykle) wykona również „I’m Back!” dla ciebie automatycznie.

Pełna recenzja SmartApp zostanie zamieszczona tutaj, po dogłębnym sprawdzeniu jej możliwości i wad. Więcej informacji znajdziesz na forum SmartThings tutaj.

One thought on “Tryb wakacyjny w SmartThings

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj /  Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj /  Zmień )

Połączenie z %s