From 3311c21882be96b3b756463a403dfd7dadd17ca4 Mon Sep 17 00:00:00 2001 From: Eric Bariaux <375613+ebariaux@users.noreply.github.com> Date: Mon, 2 Jun 2025 14:27:01 +0200 Subject: [PATCH] Review console releated documentation --- docs/architecture/apps-and-consoles.md | 11 +- .../working-on-the-mobile-consoles.md | 143 +++++++----------- .../configure-mobile-app-behaviour.md | 113 ++++++++++++-- .../deploying/release-management.md | 7 +- 4 files changed, 159 insertions(+), 115 deletions(-) diff --git a/docs/architecture/apps-and-consoles.md b/docs/architecture/apps-and-consoles.md index 3fb41c4..92ff4cd 100644 --- a/docs/architecture/apps-and-consoles.md +++ b/docs/architecture/apps-and-consoles.md @@ -9,10 +9,10 @@ sidebar_position: 3 A frontend application that optionally consumes the OR APIs; same meaning as OAuth client (The OR Manager web application is a client; for custom projects there could be zero or more apps where each app may be used across one or more realms, the apps generally provide very specific functionality as required by the project). These are generally responsive web applications. ### Console -This is the application used to load the client and can be thought of as a wrapper around a client e.g. Web Browser, Android/iOS App. Generally this is an application capable of loading a web view that renders the client. A console could be hardcoded to a specific realm and client or it could be more configurable depending on requirements. A web browser requires no installation where as Android/iOS consoles are pre-compiled and distributed. +This is the application used to load the client and can be thought of as a wrapper around a client e.g. Web Browser, Android/iOS App. Generally this is an application capable of loading a web view that renders the client. A console could be hardcoded to a specific realm and client or it could be more configurable depending on requirements. A web browser requires no installation whereas Android/iOS consoles are pre-compiled and distributed. ## Console/app interaction -Apps and consoles exchange information using the API described below which consists of `providers`, a `provider` is a piece of functionality that the console provides to the app, messages can be sent bidirectionally between the console and app. The Android and iOS consoles implement a standard mechanism for this communication and when running an app in the Web Browser the `@openremote/core` component handles communication and also implements a limited subset of `providers` (e.g. `push`). The console is accessed via the `console` property on the `@openremote/core` component but it is also exported globally as `OpenRemoteConsole`: +Apps and consoles exchange information using the API described below which consists of `providers`, a `provider` is a piece of functionality that the console provides to the app, messages can be sent bidirectionally between the console and app. The Android and iOS consoles implement a standard mechanism for this communication. When running an app in the Web Browser the `@openremote/core` component handles communication and implements a limited subset of `providers` (e.g. `push`). The console is accessed via the `console` property on the `@openremote/core` component but it is also exported globally as `OpenRemoteConsole`: ```typescript import openremote from "@openremote/core"; openremote.init(...).then(()=> { @@ -110,7 +110,7 @@ Once all providers are initialised then the app is free to decide when to enable data: JSON [any data that the app wishes to pass to this provider that may be required for enabling it] } ``` -The console then asks the user for the necessary permission(s) (if not done already) and enables the functionality of this provider then posts a message back to the app: +The console then asks the user for the necessary permission(s) (if not done already), then enables the functionality of this provider and posts a message back to the app: ```json { action: "PROVIDER_ENABLE", @@ -265,7 +265,10 @@ Returns the requested data from the provider. ``` -### TODO Notification Provider (provider: "notification") +### Notification Provider (provider: "notification") + +**This is a specification for a forthcoming provider, no implementation has been done yet!** + Show a notification immediately using the platforms standard mechanism (without using Push API) #### Enabled message request data (App -> Console) diff --git a/docs/developer-guide/working-on-the-mobile-consoles.md b/docs/developer-guide/working-on-the-mobile-consoles.md index 6a25768..25fbb1d 100644 --- a/docs/developer-guide/working-on-the-mobile-consoles.md +++ b/docs/developer-guide/working-on-the-mobile-consoles.md @@ -9,99 +9,67 @@ Make sure you've pulled the latest code of the repository. ## Android Console -Download and install [Android Studio](https://developer.android.com/studio/index.html), then open the [console-android](https://github.com/openremote/console-android) repository. +Download and install [Android Studio](https://developer.android.com/studio/index.html) -TODO: There is actually nothing to build right now, you have to create a custom project and a dependency on our Android console project from your own Android app. - -## iOS Console - -### Developing for iOS is only possible on macOS - -Download and install [Xcode](https://itunes.apple.com/nl/app/xcode/id497799835) - -Open Xcode and create a new project. -In the generals part, click on the plus symbol to add a new target. -Select Notification Service Extension. -Close the project. - -Install cocoapods through a terminal window. - -```shell -sudo gem install cocoapods +Open Android Studio and create an Android app. +In your application gradle file, add the following dependency +```groovy +implementation 'io.openremote:orlib:1.3.0' ``` -Navigate to your project directory and create a pod file. - -```shell -pod init -``` - -Open up the Podfile with a text editor and add the `ORLib` pod: -``` -workspace '' -platform :ios, '14.0' - -use_frameworks! - -def shared_pods - pod 'Firebase/Core', '~> 4.6.0' - pod 'Firebase/Messaging', '~> 4.6.0' - pod 'Fabric', '~> 1.10.2' - pod 'Crashlytics', '~> 3.13.4' - pod 'ORLib', '~> 0.3' -end - -target '' do - project '' - shared_pods -end - -target 'NotificationService' do - project '' - shared_pods -end -``` +Open your `MainActivity` and make it inherit `OrMainActivity`. +Implement the additional logic to set the proper URL and trigger the load, such as +```kotlin +class MainActivity() : OrMainActivity() { -Save and close the Podfile. -In the terminal enter the following command + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) -```shell -pod install + val platform = "Android " + Build.VERSION.RELEASE + val version = BuildConfig.VERSION_NAME + baseUrl = "https://example.com/myapp/?consolePlatform=$platform&consoleName=mygrid&consoleVersion=$version&consoleAutoEnable=false&consoleProviders=push storage" + loadUrl(baseUrl!!) + } +} ``` -A xcworkspace file is created after installing the pod. -Open this file and Xcode will start. +When using Firebase, download the `google-services.json` file and add it to you project. +Follow the Firebase [instructions](https://firebase.google.com/docs/android/setup). -Click on the `Pods` icon in the project tree and then on ORLib in the targets pane. -Search for Require Only App-Extension-Safe API and set it to `No`. -A warning will appear which can be ignored. - -Open `AppDelegate` in your project and make it inherit from `ORAppDelegate`. -Remove all the code and override `applicationDidFinishLaunchingWithOptions`. -Set the right project values. +## iOS Console -```cpp -override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { +### Developing for iOS is only possible on macOS - ORServer.hostURL = "example.com" - ORServer.realm = "example" +Download and install [Xcode](https://itunes.apple.com/nl/app/xcode/id497799835) - ORAppGroup.entitlement = "group.io.openremote.example" - - return super.application(application, didFinishLaunchingWithOptions: launchOptions) +Open Xcode and create a new iOS App project. Select `Storyboard` as the "Interface". + +In the project navigator, open the contextual menu and select "Add Package Dependencies…". +Search for URL https://github.com/openremote/console-ios-lib.git then click "Add Package" and again in the "Choose Package Products" window. +Repeat for URL https://github.com/hackiftekhar/IQKeyboardManager.git. +Repeat for URL https://github.com/AssistoLab/DropDown.git but here select "Dependency Rule" `Branch` and enter `master` for the branch name. +Repeat for URL https://github.com/firebase/firebase-ios-sdk.git but in the "Choose Package Products" window select set the target only for FirebaseAnalytics, FirebaseCrashlytics and FirebaseMessaging. + +Open `ViewController` and make it inherit `ORViewController` instead of `UIViewController` (you'll need to import module `ORLib`). +Implement the additional logic to set the proper URL and trigger the load, such as +```swift +class MainViewController: ORViewcontroller { + override func viewDidLoad() { + super.viewDidLoad() + self.baseUrl = "https://example.com/myapp/?consolePlatform=iOS \(UIDevice.current.systemVersion)&consoleName=myconsole&consoleVersion=\(Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? "N/A")&consoleProviders=push storage" + if let encodedUrl = self.baseUrl!.addingPercentEncoding(withAllowedCharacters: .urlFragmentAllowed) { + loadURL(url: URL(string: encodedUrl)!) + } } +} ``` -In the `Main.storyboard` add a second ViewController. -The initial viewcontroller should be of class ORLoginViewController. -The other ViewController should be of class ORViewController. - -In the Notification Service Extension target, open `NotificationViewController` and make it inherit from `ORNotificationService`. -Remove all the code inside. +In the generals part, click on the plus symbol to add a new target. +Select Notification Service Extension. +Don't activate the scheme. -When using Firebase, download the `GoogleService-Info.plist` and add it through Xcode. -It shuld be placed in the root of the project. -Make sure that `copy when needed` is checked when adding. +When using Firebase, download the `GoogleService-Info.plist` file and add it through Xcode. +Follow the Firebase [instructions](https://firebase.google.com/docs/ios/setup). Now your iOS app is setup to work with your OpenRemote project! @@ -109,24 +77,15 @@ Now your iOS app is setup to work with your OpenRemote project! Our consoles are able to receive push notifications that are sent by the OpenRemote Manager. -Through Firebase, together with the use of FCM tokens, you can set this up for your own project using your own account. - -*(steps are unverified)* - -### Setup Firebase and client - -1. Create a new Firebase Project at https://console.firebase.google.com using either a free or paid plan. -2. When on the 'Project Overview' page, create a new app for your preferred platform; such as Android and iOS. -3. Fill in the correct details for your app, and follow the steps respectively. These should be no different than any other Android/iOS app. - -After your config files are placed in the correct folder, (normally `google-services.json` and `GoogleService-info.plist`) and the Firebase Gradle dependencies have been added to your project, you are good to go! +Through Firebase, together with the use of FCM tokens, you can set this up for your own project using your own account. +See above for the console specific steps. ### Configure Manager to send push notifications To complete the setup process, you should configure the manager to send push notifications to the correct address on Firebase. -> Be sure that the `OR_FIREBASE_CONFIG_FILE` environment variable is set to the correct path.
-> Forks of OpenRemote should be correctly configured, but custom projects might need additional attention.
+> Be sure that the `OR_FIREBASE_CONFIG_FILE` environment variable is set to the correct path. +> Forks of OpenRemote should be correctly configured, but custom projects might need additional attention. > We normally use `/deployment/manager/fcm.json`. 1. Go to your Firebase project at https://console.firebase.google.com @@ -145,7 +104,7 @@ For most projects, you want to keep Firebase related files secret for security r We have built-in gradle scripts to help you with this; 1. Open to the `build.gradle` file in the root of your repository. -2. Add/replace the paths specified in the `gradleFileEncrypt` task with the files you want to encrypt. +2. Add/replace the paths specified in the `gradleFileEncrypt` task with the files you want to encrypt. Normally this is your `fcm.json` file, but also the files related to the consoles like `google-services.json`. 3. Double check whether these files you want to encrypt are present in your `.gitignore` files. **This is required.** 4. Generate/specify a password to encrypt the files with, by using the `GFE_PASSWORD` environment variable. Save this somewhere safe. diff --git a/docs/tutorials/configure-mobile-app-behaviour.md b/docs/tutorials/configure-mobile-app-behaviour.md index a2ef1c4..57a596c 100644 --- a/docs/tutorials/configure-mobile-app-behaviour.md +++ b/docs/tutorials/configure-mobile-app-behaviour.md @@ -4,34 +4,115 @@ sidebar_position: 5 # Configure mobile app behaviour -T.B.D. - -Here we will explain how to configure your apps to be used in the OpenRemote mobile app. You have the option to show/not show on mobile, and for which realms the app is available. Also you can define whether realm options are shown as a list or input field (if you don't want to reveal all available realms). +Here we will explain how to configure your apps to be used in the OpenRemote mobile app. Mobile apps can be found in the -[Apple App Store](https://apps.apple.com/nl/app/openremote-app/id1526315885?mt=8) and on [Google Play](https://play.google.com/store/apps/details?id=io.openremote.app&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1). +[Apple App Store](https://apps.apple.com/nl/app/openremote-app/id1526315885?mt=8) and on [Google Play](https://play.google.com/store/apps/details?id=io.openremote.app&pcampaignid=pcampaignidMKT-Other-global-all-co-prtnr-py-PartBadge-Mar2515-1). + +The first time opening the app you will be asked (up to) three things: 'App Domain', 'Select an app' and 'Enter the Realm'. Switching between domains, apps and realms can be done by long-pressing the app icon on your home screen. If you are hosting an OpenRemote instance at https://yourhost.com use the following: 'App Domain' is 'yourhost.com'. + +Several configuration options allow to influence this flow, these are described below. + +The more advanced configuration options are done via the `console_config.json` file, which is located in the `/deployment/manager/app` folder. +This file has the following structure +```json +{ + "showAppTextInput" : true | false, // Show app text input instead of drop down (user must correctly enter app name) + "showRealmTextInput" : true | false, // Show realm text input instead of drop down (user must correctly enter realm name) + "app" : null, // App name, load that specific app (don't allow choice) + "allowedApps" : [], // List of allowed apps (ignore apps that are actually available and use this list instead) + "apps" : { + "" or "default" : { + "consoleAppIncompatible" : true | false, // If set to true don't show in list + "realms" : [], // List of realms that can be used with this app + "providers" : [], // List of console providers the app wants to/should use + "description" : "" // Description of the app + } + } +} +``` + +## Domain -The first time opening the app you will be asked three things: 'App Domain', 'Select an app' and 'Enter the Realm'. Switching between domains, apps and realms can be done by long-pressing the app icon on your home screen. If you are hosting an OpenRemote instance at https://yourhost.com use the following: 'App Domain' is 'yourhost.com'. +The domain must always be manually entered by the user. Users can enter: +- a full URL (e.g. https://myapp.example.com), with optional port +- a fully qualified host name (e.g. myapp.example.com), https in used as the scheme +- an IP address, with or without scheme (e.g. 192.168.1.1) +- a simple domain (string with no dot in name), the URL used is then https://_domain_.openremote.app -## Configure apps which can be selected +## App + +By default, the system discovers the available apps and presents them to the user as a list for selection. +If there's only one available app, it's automatically selected and no option is presented to the user. + +### Configure apps which can be selected Apps can be hidden from the consoles using one of the following methods: -- Either placing an empty `.appignore` file in the folder of the platform- or custom app.
+- Either placing an empty `.appignore` file in the folder of the platform- or custom app. For example: `/ui/app/custom/.appignore` -- Or, customizing the `console_config.json` file, which is located in the `/deployment/manager/app` folder.
-The `allowedApps` field allows you to customize the list of apps that is visible in consoles.
+- Or, customizing the `console_config.json` file. +The `allowedApps` field allows you to customize the list of apps that can be selected in consoles. For example: `{ allowedApps: ['manager', 'custom'] }` -Both of these options only impact the consoles, the URLs are still available on the web.
-If during use only one App is present, the consoles will automatically skip the 'app selection'-menu, and go straight to the app. +- Or, customizing the `console_config.json` file. +Setting the `consoleAppIncompatible` to `true` for an application will prevent it from being presented or selected in the console. + +Both of these options only impact the consoles, the URLs are still available on the web. + +Again, if the filtered list only contains one app, it's automatically selected and no option is presented to the user. + +### Force app name entry + +If you don't want the console to present a list of available apps, you can force the user to manually enter the app name in a text field. +Customize the `console_config.json` file, setting the `showAppTextInput` to `true`. + +The app name entered by the user must still be a valid app name +i.e. if the `allowedApps` field has been defined, the entered app name must be present in that list. +In this case, even if only one application is available, it is not automatically selected. + +### Pre-define selected app + +You can also specify the app to be used and forbid selection by the user (the app selection option is never presented). +Customize the `console_config.json` file, setting the `app` field to the name of the app you want to be used. + +## Realm + +As for apps, by default, the console presents the user with a list of possible realms for selection. +If there's only one available realm, it's automatically selected and no option is presented to the user. + +### Configure for which realms the app can be used + +To define the realms allowed for a specific app, customize the `console_config.json` file. +Under the given app section, list the realms names in the `realms` property. +For example +```json +{ + "apps" : { + "console1" : { + "realms" : [ "master", "realm2"] + } + } +} +``` + +### Force realm name entry + +If you don't want the console to present a list of available realms, you can force the user to manually enter the realm name in a text field. +Customize the `console_config.json` file, setting the `showRealmTextInput` to `true`. -## Configure for which realms the app can be used +## Providers -T.B.D. -- shortlist available realms -- show as dropdown list or input field -- if only one realm, skip step +For example +```json +{ + "apps" : { + "console1" : { + "providers" : [ "push", "storage"] + } + } +} +``` ## See Also - [Consoles](../user-guide/manager-ui/on-mobile.md) diff --git a/docs/user-guide/deploying/release-management.md b/docs/user-guide/deploying/release-management.md index b64f361..18e3782 100644 --- a/docs/user-guide/deploying/release-management.md +++ b/docs/user-guide/deploying/release-management.md @@ -55,7 +55,7 @@ For this you can use the ORLib library which simplifies integrating OpenRemote i ORLib has its own release cycle because it is maintained in separate repositories and is only released when there are changes. The Android ORLib is maintained in the [console-android](https://github.com/openremote/console-android) repository and published as a JAR to [Maven Central](https://search.maven.org/artifact/io.openremote/orlib). -The iOS ORLib is maintained in the [console-ios](https://github.com/openremote/console-ios) repository and published as a CocoaPod to [Trunk](https://cocoapods.org/pods/orlib). +The iOS ORLib is maintained in the [console-ios-lib](https://github.com/openremote/console-ios-lib) repository and published as a Swift Package. You can find the release notes for ORLib versions on the "Releases" page of the respective GitHub repositories. @@ -112,9 +112,10 @@ When the release workflow is started it will: 1. Create a tag for the release 2. Create a release with release notes -3. Trigger a CI/CD build to publish all the release artifacts (i.e. Docker images, JARs, NPMs, CocoaPods) +3. Trigger a CI/CD build to publish all the release artifacts (i.e. Docker images, JARs, NPMs) Most of the release process is now automated but after a release some versions still need to be manually updated: * openremote/openremote: The "version" in the `package.json` files of all modules in the 'ui' directory -* openremote/console-ios: The CocoaPod "version" in the `ORLib/ORLib.podspec` file + +For the iOS ORLib, the `Marketing Version` Build Setting of the ORLib target must be manually updated PRIOR to running the release workflow.