/** * * Hubitat Package Manager v1.9.3 * * Copyright 2020 Dominick Meglio * * If you find this useful, donations are always appreciated * https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7LBRPJRLJSDDN&source=url * * * * csteele v1.9.3 improved displayHeader to include the Main Menu Option selected * refactored delete app to use new endpoint * csteele v1.9.2 added 'Connection': 'keep-alive' to install/uninstall Apps, Drivers and Bundles * extended timeout to 7 min (420 seconds) * Take advantage of v2.3.8 Bundle install/uninstall * csteele v1.9.1 updatePackage() ignores blank app or driver definitions * Take advantage of endpoints in v2.3.7 for app and driver uninstall * take advantage of endpoint for driver code list in v2.3.6 * clarify "failed download" error message with App or Driver hint * change updateTime to be NOT the 00 second * extended installBundle() timeout to 5 min (300 seconds) * csteele v1.9.0 Install 'location:' can't be empty. * add color to download icon * take advantage of endpoint for app code list in v2.3.6 * csteele v1.8.11 merge of: Add support for hub SSL (HTTPS) from kevdliu PR * csteele v1.8.10 correct File where contents are HTML [installFile() & uninstallFile()] * fix for default installBundle() (tomw) * csteele v1.8.9 allow required: true as string also * fix for a ProBundle install (a) * csteele v1.8.8 check for Null for Invalid Category & Tags * log.error changed to log.warn where the event was handled * detect/delete missing Repositories * csteele v1.8.7 fix to Update bundle. (birdslikewires) * csteele v1.8.6 Un-Match added * moved Bundles before Apps/Drivers for Install and Repair * included Bundles into modify * csteele v1.8.5 Bundles support added * csteele v1.8.4 Migrated to HubitatCommunity * added txtEnable to silence log.info messages * use httpS for Fast Search * csteele v1.8.3 No change here. Changes were to Dominic's repo to cause an upgrade to here * csteele v1.8.2.A Converted to using HubitatCommunity.com as the search resource. [Lines 66-67 & 379-380] * added footer to display version and copyright fields * added feature to identify Azure search vs sql search */ public static String version() { return "v1.9.3" } def getThisCopyright(){"© 2020 Dominick Meglio"} definition( name: "Hubitat Package Manager", namespace: "dcm.hpm", author: "Dominick Meglio", description: "Provides a utility to maintain the apps and drivers on your Hubitat making both installation and updates easier", category: "My Apps", importUrl: "https://raw.githubusercontent.com/HubitatCommunity/hubitatpackagemanager/main/apps/Package_Manager.groovy", documentationLink: "https://hubitatpackagemanager.hubitatcommunity.com/", iconUrl: "", iconX2Url: "", iconX3Url: "", singleInstance: true) preferences { page(name: "prefSettings") page(name: "prefOptions") page(name: "prefPkgInstall") page(name: "prefPkgInstallUrl") page(name: "prefInstallRepositorySearch") page(name: "prefInstallRepositorySearchResults") page(name: "prefPkgInstallRepository") page(name: "prefPkgInstallRepositoryChoose") page(name: "prefPkgModify") page(name: "prefPkgRepair") page(name: "prefPkgRepairExecute") page(name: "prefPkgUpdate") page(name: "prefPkgUninstall") page(name: "prefInstallChoices") page(name: "prefInstallVerify") page(name: "prefInstall") page(name: "prefPkgModifyChoices") page(name: "prefVerifyPackageChanges") page(name: "prefMakePackageChanges") page(name: "prefPkgUninstallConfirm") page(name: "prefUninstall") page(name: "prefPkgVerifyUpdates") page(name: "prefPkgUpdatesComplete") page(name: "prefPkgMatchUp") page(name: "prefPkgMatchUpVerify") page(name: "prefPkgMatchUpComplete") page(name: "prefPkgView") page(name: "prefPkgUnMatch") page(name: "prefPkgUnMatchVerify") page(name: "prefPkgUnMatchComplete") } import groovy.transform.Field import java.util.regex.Matcher @Field static String repositoryListing = "https://raw.githubusercontent.com/HubitatCommunity/hubitat-packagerepositories/master/repositories.json" @Field static String settingsFile = "https://raw.githubusercontent.com/HubitatCommunity/hubitat-packagerepositories/master/settings.json" @Field static String searchFuzzyApiUrl = "https://hubitatpackagemanager.azurewebsites.net/graphql" @Field static String searchFastApiUrl = "https://hubitatpackagemanager.hubitatcommunity.com/searchHPMpkgs2.php" @Field static List categories = [] @Field static List allPackages = [] @Field static def completedActions = [:] @Field static def manifestForRollback = null @Field static def downloadQueue = [:] @Field static Integer maxDownloadQueueSize = 10 @Field static String installAction = "" @Field static String installMode = "" @Field static String statusMessage = "" @Field static String errorTitle = "" @Field static String errorMessage = "" @Field static Boolean errorOccurred = false @Field static def packagesWithUpdates = [:] @Field static def optionalItemsToShow = [:] @Field static def updateDetails = [:] @Field static List appsToInstallForModify = [] @Field static List appsToUninstallForModify = [] @Field static List driversToInstallForModify = [] @Field static List driversToUninstallForModify = [] @Field static List packagesMatchingInstalledEntries = [] @Field static List iconTags = ["ZWave", "Zigbee", "Cloud", "LAN"] @Field static String srchSrcTxt = "" @Field static String searchApiUrl = "" def installed() { initialize() } def updated() { unschedule() initialize() } def initialize() { def timeOfDayForUpdateChecks if (updateCheckTime == null) timeOfDayForUpdateChecks = timeToday("00:00") else timeOfDayForUpdateChecks = timeToday(updateCheckTime, location.timeZone) schedule("13 ${timeOfDayForUpdateChecks.minutes} ${timeOfDayForUpdateChecks.hours} ? * *", checkForUpdates) performMigrations() } def uninstalled() { log.warn "uninstalling app" unschedule() } def appButtonHandler(btn) { switch (btn) { case "btnMainMenu": state.mainMenu = true break case "btnBack": state.back = true case "btnAddRepo": state.customRepo = true break case "btnUnMatch": state.UnMatch = true break case ~/^btnDeleteRepo(\d+)/: deleteCustomRepository(Matcher.lastMatcher[0][1].toInteger()) break } } def prefOptions() { state.remove("mainMenu") if (state.customRepo && customRepo != "" && customRepo != null) { def repoListing = getJSONFile(customRepo) if (repoListing == null) { clearStateSettings(true) return buildErrorPage("Error loading repository", "The repository file you specified could not be loaded.") } else { installedRepositories << customRepo if (state.customRepositories == null) state.customRepositories = [:] if (state.customRepositories[customRepo] == null) state.customRepositories << ["${customRepo}":repoListing.author] } } if (state.firstRun == true) return prefPkgMatchUp() else { clearStateSettings(true) initialize() installHPMManifest() } if (installedRepositories == null) { logDebug "No installed repositories, grabbing all" def repos = [] as List state.repositoryListingJSON.repositories.each { it -> repos << it.location } app.updateSetting("installedRepositories", repos) } state.categoriesAndTags = loadSettingsFile() return dynamicPage(name: "prefOptions", title: "", install: true, uninstall: false) { displayHeader() if (isHubSecurityEnabled() && !hpmSecurity) { section { paragraph "Hub Security appears to be enabled but is not configured in HPM. Please configure hub security." } } if (state.newRepoMessage != "") { section { paragraph state.newRepoMessage state.newRepoMessage = "" } } section { paragraph "What would you like to do?" href(name: "prefPkgInstall", title: "Install", required: false, page: "prefPkgInstall", description: "Install a new package.") href(name: "prefPkgUpdate", title: "Update", required: false, page: "prefPkgUpdate", description: "Check for updates for your installed packages.") href(name: "prefPkgModify", title: "Modify", required: false, page: "prefPkgModify", description: "Modify an already installed package. This allows you to add or remove optional components.") href(name: "prefPkgRepair", title: "Repair", required: false, page: "prefPkgRepair", description: "Repair a package by ensuring all of the newest versions are installed in case something went wrong.") href(name: "prefPkgUninstall", title: "Uninstall", required: false, page: "prefPkgUninstall", description: "Uninstall packages.") href(name: "prefPkgMatchUp", title: "Match Up", required: false, page: "prefPkgMatchUp", description: "Match up the apps and drivers you already have installed with packages available so that you can use the package manager to get future updates.") href(name: "prefPkgView", title: "View Apps and Drivers", required: false, page: "prefPkgView", description: "View the apps and drivers that are managed by packages.") href(name: "prefSettings", title: "Package Manager Settings", required: false, page: "prefSettings", params: [force:true], description: "Modify Hubitat Package Manager Settings.") } displayFooter() } } def prefSettings(params) { if (state.UnMatch) return prefPkgUnMatch() def showSettingsForSecurityEnablement = false state.newRepoMessage = "" if (state.manifests == null) state.manifests = [:] performMigrations() if (updateRepositoryListing()?.size() > 0) { state.newRepoMessage = "One or more new repositories have been added. You may want to do a Match Up to ensure all of your packages are detected." } if (isHubSecurityEnabled() && !hpmSecurity) { showSettingsForSecurityEnablement = true } installHPMManifest() if (app.getInstallationState() == "COMPLETE" && params?.force != true && !showSettingsForSecurityEnablement) return prefOptions() else { def showInstall = app.getInstallationState() == "INCOMPLETE" if (showInstall) state.firstRun = true return dynamicPage(name: "prefSettings", title: "", nextPage: "prefOptions", install: showInstall, uninstall: false) { displayHeader(' Settings') section ("Hub Security") { if (showSettingsForSecurityEnablement) { paragraph "Hub Security appears to be enabled on your hub but is not enabled within HPM. Please configure hub security below" } paragraph "In order to automatically install apps and drivers you must specify your Hubitat admin username and password if Hub Security is enabled." input "hpmSecurity", "bool", title: "Hub Security Enabled", submitOnChange: true if (hpmSecurity) { input "hpmUsername", "string", title: "Hub Security username", required: true input "hpmPassword", "password", title: "Hub Security password", required: true } paragraph "If you have SSL (HTTPS) enabled on your hub, you must enable the option below. If you're not sure, leave the option disabled." input "sslEnabled", "bool", title: "SSL (HTTPS) Enabled", submitOnChange: true if (showInstall) paragraph "Please click Done and restart the app to continue." } if (!state.firstRun) { section ("General") { input "debugOutput", "bool", title: "Enable debug logging", defaultValue: true input "txtEnable", "bool", title: "Enable text logging", defaultValue: true input "includeBetas", "bool", title: "When updating, install pre-release versions. Note: Pre-releases often include more bugs and should be considered beta software" } section { paragraph "
packageManifest.json
file).", required: true
}
section {
paragraph "