Community Installer – darmowy sklep z SmartApps

Dzisiaj przyjrzymy się sklepowi z darmowymi SmartApps stworzonemu przez społeczność SmartThings a mianowicie Community Installer autorstwa Anthony’ego Santilli. Przejdziemy przez proces instalacji sklepu oraz przykładowej aplikacji z jego zasobów.

[UWAGA]: Sklep Community Installer 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. A deweloper odpowiedzialny za Community Installer poinformował o porzuceniu wsparcia.

Community Installer

Community Installer wykorzystuje aplikację SmartApps, jako usługę do automatyzacji instalacji aplikacji SmartApp różnych deweloperów. Tym samym jest bezpłatnym sklepem posiadającym w swoim asortymencie niestandardowe SmartApps i programy obsługi czujników. Głównym wyróżnikiem aplikacji jest możliwość instalacji jednym kliknięciem interesującej nas aplikacji. Sklep został opracowany przez społeczność SmartThings. Chcąc uzyskać SmartApps niezbędne jest urządzenie mobilne z uruchomioną aplikacją SmartThings oraz dostęp do IDE SmartThings.

  • Autor : Anthony Santilli
  • Konto ST communitytonesto7
  • Wkład w kod: Corey Lista
  • Wkład do dokumentacji: Michael Struck
Logo Community Installer

Licencja Open Source/Trademarks w ramach licencji Apache, wersja 2.0: zabronione jest korzystanie z kodu Community Installer (Free Marketplace) inaczej niż na warunkach zgodnych z licencją. Możesz uzyskać kopię Licencji tutaj.

Instrukcja dodawania SmartApps

Przechodzimy do instalacji. W pierwszej kolejności należy się zalogować do IDE na https://account.smartthings.com, i kliknąć Log in. Koniecznie na to samo konto Samsung, na którym został zbudowany inteligentny dom SmartThings.

Następnie wchodzimy w My SmartApps. Tutaj posiadamy listę wszystkich niestandardowych SmartApps do tej pory zainstalowanych.

Kliknij New SmartApp i tym samym przechodzimy do instalowania.

My zdecydowaliśmy się na instalację aplikacji z posiadanego już kodu, więc na kolejnej stronie klikamy From Code. Wklejamy poniższy kod (Ctrl + V) i klikamy Create. Aktualny kod znajduje się w pliku st-community-installer.groovy.

/*
*   Communtity App Installer
*   Copyright 2018, 2019, 2020 Anthony Santilli, Corey Lista
*
// /**********************************************************************************************************************************************/
import java.security.MessageDigest

definition(
    name			: "ST-Community-Installer",
    namespace		: "tonesto7",
    author			: "tonesto7",
    description		: "The Community SmartApp/Devices Installer",
    category		: "My Apps",
    singleInstance	: true,
    iconUrl			: "${getAppImg("app_logo.png")}",
    iconX2Url		: "${getAppImg("app_logo.png")}",
    iconX3Url		: "${getAppImg("app_logo.png")}")
{
    appSetting "devMode"
}
/**********************************************************************************************************************************************/
private releaseVer() { return "1.1.0311a" }
private appVerDate() { "3-11-2020" }
/**********************************************************************************************************************************************/
preferences {
    page name: "startPage"
    page name: "mainPage"
}

mappings {
    path("/installStart") { action: [GET: "installStartHtml"] }
}

def startPage() {
    if(!atomicState?.accessToken) { getAccessToken() }
	if(!atomicState?.accessToken) {
		return dynamicPage(name: "startPage", title: "Status Page", nextPage: "", install: false, uninstall: true) {
			section ("Status Page:") {
				def title = ""
                def desc = ""
				if(!atomicState?.accessToken) { title="OAUTH Error"; desc = "OAuth is not Enabled for ${app?.label} application.  Please click remove and review the installation directions again"; }
				else { title="Unknown Error"; desc = "Application Status has not received any messages to display";	}
				log.warn "Status Message: $desc"
				paragraph title: "$title", "$desc", required: true, state: null
			}
		}
	}
    else { return mainPage() }
}

def mainPage() {
    dynamicPage (name: "mainPage", title: "", install: true, uninstall: true) {
        section("") { image getAppImg("welcome.png") }
        section("Login Options:") {
            if(!settings?.authAcctType) {
                paragraph title: "This helps to determine the login server you are sent to!", ""
            }
            input "authAcctType", "enum", title: "IDE Login Account Type", multiple: false, required: true, submitOnChange: true, options: ["samsung":"Samsung", "st":"SmartThings"], image: getAppImg("${settings?.authAcctType}_icon.png")
        }
        def hideBrowDesc = (atomicState?.isInstalled == true && ["embedded", "external"].contains(settings?.browserType))
        section("Browser Type Description:", hideable: hideBrowDesc, hidden: hideBrowDesc) {
            def embstr = "It's the most secure as the session is wiped everytime you close the view. So it will require logging in everytime you leave the view and isn't always friendly with Password managers (iOS)"
            paragraph title: "Embedded (Recommended)", embstr
            def extstr = "Will open the page outside the SmartThings app in your default browser. It will maintain your SmartThings until you logout. It will not force you to login everytime you leave the page and should be compatible with most Password managers. You can bookmark the Page for quick access."
            paragraph title: "External", extstr
        }
        section("Browser Option:") {
            input "browserType", "enum", title: "Browser Type", required: true, defaultValue: "embedded", submitOnChange: true, options: ["embedded":"Embedded", "external":"Mobile Browser"], image: ""
        }
        section("") {
            if(settings?.browserType) {
                // href "", title: "Installer Home", url: getLoginUrl(), style: (settings?.browserType == "external" ? "external" : "embedded"), required: false, description: "Tap Here to load the Installer Web App", image: getAppImg("go_img.png")
                href "", title: "Installer Home", url: getLoginUrl(), style: (settings?.browserType == "external" ? "external" : "embedded"), required: false, description: "Tap Here to launch the Installer Web App and Signin to the IDE", image: getAppImg("go_img.png")
            } else {
                paragraph title: "Browser Type Missing", "Please Select a browser type to proceed", required: true, state: null
            }
        }
    }
}

def baseUrl(path) {
    return "https://community-installer-34dac.firebaseapp.com${path}"
}

def getLoginUrl() {
    def r = URLEncoder.encode(getAppEndpointUrl("installStart"))
    def theURL = "https://account.smartthings.com/login?redirect=${r}"
    if(settings?.authAcctType == "samsung") { theURL = "https://account.smartthings.com/login/samsungaccount?redirect=${r}" }
    return theURL
}

def installStartHtml() {
    def randVerStr = "?=${now()}"
    def html = """
        <html lang="en">
            <head>
                <meta name="robots" content="noindex">
                <link rel="stylesheet" type="text/css" href="${baseUrl('/content/css/main_mdb.min.css')}" />
                <link rel="stylesheet" type="text/css" href="${baseUrl('/content/css/main_web.min.css')}" />
                https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js
                <script type="text/javascript">
                    const serverUrl     = '${apiServerUrl('')}';
                    const homeUrl       = '${getAppEndpointUrl('installStart')}';
                    const loginUrl      = '${getLoginUrl()}'
                    const baseAppUrl    = '${baseUrl('')}';
                    const appVersion    = '${releaseVer()}';
                    const appVerDate    = '${appVerDate()}';
                    const hashedUuid    = '${generateLocationHash()}';
                    const devMode       = '${isDev()}';
                </script>
            </head>
            <body>
                <div id="bodyDiv"></div>
                ${getScript()}
            </body>
        </html>"""
    render contentType: "text/html", data: html
}

def isDev() { (appSettings?.devMode == true) }
def getScript() {
	def randVerStr = "?=${now()}"
    return isDev() ? """http://$baseUrl('/content/js/ignore_me.js')""" : """http://$baseUrl('/content/js/awesome_file.js')$randVerStr"""
}

def installed() {
    log.debug "Installed with settings: ${settings}"
    atomicState?.isInstalled = true
    initialize()
}

def updated() {
    log.trace ("${app?.getLabel()} | Now Running Updated() Method")
    if(!atomicState?.isInstalled) { atomicState?.isInstalled = true }
    initialize()
}

def initialize() {
    if (!atomicState?.accessToken) {
        log.debug "Access token not defined. Attempting to refresh. Ensure OAuth is enabled in the SmartThings IDE."
        getAccessToken()
    }
}

def uninstalled() {
	revokeAccessToken()
    log.warn("${app?.getLabel()} has been Uninstalled...")
}

def generateLocationHash() {
    def s = location?.getId()
    MessageDigest digest = MessageDigest.getInstance("MD5")
    digest.update(s.bytes);
    new BigInteger(1, digest.digest()).toString(16).padLeft(32, '0')
}

def getAccessToken() {
    try {
        if(!atomicState?.accessToken) {
            log.error "SmartThings Access Token Not Found... Creating a New One!!!"
            atomicState?.accessToken = createAccessToken()
        } else { return true }
    }
    catch (ex) {
        log.error "Error: OAuth is not Enabled for ${app?.label}!.  Please click remove and Enable Oauth under the SmartApp App Settings in the IDE"
        return false
    }
}

def gitBranch()         { return "master" }
def getAppImg(file)	    { return "https://raw.githubusercontent.com/tonesto7/st-community-installer/${gitBranch()}/images/$file" }
def getAppVideo(file)	{ return "https://raw.githubusercontent.com/tonesto7/st-community-installer/${gitBranch()}/videos/$file" }
def getAppEndpointUrl(subPath)	{ return "${apiServerUrl("/api/smartapps/installations/${app.id}${subPath ? "/${subPath}" : ""}?access_token=${atomicState.accessToken}")}" }

W kolejnym kroku po wyświetleniu komunikatu „Created SmartApp”, musimy włączyć OAuth w ustawieniach SmartApp. W tym celu klikamy App Settings. Rozwijamy „OAuth” i klikamy Enable OAuth in Smart App. Na ekranie pojawi się kod Client ID (identyfikatora klienta) i Client Secret (klucza klienta). To są podstawy bezpieczeństwa SmartApp i powinny być utrzymywane w tajemnicy. Nie musisz zapisywać tych kodów. Po prostu należy włączyć OAuth, aby program Community Installer mógł działać poprawnie. Na koniec klikamy „Update”. Wracamy do kodu klikając Code po prawej na samej górze strony.

Kończąc instalację, kliknij Publish, a następnie For Me w prawym górnym rogu. Pojawi się kończący komunikat „SmartApp published successfully”.

Teraz możemy przejść do dodania SmartApps do ekosystemu SmartThings. Otwieramy aplikację na smartfonie. Na ekranie głównym aplikacji, kliknij Dodaj ( + ), następnie wybierz Smart App. Wybierz instalowaną wcześniej aplikację, czyli ST-Community-Installer.

Teraz możemy przystąpić do konfiguracji. W pierwszej kolejności musimy zalogować się do konta IDE SmartThings. Klikamy IDE Login Account Type, wybieramy czy logujemy się kontem SmartThings czy Samsung. W kolejnym kroku podajemy login i hasło. Po zalogowaniu kończmy konfigurację stukając w prawym dolnym rogu Gotowe.

Obsługa Community Installer

Aby skorzystać z darmowego sklepu ze SmartApps. Na ekranie głównym rozwijamy lewe menu, wybieramy SmartApps i wyszukujemy ST-Community-Installer. Po wejściu w aplikację klikamy Installer Home, zostaniemy przeniesieni do sklepu, gdzie możemy wybrać interesującą nas SmartApp. Na kafelkach konkretnych aplikacji możemy zauważyć ilość wyświetleń, instalacji i opinie. Tutaj posłużymy się przykładem „Sense Monitor”. Na stronie głównej SmartApp, możemy się zapoznać z autorem i aktualną wersją aplikacji. Tutaj możemy zauważyć, że aplikacja składa się z niestandardowej SmartApps oraz niestandardowego programu obsługi urządzenia. Aby zainstalować cały pakiet programów, wystarczy kliknąć Install. Rozpocznie się proces instalacji, po zakończeniu ukaże się komunikat „Install Process Completed”. Oznacza to poprawną instalację SmartApp oraz dodatkowych programów. Klikamy Gotowe w prawym górnym rogu ekranu. Aby skorzystać z zainstalowanej aplikacji wracamy do SmartApps, znajdujemy ją i klikamy nazwę, dalej należy już przejść przez proces konfiguracji.

Oświadczenie o ochronie prywatności/użytkowaniu

Community Installer wykorzystuje aplikację SmartApp jako usługę sieciową do automatyzacji instalacji aplikacji SmartApps różnych deweloperów. W żadnym momencie żadne informacje o Twoim osobistym koncie SmartThings, urządzeniach ani ustawieniach nie są przesyłane do zewnętrznej usługi internetowej.

Autorzy tej aplikacji instalatora nie są odpowiedzialni za żadne SmartApp oraz urządzenia wyświetlane zamieszczone w sklepie. Odpowiedzialność za każdą aplikację zawsze ponosi indywidualny programista. Ponadto autorzy tej aplikacji nie będą odpowiedzialni za jakiekolwiek szkody podczas korzystania z programu Community Installer.

Korzystaj z instalatora społecznościowego (darmowego rynku) na własne ryzyko!

Usunięcie SmartApp

Jeśli aplikacja SmartApp nie działa zgodnie z oczekiwaniami lub nie jest już potrzebna, usuwamy ją standardowo, jak inne aplikacje. Dotyczy to również darmowego sklepu Community Installer.

  1. Na ekranie głównym wybierz Menu (☰) i dotknij SmartApps.
  2. Wybierz Więcej opcji (⋮) i dotknij Usuń.
  3. Wybierz Minus (-)  obok żądanej aplikacji SmartApp.
  4. Stuknij Usuń, aby potwierdzić.
Więcej informacji znajdziesz tutaj.

4 myśli w temacie “Community Installer – darmowy sklep z SmartApps

  1. Witam,
    na jednym ze ekranów widzę opcje „sceny” jak ją można ustawić czy też dodać do apki w mojej tego niema.
    Mam podpięte żarówki Osram, mogę je włączyć/wyłączyć, zmienić kolor statycznie i tyle 😦 a plikacji HUE i Osram były dynamiczne sceny.
    Ktoś może coś ogarniał takiego?

    Polubienie

  2. Ok, dzięki za odpowiedz, scenariusze kolejnych czynności są ok i działają. Jednak brakuje mi scen/akcji samoczynnej zmiany barw żarówek np. zachód słońca, zorza polarna etc.
    Dodatkowo nie wiem czy macie doświadczenie z bramkami HUE czy Osram ale miały znacznie większy zasięg Zigbee i bez problemu zasięg sięgał na poddasze w domu przy obecnej bramce Smartthings nie sięga na poddasze ani nawet do garażu przez dwie ściany. Żarówki i wtyczki w gniazdach są w tych samych gniazdkach.

    Polubienie

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