commit d5dc0c7ca5123a6633e007f41c093def7986a6a6 Author: etm Date: Sat Feb 21 16:57:46 2026 +0100 Initial commit : Flutter app nymea energy monitor - NymeaService : auth complète (Hello → Authenticate → SetNotificationStatus) - Token top-level dans chaque requête JSON-RPC (fix critique GetThings) - Persistance token via shared_preferences par hôte - Dashboard : champs utilisateur/mot de passe dans le dialog de connexion - ThingDetailScreen : renommer, réglages (settingsTypes) et supprimer - NymeaThingClass : champ settingsTypes parsé depuis l'API - NymeaThing : copyWith(name) + settingValue() - Fix overflow _StateChip dans ThingsScreen Co-Authored-By: Claude Sonnet 4.6 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b45cc43 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release + +# Claude Code +.claude/ diff --git a/.metadata b/.metadata new file mode 100644 index 0000000..c0fe018 --- /dev/null +++ b/.metadata @@ -0,0 +1,45 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "90673a4eef275d1a6692c26ac80d6d746d41a73a" + channel: "stable" + +project_type: app + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + - platform: android + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + - platform: ios + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + - platform: linux + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + - platform: macos + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + - platform: web + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + - platform: windows + create_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + base_revision: 90673a4eef275d1a6692c26ac80d6d746d41a73a + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..9804a7a --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,95 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Contexte général + +Dossier parent de tous les projets : `/home/etm/Projects/` + +- **`etm_powersync_app/`** (ce projet) — application Flutter HEMS, client mobile +- **`etm-nymea/`** — serveur nymea et plugins associés (C++/Qt), le backend + +Ce projet est le **client Flutter** qui communique avec le serveur nymea via JSON-RPC 2.0. + +--- + +## Commandes + +```bash +flutter pub get # installer/mettre à jour les dépendances +flutter run # lancer sur device/émulateur connecté +flutter build apk # build Android release +flutter analyze # analyse statique Dart +flutter test # lancer les tests +``` + +## Architecture + +### State management — un seul Provider + +`NymeaService` (`lib/services/nymea_service.dart`) est le seul `ChangeNotifier`. Il est fourni à la racine dans `main.dart` via `ChangeNotifierProvider`. Tous les écrans le consomment avec `context.watch()` ou `context.read()`. Il n'y a aucune autre couche de state management. + +### Navigation + +`MainShell` dans `main.dart` utilise un `IndexedStack` de 5 écrans (l'état est préservé entre les onglets) : + +| Index | Écran | Fichier | +|-------|-------|---------| +| 0 | Dashboard | `lib/screens/dashboard_screen.dart` | +| 1 | Énergie | `lib/screens/energy_screen.dart` | +| 2 | Things | `lib/screens/things_screen.dart` | +| 3 | A/C | `lib/screens/ac_screen.dart` | +| 4 | Favoris | `lib/screens/favorites_screen.dart` | + +### Communication avec nymea + +`NymeaService.connect()` supporte deux transports : + +- **TCP brut** port 2222 (défaut) : nymea parle **en premier** (JSON délimité par `\n`). La fragmentation est gérée via `StringBuffer`. +- **WebSocket** port 4444 : c'est le **client qui parle en premier** en envoyant `JSONRPC.Hello`. + +Les requêtes utilisent des IDs auto-incrémentés stockés dans `_pendingRequests: Map`. Timeout global : 15 secondes. Les notifications push nymea (pas de champ `id`, ont un champ `notification`) sont dispatchées dans `_handleNotification()`. + +**Convention nymea énergie importante** : `currentPowerProduction` est **négatif** (producteur = négatif). Le service convertit en positif dans `_parsePowerBalance()`. + +### Mode simulation + +`NymeaService.startSimulation()` déconnecte toute connexion live, active `_isSimulation = true`, génère des things fictifs et une production PV simulée en sinus (timer 2 s). Le dashboard démarre automatiquement la simulation au premier affichage si non connecté. Toutes les méthodes du service font un garde `if (_isSimulation) return …` pour éviter les vrais appels RPC. + +### Modèles de données + +- **`EnergyData`** (`lib/models/energy_data.dart`) — objet immutable avec `copyWith`, regroupe toutes les métriques énergie temps-réel et journalières + état de la borne EV. +- **`NymeaThing` / `NymeaThingClass` / `NymeaStateType` / `NymeaActionType`** (`lib/models/nymea_models.dart`) — miroir de l'API Integrations nymea. `NymeaThingClass.primaryStateType` détermine l'état affiché sur les cards. +- **`ThingCategory` + `interfaceToCategoryMap`** (`lib/models/thing_category.dart`) — mappe les interfaces nymea (ex. `"evcharger"`, `"solarinverter"`) vers des catégories d'affichage utilisées par `ThingsScreen`. +- **`FavoriteWidget`** (`lib/models/nymea_models.dart`) — descripteurs de widgets stockés en mémoire dans `NymeaService._favoriteWidgets`. + +### Thème + +`AppTheme` (`lib/theme/app_theme.dart`) expose des constantes `Color` nommées : `primaryGreen`, `solarYellow`, `gridGray`, `homeBlue`, `batteryGreen`, `boostRed`, `pvGreen`, `minPvBlue`, etc. Toujours utiliser ces constantes plutôt que des valeurs hex brutes. + +## Conventions + +- **Code** : anglais — **Commentaires** : français +- **Nommage** : camelCase variables, PascalCase classes +- Les écrans utilisent `Consumer` ou `context.watch` — ne jamais dupliquer l'état du service dans un `State` +- **Unités** : Watts (W) pour les puissances instantanées, Wh pour les énergies journalières. L'API nymea retourne des totaux en kWh que le service multiplie par 1000. + +## Méthodes nymea principales + +| Méthode | Rôle | +|---------|------| +| `JSONRPC.Hello` | Handshake (WebSocket uniquement — envoyé par le client) | +| `Integrations.GetThings` | Charger les devices configurés | +| `Integrations.GetThingClasses` | Charger les définitions de classes (filtre `thingClassIds` supporté) | +| `Integrations.ExecuteAction` | Exécuter une action sur un thing | +| `Integrations.GetStateValue` | Lire une valeur d'état | +| `Energy.GetPowerBalance` | Snapshot du flux énergétique actuel | +| `Energy.GetEnergyLogs` | Historique énergie (échantillons horaires) | +| `Energy.SetChargingMode` | Mode borne EV : `pv`, `minpv`, `boost` | + +Notifications push gérées : `Energy.PowerBalanceChanged`, `Energy.RootMeterChanged`, `Integrations.StateChanged`, `Integrations.ThingAdded`, `Integrations.ThingRemoved`. + +## Documentation API + +- `docs/nymea_api.md` — introspection complète de l'API nymea +- `docs/nymea_integrations.md` — namespace Integrations en détail diff --git a/README.md b/README.md new file mode 100644 index 0000000..d3be253 --- /dev/null +++ b/README.md @@ -0,0 +1,17 @@ +# etm_powersync_app + +A new Flutter project. + +## Getting Started + +This project is a starting point for a Flutter application. + +A few resources to get you started if this is your first Flutter project: + +- [Learn Flutter](https://docs.flutter.dev/get-started/learn-flutter) +- [Write your first Flutter app](https://docs.flutter.dev/get-started/codelab) +- [Flutter learning resources](https://docs.flutter.dev/reference/learning-resources) + +For help getting started with Flutter development, view the +[online documentation](https://docs.flutter.dev/), which offers tutorials, +samples, guidance on mobile development, and a full API reference. diff --git a/analysis_options.yaml b/analysis_options.yaml new file mode 100644 index 0000000..0d29021 --- /dev/null +++ b/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/android/.gitignore b/android/.gitignore new file mode 100644 index 0000000..be3943c --- /dev/null +++ b/android/.gitignore @@ -0,0 +1,14 @@ +gradle-wrapper.jar +/.gradle +/captures/ +/gradlew +/gradlew.bat +/local.properties +GeneratedPluginRegistrant.java +.cxx/ + +# Remember to never publicly share your keystore. +# See https://flutter.dev/to/reference-keystore +key.properties +**/*.keystore +**/*.jks diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts new file mode 100644 index 0000000..54d3fee --- /dev/null +++ b/android/app/build.gradle.kts @@ -0,0 +1,44 @@ +plugins { + id("com.android.application") + id("kotlin-android") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.example.etm_powersync_app" + compileSdk = flutter.compileSdkVersion + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + kotlinOptions { + jvmTarget = JavaVersion.VERSION_17.toString() + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.example.etm_powersync_app" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = flutter.targetSdkVersion + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +flutter { + source = "../.." +} diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..34c43ef --- /dev/null +++ b/android/app/src/main/AndroidManifest.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/com/example/etm_powersync_app/MainActivity.kt b/android/app/src/main/kotlin/com/example/etm_powersync_app/MainActivity.kt new file mode 100644 index 0000000..9d2b5f0 --- /dev/null +++ b/android/app/src/main/kotlin/com/example/etm_powersync_app/MainActivity.kt @@ -0,0 +1,5 @@ +package com.example.etm_powersync_app + +import io.flutter.embedding.android.FlutterActivity + +class MainActivity : FlutterActivity() diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml new file mode 100644 index 0000000..f74085f --- /dev/null +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml new file mode 100644 index 0000000..304732f --- /dev/null +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -0,0 +1,12 @@ + + + + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000..db77bb4 Binary files /dev/null and b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000..17987b7 Binary files /dev/null and b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000..09d4391 Binary files /dev/null and b/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000..d5f1c8d Binary files /dev/null and b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000..4d6372e Binary files /dev/null and b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml new file mode 100644 index 0000000..06952be --- /dev/null +++ b/android/app/src/main/res/values-night/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000..cb1ef88 --- /dev/null +++ b/android/app/src/main/res/values/styles.xml @@ -0,0 +1,18 @@ + + + + + + + diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml new file mode 100644 index 0000000..399f698 --- /dev/null +++ b/android/app/src/profile/AndroidManifest.xml @@ -0,0 +1,7 @@ + + + + diff --git a/android/build.gradle.kts b/android/build.gradle.kts new file mode 100644 index 0000000..dbee657 --- /dev/null +++ b/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/android/gradle.properties b/android/gradle.properties new file mode 100644 index 0000000..fbee1d8 --- /dev/null +++ b/android/gradle.properties @@ -0,0 +1,2 @@ +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError +android.useAndroidX=true diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..e4ef43f --- /dev/null +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts new file mode 100644 index 0000000..ca7fe06 --- /dev/null +++ b/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "8.11.1" apply false + id("org.jetbrains.kotlin.android") version "2.2.20" apply false +} + +include(":app") diff --git a/docs/nymea_api.md b/docs/nymea_api.md new file mode 100644 index 0000000..bde9b7b --- /dev/null +++ b/docs/nymea_api.md @@ -0,0 +1,5938 @@ +# Nymea JSON-RPC API + +## AirConditioning.AddZone + +Create a zones. + +### Parameters + +- name +- o:indoorSensors +- o:notifications +- o:outdoorSensors +- o:thermostats +- o:windowSensors + +### Returns + +- airConditioningError +- o:zone + +### Example Request + +```json +{ + "id": 1, + "method": "AirConditioning.AddZone", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AirConditioning.GetZones + +Get all Zones. + +### Parameters + +- o:zoneId + +### Returns + +- airConditioningError +- zones + +### Example Request + +```json +{ + "id": 1, + "method": "AirConditioning.GetZones", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AirConditioning.RemoveZone + +Remove a zone. + +### Parameters + +- zoneId + +### Returns + +- airConditioningError + +### Example Request + +```json +{ + "id": 1, + "method": "AirConditioning.RemoveZone", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AirConditioning.SetZoneName + +Set zone name. + +### Parameters + +- name +- zoneId + +### Returns + +- airConditioningError + +### Example Request + +```json +{ + "id": 1, + "method": "AirConditioning.SetZoneName", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AirConditioning.SetZoneSetpointOverride + +Set zone setpoint override temperature. Parameter minutes gives the minutes until the setpoint should return to the standby/schedule. + +### Parameters + +- mode +- o:minutes +- setpointOverride +- zoneId + +### Returns + +- airConditioningError + +### Example Request + +```json +{ + "id": 1, + "method": "AirConditioning.SetZoneSetpointOverride", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AirConditioning.SetZoneStandbySetpoint + +Set zone standby setpoint temperature. + +### Parameters + +- standbySetpoint +- zoneId + +### Returns + +- airConditioningError + +### Example Request + +```json +{ + "id": 1, + "method": "AirConditioning.SetZoneStandbySetpoint", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AirConditioning.SetZoneThings + +Set Zone things + +### Parameters + +- o:indoorSensors +- o:notifications +- o:outdoorSensors +- o:thermostats +- o:windowSensors +- zoneId + +### Returns + +- airConditioningError + +### Example Request + +```json +{ + "id": 1, + "method": "AirConditioning.SetZoneThings", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AirConditioning.SetZoneWeekSchedule + +Set the time schedule for a zone. + +### Parameters + +- weekSchedule +- zoneId + +### Returns + +- airConditioningError + +### Example Request + +```json +{ + "id": 1, + "method": "AirConditioning.SetZoneWeekSchedule", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AppData.Load + +Retrieve an app data storage value that has previously been set with Store(). If no value had been set for this appId/key combination before, an empty value will be returned. + +### Parameters + +- appId +- key +- o:group + +### Returns + +- value + +### Example Request + +```json +{ + "id": 1, + "method": "AppData.Load", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## AppData.Store + +Store an app data entry to the server. App data can be used by the client application to store configuration values. The app data storage is a key-value pair storage. Each entry value is identified by an appId, a key and optionally a group. The value data is a bytearray and can contain arbitrary data, such as a JSON map or image data, however, be aware of the maximum packet size for the used transport. +This might be useful to a client application to sync settings across multiple instances of the same application. +The group parameter might be used to create groups for this application. +IMPORTANT: Currently no verification of the appId is done. The appid is merely a mechanism to prevent different different client apps from colliding by using the same key for data entries. This implies that the app data storage may not be suited for sensitive data given that anyone with a valid server token can read it. + + +### Parameters + +- appId +- key +- o:group +- value + +### Example Request + +```json +{ + "id": 1, + "method": "AppData.Store", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.DeleteMqttPolicy + +Delete a MQTT policy from the broker. + +### Parameters + +- clientId + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.DeleteMqttPolicy", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.DeleteMqttServerConfiguration + +Delete a MQTT Server interface of the server. + +### Parameters + +- id + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.DeleteMqttServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.DeleteTcpServerConfiguration + +Delete a TCP interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped. + +### Parameters + +- id + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.DeleteTcpServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.DeleteTunnelProxyServerConfiguration + +Delete a Tunnel Proxy Server interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped. + +### Parameters + +- id + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.DeleteTunnelProxyServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.DeleteWebServerConfiguration + +Delete a WebServer interface of the server. + +### Parameters + +- id + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.DeleteWebServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.DeleteWebSocketServerConfiguration + +Delete a WebSocket Server interface of the server. Note: if you are deleting the configuration for the interface you are currently connected to, the connection will be dropped. + +### Parameters + +- id + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.DeleteWebSocketServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.GetAvailableLanguages + +Returns a list of locale codes available for the server. i.e. en_US, de_AT + +### Returns + +- languages + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.GetAvailableLanguages", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.GetConfigurations + +Get all configuration parameters of the server. + +### Returns + +- basicConfiguration +- tcpServerConfigurations +- tunnelProxyServerConfigurations +- webServerConfigurations +- webSocketServerConfigurations + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.GetConfigurations", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.GetMqttPolicies + +Get all MQTT broker policies. + +### Returns + +- mqttPolicies + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.GetMqttPolicies", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.GetMqttServerConfigurations + +Get all MQTT Server configurations. + +### Returns + +- mqttServerConfigurations + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.GetMqttServerConfigurations", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.GetTimeZones + +Get the list of available timezones. + +### Returns + +- timeZones + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.GetTimeZones", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetDebugServerEnabled + +Enable or disable the debug server. + +### Parameters + +- enabled + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetDebugServerEnabled", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetLanguage + +Sets the server language to the given language. See also: "GetAvailableLanguages" + +### Parameters + +- language + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetLanguage", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetLocation + +Sets the server location. + +### Parameters + +- location + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetLocation", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetMqttPolicy + +Configure a MQTT broker policy. If the ID is an existing one, the existing policy will be modified, otherwise a new one will be added. + +### Parameters + +- policy + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetMqttPolicy", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetMqttServerConfiguration + +Configure a MQTT Server interface on the MQTT broker. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Setting authenticationEnabled to true will require MQTT clients to use credentials set in the MQTT broker policies. + +### Parameters + +- configuration + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetMqttServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetServerName + +Set the name of the server. Default is nymea. + +### Parameters + +- serverName + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetServerName", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetTcpServerConfiguration + +Configure a TCP interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped. + +### Parameters + +- configuration + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetTcpServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetTimeZone + +Set the time zone of the server. See also: "GetTimeZones" + +### Parameters + +- timeZone + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetTimeZone", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetTunnelProxyServerConfiguration + +Configure a Tunnel Proxy Server interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped. + +### Parameters + +- configuration + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetTunnelProxyServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetWebServerConfiguration + +Configure a WebServer interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. + +### Parameters + +- configuration + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetWebServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Configuration.SetWebSocketServerConfiguration + +Configure a WebSocket Server interface of the server. If the ID is an existing one, the existing config will be modified, otherwise a new one will be added. Note: if you are changing the configuration for the interface you are currently connected to, the connection will be dropped. + +### Parameters + +- configuration + +### Returns + +- configurationError + +### Example Request + +```json +{ + "id": 1, + "method": "Configuration.SetWebSocketServerConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Debug.GetLoggingCategories + +Get all available logging categories. + +### Returns + +- loggingCategories + +### Example Request + +```json +{ + "id": 1, + "method": "Debug.GetLoggingCategories", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Debug.SetLoggingCategoryLevel + +Set the logging category with the given name to the given logging level. + +### Parameters + +- level +- name + +### Returns + +- debugError + +### Example Request + +```json +{ + "id": 1, + "method": "Debug.SetLoggingCategoryLevel", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Energy.GetPowerBalance + +Get the current power balance. That is, production, consumption and acquisition. + +### Returns + +- currentPowerAcquisition +- currentPowerConsumption +- currentPowerProduction +- currentPowerStorage +- totalAcquisition +- totalConsumption +- totalProduction +- totalReturn + +### Example Request + +```json +{ + "id": 1, + "method": "Energy.GetPowerBalance", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Energy.GetPowerBalanceLogs + +Get logs for the power balance. If from is not give, the log will start at the beginning of recording. If to is not given, the logs will and at the last sample for this sample rate before now. + +### Parameters + +- o:from +- o:to +- sampleRate + +### Returns + +- powerBalanceLogEntries + +### Example Request + +```json +{ + "id": 1, + "method": "Energy.GetPowerBalanceLogs", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Energy.GetRootMeter + +Get the root meter ID. If there is no root meter set, the params will be empty. + +### Returns + +- o:rootMeterThingId + +### Example Request + +```json +{ + "id": 1, + "method": "Energy.GetRootMeter", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Energy.GetThingPowerLogs + +Get logs for one or more things power values. If thingIds is not given, logs for all energy related things will be returned. If from is not given, the log will start at the beginning of recording. If to is not given, the logs will and at the last sample for this sample rate before now. If the parameter "includeCurrent" is set to true, the result will contain the newest log entries available, regardless of the sample rate (that is, 1 minute). This may be useful to calculate the difference to the newest entry of the fetched sample rate and the current values to display the live value until the current sample is completed. + +### Parameters + +- o:from +- o:includeCurrent +- o:thingIds +- o:to +- sampleRate + +### Returns + +- o:currentEntries +- thingPowerLogEntries + +### Example Request + +```json +{ + "id": 1, + "method": "Energy.GetThingPowerLogs", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Energy.SetRootMeter + +Set the root meter. + +### Parameters + +- rootMeterThingId + +### Returns + +- energyError + +### Example Request + +```json +{ + "id": 1, + "method": "Energy.SetRootMeter", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## EvDash.AddUser + +Add a new user with the given username and password. + +### Parameters + +- password +- username + +### Returns + +- evDashError + +### Example Request + +```json +{ + "id": 1, + "method": "EvDash.AddUser", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## EvDash.GetEnabled + +Get the enabled status of EV Dash service. + +### Returns + +- enabled + +### Example Request + +```json +{ + "id": 1, + "method": "EvDash.GetEnabled", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## EvDash.GetUsers + +Get the list of available users names. + +### Returns + +- usernames + +### Example Request + +```json +{ + "id": 1, + "method": "EvDash.GetUsers", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## EvDash.RemoveUser + +Remove the user with the given username. + +### Parameters + +- username + +### Returns + +- evDashError + +### Example Request + +```json +{ + "id": 1, + "method": "EvDash.RemoveUser", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## EvDash.SetEnabled + +Enable/Disable the EV Dash service. + +### Parameters + +- enabled + +### Returns + +- evDashError + +### Example Request + +```json +{ + "id": 1, + "method": "EvDash.SetEnabled", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.AddThing + +Add a new thing to the system. Only things with a setupMethod of SetupMethodJustAdd can be added this way. For things with a setupMethod different than SetupMethodJustAdd, use PairThing. Things with CreateMethodJustAdd require all parameters to be supplied here. Things with CreateMethodDiscovery require the use of a thingDescriptorId. For discovered things, params are not required and will be taken from the ThingDescriptor, however, they may be overridden by supplying thingParams. + +### Parameters + +- name +- o:thingClassId +- o:thingDescriptorId +- o:thingParams + +### Returns + +- o:displayMessage +- o:thingId +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.AddThing", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.BrowseThing + +Browse a thing. If a ThingClass indicates a thing is browsable, this method will return the BrowserItems. If no parameter besides the thingId is used, the root node of this thingwill be returned. Any returned item which is browsable can be passed as node. Results will be children of the given node. +In case of an error during browsing, the error will be indicated and the displayMessage may contain additional information for the user. The displayMessage will be translated. A client UI showing this message to the user should be prepared for empty, but also longer strings. + +### Parameters + +- o:itemId +- thingId + +### Returns + +- o:displayMessage +- o:items +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.BrowseThing", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.ConfirmPairing + +Confirm an ongoing pairing. For SetupMethodUserAndPassword, provide the username in the "username" field and the password in the "secret" field. For SetupMethodEnterPin and provide the PIN in the "secret" field. In case of SetupMethodOAuth, the previously opened web view will eventually be redirected to http://128.0.0.1:8888 and the OAuth code as query parameters to this url. Provide the entire unmodified URL in the secret field. + +### Parameters + +- o:secret +- o:username +- pairingTransactionId + +### Returns + +- o:displayMessage +- o:thingId +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.ConfirmPairing", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.ConnectIO + +Connect two generic IO states. Input and output need to be compatible, that is, either a digital input and a digital output, or an analog input and an analog output. If successful, the connectionId will be returned. + +### Parameters + +- inputStateTypeId +- inputThingId +- o:inverted +- outputStateTypeId +- outputThingId + +### Returns + +- o:ioConnectionId +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.ConnectIO", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.DisconnectIO + +Disconnect an existing IO connection. + +### Parameters + +- ioConnectionId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.DisconnectIO", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.DiscoverThings + +Performs a thing discovery for things of the given thingClassId and returns the results. This function may take a while to return. Note that this method will include all the found things, that is, including things that may already have been added. Those things will have thingId set to the id of the already added thing. Such results may be used to reconfigure existing things and might be filtered in cases where only unknown things are of interest. + +### Parameters + +- o:discoveryParams +- thingClassId + +### Returns + +- o:displayMessage +- o:thingDescriptors +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.DiscoverThings", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.EditThing + +Edit the name of a thing. + +### Parameters + +- name +- thingId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.EditThing", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.ExecuteAction + +Execute a single action. + +### Parameters + +- actionTypeId +- o:params +- thingId + +### Returns + +- o:displayMessage +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.ExecuteAction", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.ExecuteBrowserItem + +Execute the item identified by itemId on the given thing. +In case of an error during execution, the error will be indicated and the displayMessage may contain additional information for the user. The displayMessage will be translated. A client UI showing this message to the user should be prepared for empty, but also longer strings. + +### Parameters + +- itemId +- thingId + +### Returns + +- o:displayMessage +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.ExecuteBrowserItem", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.ExecuteBrowserItemAction + +Execute the action for the browser item identified by actionTypeId and the itemId on the given thing. +In case of an error during execution, the error will be indicated and the displayMessage may contain additional information for the user. The displayMessage will be translated. A client UI showing this message to the user should be prepared for empty, but also longer strings. + +### Parameters + +- actionTypeId +- itemId +- o:params +- thingId + +### Returns + +- o:displayMessage +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.ExecuteBrowserItemAction", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetActionTypes + +Get action types for a specified thingClassId. + +### Parameters + +- thingClassId + +### Returns + +- actionTypes + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetActionTypes", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetBrowserItem + +Get a single item from the browser. This won't give any more info on an item than a regular BrowseThing call, but it allows to fetch details of an item if only the ID is known. +In case of an error during browsing, the error will be indicated and the displayMessage may contain additional information for the user. The displayMessage will be translated. A client UI showing this message to the user should be prepared for empty, but also longer strings. + +### Parameters + +- o:itemId +- thingId + +### Returns + +- o:displayMessage +- o:item +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetBrowserItem", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetEventTypes + +Get event types for a specified thingClassId. + +### Parameters + +- thingClassId + +### Returns + +- eventTypes + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetEventTypes", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetIOConnections + +Fetch IO connections. Optionally filtered by thingId and stateTypeId. + +### Parameters + +- o:thingId + +### Returns + +- o:ioConnections +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetIOConnections", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetPluginConfiguration + +Get a plugin's params. + +### Parameters + +- pluginId + +### Returns + +- o:configuration +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetPluginConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetPlugins + +Returns a list of loaded plugins. + +### Returns + +- plugins + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetPlugins", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetStateTypes + +Get state types for a specified thingClassId. + +### Parameters + +- thingClassId + +### Returns + +- stateTypes + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetStateTypes", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetStateValue + +Get the value of the given thing and the given stateType + +### Parameters + +- stateTypeId +- thingId + +### Returns + +- o:value +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetStateValue", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetStateValues + +Get all the state values of the given thing. + +### Parameters + +- thingId + +### Returns + +- o:values +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetStateValues", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetThingClasses + +Returns a list of supported thing classes, optionally filtered by vendorId or by a list of thing class ids. + +### Parameters + +- o:thingClassIds +- o:vendorId + +### Returns + +- o:thingClasses +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetThingClasses", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetThings + +Returns a list of configured things, optionally filtered by thingId. + +### Parameters + +- o:thingId + +### Returns + +- o:things +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetThings", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.GetVendors + +Returns a list of supported Vendors. + +### Returns + +- vendors + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.GetVendors", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.PairThing + +Pair a new thing. Use this to set up or reconfigure things for ThingClasses with a setupMethod different than SetupMethodJustAdd. Depending on the CreateMethod and whether a new thing is set up or an existing one is reconfigured, different parameters are required: +CreateMethodJustAdd takes the thingClassId and the parameters you want to have with that thing. If an existing thing should be reconfigured, the thingId of said thing should be given additionally. +CreateMethodDiscovery requires the use of a thingDescriptorId, previously obtained with DiscoverThings. Optionally, parameters can be overridden with the give thingParams. ThingDescriptors containing a thingId will reconfigure an existing thing, descriptors without a thingId will add a new thing to the system. +If success is true, the return values will contain a pairingTransactionId, a displayMessage and the setupMethod. Depending on the setupMethod, the application should present the use an appropriate login mask, that is, For SetupMethodDisplayPin the user should enter a pin that is displayed on the device or online service, for SetupMethodEnterPin the application should present the given PIN so the user can enter it on the device or online service. For SetupMethodPushButton, the displayMessage shall be presented to the user as informational hints to press a button on the device. For SetupMethodUserAndPassword a login mask for a user and password login should be presented to the user. In case of SetupMethodOAuth, an OAuth URL will be returned which shall be opened in a web view to allow the user logging in. +Once the login procedure has completed, the application shall proceed with ConfirmPairing, providing the results of the pairing procedure. + +### Parameters + +- o:name +- o:thingClassId +- o:thingDescriptorId +- o:thingId +- o:thingParams + +### Returns + +- o:displayMessage +- o:oAuthUrl +- o:pairingTransactionId +- o:pin +- o:setupMethod +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.PairThing", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.ReconfigureThing + +Reconfigure a thing. This comes down to removing and recreating a thing with new parameters but keeping its thing id the same (and with that keeping rules, tags etc). For things with create method CreateMethodDiscovery, a discovery (DiscoverThings) shall be performed first and this method is to be called with a thingDescriptorId of the re-discovered thing instead of the thingId directly. Thing parameters will be taken from the discovery, but can be overridden individually here by providing them in the thingParams parameter. Only writable parameters can be changed. + +### Parameters + +- o:thingDescriptorId +- o:thingId +- o:thingParams + +### Returns + +- o:displayMessage +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.ReconfigureThing", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.RemoveThing + +Remove a thing and all its childs from the system. RemovePolicy is deprecated and has no effect any more. + +### Parameters + +- d:o:removePolicy +- thingId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.RemoveThing", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.SetActionLogging + +Enable/disable logging for the given action type on the given thing. + +### Parameters + +- actionTypeId +- enabled +- thingId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.SetActionLogging", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.SetEventLogging + +Enable/disable logging for the given event type on the given thing. + +### Parameters + +- enabled +- eventTypeId +- thingId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.SetEventLogging", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.SetPluginConfiguration + +Set a plugin's params. + +### Parameters + +- configuration +- pluginId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.SetPluginConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.SetStateFilter + +Set the filter for the given state on the given thing. + +### Parameters + +- filter +- stateTypeId +- thingId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.SetStateFilter", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.SetStateLogging + +Enable/disable logging for the given state type on the given thing. + +### Parameters + +- enabled +- stateTypeId +- thingId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.SetStateLogging", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Integrations.SetThingSettings + +Change the settings of a thing. + +### Parameters + +- settings +- thingId + +### Returns + +- thingError + +### Example Request + +```json +{ + "id": 1, + "method": "Integrations.SetThingSettings", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## JSONRPC.Authenticate + +Authenticate a client to the api via user & password challenge. Provide a device name which allows the user to identify the client and revoke the token in case the device is lost or stolen. This will return a new token to be used to authorize a client at the API. + +### Parameters + +- deviceName +- password +- username + +### Returns + +- o:scopes +- o:token +- o:username +- success + +### Example Request + +```json +{ + "id": 1, + "method": "JSONRPC.Authenticate", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## JSONRPC.CreateUser + +Create a new user in the API. This is only allowed to be called when the initial setup is required. To create additional users, use Users.CreateUser instead. Call Authenticate after this to obtain a device token for the newly created user. + +### Parameters + +- o:displayName +- o:email +- password +- username + +### Returns + +- error + +### Example Request + +```json +{ + "id": 1, + "method": "JSONRPC.CreateUser", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## JSONRPC.Hello + +Initiates a connection. Use this method to perform an initial handshake of the connection. Optionally, a parameter "locale" is can be passed to set up the used locale for this connection. Strings such as ThingClass displayNames etc will be localized to this locale. If this parameter is omitted, the default system locale (depending on the configuration) is used. The reply of this method contains information about this core instance such as version information, uuid and its name. The locale valueindicates the locale used for this connection. Note: This method can be called multiple times. The locale used in the last call for this connection will be used. Other values, like initialSetupRequired might change if the setup has been performed in the meantime. + The field cacheHashes may contain a map of methods and MD5 hashes. As long as the hash for a method does not change, a client may use a previously cached copy of the call instead of fetching the content again. While the Hello call doesn't necessarily require a token, this can be called with a token. If a token is provided, it will be verified and the reply contains information about the tokens validity and the user and permissions for the given token. + +### Parameters + +- o:locale + +### Returns + +- authenticationRequired +- initialSetupRequired +- language +- locale +- name +- o:authenticated +- o:cacheHashes +- o:experiences +- o:permissionScopes +- o:username +- protocol version +- pushButtonAuthAvailable +- server +- uuid +- version + +### Example Request + +```json +{ + "id": 1, + "method": "JSONRPC.Hello", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## JSONRPC.Introspect + +Introspect this API. + +### Returns + +- methods +- notifications +- types + +### Example Request + +```json +{ + "id": 1, + "method": "JSONRPC.Introspect", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## JSONRPC.KeepAlive + +This is basically a Ping/Pong mechanism a client app may use to check server connectivity. Currently, the server does not actually do anything with this information and will return the call providing the given sessionId back to the caller. It is up to the client whether to use this or not and not required by the server to keep the connection alive. + +### Parameters + +- sessionId + +### Returns + +- sessionId +- success + +### Example Request + +```json +{ + "id": 1, + "method": "JSONRPC.KeepAlive", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## JSONRPC.RequestPushButtonAuth + +Authenticate a client to the api via Push Button method. Provide a device name which allows the user to identify the client and revoke the token in case the device is lost or stolen. If push button hardware is available, this will return with success and start listening for push button presses. When the push button is pressed, the PushButtonAuthFinished notification will be sent to the requesting client. The procedure will be cancelled when the connection is interrupted. If another client requests push button authentication while a procedure is still going on, the second call will take over and the first one will be notified by the PushButtonAuthFinished signal about the error. The application should make it clear to the user to not press the button when the procedure fails as this can happen for 2 reasons: a) a second user is trying to auth at the same time and only the currently active user should press the button or b) it might indicate an attacker trying to take over and snooping in for tokens. + +### Parameters + +- deviceName + +### Returns + +- success +- transactionId + +### Example Request + +```json +{ + "id": 1, + "method": "JSONRPC.RequestPushButtonAuth", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## JSONRPC.SetNotificationStatus + +Enable/Disable notifications for this connections. Either "enabled" or "namespaces" needs to be given but not both of them. The boolean based "enabled" parameter will enable/disable all notifications at once. If instead the list-based "namespaces" parameter is provided, all given namespaceswill be enabled, the others will be disabled. The return value of "success" will indicate success of the operation. The "enabled" property in the return value is deprecated and used for legacy compatibilty only. It will be set to true if at least one namespace has been enabled. + +### Parameters + +- d:o:enabled +- o:namespaces + +### Returns + +- d:enabled +- namespaces + +### Example Request + +```json +{ + "id": 1, + "method": "JSONRPC.SetNotificationStatus", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## JSONRPC.Version + +Version of this nymea/JSONRPC interface. + +### Returns + +- protocol version +- qtBuildVersion +- qtVersion +- version + +### Example Request + +```json +{ + "id": 1, + "method": "JSONRPC.Version", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Logging.GetLogEntries + +Get the LogEntries matching the given filter. +"sources": Builtin sources are: "core", "rules", "scripts", "integrations". May be extended by experience plugins. +"columns": Columns to be returned. +"filter": A map of column:value entries. Only = is supported currently. +"startTime": The datetime of the oldest entry, in ms. +"endTime": The datetime of the newest entry, in ms. +"sampleRate": If given, returns a sampled series of the values, filling in gaps with the previous value. +"sortOrder": Sort order of results. Note that this impacts the filling of gaps when resampling. +"limit": Maximum amount of entries to be returned. +"offset": Offset to be skipped before returning entries. + +### Parameters + +- o:columns +- o:endTime +- o:filter +- o:limit +- o:offset +- o:sampleRate +- o:sortOrder +- o:startTime +- sources + +### Returns + +- count +- o:logEntries +- offset + +### Example Request + +```json +{ + "id": 1, + "method": "Logging.GetLogEntries", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ModbusRtu.AddModbusRtuMaster + +Add a new modbus RTU master with the given configuration. The timeout value is in milli seconds and the minimum value is 10 ms. + +### Parameters + +- baudrate +- dataBits +- numberOfRetries +- parity +- serialPort +- stopBits +- timeout + +### Returns + +- modbusError +- o:modbusUuid + +### Example Request + +```json +{ + "id": 1, + "method": "ModbusRtu.AddModbusRtuMaster", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ModbusRtu.GetModbusRtuMasters + +Get the list of configured modbus RTU masters. + +### Returns + +- modbusError +- o:modbusRtuMasters + +### Example Request + +```json +{ + "id": 1, + "method": "ModbusRtu.GetModbusRtuMasters", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ModbusRtu.GetSerialPorts + +Get the list of available serial ports from the host system. + +### Returns + +- serialPorts + +### Example Request + +```json +{ + "id": 1, + "method": "ModbusRtu.GetSerialPorts", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ModbusRtu.ReconfigureModbusRtuMaster + +Reconfigure the modbus RTU master with the given UUID and configuration. + +### Parameters + +- baudrate +- dataBits +- modbusUuid +- numberOfRetries +- parity +- serialPort +- stopBits +- timeout + +### Returns + +- modbusError + +### Example Request + +```json +{ + "id": 1, + "method": "ModbusRtu.ReconfigureModbusRtuMaster", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ModbusRtu.RemoveModbusRtuMaster + +Remove the modbus RTU master with the given modbus UUID. + +### Parameters + +- modbusUuid + +### Returns + +- modbusError + +### Example Request + +```json +{ + "id": 1, + "method": "ModbusRtu.RemoveModbusRtuMaster", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.ConnectWifiNetwork + +Connect to the wifi network with the given ssid and password. + +### Parameters + +- interface +- o:password +- ssid + +### Returns + +- networkManagerError + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.ConnectWifiNetwork", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.CreateWiredConnection + +Create a wired connection. + +### Parameters + +- interface +- o:dns +- o:gateway +- o:ip +- o:prefix +- type + +### Returns + +- networkManagerError + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.CreateWiredConnection", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.DisconnectInterface + +Disconnect the given network interface. The interface will remain disconnected until the user connect it again. + +### Parameters + +- interface + +### Returns + +- networkManagerError + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.DisconnectInterface", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.EnableNetworking + +Enable or disable networking in the NetworkManager. + +### Parameters + +- enable + +### Returns + +- networkManagerError + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.EnableNetworking", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.EnableWirelessNetworking + +Enable or disable wireless networking in the NetworkManager. + +### Parameters + +- enable + +### Returns + +- networkManagerError + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.EnableWirelessNetworking", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.GetNetworkDevices + +Get the list of current network devices. + +### Returns + +- networkManagerError +- o:wiredNetworkDevices +- o:wirelessNetworkDevices + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.GetNetworkDevices", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.GetNetworkStatus + +Get the current network manager status. + +### Returns + +- networkManagerError +- o:status + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.GetNetworkStatus", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.GetWirelessAccessPoints + +Get the current list of wireless network access points for the given interface. The interface has to be a WirelessNetworkDevice. + +### Parameters + +- interface + +### Returns + +- networkManagerError +- o:wirelessAccessPoints + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.GetWirelessAccessPoints", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.ScanWifiNetworks + +Start a wifi scan for searching new networks. + +### Parameters + +- interface + +### Returns + +- networkManagerError + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.ScanWifiNetworks", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NetworkManager.StartAccessPoint + +Start a WiFi Access point on the given interface with the given SSID and password. Use DisconnectInterface to stop it again. + +### Parameters + +- interface +- password +- ssid + +### Returns + +- networkManagerError + +### Example Request + +```json +{ + "id": 1, + "method": "NetworkManager.StartAccessPoint", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetAcquisitionTolerance + +Get the acquisition tolerance. This value will control how much solar surplus is required to start the charging. + +### Returns + +- acquisitionTolerance + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetAcquisitionTolerance", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetAvailableSpotMarketProviders + +Get the list of available spot market data providers. + +### Returns + +- providers + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetAvailableSpotMarketProviders", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetBatteryLevelConsideration + +Get the battery level consideration. This value will control how much the energy storage is taking in account + +### Returns + +- batteryLevelConsideration + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetBatteryLevelConsideration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetChargingInfos + +Get the charging info for all or a single EV charger + +### Parameters + +- o:evChargerId + +### Returns + +- chargingInfos + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetChargingInfos", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetChargingSchedules + +Get the planed charging schedules. + +### Returns + +- chargingSchedules + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetChargingSchedules", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetLockOnUnplug + +Get the lock on unplug setting. + +### Returns + +- lockOnUnplug + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetLockOnUnplug", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetPhasePowerLimit + +Get the phase power consumption limit. 0 if unset. This needs to be set in order for the smart charging to do anything. + +### Returns + +- phasePowerLimit + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetPhasePowerLimit", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetSpotMarketConfiguration + +Get the current spotmarket configuration. + +### Returns + +- available +- enabled +- o:providerId + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetSpotMarketConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.GetSpotMarketScoreEntries + +Get the current score entries from the current spot market. If spot market is not enabled or not available, the list will be empty. The weighting of the available score entries goes from 0 (worst) to 1.0 (best). + +### Returns + +- spotMarketScoreEntries + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.GetSpotMarketScoreEntries", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.SetAcquisitionTolerance + +Set the acquisition tolerance for the charging. + +### Parameters + +- acquisitionTolerance + +### Returns + +- energyError + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.SetAcquisitionTolerance", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.SetBatteryLevelConsideration + +Set the battery level consideration for the charging. + +### Parameters + +- batteryLevelConsideration + +### Returns + +- energyError + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.SetBatteryLevelConsideration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.SetChargingInfo + +Set the charging info for an EV charger. Only given properties will be set, others will be untouched. + +### Parameters + +- chargingInfo + +### Returns + +- energyError + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.SetChargingInfo", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.SetLockOnUnplug + +Set the lock on unplug setting. + +### Parameters + +- lockOnUnplug + +### Returns + +- energyError + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.SetLockOnUnplug", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.SetPhasePowerLimit + +Set the phase power consumption limit. This is the maximum allowed Ampere per phase. A value of 0 means unset. All smart charging will be disabled. + +### Parameters + +- phasePowerLimit + +### Returns + +- energyError + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.SetPhasePowerLimit", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## NymeaEnergy.SetSpotMarketConfiguration + +Set the current spotmarket configuration. If enabled, the provideId must be valid. You can get the available providers using GetAvailableSpotMarketProviders. + +### Parameters + +- enabled +- o:providerId + +### Returns + +- energyError + +### Example Request + +```json +{ + "id": 1, + "method": "NymeaEnergy.SetSpotMarketConfiguration", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.AddRule + +Add a rule. You can describe rules by one or many EventDesciptors and a StateEvaluator. Note that only one of either eventDescriptor or eventDescriptorList may be passed at a time. A rule can be created but left disabled, meaning it won't actually be executed until set to enabled. If not given, enabled defaults to true. A rule can have a list of actions and exitActions. It must have at least one Action. For state based rules, actions will be executed when the system enters a state matching the stateDescriptor. The exitActions will be executed when the system leaves the described state again. For event based rules, actions will be executed when a matching event happens and if the stateEvaluator matches the system's state. ExitActions for such rules will be executed when a matching event happens and the stateEvaluator is not matching the system's state. A rule marked as executable can be executed via the API using Rules.ExecuteRule, that means, its actions will be executed regardless of the eventDescriptor and stateEvaluators. + +### Parameters + +- actions +- name +- o:enabled +- o:eventDescriptors +- o:executable +- o:exitActions +- o:stateEvaluator +- o:timeDescriptor + +### Returns + +- o:ruleId +- ruleError + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.AddRule", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.DisableRule + +Disable a rule. The rule won't be triggered by it's events or state changes while it is disabled. If successful, the notification "Rule.RuleConfigurationChanged" will be emitted. + +### Parameters + +- ruleId + +### Returns + +- ruleError + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.DisableRule", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.EditRule + +Edit the parameters of a rule. The configuration of the rule with the given ruleId will be replaced with the new given configuration. In ordert to enable or disable a Rule, please use the methods "Rules.EnableRule" and "Rules.DisableRule". If successful, the notification "Rule.RuleConfigurationChanged" will be emitted. + +### Parameters + +- actions +- name +- o:enabled +- o:eventDescriptors +- o:executable +- o:exitActions +- o:stateEvaluator +- o:timeDescriptor +- ruleId + +### Returns + +- o:rule +- ruleError + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.EditRule", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.EnableRule + +Enabled a rule that has previously been disabled.If successful, the notification "Rule.RuleConfigurationChanged" will be emitted. + +### Parameters + +- ruleId + +### Returns + +- ruleError + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.EnableRule", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.ExecuteActions + +Execute the action list of the rule with the given ruleId. + +### Parameters + +- ruleId + +### Returns + +- ruleError + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.ExecuteActions", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.ExecuteExitActions + +Execute the exit action list of the rule with the given ruleId. + +### Parameters + +- ruleId + +### Returns + +- ruleError + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.ExecuteExitActions", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.FindRules + +Find a list of rules containing any of the given parameters. + +### Parameters + +- thingId + +### Returns + +- ruleIds + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.FindRules", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.GetRuleDetails + +Get details for the rule identified by ruleId + +### Parameters + +- ruleId + +### Returns + +- o:rule +- ruleError + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.GetRuleDetails", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.GetRules + +Get the descriptions of all configured rules. If you need more information about a specific rule use the method Rules.GetRuleDetails. + +### Returns + +- ruleDescriptions + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.GetRules", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Rules.RemoveRule + +Remove a rule + +### Parameters + +- ruleId + +### Returns + +- ruleError + +### Example Request + +```json +{ + "id": 1, + "method": "Rules.RemoveRule", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Scripts.AddScript + +Add a script + +### Parameters + +- content +- name + +### Returns + +- o:errors +- o:script +- scriptError + +### Example Request + +```json +{ + "id": 1, + "method": "Scripts.AddScript", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Scripts.EditScript + +Edit a script + +### Parameters + +- id +- o:content +- o:name + +### Returns + +- o:errors +- scriptError + +### Example Request + +```json +{ + "id": 1, + "method": "Scripts.EditScript", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Scripts.GetScriptContent + +Get a scripts content. + +### Parameters + +- id + +### Returns + +- o:content +- scriptError + +### Example Request + +```json +{ + "id": 1, + "method": "Scripts.GetScriptContent", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Scripts.GetScripts + +Get all script, that is, their names and properties, but no content. + +### Returns + +- scripts + +### Example Request + +```json +{ + "id": 1, + "method": "Scripts.GetScripts", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Scripts.RemoveScript + +remove a script + +### Parameters + +- id + +### Returns + +- scriptError + +### Example Request + +```json +{ + "id": 1, + "method": "Scripts.RemoveScript", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.CheckForUpdates + +Instruct the system to poll the server for updates. Normally the system should automatically do this in regular intervals, however, if the client wants to allow the user to manually check for new updates now, this can be called. Returns true if the operation has been started successfully and the update manager will become busy. In order to know whether there are updates available, clients should walk through the list of packages retrieved from GetPackages and check whether there are packages with the updateAvailable flag set to true. + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.CheckForUpdates", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.EnableRepository + +Enable or disable a repository. + +### Parameters + +- enabled +- repositoryId + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.EnableRepository", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.GetCapabilities + +Get the list of capabilites on this system. The property "powerManagement" indicates whether restarting nymea and rebooting or shutting down is supported on this system. The property "updateManagement indicates whether system update features are available in this system. The property "timeManagement" indicates whether the system time can be configured on this system. Note that GetTime will be available in any case. + +### Returns + +- powerManagement +- timeManagement +- updateManagement + +### Example Request + +```json +{ + "id": 1, + "method": "System.GetCapabilities", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.GetPackages + +Get the list of packages currently available to the system. This might include installed available but not installed packages. Installed packages will have the installedVersion set to a non-empty value. + +### Returns + +- packages + +### Example Request + +```json +{ + "id": 1, + "method": "System.GetPackages", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.GetRepositories + +Get the list of repositories currently available to the system. + +### Returns + +- repositories + +### Example Request + +```json +{ + "id": 1, + "method": "System.GetRepositories", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.GetSystemInfo + +Returns information about the system nymea is running on. + +### Returns + +- deviceSerialNumber + +### Example Request + +```json +{ + "id": 1, + "method": "System.GetSystemInfo", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.GetTime + +Get the system time and configuraton. The "time" and "timeZone" properties give the current server time and time zone. "automaticTimeAvailable" indicates whether this system supports automatically setting the clock (e.g. using NTP). "automaticTime" will be true if the system is configured to automatically update the clock. + +### Returns + +- automaticTime +- automaticTimeAvailable +- time +- timeZone + +### Example Request + +```json +{ + "id": 1, + "method": "System.GetTime", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.GetTimeZones + +Returns the list of IANA specified time zone IDs which can be used to select a time zone. It is not required to use this method if the client toolkit already provides means to obtain a list of IANA time zone ids. + +### Returns + +- timeZones + +### Example Request + +```json +{ + "id": 1, + "method": "System.GetTimeZones", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.GetUpdateStatus + +Get the current status of the update system. "busy" indicates that the system is current busy with an operation regarding updates. This does not necessarily mean an actual update is running. When this is true, update related functions on the client should be marked as busy and no interaction with update components shall be allowed. An example for such a state is when the system queries the server if there are updates available, typically after a call to CheckForUpdates. "updateRunning" on the other hand indicates an actual update process is ongoing. The user should be informed about it, the system also might restart at any point while an update is running. + +### Returns + +- busy +- updateRunning + +### Example Request + +```json +{ + "id": 1, + "method": "System.GetUpdateStatus", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.Reboot + +Initiate a reboot of the system. The return value will indicate whether the procedure has been initiated successfully. + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.Reboot", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.RemovePackages + +Starts removing a package. Returns true if the removal has been started successfully. Before calling this method, clients should check whether the package can be removed (canRemove set to true). + +### Parameters + +- packageIds + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.RemovePackages", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.Restart + +Initiate a restart of the nymea service. The return value will indicate whether the procedure has been initiated successfully. + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.Restart", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.RollbackPackages + +Starts a rollback. Returns true if the rollback has been started successfully. Before calling this method, clients should check whether the package can be rolled back (canRollback set to true). + +### Parameters + +- packageIds + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.RollbackPackages", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.SetTime + +Set the system time configuraton. The system can be configured to update the time automatically by setting "automaticTime" to true. This will only work if the "timeManagement" capability is available on this system and "GetTime" indicates the availability of automatic time settings. If any of those requirements are not met, this method will return "false" in the "success" property. In order to manually configure the time, "automaticTime" should be set to false and "time" should be set. Note that if "automaticTime" is set to true and a manual "time" is still passed, the system will attempt to configure automatic time updates and only set the manual time if automatic mode fails. A time zone can always be passed optionally to change the system time zone and should be a IANA time zone id. + +### Parameters + +- o:automaticTime +- o:time +- o:timeZone + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.SetTime", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.Shutdown + +Initiate a shutdown of the system. The return value will indicate whether the procedure has been initiated successfully. + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.Shutdown", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## System.UpdatePackages + +Starts updating/installing packages with the given ids. Returns true if the upgrade has been started successfully. Note that it might still fail later. Before calling this method, clients should check the packages whether they are in a state where they can either be installed (no installedVersion set) or upgraded (updateAvailable set to true). + +### Parameters + +- o:packageIds + +### Returns + +- success + +### Example Request + +```json +{ + "id": 1, + "method": "System.UpdatePackages", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Tags.AddTag + +Add a Tag. A Tag must have a thingId OR a ruleId (call this method twice if you want to attach the same tag to a thing and a rule), an appId (Use the appId of your app), a tagId (e.g. "favorites") and a value. Upon success, a TagAdded notification will be emitted. Calling this method twice for the same ids (thing/rule, appId and tagId) but with a different value will update the tag's value and the TagValueChanged notification will be emitted. + +### Parameters + +- tag + +### Returns + +- tagError + +### Example Request + +```json +{ + "id": 1, + "method": "Tags.AddTag", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Tags.GetTags + +Get the Tags matching the given filter. Tags can be filtered by a thingID, a ruleId, an appId, a tagId or a combination of any (however, combining thingId and ruleId will return an empty result set). + +### Parameters + +- o:appId +- o:ruleId +- o:tagId +- o:thingId + +### Returns + +- o:tags +- tagError + +### Example Request + +```json +{ + "id": 1, + "method": "Tags.GetTags", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Tags.RemoveTag + +Remove a Tag. Tag value is optional and will be disregarded. If the ids match, the tag will be deleted and a TagRemoved notification will be emitted. + +### Parameters + +- tag + +### Returns + +- tagError + +### Example Request + +```json +{ + "id": 1, + "method": "Tags.RemoveTag", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.ChangePassword + +Change the password for the currently logged in user. + +### Parameters + +- newPassword + +### Returns + +- error + +### Example Request + +```json +{ + "id": 1, + "method": "Users.ChangePassword", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.ChangeUserPassword + +Change the password for the given user. All tokens for this user will be removed in order to force all clients to log in again. + +### Parameters + +- newPassword +- username + +### Returns + +- error + +### Example Request + +```json +{ + "id": 1, + "method": "Users.ChangeUserPassword", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.CreateUser + +Create a new user in the API with the given username and password. Use scopes to define the permissions for the new user. If the user has not the permission "PermissionScopeAccessAllThings", the list of things this user has access to can be defined in the "allowedThingIds" property. If no scopes are given, this user will be an admin user. Call Authenticate after this to obtain a device token for this user. + +### Parameters + +- o:allowedThingIds +- o:displayName +- o:email +- o:scopes +- password +- username + +### Returns + +- error + +### Example Request + +```json +{ + "id": 1, + "method": "Users.CreateUser", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.GetTokens + +Get all the tokens for the current user. + +### Returns + +- error +- o:tokenInfoList + +### Example Request + +```json +{ + "id": 1, + "method": "Users.GetTokens", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.GetUserInfo + +Get info about the current token (the currently logged in user). + +### Returns + +- error +- o:userInfo + +### Example Request + +```json +{ + "id": 1, + "method": "Users.GetUserInfo", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.GetUserTokens + +Get all the tokens for the given username. + +### Parameters + +- username + +### Returns + +- error +- o:tokenInfoList + +### Example Request + +```json +{ + "id": 1, + "method": "Users.GetUserTokens", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.GetUsers + +Return a list of all users in the system. + +### Returns + +- users + +### Example Request + +```json +{ + "id": 1, + "method": "Users.GetUsers", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.RemoveToken + +Revoke access for a given token. Depending on the logged in user only the own tokens can be removed. If you are logged in as admin, any token can be removed. + +### Parameters + +- tokenId + +### Returns + +- error + +### Example Request + +```json +{ + "id": 1, + "method": "Users.RemoveToken", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.RemoveUser + +Remove a user from the system. + +### Parameters + +- username + +### Returns + +- error + +### Example Request + +```json +{ + "id": 1, + "method": "Users.RemoveUser", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.SetUserInfo + +Change user info. If username is given, info for the respective user is changed, otherwise the current user info is edited. Requires admin permissions to edit user info other than the own. + +### Parameters + +- o:displayName +- o:email +- o:username + +### Returns + +- error + +### Example Request + +```json +{ + "id": 1, + "method": "Users.SetUserInfo", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Users.SetUserScopes + +Set the permissions (scopes) for a given user. If the user has not the permission "PermissionScopeAccessAllThings" the list of thing IDs this user has access to can be defined in the "allowedThingIds" property. + +### Parameters + +- o:allowedThingIds +- scopes +- username + +### Returns + +- error + +### Example Request + +```json +{ + "id": 1, + "method": "Users.SetUserScopes", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.AddNetwork + +Add a new Z-Wave network with the given serial port. + +### Parameters + +- serialPort + +### Returns + +- o:networkUuid +- zwaveError + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.AddNetwork", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.AddNode + +Start the node inclusion procedure for the given Z-Wave network. + +### Parameters + +- networkUuid + +### Returns + +- zwaveError + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.AddNode", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.CancelPendingOperation + +Cancel any running node inclusion or removal procedure for the given Z-Wave network. + +### Parameters + +- networkUuid + +### Returns + +- zwaveError + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.CancelPendingOperation", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.FactoryResetNetwork + +Factory reset the controller for the given Z-Wave network. + +### Parameters + +- networkUuid + +### Returns + +- zwaveError + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.FactoryResetNetwork", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.GetNetworks + +Get all the Z-Wave networks in the system. + +### Returns + +- networks + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.GetNetworks", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.GetNodes + +Get the list of nodes in a network + +### Parameters + +- networkUuid + +### Returns + +- o:nodes +- zwaveError + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.GetNodes", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.GetSerialPorts + +Get the list of available serial ports from the host system. + +### Returns + +- serialPorts + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.GetSerialPorts", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.IsZWaveAvailable + +Query if the Z-Wave subsystem is available at all. + +### Returns + +- available + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.IsZWaveAvailable", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.RemoveFailedNode + +Remove the given failed node from the given Z-Wave network. This will not work if node is not marked as failed. + +### Parameters + +- networkUuid +- nodeId + +### Returns + +- zwaveError + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.RemoveFailedNode", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.RemoveNetwork + +Remove the given Z-Wave network from the system. + +### Parameters + +- networkUuid + +### Returns + +- zwaveError + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.RemoveNetwork", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## ZWave.RemoveNode + +Start the node removal procedure for the given Z-Wave network. + +### Parameters + +- networkUuid + +### Returns + +- zwaveError + +### Example Request + +```json +{ + "id": 1, + "method": "ZWave.RemoveNode", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.AddNetwork + +Create a new ZigBee network for the given 'serialPort', 'baudRate' and 'backend'. The serial ports can be fetched from the available adapters. See 'GetAdapters' for more information. The available backends can be fetched using the 'GetAvailableBackends' method. + +### Parameters + +- backend +- baudRate +- o:channelMask +- serialPort + +### Returns + +- o:networkUuid +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.AddNetwork", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.CreateBinding + +Create a binding. Use destinationAddress and destinationEndpointId to create a node to node binding, or use destinationGroupAddress to create a group binding. + +### Parameters + +- clusterId +- networkUuid +- o:destinationAddress +- o:destinationEndpointId +- o:destinationGroupAddress +- sourceAddress +- sourceEndpointId + +### Returns + +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.CreateBinding", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.FactoryResetNetwork + +Factory reset the network with the given 'networkUuid'. The network does not have to be online for this procedure, and all associated nodes and things will be removed permanently. + +### Parameters + +- networkUuid + +### Returns + +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.FactoryResetNetwork", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.GetAdapters + +Get the list of available ZigBee adapters and serial ports in order to set up the ZigBee network on the desired interface. The 'serialPort' property can be used as unique identifier for an adapter. If an adapter hardware has been recognized as a well known ZigBee adapter, the 'hardwareRecognized' property will be true and the 'baudRate' and 'backend' configurations can be used as they where given, otherwise the user might set the backend and baud rate manually. The available backends can be fetched using the GetAvailableBackends method. + +### Returns + +- adapters + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.GetAdapters", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.GetAvailableBackends + +Get the list of available ZigBee backends. + +### Returns + +- backends + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.GetAvailableBackends", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.GetNetworks + +Returns the list of configured ZigBee networks in the system. + +### Returns + +- zigbeeNetworks + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.GetNetworks", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.GetNodes + +Returns the list of ZigBee nodes from the network the given 'networkUuid' in the system. + +### Parameters + +- networkUuid + +### Returns + +- o:zigbeeNodes +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.GetNodes", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.RefreshBindings + +Refresh the binding table for the given node. + +### Parameters + +- ieeeAddress +- networkUuid + +### Returns + +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.RefreshBindings", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.RefreshNeighborTables + +Refresh the neighbor table for all nodes. Note that calling this may cause a lot of traffic in the ZigBee network. + +### Parameters + +- networkUuid + +### Returns + +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.RefreshNeighborTables", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.RemoveBinding + +Remove a binding. + +### Parameters + +- clusterId +- networkUuid +- o:destinationAddress +- o:destinationEndpointId +- o:destinationGroupAddress +- sourceAddress +- sourceEndpointId + +### Returns + +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.RemoveBinding", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.RemoveNetwork + +Remove the ZigBee network with the given network uuid. + +### Parameters + +- networkUuid + +### Returns + +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.RemoveNetwork", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.RemoveNode + +Remove a ZigBee node with the given 'ieeeAddress' from the network with the given 'networkUuid'. If there is a thing configured for this node, also the thing will be removed from the system. The coordinator node cannot be removed. + +### Parameters + +- ieeeAddress +- networkUuid + +### Returns + +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.RemoveNode", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + +## Zigbee.SetPermitJoin + +Allow or deny nodes to join the network with the given 'networkUuid' for a specific 'duration' in seconds. The duration value has to be between 0 and 255 seconds. The 'permitJoinDuration' property of ZigBee network object indicates how long permit has been enabled and the 'permitJoiningRemaining' indicates the rest of the time. Those values can be used to show a countdown or progressbar. This method can be recalled for resetting the timeout. If the duration is set to 0 seconds, joining will be disabled immediatly for the entire network. The 'shortAddress' is optional and defaults to the broadcast address 0xfffc for all routers in the network. If the short address matches the address of a router node in the network, only that specific router will be able to allow new nodes to join the network. A new node will join to the router with the best link quality index (LQI). + +### Parameters + +- duration +- networkUuid +- o:shortAddress + +### Returns + +- zigbeeError + +### Example Request + +```json +{ + "id": 1, + "method": "Zigbee.SetPermitJoin", + "params": {} +} +``` + +### Example Response + +```json +{ + "id": 1, + "status": "success", + "params": {} +} +``` + diff --git a/docs/nymea_integrations.md b/docs/nymea_integrations.md new file mode 100644 index 0000000..9af1ccb --- /dev/null +++ b/docs/nymea_integrations.md @@ -0,0 +1,10892 @@ +# Nymea Integrations Documentation + +## Plugins + +### Tado +- ID: `b4f2d2ee-50bb-4786-b7f5-261fed204fa5` +- Version: + +### daylightSensor +- ID: `4b7d63a7-fc39-4a50-a459-457fa7653089` +- Version: + +### netatmo +- ID: `69d14951-0c02-4877-bcef-dffdf48b7ccb` +- Version: + +### homeConnect +- ID: `109abdc7-5d53-4f63-a4b2-851e97cea8ea` +- Version: + +### DateTime +- ID: `c26014c6-87fb-4233-85ed-01d18625018d` +- Version: + +### genericShading +- ID: `82f10aec-22cf-4fa9-aa46-f2f9d0db32a4` +- Version: + +### genericGarages +- ID: `5049e7d8-bed7-43c6-9107-b0c1c558ae35` +- Version: + +### genericSensors +- ID: `ee7b2965-d38f-4f73-aed0-e8887423ff1a` +- Version: + +### genericEnergy +- ID: `b3188696-2585-4806-bf98-30ab576ce5c8` +- Version: + +### OpenWeatherMap +- ID: `bc6af567-2338-41d5-aac1-462dec6e4783` +- Version: + +### tplink +- ID: `024ff2e3-30df-44a1-9c8d-63cc416f1fb8` +- Version: + +### ZigbeeEurotronic +- ID: `1fa06c99-ddb8-4dd2-abf8-8fa1abfe6d48` +- Version: + +### solarlog +- ID: `606adc5a-c9a5-45fa-9652-ea385dcb0b81` +- Version: + +### shelly +- ID: `6162773b-0435-408c-a4f8-7860d38031a9` +- Version: + +### Bose +- ID: `472a3f24-b05c-49b3-ad9a-dfda608b6760` +- Version: + +### fronius +- ID: `02319cfc-8b55-49ba-99bc-0588bbfab063` +- Version: + +### genericHeatingCooling +- ID: `0d582885-8295-41bc-99fb-b4bcee4f626c` +- Version: + +### genericLights +- ID: `8b803622-0e48-4987-970e-927d92ad18d5` +- Version: + +### PhilipsHue +- ID: `5f2e634b-b7f3-48ee-976a-b5ae22aa5c55` +- Version: + +### ZigbeeGewiss +- ID: `98959344-92a2-47c5-b071-36db610f147c` +- Version: + +### genericThings +- ID: `27869a19-3084-4b48-8b00-63bdd3125c7c` +- Version: + +### Pushbullet +- ID: `46986575-0e62-483d-b5a8-76ac356fcce7` +- Version: + +### Nanoleaf +- ID: `360867ec-1594-498d-8182-fbab1fe17489` +- Version: + +### ZigbeeDevelco +- ID: `1b9e976d-e842-40e1-9fad-87d71a69c721` +- Version: + +### MailNotification +- ID: `1ae35df1-1b51-4c93-94fa-3febc77e0318` +- Version: + +### ZigbeeTradfri +- ID: `ad9480c8-05f0-4ba1-92b1-4dd8e2ae2830` +- Version: + +### ZWaveQubino +- ID: `8b55a5c9-3770-49ca-a8fe-3bcb735c67a2` +- Version: + +### ZigbeeLumi +- ID: `4a6e97da-0e4b-4731-8bfe-c93d806a9383` +- Version: + +### AirQualityIndex +- ID: `57d69b76-4d2d-41ec-bef6-949a79ffbe6b` +- Version: + +### doorBird +- ID: `6fe1614a-fc47-4eb2-a47c-13c50f1798ee` +- Version: + +### ZWaveGeneric +- ID: `5605f31e-e05b-4d30-bdf4-a8fcc2ec201d` +- Version: + +### pushNotifications +- ID: `fdcea3b3-8d79-4fbb-8101-1ab45d71cedb` +- Version: + +### Kodi +- ID: `e7186890-99fa-4c5b-8247-09c6d450d490` +- Version: + +### Telegram +- ID: `bc95b5c8-f2f1-4bcb-bf88-8d165ee06114` +- Version: + +### genericThing +- ID: `3c7bb595-b72a-4c3c-8414-1b2ac26bc021` +- Version: + +### genericButtons +- ID: `6e22161e-39b7-4416-8623-39e730721efb` +- Version: + +### unifi +- ID: `88bc00c7-9ea8-4aa6-8aec-831639e8fccc` +- Version: + +### ZigbeeTuya +- ID: `02948158-2e0a-4c8a-8a13-0b3d8cfdf4da` +- Version: + +### bgeTech +- ID: `e373f492-4527-4d5f-aa48-34d38c55b0d6` +- Version: + +### anelElektronik +- ID: `7a3e5b64-20e4-42bd-b86b-989b84afc22a` +- Version: + +### SomfyTahoma +- ID: `4e8be1c1-daa8-4e21-9e85-b2372ab1a450` +- Version: + +### sma +- ID: `b8442bbf-9d3f-4aa2-9443-b3a31ae09bac` +- Version: + +### ZigbeeSchneiderElectric +- ID: `01f285a6-f927-4648-a4eb-4f2124f9d490` +- Version: + +### Denon +- ID: `cd758269-dbbb-4ef0-80ab-48bd9a8a2765` +- Version: + +### myStrom +- ID: `fc7f1a24-42a8-45ce-9ffb-136292eb0164` +- Version: + +### ZigbeeGeneric +- ID: `6a4343be-9fd6-4015-9ff5-38542651c534` +- Version: + +### GpioController +- ID: `127ead55-996a-44ac-ba82-fc3c634e018a` +- Version: + +### ZWaveSpringsWindowFashions +- ID: `2872e07a-d6fe-433f-8d6c-cd2f880d6fa3` +- Version: + +### Lifx +- ID: `4e00ee30-79e2-447b-8dcc-c34470f41992` +- Version: + +### NetworkDetector +- ID: `8e0f791e-b273-4267-8605-b7c2f55a68ab` +- Version: + +### flowerCare +- ID: `74e2106a-3407-4e89-a27a-1c890d78bee7` +- Version: + +### Sonos +- ID: `cdb07719-c445-4fa5-9c7a-564ee02a4412` +- Version: + +### ZigbeePhilipsHue +- ID: `0ca340b7-061a-42e6-ab7d-d7b4fd235d02` +- Version: + +### ZigbeeJung +- ID: `d0184b49-6e6d-42fe-92e1-e2ede67ca7df` +- Version: + +### Keba +- ID: `9142b09f-30a9-43d0-9ede-2f8debe075ac` +- Version: + +### tasmota +- ID: `d136e0c0-0cbf-4731-aabb-b2201088d6cb` +- Version: + +### ZWaveFibaro +- ID: `fc5336be-bc9e-48d1-9ad4-d2365321c000` +- Version: + +### OpenUv +- ID: `9b7d9cc8-77df-4197-a6fc-8a365747a3b1` +- Version: + +### genericCar +- ID: `83ede9b2-aa5f-49ff-8f7d-5ca30d8964df` +- Version: + + +## Thing Classes + +### smokedetector + +- ThingClassId: `e883a8ef-1fb7-4d7f-b40b-9cbc0133e58a` + +#### States + +- fireDetected (Bool) → stateTypeId: `6c3ee0ce-fc0f-477c-9a01-be61e061463b` +- batteryCritical (Bool) → stateTypeId: `8f67b692-243b-4ce8-9983-0d1206439f16` +- signalStrength (Uint) → stateTypeId: `47f8506c-af7f-4928-b0ce-8c52ce4f740b` +- connected (Bool) → stateTypeId: `98cf101c-cb0e-47a9-9c27-b6a0cdf9ba4b` + + +--- + +### airQualityIndex + +- ThingClassId: `23ea32c9-38b0-4155-bacc-3afa8c09f6ee` + +#### States + +- connected (Bool) → stateTypeId: `7b9135cd-2461-4d33-b2b3-3dc600983895` +- stationName (String) → stateTypeId: `8385f3d5-62f7-482e-927c-b5d61a70d607` +- pm25 (Double) → stateTypeId: `bc8c4c83-d229-4be4-8732-bc4f2390f399` +- pm10 (Double) → stateTypeId: `24b41ec4-e26b-4dfb-b52c-8e2b1bbdafc6` +- o3 (Double) → stateTypeId: `4e88526d-009f-4820-9a84-09b3646d23c9` +- no2 (Double) → stateTypeId: `6ed6c505-f36e-44c4-a982-f395b04e539b` +- co (Double) → stateTypeId: `54ac72f3-6444-46a8-a43d-210c2a6fbfb5` +- so2 (Double) → stateTypeId: `f3a05e65-a9b3-48fd-be43-688d4c293cc9` +- temperature (Double) → stateTypeId: `94219802-0a82-4761-99b3-c6b6dfc096db` +- humidity (Double) → stateTypeId: `4fc45fca-25ab-45a0-b862-817eea1f51e3` +- pressure (Double) → stateTypeId: `5f799040-08f8-44d1-aa0a-4cab7caad839` +- windSpeed (Double) → stateTypeId: `c4366608-2511-428b-964e-2ad9e37f8f3c` + + +--- + +### kasaPowerStrip300 + +- ThingClassId: `bbdee989-9431-4187-b135-5030a7a11be2` + +#### States + +- connected (Bool) → stateTypeId: `9bcec21d-7207-44c6-8ebf-d2720bb7a63a` +- signalStrength (Uint) → stateTypeId: `1a587f62-8274-4c2e-bdc6-1b0b6368e5f7` +- totalEnergyConsumed (Double) → stateTypeId: `f2992226-1f36-477f-b053-04dc5dc3a31c` +- currentPower (Double) → stateTypeId: `f973b4e8-99fb-4331-8193-e287bd37f5a0` + + +--- + +### controller + +- ThingClassId: `1da7534c-dd51-4cd2-ab56-48428892c436` + +#### States + +- connected (Bool) → stateTypeId: `2efc35f6-dc58-4cd2-98cc-7e0a1a4f4e01` + + +--- + +### powerSocket + +- ThingClassId: `800a8df8-06cb-4d93-8334-944fcce9651a` + +#### States + +- connected (Bool) → stateTypeId: `b5abd47e-95f1-4e35-94fa-be87c396073a` +- signalStrength (Uint) → stateTypeId: `21889797-32c0-4f1b-903d-8af71981882b` +- version (String) → stateTypeId: `41c74445-4d2d-46dc-8a63-c98f1df8e742` +- power (Bool) → stateTypeId: `2c8268b9-d76b-415a-b2e9-6bfeabd98a76` + +#### Actions + +- power → actionTypeId: `2c8268b9-d76b-415a-b2e9-6bfeabd98a76` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "2c8268b9-d76b-415a-b2e9-6bfeabd98a76", + "params": { + "power": "" + } + } + } + +- alert → actionTypeId: `4e3b1430-d98e-4f05-bae6-301dac34bd4b` + +--- + +### tadoAccount + +- ThingClassId: `69be7d15-5658-4442-872e-42abbd8bff81` + +#### States + +- connected (Bool) → stateTypeId: `2f79bc1d-27ed-480a-b583-728363c83ea6` +- loggedIn (Bool) → stateTypeId: `2aed240b-8c5c-418b-a9d1-0d75412c1c27` +- userDisplayName (String) → stateTypeId: `33f55afc-a673-47a4-9fb0-75fdac6a66f4` + + +--- + +### closableSensor + +- ThingClassId: `82a859f0-41ed-4a53-93b0-260a1435ac75` + +#### States + +- closed (Bool) → stateTypeId: `6d4523c2-66f1-4fbf-b0d9-bd11a1920b50` +- tampered (Bool) → stateTypeId: `948bc2da-23fb-44fd-a74c-c917bf657bf0` +- batteryLevel (Int) → stateTypeId: `34a8f7f1-19f8-47be-a1b2-4d7ea52fee1e` +- batteryCritical (Bool) → stateTypeId: `455e1ebc-5534-4053-8db3-c0b6b79f8c41` +- connected (Bool) → stateTypeId: `10d8aa94-943e-40f6-a10e-0ac77bcdecd3` +- signalStrength (Uint) → stateTypeId: `4ef57e47-2b83-4d41-8cfb-21bf2f5ee62d` + + +--- + +### powerSocket + +- ThingClassId: `b2a9a251-f957-42c8-90d6-c421bdb98547` + +#### States + +- connected (Bool) → stateTypeId: `7b0f1f5f-f174-4672-af27-c0459829bee8` +- signalStrength (Uint) → stateTypeId: `528ed056-0b50-4002-833a-78ffcf64442f` +- power (Bool) → stateTypeId: `ac01cd1c-009c-4c83-b27b-273920bd775e` + +#### Actions + +- power → actionTypeId: `ac01cd1c-009c-4c83-b27b-273920bd775e` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ac01cd1c-009c-4c83-b27b-273920bd775e", + "params": { + "power": "" + } + } + } + + +--- + +### pressureSensor + +- ThingClassId: `9a8d804b-d1dc-450a-8c41-be491e5cdda0` + +#### States + +- pressure (Double) → stateTypeId: `e645a979-1465-4592-b8b0-f4c123db0800` +- input (Double) → stateTypeId: `c320577c-371a-442b-ac80-b692ff2064c9` + +#### Actions + +- pressure → actionTypeId: `e645a979-1465-4592-b8b0-f4c123db0800` + - Parameters: + - pressure (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e645a979-1465-4592-b8b0-f4c123db0800", + "params": { + "pressure": "" + } + } + } + +- input → actionTypeId: `c320577c-371a-442b-ac80-b692ff2064c9` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c320577c-371a-442b-ac80-b692ff2064c9", + "params": { + "input": "" + } + } + } + + +--- + +### dryer + +- ThingClassId: `f360cc43-41fc-454a-b6df-09ec0a66c22a` + +#### States + +- connected (Bool) → stateTypeId: `485f895a-5c2d-4e1a-8f77-a2d020363635` +- closed (Bool) → stateTypeId: `81aa609e-69c0-4d5c-98f0-46e6f14c7eaa` +- operationState (String) → stateTypeId: `52fde732-ed14-437e-8fbf-461d2ed19654` +- localControlState (Bool) → stateTypeId: `d73c04c4-7082-4259-a225-10c453247103` +- remoteControlActivationState (Bool) → stateTypeId: `ed8a56a1-18db-469f-b51d-487111037c71` +- remoteStartAllowanceState (Bool) → stateTypeId: `d18d89c1-d04f-491c-b817-7234ea531deb` +- progress (Int) → stateTypeId: `eaf84b93-bacd-42b1-afaf-a890c8b2a099` +- selectedProgram (String) → stateTypeId: `4ad5424c-6ccd-4e29-9aba-41f960618401` +- dryingTarget (String) → stateTypeId: `829c1ec6-5b5a-490a-b487-52287eab91ba` +- endTime (String) → stateTypeId: `6586f2d9-daec-43fa-8f7f-f3afc9d70046` + +#### Actions + +- dryingTarget → actionTypeId: `829c1ec6-5b5a-490a-b487-52287eab91ba` + - Parameters: + - dryingTarget (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "829c1ec6-5b5a-490a-b487-52287eab91ba", + "params": { + "dryingTarget": "" + } + } + } + +- start → actionTypeId: `aedd85a6-0f9a-4bc4-b2ba-90ba11d1a955` +- stop → actionTypeId: `8c9923f6-2a2d-48bb-aaf4-5f887565c58a` + +--- + +### gasSensor + +- ThingClassId: `25c6725f-5c15-485b-9ec4-cb0e11ab6b32` + +#### States + +- gasLevel (Double) → stateTypeId: `5135648f-57b7-44b0-b9d0-c5accad09356` +- input (Double) → stateTypeId: `e3eb500a-ac00-426c-932a-dee4fd6fbcf5` + +#### Actions + +- gasLevel → actionTypeId: `5135648f-57b7-44b0-b9d0-c5accad09356` + - Parameters: + - gasLevel (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5135648f-57b7-44b0-b9d0-c5accad09356", + "params": { + "gasLevel": "" + } + } + } + +- input → actionTypeId: `e3eb500a-ac00-426c-932a-dee4fd6fbcf5` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e3eb500a-ac00-426c-932a-dee4fd6fbcf5", + "params": { + "input": "" + } + } + } + + +--- + +### ventilation + +- ThingClassId: `24af8dd3-ddf0-47f0-bf09-70fdfd8dceab` + +#### States + +- power (Bool) → stateTypeId: `846711b7-ea5a-4c66-a267-001c60406509` + +#### Actions + +- power → actionTypeId: `846711b7-ea5a-4c66-a267-001c60406509` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "846711b7-ea5a-4c66-a267-001c60406509", + "params": { + "power": "" + } + } + } + + +--- + +### virtualPowerSwitch + +- ThingClassId: `8ea0a168-74ff-4445-8c13-74aab195af4e` + +#### States + +- power (Bool) → stateTypeId: `bd3be4e3-7377-421a-a374-104dd451de6d` + +#### Actions + +- power → actionTypeId: `bd3be4e3-7377-421a-a374-104dd451de6d` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bd3be4e3-7377-421a-a374-104dd451de6d", + "params": { + "power": "" + } + } + } + + +--- + +### tasmotaLight + +- ThingClassId: `83e5d9e6-5ac8-4e41-9717-481415048d49` + +#### States + +- connected (Bool) → stateTypeId: `72050de9-c318-4e53-93e5-36f7c2fc7cab` +- signalStrength (Uint) → stateTypeId: `dcc39f5e-6bcb-4c04-910e-8dd5f9ad5402` +- power (Bool) → stateTypeId: `88dbdf8e-45ff-466f-8352-8654a6b5fe68` + +#### Actions + +- power → actionTypeId: `88dbdf8e-45ff-466f-8352-8654a6b5fe68` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "88dbdf8e-45ff-466f-8352-8654a6b5fe68", + "params": { + "power": "" + } + } + } + + +--- + +### humiditySensor + +- ThingClassId: `d295bc64-773c-42a9-83e2-80db5fa0d1ce` + +#### States + +- humidity (Double) → stateTypeId: `925225d9-2965-444a-9c42-63c2873700fb` +- input (Double) → stateTypeId: `a8223e65-e704-4f84-9bbe-d8fc42597047` + +#### Actions + +- humidity → actionTypeId: `925225d9-2965-444a-9c42-63c2873700fb` + - Parameters: + - humidity (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "925225d9-2965-444a-9c42-63c2873700fb", + "params": { + "humidity": "" + } + } + } + +- input → actionTypeId: `a8223e65-e704-4f84-9bbe-d8fc42597047` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a8223e65-e704-4f84-9bbe-d8fc42597047", + "params": { + "input": "" + } + } + } + + +--- + +### impulseSmartMeter + +- ThingClassId: `c3123967-f741-4fe1-a0d4-9a3e405d7e52` + +#### States + +- currentPower (Double) → stateTypeId: `5983d714-5f80-42d8-bee2-9228b6382b3b` +- totalEnergyConsumed (Double) → stateTypeId: `5821edb7-e6cb-4e5a-9d0b-3375126d3367` +- impulseInput (Bool) → stateTypeId: `9cd7e5ca-f8f8-48d5-9785-911ae75158c3` + +#### Actions + +- impulseInput → actionTypeId: `9cd7e5ca-f8f8-48d5-9785-911ae75158c3` + - Parameters: + - impulseInput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9cd7e5ca-f8f8-48d5-9785-911ae75158c3", + "params": { + "impulseInput": "" + } + } + } + + +--- + +### AVRX1000 + +- ThingClassId: `1cd3d67e-aba0-450e-9e2a-483a1527aba6` + +#### States + +- connected (Bool) → stateTypeId: `fc1dee8b-8fcc-4ec2-8fe6-6be4f5f47a5c` +- power (Bool) → stateTypeId: `1cdb6b54-6831-4900-95b2-c78f64497701` +- mute (Bool) → stateTypeId: `3e11470d-a5b7-499c-be55-9b1b4fe5eedf` +- volume (Int) → stateTypeId: `773636b9-304d-463a-8755-fc7488dc0ff3` +- toneControl (Bool) → stateTypeId: `d57c1e5e-2cc9-4638-999c-1523f16dbb83` +- bass (Int) → stateTypeId: `2c92b22e-d5b2-4991-a523-64222bffc9e7` +- treble (Int) → stateTypeId: `38a3be02-6ed4-4a84-903e-eb923b933989` +- inputSource (String) → stateTypeId: `f29ffa2c-31d6-4d88-b160-a38288c82ce1` +- surroundMode (String) → stateTypeId: `4f203bdd-691c-4384-a934-2d49a5448f0a` +- artist (String) → stateTypeId: `50b34df4-90f7-41aa-9a57-6f2d31a18430` +- collection (String) → stateTypeId: `d4f14d93-8cae-4e1b-9ee7-a5c21c0211df` +- title (String) → stateTypeId: `d32493d8-5faf-4c7a-ba94-847dc9b81615` +- artwork (String) → stateTypeId: `6c4a208b-5b04-40cc-b14b-8f79aff30307` +- playerType (String) → stateTypeId: `2f372374-16f3-4900-afdc-834f51075d07` +- playbackStatus (String) → stateTypeId: `8ef6708c-812a-4e6a-a608-9e480aa3b7bf` +- shuffle (Bool) → stateTypeId: `8ad33cb9-e758-433d-a013-2e4d43157c92` +- repeat (String) → stateTypeId: `9478987b-14e4-4572-a059-a18a5a9db229` + +#### Actions + +- power → actionTypeId: `1cdb6b54-6831-4900-95b2-c78f64497701` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1cdb6b54-6831-4900-95b2-c78f64497701", + "params": { + "power": "" + } + } + } + +- mute → actionTypeId: `3e11470d-a5b7-499c-be55-9b1b4fe5eedf` + - Parameters: + - mute (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "3e11470d-a5b7-499c-be55-9b1b4fe5eedf", + "params": { + "mute": "" + } + } + } + +- volume → actionTypeId: `773636b9-304d-463a-8755-fc7488dc0ff3` + - Parameters: + - volume (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "773636b9-304d-463a-8755-fc7488dc0ff3", + "params": { + "volume": "" + } + } + } + +- toneControl → actionTypeId: `d57c1e5e-2cc9-4638-999c-1523f16dbb83` + - Parameters: + - toneControl (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d57c1e5e-2cc9-4638-999c-1523f16dbb83", + "params": { + "toneControl": "" + } + } + } + +- bass → actionTypeId: `2c92b22e-d5b2-4991-a523-64222bffc9e7` + - Parameters: + - bass (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "2c92b22e-d5b2-4991-a523-64222bffc9e7", + "params": { + "bass": "" + } + } + } + +- treble → actionTypeId: `38a3be02-6ed4-4a84-903e-eb923b933989` + - Parameters: + - treble (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "38a3be02-6ed4-4a84-903e-eb923b933989", + "params": { + "treble": "" + } + } + } + +- inputSource → actionTypeId: `f29ffa2c-31d6-4d88-b160-a38288c82ce1` + - Parameters: + - inputSource (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f29ffa2c-31d6-4d88-b160-a38288c82ce1", + "params": { + "inputSource": "" + } + } + } + +- surroundMode → actionTypeId: `4f203bdd-691c-4384-a934-2d49a5448f0a` + - Parameters: + - surroundMode (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4f203bdd-691c-4384-a934-2d49a5448f0a", + "params": { + "surroundMode": "" + } + } + } + +- playbackStatus → actionTypeId: `8ef6708c-812a-4e6a-a608-9e480aa3b7bf` + - Parameters: + - playbackStatus (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8ef6708c-812a-4e6a-a608-9e480aa3b7bf", + "params": { + "playbackStatus": "" + } + } + } + +- shuffle → actionTypeId: `8ad33cb9-e758-433d-a013-2e4d43157c92` + - Parameters: + - shuffle (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8ad33cb9-e758-433d-a013-2e4d43157c92", + "params": { + "shuffle": "" + } + } + } + +- repeat → actionTypeId: `9478987b-14e4-4572-a059-a18a5a9db229` + - Parameters: + - repeat (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9478987b-14e4-4572-a059-a18a5a9db229", + "params": { + "repeat": "" + } + } + } + +- increaseVolume → actionTypeId: `4ae686d6-2307-40a0-bd38-2cd3a92342cc` + - Parameters: + - step (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4ae686d6-2307-40a0-bd38-2cd3a92342cc", + "params": { + "step": "" + } + } + } + +- decreaseVolume → actionTypeId: `d3752c32-92e3-4396-8e2f-ab5e57c6cfb1` + - Parameters: + - step (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d3752c32-92e3-4396-8e2f-ab5e57c6cfb1", + "params": { + "step": "" + } + } + } + +- skipBack → actionTypeId: `3f2eb789-918c-475a-a295-14c0c24338b8` +- stop → actionTypeId: `ddab0869-5b90-4fd4-9c40-9ad57101b87c` +- play → actionTypeId: `d04eb30b-838d-4fbd-b781-c01005b59756` +- pause → actionTypeId: `3de38047-006f-4d97-9326-08bb5ad79b05` +- skipNext → actionTypeId: `bf9664e4-a53e-474c-afcc-88f25e6fe365` + +--- + +### lumiLongpressButtonSensor + +- ThingClassId: `ae3c8713-4660-427b-8916-a08723183ba8` + +#### States + +- connected (Bool) → stateTypeId: `a4285c0e-52c5-47a3-9129-1454421bdd01` +- signalStrength (Uint) → stateTypeId: `d6f425ee-ff76-4e41-93c8-53efd828a169` +- version (String) → stateTypeId: `db532b4b-2d0f-4d77-bbb5-6f81e1981161` + + +--- + +### co2Sensor + +- ThingClassId: `a58a2dae-4148-4a4d-ab34-2a11124454a0` + +#### States + +- co2 (Double) → stateTypeId: `755c4c7f-093e-41dd-a38d-9ee18c9890d6` +- input (Double) → stateTypeId: `7dc765f8-fa9b-4199-8f21-49ed452f226d` + +#### Actions + +- co2 → actionTypeId: `755c4c7f-093e-41dd-a38d-9ee18c9890d6` + - Parameters: + - co2 (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "755c4c7f-093e-41dd-a38d-9ee18c9890d6", + "params": { + "co2": "" + } + } + } + +- input → actionTypeId: `7dc765f8-fa9b-4199-8f21-49ed452f226d` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7dc765f8-fa9b-4199-8f21-49ed452f226d", + "params": { + "input": "" + } + } + } + + +--- + +### solarlog + +- ThingClassId: `1374b47e-5555-4ec1-b2cd-6474048dd30c` + +#### States + +- connected (Bool) → stateTypeId: `eb9f8575-71e3-42a9-aa4d-ffea9586cc4f` +- lastupdate (String) → stateTypeId: `b944c513-a7f0-4bc1-941e-aae9849557fe` +- currentPower (Double) → stateTypeId: `0bf515d8-0f48-4eba-9255-f774d68c80fe` +- pdc (Double) → stateTypeId: `e4183a70-c848-447a-962a-f19dc5974140` +- uac (Double) → stateTypeId: `7dc46b2e-5fba-4cc6-a159-09472cdfac62` +- dcVoltage (Double) → stateTypeId: `bb891a05-59d8-4a3b-a0ea-b63af58558f7` +- yieldDay (Double) → stateTypeId: `53ed041a-e3c3-4ae5-9a79-1cd7ad82e9a8` +- yieldYesterday (Double) → stateTypeId: `bd96d0b3-e921-49eb-8b34-0b3be5bb27fa` +- yieldMonth (Double) → stateTypeId: `9a77662a-2034-4031-8e7a-1e6347089d97` +- yieldYear (Double) → stateTypeId: `d18169ce-deeb-4f7b-b737-818a91760041` +- totalEnergyProduced (Double) → stateTypeId: `3afb6ea1-fef8-4c17-8307-c7547a7a6f3c` +- powerUsage (Double) → stateTypeId: `5b665247-278a-4b59-9046-add40763e937` +- consYieldDay (Double) → stateTypeId: `40ff1d14-a5d2-4fdb-919c-58dfbcdca123` +- consYieldYesterday (Double) → stateTypeId: `5d6d5ba5-ebc3-42ce-9d08-802da694b4da` +- consYieldMonth (Double) → stateTypeId: `a45a557a-a937-4382-8ef5-76f1ff5940e4` +- consYieldYear (Double) → stateTypeId: `1d42619b-3a50-4bde-b325-67a8014332ef` +- consYieldTotal (Double) → stateTypeId: `34f60062-5dec-45ed-9a27-4fbc083cb36e` +- totalPower (Double) → stateTypeId: `0aa21401-2a3d-4149-803b-f0ba8c66b2f7` + + +--- + +### lightSensor + +- ThingClassId: `d4d873fd-f0fc-433f-b615-91c1506a1890` + +#### States + +- lightIntensity (Double) → stateTypeId: `fe12ef32-9f2f-41cd-acb7-6b8e4acffa3b` +- input (Double) → stateTypeId: `520e5d27-7d15-4d79-94cf-5d01f5a09ea8` + +#### Actions + +- lightIntensity → actionTypeId: `fe12ef32-9f2f-41cd-acb7-6b8e4acffa3b` + - Parameters: + - lightIntensity (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "fe12ef32-9f2f-41cd-acb7-6b8e4acffa3b", + "params": { + "lightIntensity": "" + } + } + } + +- input → actionTypeId: `520e5d27-7d15-4d79-94cf-5d01f5a09ea8` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "520e5d27-7d15-4d79-94cf-5d01f5a09ea8", + "params": { + "input": "" + } + } + } + + +--- + +### flushShutter + +- ThingClassId: `08d2df02-e205-43ff-a68c-08f1b2a023dc` + +#### States + +- connected (Bool) → stateTypeId: `a53d1348-0336-481f-8412-bb42b7ca7ffd` +- signalStrength (Uint) → stateTypeId: `5b6b1e02-68dc-4a07-844e-46b6884752a7` +- moving (Bool) → stateTypeId: `a51dea82-6745-4855-8728-3f3cfee0f7f4` +- percentage (Int) → stateTypeId: `4c7bc094-d39a-4fef-b7fb-87d5f2fb2f67` +- currentPower (Double) → stateTypeId: `e53721d4-c0f7-4350-8ee0-9cddc712bc64` +- totalEnergyConsumed (Double) → stateTypeId: `8e9b9169-1848-400d-a8ab-c4600d870ac2` +- calibration (Bool) → stateTypeId: `c0540714-4973-45c8-a65e-d04def8d3ad2` + +#### Actions + +- percentage → actionTypeId: `4c7bc094-d39a-4fef-b7fb-87d5f2fb2f67` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4c7bc094-d39a-4fef-b7fb-87d5f2fb2f67", + "params": { + "percentage": "" + } + } + } + +- calibration → actionTypeId: `c0540714-4973-45c8-a65e-d04def8d3ad2` + - Parameters: + - calibration (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c0540714-4973-45c8-a65e-d04def8d3ad2", + "params": { + "calibration": "" + } + } + } + +- open → actionTypeId: `6862c2f8-9a62-4db9-b7ab-c74bb3bf0b4b` +- close → actionTypeId: `21ffb9be-49df-44c2-af2e-b2c5af553496` +- stop → actionTypeId: `ad9a446f-23e6-4413-a530-b5ba1cbc061a` + +--- + +### smartPlug + +- ThingClassId: `01438844-0048-4276-91f8-c93ac0a5171d` + +#### States + +- power (Bool) → stateTypeId: `77198588-cfd0-44ea-beb5-3a7ce06d4c1d` +- connected (Bool) → stateTypeId: `6fdf4b26-6b93-4db9-9ff4-e755f5da0a3c` + +#### Actions + +- power → actionTypeId: `77198588-cfd0-44ea-beb5-3a7ce06d4c1d` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "77198588-cfd0-44ea-beb5-3a7ce06d4c1d", + "params": { + "power": "" + } + } + } + + +--- + +### dimmerSwitch + +- ThingClassId: `b2711164-a848-4715-8ddf-33ca86f9f4cf` + +#### States + +- connected (Bool) → stateTypeId: `5ac101b2-4bb7-4b5c-8493-08b1ae7ca0c1` +- signalStrength (Uint) → stateTypeId: `5a6e325e-a6ee-4a36-b429-f5d8c8adb80b` +- batteryLevel (Int) → stateTypeId: `3e28e0b3-fe23-4293-8876-8384def6c4fb` +- batteryCritical (Bool) → stateTypeId: `4223a3bc-9616-4ed2-ae50-704b9df62d0e` +- updateStatus (String) → stateTypeId: `92ecca97-4b27-47a3-a91b-948be70d36da` +- currentVersion (String) → stateTypeId: `d04a07c7-f1ef-4645-8de3-f2af2ee602f3` +- availableVersion (String) → stateTypeId: `33f0fa54-2c33-4b9c-a2a5-5908ad1ac32c` +- updateProgress (Uint) → stateTypeId: `9eb669bf-db22-4a58-843a-063457b0f586` + +#### Actions + +- performUpdate → actionTypeId: `22a24b4c-4c1a-490d-abe1-25b120ceef71` + +--- + +### shellyPlus1 + +- ThingClassId: `83766db4-a553-4df7-aeff-35fb18c01f3a` + +#### States + +- power (Bool) → stateTypeId: `231365ce-45d6-4087-8ed6-1de3b0ef0485` +- connected (Bool) → stateTypeId: `30c5bbb2-7b02-445b-af16-8a082321383b` +- signalStrength (Uint) → stateTypeId: `f2b1f70c-dab0-474d-81bd-816ff3c63f47` +- updateStatus (String) → stateTypeId: `2c312a9e-ae76-4042-8030-89c8c86320e9` +- currentVersion (String) → stateTypeId: `3fed15bd-500b-4cce-9b21-a931f411b587` +- availableVersion (String) → stateTypeId: `d236c735-012c-44c7-919e-809cae89de55` + +#### Actions + +- power → actionTypeId: `231365ce-45d6-4087-8ed6-1de3b0ef0485` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "231365ce-45d6-4087-8ed6-1de3b0ef0485", + "params": { + "power": "" + } + } + } + +- reboot → actionTypeId: `212aaf17-faf1-4495-8475-0718b9b39628` +- performUpdate → actionTypeId: `fa3a8bd6-182f-443f-ae41-d2c4aee6339d` + +--- + +### sonoff_basic + +- ThingClassId: `f39fdfa8-73e0-4cf4-8d05-dc237ced7a57` + +#### States + +- connected (Bool) → stateTypeId: `9cde6321-2abf-4a58-a1d6-c7418edb9747` +- signalStrength (Uint) → stateTypeId: `f70e202a-c178-4fbe-a778-713220d11b23` +- power (Bool) → stateTypeId: `0b5a48c9-73b8-42ab-9909-71b8dc2227e3` + +#### Actions + +- power → actionTypeId: `0b5a48c9-73b8-42ab-9909-71b8dc2227e3` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "0b5a48c9-73b8-42ab-9909-71b8dc2227e3", + "params": { + "power": "" + } + } + } + + +--- + +### lumiAirMonitor + +- ThingClassId: `1a9fb2ea-543e-46b2-a10d-9a977232367b` + +#### States + +- connected (Bool) → stateTypeId: `92f74c82-5a3e-4bb7-b3f3-205a6a19620f` +- signalStrength (Uint) → stateTypeId: `f948308d-ed05-47fb-a893-f1c855db10af` +- version (String) → stateTypeId: `42e7712d-ff8b-4af5-be33-e4a55527a0b1` +- temperature (Double) → stateTypeId: `7ce4b747-dfc2-40db-ba55-fa430de97416` +- humidity (Double) → stateTypeId: `85bd3b3f-11b7-409f-95bd-f5b5edc95158` +- voc (Uint) → stateTypeId: `028b0c34-db30-4a3a-bfad-f146b1a96b35` +- batteryCritical (Bool) → stateTypeId: `0689e60d-8022-4537-9284-53d7cd91a78b` +- batteryLevel (Int) → stateTypeId: `0e143e89-d021-40af-a349-de219ceb2084` +- currentVersion (String) → stateTypeId: `2c77e659-c1a0-4cfa-b9de-0a131e491ab6` +- updateStatus (String) → stateTypeId: `7affb09a-6df6-4fb7-88df-a3785b7aa0b5` +- availableVersion (String) → stateTypeId: `799bd935-be61-453f-8e24-a89546e4213d` +- updateProgress (Uint) → stateTypeId: `a6b7f2e2-3d7b-431f-91d8-72f0d47522dd` + +#### Actions + +- performUpdate → actionTypeId: `208a06cd-bbe5-4eb7-afb0-149d257b19b0` + +--- + +### powerSocket + +- ThingClassId: `856bb6a7-65e8-44cb-b77a-ce46f742f33d` + +#### States + +- connected (Bool) → stateTypeId: `99117bce-b9c3-4b43-b853-65585a99926e` +- signalStrength (Uint) → stateTypeId: `51a5f34e-880c-4b77-899c-763f2b9bef97` +- power (Bool) → stateTypeId: `7d28e7b0-0c4a-4d69-a595-53b9e9b512c9` +- currentVersion (String) → stateTypeId: `301b9aee-4a30-4873-bfd9-cfcacc40fbf1` +- updateStatus (String) → stateTypeId: `66b60151-5777-45e3-be51-9b490b650990` +- availableVersion (String) → stateTypeId: `844eecd8-2a4f-45a5-ac2d-5bb73eaf5a29` +- updateProgress (Uint) → stateTypeId: `4977cd0d-8c73-43c1-a9a6-c0db8d54219d` + +#### Actions + +- power → actionTypeId: `7d28e7b0-0c4a-4d69-a595-53b9e9b512c9` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7d28e7b0-0c4a-4d69-a595-53b9e9b512c9", + "params": { + "power": "" + } + } + } + +- performUpdate → actionTypeId: `b5b4841d-0c50-4d21-8101-36a631c1aa00` + +--- + +### motionSensor + +- ThingClassId: `8e260080-3aa3-42fc-9908-05dd163f9dcf` + +#### States + +- isPresent (Bool) → stateTypeId: `48e4d1c6-5415-4c03-9935-6db0c818557d` +- tampered (Bool) → stateTypeId: `f4586208-a20e-41c9-9ba7-01254617ddd6` +- batteryLevel (Int) → stateTypeId: `02523370-2bb6-4103-bd1e-ddb9952dd43a` +- batteryCritical (Bool) → stateTypeId: `bf7ad9fc-4ed2-4671-8e32-a63f8eb6327c` +- connected (Bool) → stateTypeId: `076fca3a-31af-4634-b571-fd82b4a5542c` +- signalStrength (Uint) → stateTypeId: `821f9296-4dc1-435b-89ef-e193361f54cb` + + +--- + +### hood + +- ThingClassId: `62ce7eee-f6bb-43e5-8adf-dfd030276987` + +#### States + +- connected (Bool) → stateTypeId: `bb137bcd-bb6e-464b-8fdc-fb376efd1f59` +- localControlState (Bool) → stateTypeId: `a7680cc1-528c-47ac-a917-d9f3866e9504` +- operationState (String) → stateTypeId: `d1cf12ef-c0e9-452f-99bf-5e65a4dd622c` +- ventingLevel (Int) → stateTypeId: `09e73cec-5b98-4d31-86fb-cd671f210196` + + +--- + +### homeConnectAccount + +- ThingClassId: `babc1a39-730a-4516-95bf-ff51a8ce887a` + +#### States + +- connected (Bool) → stateTypeId: `1180576a-1de2-4815-b442-877b572ce586` +- loggedIn (Bool) → stateTypeId: `ff40d5c7-3095-4b3e-9e10-4c0774336764` +- userDisplayName (String) → stateTypeId: `5d3b2396-6528-47c2-b5a4-f751531bccea` + + +--- + +### temperatureSensor + +- ThingClassId: `cf3d65db-6f68-457b-968c-cfb66cbd5311` + +#### States + +- temperature (Double) → stateTypeId: `d0b6c4be-339e-4b0f-a234-0611b7565395` +- input (Double) → stateTypeId: `fed37466-1264-4ac1-84fd-aff3a1f7ff04` + +#### Actions + +- temperature → actionTypeId: `d0b6c4be-339e-4b0f-a234-0611b7565395` + - Parameters: + - temperature (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d0b6c4be-339e-4b0f-a234-0611b7565395", + "params": { + "temperature": "" + } + } + } + +- input → actionTypeId: `fed37466-1264-4ac1-84fd-aff3a1f7ff04` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "fed37466-1264-4ac1-84fd-aff3a1f7ff04", + "params": { + "input": "" + } + } + } + + +--- + +### pushNotifications + +- ThingClassId: `f0dd4c03-0aca-42cc-8f34-9902457b05de` + +#### Actions + +- notify → actionTypeId: `ed9a0196-6c24-4e05-9cbc-c6834de38005` + - Parameters: + - title (String) + - body (String) + - notificationId (String) + - sound (Bool) + - remove (Bool) + - data (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ed9a0196-6c24-4e05-9cbc-c6834de38005", + "params": { + "title": "", + "body": "", + "notificationId": "", + "sound": "", + "remove": "", + "data": "" + } + } + } + + +--- + +### powerMeterSocket + +- ThingClassId: `7cd9f139-013b-49da-ab71-794cd1e22f5d` + +#### States + +- connected (Bool) → stateTypeId: `3f0cb179-c74d-4e24-9b81-c0539de83cd2` +- signalStrength (Uint) → stateTypeId: `94ae4ee4-269b-4637-818a-25621fe40dc7` +- version (String) → stateTypeId: `04ae808c-4720-4d06-b6d8-9772b4bd9e3c` +- power (Bool) → stateTypeId: `bfe70a26-f6a2-412c-94af-b31b9e91d5ea` +- currentPower (Double) → stateTypeId: `33a572a4-fd5b-46e7-8618-eba3b7770309` +- totalEnergyConsumed (Double) → stateTypeId: `b653dea0-8028-49f8-be09-f0fd5521f43c` + +#### Actions + +- power → actionTypeId: `bfe70a26-f6a2-412c-94af-b31b9e91d5ea` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bfe70a26-f6a2-412c-94af-b31b9e91d5ea", + "params": { + "power": "" + } + } + } + +- alert → actionTypeId: `fac41f4f-dcba-48ef-adc5-d6478e67746d` + +--- + +### washer + +- ThingClassId: `aaec390e-a61f-40ea-b42c-80f69428690b` + +#### States + +- connected (Bool) → stateTypeId: `950a8bf0-83c4-4e1b-9c00-167a4d3e3c22` +- closed (Bool) → stateTypeId: `99296e86-09bf-4b74-b122-ee82b6bfdb62` +- operationState (String) → stateTypeId: `2ad3e2f8-c955-4e1d-b394-1e71a16f03bb` +- localControlState (Bool) → stateTypeId: `f3aa6f6e-bfa3-4465-906c-3d5137d4098c` +- remoteControlActivationState (Bool) → stateTypeId: `3c9c7163-b5f5-47cc-86b1-aa95273a22f6` +- remoteStartAllowanceState (Bool) → stateTypeId: `f7a68b23-6d74-451b-89c8-b2d2fb5d0839` +- progress (Int) → stateTypeId: `312d817d-3384-41fb-a8ba-15c137844ee0` +- selectedProgram (String) → stateTypeId: `d10066ad-0ad3-49d2-a3c3-ee6002c1a18d` +- temperature (String) → stateTypeId: `29ed9597-2ace-48f5-91bc-171ac2601bfc` +- spinSpeed (String) → stateTypeId: `ab65bfa0-37d8-4df6-80f0-80377a43a520` +- endTime (String) → stateTypeId: `e9b93ad1-fe9e-4ba2-ac7c-9407fa80c846` + +#### Actions + +- start → actionTypeId: `c87d6825-f37d-4da6-8545-945bd589dbc2` +- stop → actionTypeId: `044582ca-30e6-4d37-9377-809fb5fa120a` + +--- + +### counterRpi + +- ThingClassId: `75b13371-a064-47a7-bb82-e9d93a5b5027` + +#### States + +- counter (Int) → stateTypeId: `891bc1ce-2f9b-4518-aed9-90e78bc2409e` + + +--- + +### cookProcessor + +- ThingClassId: `8b792638-11dc-4288-ac94-5b41d9e11a4e` + +#### States + +- connected (Bool) → stateTypeId: `434c5690-a62d-4815-ad8b-e3c306745d9f` +- operationState (String) → stateTypeId: `9aed899f-09cc-4f20-965a-9724372a1093` + + +--- + +### ioModule + +- ThingClassId: `3fb419ef-795d-4f4d-b801-e7eaff16cdb0` + +#### States + +- connected (Bool) → stateTypeId: `16d5ebb7-21d1-4294-98a6-ca06eea8e3a3` +- signalStrength (Uint) → stateTypeId: `0e09e6a6-8b3f-4b63-acb1-ac04ab31957a` +- version (String) → stateTypeId: `f28c9a61-b8ab-419c-bd85-58692df26ac7` +- output1 (Bool) → stateTypeId: `aaeda2c6-439a-452a-b829-45d6249bdee6` +- output2 (Bool) → stateTypeId: `105cf314-35b5-4a8b-8e6d-d011009f97ff` +- input1 (Bool) → stateTypeId: `bc23c7e8-f4ad-47c4-b938-f9af2dbd3393` +- input2 (Bool) → stateTypeId: `065b0dc0-6d31-40ec-b356-02fea57e2fe1` +- input3 (Bool) → stateTypeId: `8f2b052a-30b7-49aa-a8d4-503cb0b9b66b` +- input4 (Bool) → stateTypeId: `caef986c-da13-4ef3-ab81-316244c7be1e` + +#### Actions + +- output1 → actionTypeId: `aaeda2c6-439a-452a-b829-45d6249bdee6` + - Parameters: + - output1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "aaeda2c6-439a-452a-b829-45d6249bdee6", + "params": { + "output1": "" + } + } + } + +- output2 → actionTypeId: `105cf314-35b5-4a8b-8e6d-d011009f97ff` + - Parameters: + - output2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "105cf314-35b5-4a8b-8e6d-d011009f97ff", + "params": { + "output2": "" + } + } + } + +- alert → actionTypeId: `62c5562a-8bdf-49b4-8e1d-f27442b2b360` +- impulseOutput1 → actionTypeId: `45ec5c65-0719-4148-82ea-3e69b34be939` +- impulseOutput2 → actionTypeId: `d780946c-4ddf-4b59-a669-dbf6ecfda5d6` + +--- + +### remote + +- ThingClassId: `bb482d39-67ef-46dc-88e9-7b181d642b28` + +#### States + +- connected (Bool) → stateTypeId: `9f9fac89-2dcd-4db6-b214-0065662af62a` +- batteryLevel (Int) → stateTypeId: `683e493a-9796-4d5e-b0e3-61cb178d5819` +- batteryCritical (Bool) → stateTypeId: `f8516899-6312-4110-bb97-70ffa81dc530` + + +--- + +### gwa1501BinaryInput + +- ThingClassId: `5daf398f-2eba-47c1-8805-ca34f075c7ea` + +#### States + +- connected (Bool) → stateTypeId: `c4a8d75d-fce0-4243-a25d-9a10a6c7e811` +- signalStrength (Uint) → stateTypeId: `17150f4b-6ef1-444a-b178-293a057275dc` +- batteryLevel (Int) → stateTypeId: `9dcf9715-267e-43c6-bcc7-9822e5361228` +- batteryCritical (Bool) → stateTypeId: `8b4b82e8-69e4-4160-90be-3040d455fd97` +- input1 (Bool) → stateTypeId: `9005783a-88ec-4f93-a486-992b2d6ae3ab` +- input2 (Bool) → stateTypeId: `cd6362a6-2d94-41e4-ad0c-31a1cf910f33` + + +--- + +### kasaSocket + +- ThingClassId: `2f40e28c-2484-4e09-bda9-e7accc29ab41` + +#### States + +- connected (Bool) → stateTypeId: `59feb3a8-d35e-4c10-ac2e-01361e711a5e` +- signalStrength (Uint) → stateTypeId: `16b71516-2ff4-4a2f-b0fc-53fff11f3a16` +- power (Bool) → stateTypeId: `b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8` + +#### Actions + +- power → actionTypeId: `b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b1d006a6-f2f5-475c-ab9e-8b431b1ac5f8", + "params": { + "power": "" + } + } + } + + +--- + +### generic + +- ThingClassId: `f5c02d35-b06e-4950-8238-847d50cabfdf` + +#### States + +- stringState (String) → stateTypeId: `f477e227-0d2d-4d88-a545-7dedf36266d5` +- digitalInput (Bool) → stateTypeId: `3cf5eb01-dae8-49cd-8c5f-b0224be0044f` +- digitalOutput (Bool) → stateTypeId: `605b4d8e-71a7-441e-900a-e07c305acd93` +- analogInput (Double) → stateTypeId: `810fcd3c-7854-4bb1-82f6-1403ba54875e` +- analogOutput (Double) → stateTypeId: `de8ec1b1-8026-4fd8-aefb-dedc07616aa4` + +#### Actions + +- stringState → actionTypeId: `f477e227-0d2d-4d88-a545-7dedf36266d5` + - Parameters: + - stringState (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f477e227-0d2d-4d88-a545-7dedf36266d5", + "params": { + "stringState": "" + } + } + } + +- digitalInput → actionTypeId: `3cf5eb01-dae8-49cd-8c5f-b0224be0044f` + - Parameters: + - digitalInput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "3cf5eb01-dae8-49cd-8c5f-b0224be0044f", + "params": { + "digitalInput": "" + } + } + } + +- digitalOutput → actionTypeId: `605b4d8e-71a7-441e-900a-e07c305acd93` + - Parameters: + - digitalOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "605b4d8e-71a7-441e-900a-e07c305acd93", + "params": { + "digitalOutput": "" + } + } + } + +- analogInput → actionTypeId: `810fcd3c-7854-4bb1-82f6-1403ba54875e` + - Parameters: + - analogInput (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "810fcd3c-7854-4bb1-82f6-1403ba54875e", + "params": { + "analogInput": "" + } + } + } + +- analogOutput → actionTypeId: `de8ec1b1-8026-4fd8-aefb-dedc07616aa4` + - Parameters: + - analogOutput (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "de8ec1b1-8026-4fd8-aefb-dedc07616aa4", + "params": { + "analogOutput": "" + } + } + } + + +--- + +### virtualButton + +- ThingClassId: `820b2f2d-0d92-48c8-8fd4-f94ce8fc4103` + +#### Actions + +- press → actionTypeId: `01f38af1-b2ab-4ec3-844e-ef52f0f229a9` + +--- + +### motionSensor + +- ThingClassId: `500a8b65-ad34-4bf0-a35d-c167510999f2` + +#### States + +- isPresent (Bool) → stateTypeId: `73523dee-93c1-4143-abff-7685b2d1bb1c` +- tampered (Bool) → stateTypeId: `c9c0343a-e396-4a21-ab7f-5f3d88cc55c5` +- batteryLevel (Int) → stateTypeId: `4ed91f61-298f-411a-a1b8-403d77eecf34` +- batteryCritical (Bool) → stateTypeId: `ca81d872-dcf0-430d-8b00-98e6e4e4ccf4` +- connected (Bool) → stateTypeId: `5d12e9da-2f5c-4d40-a20a-b5d378fd0387` +- signalStrength (Uint) → stateTypeId: `5062aac1-aa2d-4a35-9435-482ff45a4d02` + + +--- + +### light + +- ThingClassId: `c50d3216-f307-4f9f-8190-4391510c385c` + +#### States + +- power (Bool) → stateTypeId: `8b6e4a67-6522-408b-b676-8d2f09ed2d54` + +#### Actions + +- power → actionTypeId: `8b6e4a67-6522-408b-b676-8d2f09ed2d54` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8b6e4a67-6522-408b-b676-8d2f09ed2d54", + "params": { + "power": "" + } + } + } + + +--- + +### awning + +- ThingClassId: `d3a3bb40-4b2d-4bdc-989f-5254f03b4c90` + +#### States + +- percentage (Int) → stateTypeId: `c409cb9b-82ef-4f59-ae89-eb783d4ebe97` +- moving (Bool) → stateTypeId: `2507ac5a-9658-42cb-80f6-73f673c32771` +- signalStrength (Uint) → stateTypeId: `b2ad6f4a-c507-45c3-a951-b344603cc3fc` +- connected (Bool) → stateTypeId: `8f972969-10dd-4954-9c8b-de56070a6668` + +#### Actions + +- percentage → actionTypeId: `c409cb9b-82ef-4f59-ae89-eb783d4ebe97` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c409cb9b-82ef-4f59-ae89-eb783d4ebe97", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `9612954c-02cb-4159-9a29-f36eaf1c7f6a` +- stop → actionTypeId: `33bec73b-4d15-493a-b553-bcee32c40ee1` +- close → actionTypeId: `20cae53b-f36d-425b-b937-3e46519893a3` + +--- + +### flowerCare + +- ThingClassId: `297e2efa-168c-4eb8-bf3f-f8694dc0a2b9` + +#### States + +- connected (Bool) → stateTypeId: `6254103a-ff8b-4f62-afda-6b5be1c933ec` +- batteryLevel (Int) → stateTypeId: `801a00ab-ce3b-4b10-9236-2f845c469a26` +- batteryCritical (Bool) → stateTypeId: `700a83e6-9fbb-4330-b00e-e9d0874b4f66` +- temperature (Double) → stateTypeId: `4577a032-bafd-49ca-8625-6dcf90819e88` +- moisture (Double) → stateTypeId: `5e3ac82a-1dda-4399-888e-529b391a814a` +- lightIntensity (Double) → stateTypeId: `7e0a3b3d-72f4-4547-bd1e-2711be61c1a7` +- conductivity (Double) → stateTypeId: `f77608b3-8b5b-43a9-aab6-0dc35c694ec3` + + +--- + +### client + +- ThingClassId: `cf1a99ce-ad17-4cc7-8558-480daba20e72` + +#### States + +- isPresent (Bool) → stateTypeId: `7c2420eb-31eb-43b8-b28c-0dba4a4a3910` +- lastSeenTime (Int) → stateTypeId: `8491c998-6100-4a1c-b0b7-6d44696aceba` + + +--- + +### inverter + +- ThingClassId: `540aa956-8b8f-4982-9f58-343a76cea846` + +#### States + +- connected (Bool) → stateTypeId: `eda29c50-73ac-40e0-9c92-26fee352e688` +- currentPower (Double) → stateTypeId: `788accbc-b86e-471b-b37f-14c9c6411526` +- energyDay (Double) → stateTypeId: `b6af1bf5-753d-47b6-a151-e4d801fe6ff8` +- energyYear (Int) → stateTypeId: `7fd2fa28-9bcc-4f01-a823-459437d185f6` +- totalEnergyProduced (Double) → stateTypeId: `d6dbb879-4cbc-4db3-830e-b92ba91a13e5` + + +--- + +### sunnyWebBox + +- ThingClassId: `49304127-ce9b-45dd-8511-05030a4ac003` + +#### States + +- connected (Bool) → stateTypeId: `c05e6a1a-252c-4f2b-8b31-09cf113d01c1` +- currentPower (Double) → stateTypeId: `ff4ff872-2f0f-4ca4-9fe2-220eeaf16cc2` +- dayEnergyProduced (Double) → stateTypeId: `16f34c5c-8dbb-4dcc-9faa-4b782d57226c` +- totalEnergyProduced (Double) → stateTypeId: `0bb4e227-7e38-49ca-9b32-ce4621c9305b` +- mode (String) → stateTypeId: `1974550b-6059-4b0e-83f4-70177e20dac3` +- error (String) → stateTypeId: `4e64f9ca-7e5a-4897-8035-6f2ae88fde89` + + +--- + +### lumiPowerSocket + +- ThingClassId: `76afde12-e781-4723-94ca-5704e800e821` + +#### States + +- connected (Bool) → stateTypeId: `58e01e24-fa6e-4518-ad05-f3b118901f69` +- signalStrength (Uint) → stateTypeId: `81926f63-4dc8-4701-a62d-07b20a849b37` +- currentVersion (String) → stateTypeId: `e4a8e90c-4e38-4b3b-b5e6-fd336e3fa2a8` +- updateStatus (String) → stateTypeId: `21e03a17-7bb8-41f7-8cba-9194354892f9` +- availableVersion (String) → stateTypeId: `79ca6068-5532-4b3c-b8e2-d2533b03cc93` +- updateProgress (Uint) → stateTypeId: `6655f819-b020-4573-843d-32d17a931db7` +- power (Bool) → stateTypeId: `4c81aa6b-3a8a-4d2c-be87-29486ca242af` +- currentPower (Double) → stateTypeId: `2c05bb81-3be9-46a9-8bc6-94d72ee4a668` +- totalEnergyConsumed (Double) → stateTypeId: `5616730e-6097-4bcb-8dfe-47667c5d197a` + +#### Actions + +- power → actionTypeId: `4c81aa6b-3a8a-4d2c-be87-29486ca242af` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4c81aa6b-3a8a-4d2c-be87-29486ca242af", + "params": { + "power": "" + } + } + } + +- alert → actionTypeId: `67052e4d-350a-406f-91a9-3ce3f8eaaa7f` +- performUpdate → actionTypeId: `447936ea-96aa-4e37-a5ae-c62e3f7f3d05` + +--- + +### tasmotaSwitch + +- ThingClassId: `8a5e69c0-14ad-4ae8-9ff9-10055de6ffdf` + +#### States + +- connected (Bool) → stateTypeId: `b4607e5d-70c4-4e76-9d9a-c6de7c50377e` +- signalStrength (Uint) → stateTypeId: `34e54234-d2d6-4c93-8d52-bada19e5ff23` +- power (Bool) → stateTypeId: `413503d7-fc9f-417a-95fa-5c350a6f69f9` + +#### Actions + +- power → actionTypeId: `413503d7-fc9f-417a-95fa-5c350a6f69f9` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "413503d7-fc9f-417a-95fa-5c350a6f69f9", + "params": { + "power": "" + } + } + } + + +--- + +### socket + +- ThingClassId: `9d8da004-a8a1-457f-a8ee-b86133828a49` + +#### States + +- connected (Bool) → stateTypeId: `e7e868a0-2de4-46ba-8ce7-87eaa4fc8e06` +- power (Bool) → stateTypeId: `47329958-c33f-478f-b2a0-910abd150da8` + +#### Actions + +- power → actionTypeId: `47329958-c33f-478f-b2a0-910abd150da8` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "47329958-c33f-478f-b2a0-910abd150da8", + "params": { + "power": "" + } + } + } + + +--- + +### gateway + +- ThingClassId: `6c09e0b9-f0cc-4dea-9994-9e039eff78f1` + +#### States + +- connected (Bool) → stateTypeId: `18ba7fb7-c9e8-4c61-86b3-a8d3b825ed00` + + +--- + +### shelly1 + +- ThingClassId: `f810b66a-7177-4397-9771-4229abaabbb6` + +#### States + +- power (Bool) → stateTypeId: `5b7eeb6c-6113-41f3-a61b-3076d087c9fe` +- connected (Bool) → stateTypeId: `e5d41e05-2296-457e-97d8-98a5ac0de615` +- signalStrength (Uint) → stateTypeId: `74c631ed-fc3d-49e8-9dec-99cafa70c559` +- updateStatus (String) → stateTypeId: `68bf3780-8f7f-4ecb-8498-830e257c192c` +- currentVersion (String) → stateTypeId: `e033cca0-03fa-4b2e-9d7b-d4a2c8ffbb8c` +- availableVersion (String) → stateTypeId: `6e794011-d184-4ab2-9c3a-3b2205880cbc` + +#### Actions + +- power → actionTypeId: `5b7eeb6c-6113-41f3-a61b-3076d087c9fe` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5b7eeb6c-6113-41f3-a61b-3076d087c9fe", + "params": { + "power": "" + } + } + } + +- reboot → actionTypeId: `b4067d54-36c5-4d30-bbc3-c8c712d6fd32` +- performUpdate → actionTypeId: `6f814339-9a48-4027-a3f8-760742ff22ba` + +--- + +### bridge + +- ThingClassId: `642aa4c7-19aa-45ed-ba06-aa1ae6c9edf7` + +#### States + +- connected (Bool) → stateTypeId: `15794d26-fde8-4a61-8f83-d7830534975f` +- apiVersion (String) → stateTypeId: `7a230e89-c4ce-4276-90e0-6a9ddb890603` +- updateStatus (String) → stateTypeId: `16a126f3-0cef-4931-bb2b-9e1b49bec7fc` +- currentVersion (String) → stateTypeId: `4c707b18-6604-4e6d-b6bc-4e27769c2adc` + +#### Actions + +- searchNewDevices → actionTypeId: `cca3f171-6318-44e7-a2ac-d841857c1c24` + - Parameters: + - serial (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "cca3f171-6318-44e7-a2ac-d841857c1c24", + "params": { + "serial": "" + } + } + } + +- checkForUpdates → actionTypeId: `07a85e91-d064-4bce-b017-13fd0c320c0b` +- performUpdate → actionTypeId: `6dfbc7c0-7372-42f6-82ba-e777cb32dc4c` + +--- + +### smokeSensor + +- ThingClassId: `258dd38e-72ba-4295-b04b-ea9ef8e3312b` + +#### States + +- connected (Bool) → stateTypeId: `f1a65b25-c0f9-4535-9f85-45b42d91cfa1` +- signalStrength (Uint) → stateTypeId: `f0b38b1c-0f1d-4359-b732-06aae73b9edf` +- fireDetected (Bool) → stateTypeId: `58b073a2-62a0-4754-9e57-4dac80095ed1` +- smokeConcentration (Double) → stateTypeId: `aaef289e-d1fc-4e44-8c1d-bbb6ad28ea33` +- tampered (Bool) → stateTypeId: `cca93a41-206c-41fa-809c-07f4f34b010f` +- batteryLevel (Int) → stateTypeId: `9abc0e1b-242a-4f4b-a656-26563c761ed9` +- batteryCritical (Bool) → stateTypeId: `37bae504-1471-4689-b8fa-cf494a5522a8` + + +--- + +### simpleHeatPump + +- ThingClassId: `9fdb33bb-8e38-4108-8234-3b1d07bbc801` + +#### States + +- power (Bool) → stateTypeId: `ac2ac0f9-058c-4586-8871-2d9dbc6e1758` + +#### Actions + +- power → actionTypeId: `ac2ac0f9-058c-4586-8871-2d9dbc6e1758` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ac2ac0f9-058c-4586-8871-2d9dbc6e1758", + "params": { + "power": "" + } + } + } + + +--- + +### windModule + +- ThingClassId: `160096e8-5ad0-4ca5-b7f2-60d64865ca71` + +#### States + +- updateTime (Int) → stateTypeId: `aa4be9dc-06e4-48a2-b83e-45c523da116b` +- windSpeed (Double) → stateTypeId: `9f6c1540-9933-4ef1-96d7-aecade2a8199` +- windDirection (Int) → stateTypeId: `65ad8900-583a-4bf7-8bff-f738225ca017` +- signalStrength (Uint) → stateTypeId: `7eafdb74-c99a-40c4-95ca-99f5ddf82355` +- connected (Bool) → stateTypeId: `5d369774-78df-4259-bdff-cc82b946470b` +- batteryLevel (Int) → stateTypeId: `560e0bd7-3c75-430e-8ef3-65bbbe85a3af` +- batteryCritical (Bool) → stateTypeId: `5dcddcf9-da07-4bac-9988-018168a516ad` + + +--- + +### colorLight + +- ThingClassId: `d32953a5-ac30-479e-bd8d-e523c745902d` + +#### States + +- connected (Bool) → stateTypeId: `e4954ad7-812b-491f-9187-ba6cd6cd1755` +- signalStrength (Uint) → stateTypeId: `3a65294c-a5b8-475e-ab1c-8a5df5c3ab51` +- power (Bool) → stateTypeId: `3ab42d68-2394-40ff-8704-571e5b1b28e9` +- brightness (Int) → stateTypeId: `58f16042-b027-439b-96f6-39ae4b5772f8` +- colorTemperature (Int) → stateTypeId: `472d3582-cff9-42d1-914a-433ebdf8bf37` +- color (Color) → stateTypeId: `92338bb1-c3ef-46ee-8e87-3dcabad6d0d2` +- updateStatus (String) → stateTypeId: `7d59df4c-7964-4c05-af04-a2672e30d919` +- currentVersion (String) → stateTypeId: `985ef8bf-22c7-40b8-8de6-8ba5f54ab287` +- availableVersion (String) → stateTypeId: `8ae98171-c2bc-4d87-a1e1-8d73f669fb4f` +- updateProgress (Uint) → stateTypeId: `b2fd7717-c6ce-425e-9b39-d9e953f5d687` + +#### Actions + +- power → actionTypeId: `3ab42d68-2394-40ff-8704-571e5b1b28e9` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "3ab42d68-2394-40ff-8704-571e5b1b28e9", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `58f16042-b027-439b-96f6-39ae4b5772f8` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "58f16042-b027-439b-96f6-39ae4b5772f8", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `472d3582-cff9-42d1-914a-433ebdf8bf37` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "472d3582-cff9-42d1-914a-433ebdf8bf37", + "params": { + "colorTemperature": "" + } + } + } + +- color → actionTypeId: `92338bb1-c3ef-46ee-8e87-3dcabad6d0d2` + - Parameters: + - color (Color) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "92338bb1-c3ef-46ee-8e87-3dcabad6d0d2", + "params": { + "color": "" + } + } + } + +- alert → actionTypeId: `2a0dc479-34e8-4f56-bd24-b004d4b762e9` +- performUpdate → actionTypeId: `392cd1ac-af9c-4035-ae6c-20c033ebf317` + +--- + +### gpioOutputBbb + +- ThingClassId: `75d54a59-f9b0-4bc4-a86c-6b1fc47e0663` + +#### States + +- power (Bool) → stateTypeId: `82b567c6-a33c-484e-b5e7-e04795498d00` + +#### Actions + +- power → actionTypeId: `82b567c6-a33c-484e-b5e7-e04795498d00` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "82b567c6-a33c-484e-b5e7-e04795498d00", + "params": { + "power": "" + } + } + } + + +--- + +### soundRemote + +- ThingClassId: `a18e398d-c14b-4bcd-8e6d-b64737436814` + +#### States + +- connected (Bool) → stateTypeId: `41ca0f43-998e-4a5e-ad6b-ae7deab38461` +- signalStrength (Uint) → stateTypeId: `9485fea7-adfc-47aa-a7c4-76f38eff49ca` +- batteryLevel (Int) → stateTypeId: `1a0e2e7b-1b2a-461c-a24f-1323c2aea4a1` +- batteryCritical (Bool) → stateTypeId: `59312570-9cab-4e64-ac2f-2eda1c5ac314` +- level (Uint) → stateTypeId: `58657999-e062-4a12-81e7-f81d7842d18b` +- currentVersion (String) → stateTypeId: `1958f3f7-509b-4222-9598-b6edd1bb9c1c` +- updateStatus (String) → stateTypeId: `73255d32-c21e-467a-86aa-3458660ac2ea` +- availableVersion (String) → stateTypeId: `0780be81-d4e3-4dc2-86dd-85bd8624737e` +- updateProgress (Uint) → stateTypeId: `7f53f37a-fccc-4909-8cb0-223b75046c79` + +#### Actions + +- performUpdate → actionTypeId: `5f8d2a0e-b80c-4479-8699-8ac46c98c34b` + +--- + +### shellyFlood + +- ThingClassId: `d59f08e4-64e3-49f1-96e1-60b63136e3d9` + +#### States + +- waterDetected (Bool) → stateTypeId: `c8ecb7c4-da20-49b4-a086-8c137d3dc349` +- temperature (Double) → stateTypeId: `1f62ad7a-5200-4807-ad5d-7d3bff1f8966` +- connected (Bool) → stateTypeId: `0c445ba9-091d-4cca-bca1-b15c51a95d0f` +- signalStrength (Uint) → stateTypeId: `bbb6d325-9712-4f29-81b6-65fd09264a99` +- batteryLevel (Int) → stateTypeId: `e321f13e-8efc-4882-8498-def48b3e8ae4` +- batteryCritical (Bool) → stateTypeId: `0b657f84-f09c-46af-ac28-069b2b67bac3` +- updateStatus (String) → stateTypeId: `a5120193-9396-45c5-bd16-e92a229899db` +- currentVersion (String) → stateTypeId: `15c1f27c-2379-4df0-afa9-086b63282d2a` +- availableVersion (String) → stateTypeId: `e86ef323-4531-459f-9c8c-d150a93ad208` + +#### Actions + +- performUpdate → actionTypeId: `0263209a-65b2-4521-a241-db597fb003ea` + +--- + +### airQualitySensor + +- ThingClassId: `9f966405-4d63-4ae8-8472-a3ab7bbcadaa` + +#### States + +- connected (Bool) → stateTypeId: `c6f65bb8-1234-40f2-8855-84ca28f48150` +- signalStrength (Uint) → stateTypeId: `19cfb35b-6a2e-4efe-9366-287c2f13c027` +- version (String) → stateTypeId: `5d1c46ca-9306-473a-a721-165831ff53cc` +- temperature (Double) → stateTypeId: `2d31d98e-dcd7-4700-a90e-a0d051ad6b40` +- humidity (Double) → stateTypeId: `5bc2825c-666f-4013-9583-3a88ceebecc2` +- batteryCritical (Bool) → stateTypeId: `048ed452-785f-4361-b7a1-f955f4a622b2` +- voc (Uint) → stateTypeId: `1ba14107-4241-46d0-b65f-eb6e8c6f8e08` +- updateStatus (String) → stateTypeId: `0ce38986-4700-47ef-a672-51853485e5f5` +- currentVersion (String) → stateTypeId: `b66948ad-59fd-420b-a7cd-4937b63050d5` +- availableVersion (String) → stateTypeId: `80434d6d-2cde-4671-a050-8352f6aff2de` +- updateProgress (Uint) → stateTypeId: `0b9488fa-458f-4c9b-9035-60f7d3d559e4` + +#### Actions + +- performUpdate → actionTypeId: `24b2a7ec-66c7-4e9e-8f92-1dee3373ff63` + +--- + +### presenceSensor + +- ThingClassId: `17978e89-290f-4101-8a9e-85cb1cb5e12a` + +#### States + +- connected (Bool) → stateTypeId: `af307ed4-6dd0-4e5e-9ea0-822f473613e7` +- signalStrength (Uint) → stateTypeId: `dc265b4f-da86-43d0-9d55-aa83a9dff323` +- isPresent (Bool) → stateTypeId: `98d3096b-4e42-4b6e-ae29-21b876fbfe3b` +- targetDistance (Double) → stateTypeId: `020e64e0-82a3-4bb6-8869-fc32368695f6` +- lightIntensity (Double) → stateTypeId: `242c732d-47d3-496e-9004-1a36647b398a` +- selfTest (String) → stateTypeId: `91e6ba5e-8dd1-4211-9a18-9d1511198614` + + +--- + +### shellyEm + +- ThingClassId: `bcc7326d-555a-4763-80ce-7354e67cc700` + +#### States + +- connected (Bool) → stateTypeId: `75f1a571-b21c-43c2-b4a3-ab8e9d7ef08c` +- signalStrength (Uint) → stateTypeId: `87664175-4b84-4cfe-9bee-5d1bcf2566f8` +- updateStatus (String) → stateTypeId: `ad5d523e-9a4d-47d2-912c-c8ec5081f9ff` +- currentVersion (String) → stateTypeId: `f5f03ab2-fec6-4502-8a47-100211878a8a` +- availableVersion (String) → stateTypeId: `97ab36bb-355b-4559-838a-fe49a9cbd13e` +- power (Bool) → stateTypeId: `9a2c6304-91d6-45fc-8ef7-75355457eca5` + +#### Actions + +- power → actionTypeId: `9a2c6304-91d6-45fc-8ef7-75355457eca5` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9a2c6304-91d6-45fc-8ef7-75355457eca5", + "params": { + "power": "" + } + } + } + +- performUpdate → actionTypeId: `6a30f435-2b35-4df5-8a20-ef3dbec817c9` +- reset → actionTypeId: `09f6d675-4c22-4a9f-b9f2-3349ab947529` + +--- + +### netPwrCtlHome + +- ThingClassId: `d70433ac-9738-49ca-932f-6d3e20bcc6d4` + +#### States + +- connected (Bool) → stateTypeId: `9cde6321-2abf-4a58-a1d6-c7418edb9747` + + +--- + +### shellyGas + +- ThingClassId: `f032e312-0911-450e-9456-67c27f31bebd` + +#### States + +- gasLevel (Double) → stateTypeId: `f7549376-226f-42aa-ae0e-1a62884908d8` +- connected (Bool) → stateTypeId: `4c912d66-398f-4c82-9ae1-a08d191cfbc7` +- signalStrength (Uint) → stateTypeId: `71a6ef7a-c116-4cc6-94ab-943c0aad4d5f` +- updateStatus (String) → stateTypeId: `8ceb701b-7a6d-4f81-a09e-72e8ace12057` +- currentVersion (String) → stateTypeId: `98911e5d-16f6-4502-a7df-111c7007a660` +- availableVersion (String) → stateTypeId: `8c805225-86fb-4a50-b8af-4bbe0b4d7dde` +- sensorOperation (String) → stateTypeId: `efbc314f-d3e4-4558-9736-e7499d2bd8ba` +- selfTest (String) → stateTypeId: `36d55e34-27a5-4e1d-9c87-9f89c65e8aed` +- gas (String) → stateTypeId: `eb69d7d4-0947-4829-a3de-c0c0f94124bd` +- valveState (String) → stateTypeId: `5bc36b2c-4110-44ec-816f-8a3421343bb4` + +#### Actions + +- performUpdate → actionTypeId: `8aa54702-b76f-46a1-a23b-1fc6d699eea8` +- selfTest → actionTypeId: `28016a8c-fb0e-4c1b-9f8d-787eedadf0e0` +- mute → actionTypeId: `c9cf63b5-0582-441f-9508-1d45c468d9f4` +- unmute → actionTypeId: `53455722-50b5-4597-b8d9-195b6dc65e96` +- openValve → actionTypeId: `ae583f53-aced-439d-a7d6-82bd1e48477d` +- closeValve → actionTypeId: `9e46233b-d6d4-42f7-9cdc-a08cf72a5b49` + +--- + +### sdm630 + +- ThingClassId: `f37597bb-35fe-48f2-9617-343dd54c0903` + +#### States + +- connected (Bool) → stateTypeId: `8050bd0b-1dad-4a7e-b632-c71ead3c9f8b` +- voltagePhaseA (Double) → stateTypeId: `db018146-0441-4dc0-9834-6d43ebaf8311` +- voltagePhaseB (Double) → stateTypeId: `406f6d02-d5eb-49b3-87da-3247568e6054` +- voltagePhaseC (Double) → stateTypeId: `ace6294d-deaa-4d9a-af78-d64379bcb229` +- currentPhaseA (Double) → stateTypeId: `4baf1d08-5ffa-49cf-95ef-9527b0c6f081` +- currentPhaseB (Double) → stateTypeId: `99e47d06-0a6a-4bfd-b164-61ecb6ba2818` +- currentPhaseC (Double) → stateTypeId: `4a092a66-352d-4d60-90ab-6ac5f58b92fe` +- currentPower (Double) → stateTypeId: `c824e97b-a6d1-4030-9d7a-00af6fb8e1c3` +- currentPowerPhaseA (Double) → stateTypeId: `3982fb12-b179-40f7-9b27-36adb1cadd37` +- currentPowerPhaseB (Double) → stateTypeId: `2a231c58-b095-4037-8394-a730431e70b8` +- currentPowerPhaseC (Double) → stateTypeId: `ee8c4f0c-2b69-4210-9966-1553a592b06d` +- frequency (Double) → stateTypeId: `ab24f26c-dc15-4ec3-8d76-06a48285440b` +- totalEnergyConsumed (Double) → stateTypeId: `98d858a8-22e8-4262-b5c7-25bb027942ad` +- totalEnergyProduced (Double) → stateTypeId: `e469b3ff-a4c2-42da-af35-ccafaef214af` +- energyConsumedPhaseA (Double) → stateTypeId: `6ca06c81-fe75-4448-a22f-47c303421440` +- energyConsumedPhaseB (Double) → stateTypeId: `fa2b879b-2a81-4bc8-9577-98082c4d9330` +- energyConsumedPhaseC (Double) → stateTypeId: `4c084c9e-7a5d-42d1-96b2-a8a4b4a25713` +- energyProducedPhaseA (Double) → stateTypeId: `308fa88e-6054-4c79-b12a-be2d0a404ef6` +- energyProducedPhaseB (Double) → stateTypeId: `48ab6e61-dfb4-4f85-b5cc-9d89e53c6b39` +- energyProducedPhaseC (Double) → stateTypeId: `6b3ddf15-3d4b-4dc1-8e5a-84fbf90b49ff` + + +--- + +### shellyMotion + +- ThingClassId: `a82737bb-f2d6-442e-a468-5acc0a2e4cd7` + +#### States + +- isPresent (Bool) → stateTypeId: `45c0cc07-0e13-449c-86a7-ab65d5cdf637` +- lightIntensity (Double) → stateTypeId: `a1e12487-ebab-4993-a075-78275aac7b0d` +- vibration (Bool) → stateTypeId: `76438c2d-9742-4680-9139-d4b4e988cfd2` +- connected (Bool) → stateTypeId: `9ed997fa-1ec8-44d2-ac44-c99d4e259dae` +- signalStrength (Uint) → stateTypeId: `ecc61ce2-cb66-47ce-a65c-3b9e43ce6fdc` +- updateStatus (String) → stateTypeId: `a604a66c-3143-45ce-a6e3-17a339f428ab` +- currentVersion (String) → stateTypeId: `e2d98172-5833-454b-9b4b-04693c6b9232` +- availableVersion (String) → stateTypeId: `0c9e8da4-1b1c-4047-8e9d-c5c580bcf43f` +- batteryCritical (Bool) → stateTypeId: `1d03941e-9c41-446b-b698-f8dff335bf11` +- batteryLevel (Int) → stateTypeId: `f6d89aa6-7dba-4bb0-89cf-36d85208933f` + +#### Actions + +- performUpdate → actionTypeId: `17327674-f160-44e1-8a3d-fc2b6e1ee319` + +--- + +### dimmableLight + +- ThingClassId: `b89762f6-056f-442d-8edc-6ab877ae9a57` + +#### States + +- connected (Bool) → stateTypeId: `d6f7b579-08c2-4193-9eca-9b37a77e9a65` +- signalStrength (Uint) → stateTypeId: `9edb92b1-8a78-4628-9e2c-c0640860dbf8` +- power (Bool) → stateTypeId: `a0945256-b0ba-4767-b856-6c518eb9f6df` +- brightness (Int) → stateTypeId: `55a1b729-b865-4f05-a6b7-388a50e275f7` +- updateStatus (String) → stateTypeId: `0173bd05-ce4e-46df-a0dd-e565dd56db4a` +- currentVersion (String) → stateTypeId: `0c1388fb-fb1d-4b66-ac3c-4e0ba907b030` +- availableVersion (String) → stateTypeId: `6c202e40-f7f8-4472-8d76-a3845dca3439` +- updateProgress (Uint) → stateTypeId: `26d1277d-6868-4738-a2c2-f95b97da4117` + +#### Actions + +- power → actionTypeId: `a0945256-b0ba-4767-b856-6c518eb9f6df` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a0945256-b0ba-4767-b856-6c518eb9f6df", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `55a1b729-b865-4f05-a6b7-388a50e275f7` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "55a1b729-b865-4f05-a6b7-388a50e275f7", + "params": { + "brightness": "" + } + } + } + +- alert → actionTypeId: `c4ef7e85-b3cc-4c17-8347-e3e3c28771eb` +- performUpdate → actionTypeId: `7e644f8e-5f95-44db-9abc-a1d66986cee0` + +--- + +### kasaSwitch200 + +- ThingClassId: `d527e576-d65e-4ae6-ae43-c89b594fb4c1` + +#### States + +- connected (Bool) → stateTypeId: `8792b3d1-f83d-44c3-b649-249a935d1eb4` +- signalStrength (Uint) → stateTypeId: `6387c4e3-b0c1-4151-a3c9-925929c2d51e` +- power (Bool) → stateTypeId: `3b0daf6c-ba04-4ff1-a381-685c869665b1` + +#### Actions + +- power → actionTypeId: `3b0daf6c-ba04-4ff1-a381-685c869665b1` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "3b0daf6c-ba04-4ff1-a381-685c869665b1", + "params": { + "power": "" + } + } + } + + +--- + +### shellyEmChannel + +- ThingClassId: `67ccc046-c8b5-4584-8f7f-6fe0a0c6a860` + +#### States + +- connected (Bool) → stateTypeId: `d96d7505-f270-49ad-abb2-4f29ac11fb84` +- signalStrength (Uint) → stateTypeId: `d1928e72-73e6-4009-846e-149f80ad5899` +- totalEnergyConsumed (Double) → stateTypeId: `4ce53fa0-d6b7-4c1b-87d9-edcaeedb640e` +- totalEnergyProduced (Double) → stateTypeId: `7fe88e8f-a1c4-4e8d-a1de-9135b80bc7e3` +- currentPower (Double) → stateTypeId: `a85041e8-a19e-4695-8404-3e3a06b1e92a` +- currentPhaseA (Double) → stateTypeId: `1d457f50-0951-4ba5-8d8e-b79ea5a75535` +- voltagePhaseA (Double) → stateTypeId: `d6cb777f-c9af-46d8-845a-883ac05c206a` + + +--- + +### thermostat + +- ThingClassId: `ca9af6cf-2d15-4d54-ba07-3d2ce03445b8` + +#### States + +- targetTemperature (Double) → stateTypeId: `88ad3957-2912-4de1-b53d-b360565dd361` +- temperature (Double) → stateTypeId: `497af03a-a893-438c-aba2-1bf3ecfc66c5` +- heatingOn (Bool) → stateTypeId: `88d5dda1-b8f6-49f1-a55a-20415f9157b3` +- coolingOn (Bool) → stateTypeId: `c77a3d3f-46c7-4026-b9ab-02ab88077cc4` +- connected (Bool) → stateTypeId: `e9fb2b10-96da-4b70-afda-46e948399af8` +- signalStrength (Uint) → stateTypeId: `8f0512ab-ced2-4dcb-90fe-aaa532efd0dd` +- version (String) → stateTypeId: `c8bd12d2-b425-4422-9e0e-a65542a47b70` +- batteryLevel (Int) → stateTypeId: `3a733e99-850b-4c56-b058-d39850ef2fee` +- batteryCritical (Bool) → stateTypeId: `5cec4399-ba7c-4c78-8c30-c91040ad99cf` + +#### Actions + +- targetTemperature → actionTypeId: `88ad3957-2912-4de1-b53d-b360565dd361` + - Parameters: + - targetTemperature (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "88ad3957-2912-4de1-b53d-b360565dd361", + "params": { + "targetTemperature": "" + } + } + } + + +--- + +### pushNotification + +- ThingClassId: `56029c6d-777b-4889-9e17-29f813d34da4` + +#### Actions + +- notify → actionTypeId: `1378480f-6583-44e2-8fdd-22afe979a9a3` + - Parameters: + - title (String) + - body (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1378480f-6583-44e2-8fdd-22afe979a9a3", + "params": { + "title": "", + "body": "" + } + } + } + + +--- + +### powerSocket + +- ThingClassId: `e0ac647a-34a2-40ee-b8a3-8da6668f8a35` + +#### States + +- connected (Bool) → stateTypeId: `8ffdef7e-138b-4671-9309-ce81f2f9b818` +- signalStrength (Uint) → stateTypeId: `e4448f7c-719f-4ece-abb6-05b4e8b7a262` +- power (Bool) → stateTypeId: `b89f9bf8-59eb-4d04-8f93-eef4b8d88989` +- currentPower (Double) → stateTypeId: `97836b20-dc36-418f-b2af-74b71c6b27f3` +- totalEnergyConsumed (Double) → stateTypeId: `6ae69f17-7fcd-4cb3-a071-ff48ebb720ff` +- currentVersion (String) → stateTypeId: `1dc9223c-7d23-40b1-b46a-21eecd817ea4` +- availableVersion (String) → stateTypeId: `140b1a2c-d4da-48fc-bc82-80e2b17a1534` +- updateStatus (String) → stateTypeId: `07eece60-8b52-4a92-9f06-be2dc19145e5` +- updateProgress (Uint) → stateTypeId: `36bd5cea-a38a-4b9a-8ee3-272558788f70` + +#### Actions + +- power → actionTypeId: `b89f9bf8-59eb-4d04-8f93-eef4b8d88989` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b89f9bf8-59eb-4d04-8f93-eef4b8d88989", + "params": { + "power": "" + } + } + } + +- performUpdate → actionTypeId: `ecef7366-d925-4e44-8757-d39b546c1744` + +--- + +### shelly25 + +- ThingClassId: `465efb0d-da68-4177-a040-940c7f451e29` + +#### States + +- connected (Bool) → stateTypeId: `36a50e24-707e-4d5d-8eba-d2a73f626e2b` +- signalStrength (Uint) → stateTypeId: `35503b8a-1919-4df5-91cf-b7e381af654a` +- updateStatus (String) → stateTypeId: `0f03f1f3-5575-4375-9889-499a172c66c4` +- currentVersion (String) → stateTypeId: `69f6cb77-1775-4d94-8592-798fdc26a9fc` +- availableVersion (String) → stateTypeId: `eb8ce8b3-979f-4661-a0ed-d31d3e217e77` +- channel1 (Bool) → stateTypeId: `118d572c-cc12-4037-82d8-7d8f6fb4a364` +- channel2 (Bool) → stateTypeId: `7952aec0-cd27-4ef9-87a6-c499564bc1d4` + +#### Actions + +- channel1 → actionTypeId: `118d572c-cc12-4037-82d8-7d8f6fb4a364` + - Parameters: + - channel1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "118d572c-cc12-4037-82d8-7d8f6fb4a364", + "params": { + "channel1": "" + } + } + } + +- channel2 → actionTypeId: `7952aec0-cd27-4ef9-87a6-c499564bc1d4` + - Parameters: + - channel2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7952aec0-cd27-4ef9-87a6-c499564bc1d4", + "params": { + "channel2": "" + } + } + } + +- reboot → actionTypeId: `4085a6a0-746f-490d-9e38-897c24f866b6` +- performUpdate → actionTypeId: `14a24bc3-8215-430e-b4ff-e25ccee29691` + +--- + +### light + +- ThingClassId: `e569a3cc-6e79-4e24-af35-c5fa327a7314` + +#### States + +- brightness (Int) → stateTypeId: `1b51ce68-1f7e-4f06-b68d-bfca2d61b353` +- power (Bool) → stateTypeId: `654ddcdf-b0b7-4c38-a70d-878f0f3857a5` +- signalStrength (Uint) → stateTypeId: `cfaa5533-d26e-4545-9f44-6567c9d7888a` +- connected (Bool) → stateTypeId: `fb8dcd84-70ad-4f3e-97c4-93296608e33d` + +#### Actions + +- brightness → actionTypeId: `1b51ce68-1f7e-4f06-b68d-bfca2d61b353` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1b51ce68-1f7e-4f06-b68d-bfca2d61b353", + "params": { + "brightness": "" + } + } + } + +- power → actionTypeId: `654ddcdf-b0b7-4c38-a70d-878f0f3857a5` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "654ddcdf-b0b7-4c38-a70d-878f0f3857a5", + "params": { + "power": "" + } + } + } + + +--- + +### o2Sensor + +- ThingClassId: `a8cf20ec-132b-4f6f-b5ec-73dc2f873b43` + +#### States + +- o2saturation (Double) → stateTypeId: `a3ff7641-87d9-4b07-b8e5-e6aa92b90088` +- input (Double) → stateTypeId: `7e74fca7-84d0-4f3e-9f26-4232b7b9f507` + +#### Actions + +- o2saturation → actionTypeId: `a3ff7641-87d9-4b07-b8e5-e6aa92b90088` + - Parameters: + - o2saturation (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a3ff7641-87d9-4b07-b8e5-e6aa92b90088", + "params": { + "o2saturation": "" + } + } + } + +- input → actionTypeId: `7e74fca7-84d0-4f3e-9f26-4232b7b9f507` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7e74fca7-84d0-4f3e-9f26-4232b7b9f507", + "params": { + "input": "" + } + } + } + + +--- + +### powerSocket + +- ThingClassId: `695b54dc-99f8-4fb2-a773-57e268b7a193` + +#### States + +- connected (Bool) → stateTypeId: `7db10726-fec9-43d7-a807-b94295836a8a` +- signalStrength (Uint) → stateTypeId: `abe47f33-787c-4820-8bb3-6a5ccd1de24d` +- power (Bool) → stateTypeId: `a51dea82-6745-4855-8728-3f3cfee0f7f4` +- currentPower (Double) → stateTypeId: `be16e4f3-4a4d-4447-9d74-660f46b6d580` +- totalEnergyConsumed (Double) → stateTypeId: `628b37bc-28ed-4c4c-aa83-80383fd99316` + +#### Actions + +- power → actionTypeId: `a51dea82-6745-4855-8728-3f3cfee0f7f4` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a51dea82-6745-4855-8728-3f3cfee0f7f4", + "params": { + "power": "" + } + } + } + + +--- + +### xiaomiMotionSensor + +- ThingClassId: `73bfe746-4fc7-4a2a-a3c2-32dc44214170` + +#### States + +- connected (Bool) → stateTypeId: `d0239a0a-9320-45b6-8652-5e6af4f544d8` +- signalStrength (Uint) → stateTypeId: `84a2061d-da9c-4755-87b2-770dc92a2a53` +- version (String) → stateTypeId: `ad45268e-54f0-44fe-9a8f-25ccdca92452` +- isPresent (Bool) → stateTypeId: `9a30ff91-64cb-432c-8db7-cf6a751e8601` +- lastSeenTime (Int) → stateTypeId: `55229e22-e42b-4d38-af4b-fb668439d38a` + + +--- + +### onOffLight + +- ThingClassId: `7fbc3165-e618-4dc0-8255-8dac2cc08dfa` + +#### States + +- connected (Bool) → stateTypeId: `7548ac08-4ea1-4dcd-98b9-9d58bbc06ab7` +- signalStrength (Uint) → stateTypeId: `5857943e-ed90-4321-966e-b56eddaf2441` +- version (String) → stateTypeId: `f5b5e0b3-2c34-4ccc-baef-8e29b84e7a2b` +- power (Bool) → stateTypeId: `ae03155c-f17f-4d9f-bb40-157a8cb1f83c` + +#### Actions + +- power → actionTypeId: `ae03155c-f17f-4d9f-bb40-157a8cb1f83c` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ae03155c-f17f-4d9f-bb40-157a8cb1f83c", + "params": { + "power": "" + } + } + } + +- alert → actionTypeId: `9388290d-5db2-484a-a702-53a0d842d412` + +--- + +### coffeeMaker + +- ThingClassId: `f6b39ce2-8276-4db7-b2a3-4a04cafacbb9` + +#### States + +- connected (Bool) → stateTypeId: `796aa7d3-db32-4b6a-88b0-323813feceb3` +- closed (Bool) → stateTypeId: `5011efa7-9915-4ecc-b717-6ced369abcb7` +- operationState (String) → stateTypeId: `693fc8d2-d9a9-4109-b8c5-f3d22091500c` +- localControlState (Bool) → stateTypeId: `dc0fbd4b-364e-4856-a237-7d789a99f321` +- remoteStartAllowanceState (Bool) → stateTypeId: `598985c1-7c9a-4b04-aabd-f72e6dd8cab8` +- progress (Int) → stateTypeId: `a121f86a-ab69-4be9-bbe2-631e2210fee7` +- selectedProgram (String) → stateTypeId: `648e3a8e-74c4-41e8-bcbb-dd8b5757d375` +- strength (String) → stateTypeId: `714a12bc-63a5-4423-aad9-47d77f41ae47` +- fillQuantity (Int) → stateTypeId: `b3aea372-bc51-4e92-b92f-5b9613c20a9c` +- temperature (String) → stateTypeId: `29dc7edb-c34f-41da-9d2a-e46bda34885b` + +#### Actions + +- strength → actionTypeId: `714a12bc-63a5-4423-aad9-47d77f41ae47` + - Parameters: + - strength (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "714a12bc-63a5-4423-aad9-47d77f41ae47", + "params": { + "strength": "" + } + } + } + +- fillQuantity → actionTypeId: `b3aea372-bc51-4e92-b92f-5b9613c20a9c` + - Parameters: + - fillQuantity (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b3aea372-bc51-4e92-b92f-5b9613c20a9c", + "params": { + "fillQuantity": "" + } + } + } + +- temperature → actionTypeId: `29dc7edb-c34f-41da-9d2a-e46bda34885b` + - Parameters: + - temperature (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "29dc7edb-c34f-41da-9d2a-e46bda34885b", + "params": { + "temperature": "" + } + } + } + +- start → actionTypeId: `025f7cb5-83a7-40d3-9628-05eda18f5568` +- stop → actionTypeId: `12f5b09e-a23a-43ee-ba4b-8b0f34792496` + +--- + +### shellyRgbw2 + +- ThingClassId: `17f24cec-e6ed-4abd-9d42-60999f391dba` + +#### States + +- connected (Bool) → stateTypeId: `98b6e1ba-8d5c-4cb1-82a0-2d06c71cdba6` +- signalStrength (Uint) → stateTypeId: `194ecf76-c45f-4c36-8695-08a26ce065f3` +- power (Bool) → stateTypeId: `14abcd30-9db2-4065-ae81-501a55fbb145` +- brightness (Int) → stateTypeId: `3f74eb92-d95b-48c2-8ac6-29bea9f65ce3` +- colorTemperature (Int) → stateTypeId: `a32a457f-fdc0-46ce-9106-6f9d4f4a6b16` +- color (Color) → stateTypeId: `6ef7c686-350d-4069-9c41-9b90b3906748` +- whiteChannel (Uint) → stateTypeId: `8006331c-53ca-4386-8d5c-da62c175af01` +- currentPower (Double) → stateTypeId: `82ce0c4f-cb81-43c7-bc07-003f8a3cfbc8` +- updateStatus (String) → stateTypeId: `3d22110c-db53-4420-8e0f-314555484926` +- currentVersion (String) → stateTypeId: `8f2fd109-553a-48df-9b08-6a7fdcba46c1` +- availableVersion (String) → stateTypeId: `e0d58e73-8a36-4f36-901b-f6be6a84942d` + +#### Actions + +- power → actionTypeId: `14abcd30-9db2-4065-ae81-501a55fbb145` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "14abcd30-9db2-4065-ae81-501a55fbb145", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `3f74eb92-d95b-48c2-8ac6-29bea9f65ce3` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "3f74eb92-d95b-48c2-8ac6-29bea9f65ce3", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `a32a457f-fdc0-46ce-9106-6f9d4f4a6b16` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a32a457f-fdc0-46ce-9106-6f9d4f4a6b16", + "params": { + "colorTemperature": "" + } + } + } + +- color → actionTypeId: `6ef7c686-350d-4069-9c41-9b90b3906748` + - Parameters: + - color (Color) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "6ef7c686-350d-4069-9c41-9b90b3906748", + "params": { + "color": "" + } + } + } + +- whiteChannel → actionTypeId: `8006331c-53ca-4386-8d5c-da62c175af01` + - Parameters: + - whiteChannel (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8006331c-53ca-4386-8d5c-da62c175af01", + "params": { + "whiteChannel": "" + } + } + } + +- reboot → actionTypeId: `1390811d-dc71-4d89-a6e1-a808e03225f9` +- performUpdate → actionTypeId: `abca86b9-74b0-4a17-a8ee-89811b5981a0` + +--- + +### colorLight + +- ThingClassId: `8d157281-73c0-4d2c-96a0-572d26e9dd4f` + +#### States + +- connected (Bool) → stateTypeId: `bc56076a-cfa3-4f93-bbf5-2fe9b067cdc3` +- signalStrength (Uint) → stateTypeId: `62789a2c-c6e6-47b4-b022-29a2d183f690` +- version (String) → stateTypeId: `084b8268-4ae6-482d-b42b-67a57b5a7147` +- power (Bool) → stateTypeId: `16cfb549-5347-4dc9-b5de-e4028cb4dddd` +- brightness (Int) → stateTypeId: `7329b2eb-fb7e-4098-a551-c3ff24fc2962` +- colorTemperature (Int) → stateTypeId: `c2817667-afd0-434b-b0a3-e020d2c90082` +- color (Color) → stateTypeId: `51e8e6da-426c-4812-9c00-70f1356190dc` + +#### Actions + +- power → actionTypeId: `16cfb549-5347-4dc9-b5de-e4028cb4dddd` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "16cfb549-5347-4dc9-b5de-e4028cb4dddd", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `7329b2eb-fb7e-4098-a551-c3ff24fc2962` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7329b2eb-fb7e-4098-a551-c3ff24fc2962", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `c2817667-afd0-434b-b0a3-e020d2c90082` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c2817667-afd0-434b-b0a3-e020d2c90082", + "params": { + "colorTemperature": "" + } + } + } + +- color → actionTypeId: `51e8e6da-426c-4812-9c00-70f1356190dc` + - Parameters: + - color (Color) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "51e8e6da-426c-4812-9c00-70f1356190dc", + "params": { + "color": "" + } + } + } + +- alert → actionTypeId: `062fa97d-50b6-48ee-ab74-03701e4c7220` + +--- + +### shellyPlus25 + +- ThingClassId: `86b037f5-c7f8-4778-b6d1-2b11c4ba1027` + +#### States + +- connected (Bool) → stateTypeId: `8f4fe4d4-7036-4a1a-9960-091a4a7f6f02` +- signalStrength (Uint) → stateTypeId: `01158eee-3605-45c2-8b6d-2c0a69321c5b` +- updateStatus (String) → stateTypeId: `395a188b-c2e2-40d1-a5f2-9ed4a9ff558f` +- currentVersion (String) → stateTypeId: `c1f5d20a-3b06-4405-afca-20dfd41e3a34` +- availableVersion (String) → stateTypeId: `32134deb-8e37-4d65-ae10-aad0cb44ff7b` +- channel1 (Bool) → stateTypeId: `bf969a1f-aa8a-40aa-8e50-af37b8b0ffe6` +- channel2 (Bool) → stateTypeId: `43b41b49-def1-469b-b993-788647dc8839` + +#### Actions + +- channel1 → actionTypeId: `bf969a1f-aa8a-40aa-8e50-af37b8b0ffe6` + - Parameters: + - channel1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bf969a1f-aa8a-40aa-8e50-af37b8b0ffe6", + "params": { + "channel1": "" + } + } + } + +- channel2 → actionTypeId: `43b41b49-def1-469b-b993-788647dc8839` + - Parameters: + - channel2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "43b41b49-def1-469b-b993-788647dc8839", + "params": { + "channel2": "" + } + } + } + +- reboot → actionTypeId: `7714490b-117d-4d25-a695-9e151997f128` +- performUpdate → actionTypeId: `9d5e04b8-cac4-49ce-9e32-efc3a06beb4b` + +--- + +### sonosConnection + +- ThingClassId: `22df416d-7732-44f1-b6b9-e41296211178` + +#### States + +- connected (Bool) → stateTypeId: `5aa4360c-61de-47d0-a72e-a19d57712e1c` +- loggedIn (Bool) → stateTypeId: `48b5c1bf-7df0-45d0-9ba3-290fc3acddc3` +- userDisplayName (String) → stateTypeId: `fb993eab-f1b5-44dd-9b99-041faec5a3b9` + + +--- + +### remoteControl + +- ThingClassId: `b909dc16-61fa-4c5f-ad7d-195327f78f8d` + +#### States + +- batteryCritical (Bool) → stateTypeId: `445e279e-31e7-4a80-b382-62417ad61414` +- batteryLevel (Int) → stateTypeId: `812daed6-1630-4d01-a039-3977edc965c0` +- connected (Bool) → stateTypeId: `5b563fa9-1140-4f1f-8b87-4c1a287ccad5` +- signalStrength (Uint) → stateTypeId: `599ca06d-a532-4633-8b79-30a50325e4a2` +- version (String) → stateTypeId: `87ac4e00-bf34-4a15-9cc3-a98c5099c1eb` + + +--- + +### wallSwitch + +- ThingClassId: `e967027f-f8fc-410c-8b48-6ac4c42e2777` + +#### States + +- connected (Bool) → stateTypeId: `b51071af-1290-41f1-b2eb-e84527342ade` +- batteryLevel (Int) → stateTypeId: `b025cab6-d128-43eb-ba63-b16861d6ab10` +- batteryCritical (Bool) → stateTypeId: `7fcf84e4-5638-46ce-9a7c-85b8bd466b38` + + +--- + +### tahoma + +- ThingClassId: `fedd72b8-547d-4e4f-b73e-71344a8ba0c1` + +#### States + +- connected (Bool) → stateTypeId: `10ebf650-a93a-4ee3-945b-fba10d4e35a5` +- loggedIn (Bool) → stateTypeId: `97fefa85-db79-4efd-8d83-4a15d72996e1` +- userDisplayName (String) → stateTypeId: `75609987-be60-4932-94f6-ead791b5fa58` + + +--- + +### netPwrCtlHut + +- ThingClassId: `bc9a90e0-b320-46f1-8d7b-2d24f40af5ea` + +#### States + +- connected (Bool) → stateTypeId: `3b30c586-4756-4903-8405-b00bc9d34685` +- temperature (Double) → stateTypeId: `7689239c-e6c3-48cc-ae90-bd1cad44b631` +- humidity (Double) → stateTypeId: `6e38c9f7-cdd7-4909-9312-2047812d1883` +- lightIntensity (Double) → stateTypeId: `60792bc4-fc67-47f6-8c3f-45717a072d59` + + +--- + +### shellyDimmer + +- ThingClassId: `3a1d6fc1-c623-4b45-9c81-1573fcc15f99` + +#### States + +- connected (Bool) → stateTypeId: `49ff0891-1798-459f-a97c-f1cc4e643a46` +- signalStrength (Uint) → stateTypeId: `a6855b46-7da8-4160-b698-7707600581b5` +- power (Bool) → stateTypeId: `e4a6ac87-31fb-4516-9cf3-f135621e902c` +- brightness (Int) → stateTypeId: `f41c93ac-6911-45fc-9221-7dd26bf65fd0` +- currentPower (Double) → stateTypeId: `b3336ca6-1577-4230-8708-98875148606e` +- updateStatus (String) → stateTypeId: `8d3b3d63-86f1-46cb-92ef-d27c0d9d0a4e` +- currentVersion (String) → stateTypeId: `2fac7af0-1aa0-4e8d-b3fb-584b49647887` +- availableVersion (String) → stateTypeId: `e6418140-db00-4f9b-a7fc-bf4a56a3a8a7` + +#### Actions + +- power → actionTypeId: `e4a6ac87-31fb-4516-9cf3-f135621e902c` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e4a6ac87-31fb-4516-9cf3-f135621e902c", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `f41c93ac-6911-45fc-9221-7dd26bf65fd0` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f41c93ac-6911-45fc-9221-7dd26bf65fd0", + "params": { + "brightness": "" + } + } + } + +- reboot → actionTypeId: `dca1d1bb-b377-41b8-ac26-579060448fd7` +- performUpdate → actionTypeId: `893031b8-9abd-4a83-8da4-ea57acb621ad` + +--- + +### venetianBlind + +- ThingClassId: `e6b96ced-8d50-45da-91c8-792d364d2795` + +#### States + +- openingOutput (Bool) → stateTypeId: `6041dacf-5303-4dc0-ba3c-7ecaa438f2dd` +- closingOutput (Bool) → stateTypeId: `84dd2fa1-85fe-47f3-9e32-e6083432d39c` +- status (String) → stateTypeId: `6fb7826e-b6d8-42f8-b712-719496046436` +- moving (Bool) → stateTypeId: `6234c07e-4200-4f2c-8cbd-bff24c38c243` +- percentage (Int) → stateTypeId: `33dc8019-336d-4d50-8d60-dff8508338ca` +- angle (Int) → stateTypeId: `fcb700c4-5da8-4385-85b0-6616e807974e` + +#### Actions + +- openingOutput → actionTypeId: `6041dacf-5303-4dc0-ba3c-7ecaa438f2dd` + - Parameters: + - openingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "6041dacf-5303-4dc0-ba3c-7ecaa438f2dd", + "params": { + "openingOutput": "" + } + } + } + +- closingOutput → actionTypeId: `84dd2fa1-85fe-47f3-9e32-e6083432d39c` + - Parameters: + - closingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "84dd2fa1-85fe-47f3-9e32-e6083432d39c", + "params": { + "closingOutput": "" + } + } + } + +- percentage → actionTypeId: `33dc8019-336d-4d50-8d60-dff8508338ca` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "33dc8019-336d-4d50-8d60-dff8508338ca", + "params": { + "percentage": "" + } + } + } + +- angle → actionTypeId: `fcb700c4-5da8-4385-85b0-6616e807974e` + - Parameters: + - angle (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "fcb700c4-5da8-4385-85b0-6616e807974e", + "params": { + "angle": "" + } + } + } + +- open → actionTypeId: `3e728e50-3d45-4035-b215-1e604cf3159b` +- stop → actionTypeId: `6e3eeb5d-d7ed-4175-9795-e76451e0a00b` +- close → actionTypeId: `1c71f050-f6cb-4929-9c9d-7c262f77c143` + +--- + +### shutter + +- ThingClassId: `7917c2e7-d7d2-4c47-a38d-41f7dd7693d9` + +#### States + +- openingOutput (Bool) → stateTypeId: `cc547728-b309-4695-b355-49748ef2521c` +- closingOutput (Bool) → stateTypeId: `1c35df0e-4c41-455f-893a-0145377952a0` +- status (String) → stateTypeId: `6d6e72dc-4d2b-4ec1-82c2-54405a682711` + +#### Actions + +- openingOutput → actionTypeId: `cc547728-b309-4695-b355-49748ef2521c` + - Parameters: + - openingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "cc547728-b309-4695-b355-49748ef2521c", + "params": { + "openingOutput": "" + } + } + } + +- closingOutput → actionTypeId: `1c35df0e-4c41-455f-893a-0145377952a0` + - Parameters: + - closingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1c35df0e-4c41-455f-893a-0145377952a0", + "params": { + "closingOutput": "" + } + } + } + +- open → actionTypeId: `9deb662d-2378-4345-a898-8742d41e43c1` +- stop → actionTypeId: `db5f3332-1f4e-4f9e-84d2-93c5d7de315c` +- close → actionTypeId: `cf5303f1-67c7-4cef-b11c-eb9de6fc8a87` + +--- + +### shellyAddonTempSensor + +- ThingClassId: `dffcc66b-bb93-4de0-9ad4-0b2ca0fa813a` + +#### States + +- connected (Bool) → stateTypeId: `982846ff-e045-4e4d-8959-b5ea65b83082` +- signalStrength (Uint) → stateTypeId: `5e9ed1dd-a1f7-4755-ac6f-30013580d363` +- temperature (Double) → stateTypeId: `b0062fc6-8fa1-4754-904a-c18614114998` + + +--- + +### extendedBlind + +- ThingClassId: `40aa9f3c-a23c-4f7f-8786-fcf3554f3e19` + +#### States + +- openingOutput (Bool) → stateTypeId: `e559f077-e904-4bbc-8ec3-344b814d2eab` +- closingOutput (Bool) → stateTypeId: `1a4a5839-a30d-4239-a124-63bfdc74a8f6` +- status (String) → stateTypeId: `c2354d7e-198a-43ae-aa5f-c6710010c7e1` +- moving (Bool) → stateTypeId: `941d1e1f-8dd7-4493-812f-6cefefd88c2e` +- percentage (Int) → stateTypeId: `181df603-d45f-4d3d-a358-97aa3e4ac0bd` + +#### Actions + +- openingOutput → actionTypeId: `e559f077-e904-4bbc-8ec3-344b814d2eab` + - Parameters: + - openingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e559f077-e904-4bbc-8ec3-344b814d2eab", + "params": { + "openingOutput": "" + } + } + } + +- closingOutput → actionTypeId: `1a4a5839-a30d-4239-a124-63bfdc74a8f6` + - Parameters: + - closingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1a4a5839-a30d-4239-a124-63bfdc74a8f6", + "params": { + "closingOutput": "" + } + } + } + +- percentage → actionTypeId: `181df603-d45f-4d3d-a358-97aa3e4ac0bd` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "181df603-d45f-4d3d-a358-97aa3e4ac0bd", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `5a7599fa-8351-4ed6-9b98-fa2f3be54304` +- stop → actionTypeId: `ab67e4bf-c7b6-489b-9b49-3e0a1c7d33ca` +- close → actionTypeId: `97d6351d-7440-47f3-bdba-a31bb15368ac` + +--- + +### dimmableLight + +- ThingClassId: `fdfbd11f-bd99-4876-8254-7f91f96ca4fc` + +#### States + +- power (Bool) → stateTypeId: `74535080-b6d9-41db-8e35-ef90e9042b75` +- brightness (Int) → stateTypeId: `88786787-8025-4967-b7a6-f3b670216ac0` + +#### Actions + +- power → actionTypeId: `74535080-b6d9-41db-8e35-ef90e9042b75` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "74535080-b6d9-41db-8e35-ef90e9042b75", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `88786787-8025-4967-b7a6-f3b670216ac0` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "88786787-8025-4967-b7a6-f3b670216ac0", + "params": { + "brightness": "" + } + } + } + + +--- + +### shellyI3 + +- ThingClassId: `a4557bcc-bdae-4178-b774-5881a8ae490a` + +#### States + +- connected (Bool) → stateTypeId: `9b17b10d-07ee-4a3d-813f-ef37e79e7241` +- signalStrength (Uint) → stateTypeId: `54fc5565-5d40-4847-b59e-95bfd8845381` +- input1 (Bool) → stateTypeId: `61e98cc9-4449-4fb2-818e-692303244ce2` +- input2 (Bool) → stateTypeId: `04497ff2-a231-4d3d-adeb-66275a3b128b` +- input3 (Bool) → stateTypeId: `5895fc2d-19a4-40c2-8522-7c4462e55a3e` +- updateStatus (String) → stateTypeId: `889d7f2c-488c-4c91-905d-8669125d5c8b` +- currentVersion (String) → stateTypeId: `33e7d186-7c6b-4c4e-89c3-80362ef76615` +- availableVersion (String) → stateTypeId: `c3ff6d31-7301-412f-9aff-72ac36ba83c9` + +#### Actions + +- reboot → actionTypeId: `162e7791-6890-4075-8e57-a4c15b9359bb` +- performUpdate → actionTypeId: `1c677ecb-c54e-4c95-a3f7-e68fabeeda08` + +--- + +### colorTemperatureLight + +- ThingClassId: `34ee15f7-8e94-4927-bfd2-7123aac0b1be` + +#### States + +- power (Bool) → stateTypeId: `316c8852-6e53-4404-891a-83c1f0fa0c84` +- brightness (Int) → stateTypeId: `76b54a6d-fae9-4cb6-8603-a3a615e153f9` +- colorTemperature (Int) → stateTypeId: `3a2459ed-af20-4ea0-8bd7-97b59be594f7` + +#### Actions + +- power → actionTypeId: `316c8852-6e53-4404-891a-83c1f0fa0c84` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "316c8852-6e53-4404-891a-83c1f0fa0c84", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `76b54a6d-fae9-4cb6-8603-a3a615e153f9` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "76b54a6d-fae9-4cb6-8603-a3a615e153f9", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `3a2459ed-af20-4ea0-8bd7-97b59be594f7` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "3a2459ed-af20-4ea0-8bd7-97b59be594f7", + "params": { + "colorTemperature": "" + } + } + } + + +--- + +### tap + +- ThingClassId: `2b8c1fb8-67ee-42e9-947b-16e0a09f0d4e` + +#### States + +- connected (Bool) → stateTypeId: `5e21b032-1230-4e93-8543-0c4773da17d3` + + +--- + +### shellyPlusPlug + +- ThingClassId: `2c470ea4-6ef2-4aa2-b2f3-b6d8750ac577` + +#### States + +- power (Bool) → stateTypeId: `87a60ee4-a6b8-463a-a4bc-c7c5e412239f` +- connected (Bool) → stateTypeId: `ee89944e-eab9-4554-9c7b-0b433f3cf287` +- signalStrength (Uint) → stateTypeId: `e244927d-0003-4107-83e1-3fad923cf738` +- updateStatus (String) → stateTypeId: `8e16b8c8-6981-4eb9-88fe-a863f263f5ba` +- currentVersion (String) → stateTypeId: `78174fac-2cec-4f1b-94c4-d413dd1a54ba` +- availableVersion (String) → stateTypeId: `89da9eb8-a01f-4bc2-9d96-d2d6305a08d7` +- totalEnergyConsumed (Double) → stateTypeId: `5493ecc3-8596-436b-9334-0fe4154656ec` +- currentPower (Double) → stateTypeId: `1dcc910d-ab0e-4c31-b6fa-8105324e416b` + +#### Actions + +- power → actionTypeId: `87a60ee4-a6b8-463a-a4bc-c7c5e412239f` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "87a60ee4-a6b8-463a-a4bc-c7c5e412239f", + "params": { + "power": "" + } + } + } + +- reboot → actionTypeId: `e4a997c5-072f-4212-9ccc-7bfebd20b333` +- performUpdate → actionTypeId: `ae862b2d-0bad-4c37-9d7f-b1fca93f00a0` + +--- + +### awning + +- ThingClassId: `9e69585f-90ba-44e4-ad90-5b4bffbe345a` + +#### States + +- openingOutput (Bool) → stateTypeId: `4bb951a4-ea23-4cf0-9269-41d2c4eaf5a4` +- closingOutput (Bool) → stateTypeId: `59bfd575-709f-4e43-9726-de26e6d4ca8b` +- status (String) → stateTypeId: `ff6f2565-2a2e-4d34-b10f-d3f73b676399` + +#### Actions + +- openingOutput → actionTypeId: `4bb951a4-ea23-4cf0-9269-41d2c4eaf5a4` + - Parameters: + - openingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4bb951a4-ea23-4cf0-9269-41d2c4eaf5a4", + "params": { + "openingOutput": "" + } + } + } + +- closingOutput → actionTypeId: `59bfd575-709f-4e43-9726-de26e6d4ca8b` + - Parameters: + - closingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "59bfd575-709f-4e43-9726-de26e6d4ca8b", + "params": { + "closingOutput": "" + } + } + } + +- open → actionTypeId: `979e9c51-5a93-4635-85e3-01874306b229` +- stop → actionTypeId: `555cafe4-bd12-42c6-bab1-8cd59af6468e` +- close → actionTypeId: `53b5ba77-9a34-4cd6-ad24-fb01fc465f98` + +--- + +### lumiVibrationSensor + +- ThingClassId: `775be45e-08d8-4ae8-bc95-5721a5317856` + +#### States + +- connected (Bool) → stateTypeId: `12970c44-5c59-4c6b-a244-6bc413d32c66` +- signalStrength (Uint) → stateTypeId: `eb8bbd63-1f1c-4499-8385-06fbe8e301db` +- version (String) → stateTypeId: `8a4aceef-c8ee-487a-946c-20f26fc2d5ed` +- angleX (Double) → stateTypeId: `8ef735ef-332a-40f5-aa57-0408c5d05d46` +- angleY (Double) → stateTypeId: `0d398c75-9adf-4835-883b-e578e124af98` +- angleZ (Double) → stateTypeId: `7ead841c-5a20-456b-85ed-983bda234718` +- angleAbsoluteX (Double) → stateTypeId: `10be3741-5bfc-4173-bf4f-e95af0e60d03` +- angleAbsoluteY (Double) → stateTypeId: `97bf3f80-f70e-4bb1-b4e0-546f153dd3bc` + + +--- + +### dimmableBulb + +- ThingClassId: `a5b02af8-7c97-4a78-9c78-bafee7407b5e` + +#### States + +- connected (Bool) → stateTypeId: `d33f98ef-5e0f-464c-afed-88b95cc701cd` +- power (Bool) → stateTypeId: `9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0` +- brightness (Int) → stateTypeId: `a0a1bdcc-2761-4d90-85d1-5ce887546611` +- colorTemperature (Int) → stateTypeId: `95797dee-b836-4047-98d5-afbbce4f8c42` + +#### Actions + +- power → actionTypeId: `9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9e1344ea-cd05-4dd8-8948-8d2f5e00e1b0", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `a0a1bdcc-2761-4d90-85d1-5ce887546611` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a0a1bdcc-2761-4d90-85d1-5ce887546611", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `95797dee-b836-4047-98d5-afbbce4f8c42` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "95797dee-b836-4047-98d5-afbbce4f8c42", + "params": { + "colorTemperature": "" + } + } + } + + +--- + +### shortcutButton + +- ThingClassId: `7a81dd57-0b79-4735-840d-69775d937095` + +#### States + +- connected (Bool) → stateTypeId: `29cb833d-125f-45b0-add4-da69f22d8dcc` +- signalStrength (Uint) → stateTypeId: `24c227cd-aaeb-440e-b45d-0711074ef633` +- batteryLevel (Int) → stateTypeId: `164e8d24-e4b7-4d88-a5d4-5649dfaf0180` +- batteryCritical (Bool) → stateTypeId: `13a68aa5-4118-4dc9-b55e-e715bc423e08` +- currentVersion (String) → stateTypeId: `065f348a-54f2-4203-9a6c-b747e92d169a` +- updateStatus (String) → stateTypeId: `a1254e8e-ac96-40b4-a2dd-dcdbbb3653a8` +- availableVersion (String) → stateTypeId: `352aa728-61e4-4d04-9bb9-9c438ccfb531` +- updateProgress (Uint) → stateTypeId: `af65f485-117f-4a26-911c-ece1d6e07ce9` + +#### Actions + +- performUpdate → actionTypeId: `83b33b50-a8fd-4234-be89-7b6e7da83b06` + +--- + +### outdoor + +- ThingClassId: `6cc01d62-7317-4ec4-8ac4-a4cab762c179` + +#### States + +- updateTime (Int) → stateTypeId: `154aad5c-4998-43c2-b9ee-0b997eb6dd69` +- temperature (Double) → stateTypeId: `f98776bd-887e-4b01-a87f-3d8224180563` +- temperatureMin (Double) → stateTypeId: `b71e0c8b-3c94-421e-830e-dab97b6c104e` +- temperatureMax (Double) → stateTypeId: `aae071dc-70d5-4a6a-8daa-3dca0d150bd7` +- humidity (Double) → stateTypeId: `7ba6ddeb-5142-4b87-9729-487fcda394df` +- signalStrength (Uint) → stateTypeId: `0faa3d08-9004-46fb-a5aa-a59b75e454cc` +- connected (Bool) → stateTypeId: `21d7f2b7-e45b-4986-b3da-d6e8c0421bfc` +- batteryLevel (Int) → stateTypeId: `15d8fae1-ba47-42e1-994d-530e8017c965` +- batteryCritical (Bool) → stateTypeId: `f8aeb144-014d-4ccb-81db-64ffc70f1c97` + + +--- + +### modbusBatteryInverter + +- ThingClassId: `06bed8fd-cadb-4cef-8440-7806fb0165e6` + +#### States + +- connected (Bool) → stateTypeId: `9c4999a1-304d-4724-99cd-eb0cd27590ef` +- batteryLevel (Int) → stateTypeId: `fe5ca68e-ddc2-45e7-aac2-b0e67ac40f87` +- batteryCritical (Bool) → stateTypeId: `56f18b28-ed88-4c1a-a297-a5cad109b055` +- currentPower (Double) → stateTypeId: `e1a91af1-8d1a-4564-9ade-b5488d63b90d` +- capacity (Double) → stateTypeId: `13cdb994-dd9e-49ac-a347-d2ab9aef5b45` +- chargingState (String) → stateTypeId: `a313b416-5ded-43c9-b1a1-a9af50492d0b` +- firmwareVersion (String) → stateTypeId: `952b3d30-1c09-4b0e-b303-56c89d3fa108` + + +--- + +### colorTemperatureLight + +- ThingClassId: `35f749f7-b60a-4922-bd25-1bdd2eddcbe3` + +#### States + +- connected (Bool) → stateTypeId: `38f3ddea-ceb0-47ae-bbd8-e70b5a89b1bf` +- power (Bool) → stateTypeId: `4e579f6a-e4b3-4876-804a-9fcc066f90f9` +- colorTemperature (Int) → stateTypeId: `fee57738-45c7-48fe-a06b-1397376361f0` +- brightness (Int) → stateTypeId: `bdf6f831-b448-4ff6-9f85-12e26b4e5534` + +#### Actions + +- power → actionTypeId: `4e579f6a-e4b3-4876-804a-9fcc066f90f9` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4e579f6a-e4b3-4876-804a-9fcc066f90f9", + "params": { + "power": "" + } + } + } + +- colorTemperature → actionTypeId: `fee57738-45c7-48fe-a06b-1397376361f0` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "fee57738-45c7-48fe-a06b-1397376361f0", + "params": { + "colorTemperature": "" + } + } + } + +- brightness → actionTypeId: `bdf6f831-b448-4ff6-9f85-12e26b4e5534` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bdf6f831-b448-4ff6-9f85-12e26b4e5534", + "params": { + "brightness": "" + } + } + } + +- alert → actionTypeId: `8818e8b9-14ed-4344-96fb-c852abc85921` + - Parameters: + - alert (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8818e8b9-14ed-4344-96fb-c852abc85921", + "params": { + "alert": "" + } + } + } + + +--- + +### smartButton + +- ThingClassId: `edfa223b-aade-4369-a4e2-77b99989f49d` + +#### States + +- batteryLevel (Int) → stateTypeId: `2837540f-a97b-4a92-9e17-900db38577e4` +- batteryCritical (Bool) → stateTypeId: `3d79d36e-008e-41c8-9bb5-28db235b93ce` +- connected (Bool) → stateTypeId: `4748fc45-5ffd-4472-97a2-9fef256937db` +- signalStrength (Uint) → stateTypeId: `0eb19a1e-04d1-44ce-9554-f70c47a4f48a` +- updateStatus (String) → stateTypeId: `2aa27a75-e336-4599-b95b-55175bad4acd` +- currentVersion (String) → stateTypeId: `7c1c798d-334a-4132-8677-f8a49eab0804` +- availableVersion (String) → stateTypeId: `f475fbca-d17b-4751-81cd-74f9da657553` +- updateProgress (Uint) → stateTypeId: `634434d6-9ccd-4e8b-992d-d8b062b47ed7` + +#### Actions + +- performUpdate → actionTypeId: `43a72851-7c66-49e4-841b-72ca05eae733` + +--- + +### doorBird + +- ThingClassId: `0485eb61-2a22-42ba-9dd2-a5961485bf08` + +#### States + +- connected (Bool) → stateTypeId: `186c270b-923c-46e4-a7da-33e45427cdbb` +- isPresent (Bool) → stateTypeId: `0f5eb200-6c0d-45c5-9156-3060fd66d332` +- lastSeenTime (Int) → stateTypeId: `295c9700-b598-4681-898f-d63e2889cedf` + +#### Actions + +- openDoor → actionTypeId: `b6c3377b-91de-411a-9d48-8b509c39d67c` + - Parameters: + - number (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b6c3377b-91de-411a-9d48-8b509c39d67c", + "params": { + "number": "" + } + } + } + +- lightOn → actionTypeId: `3a6cfc5d-804c-4d21-91b5-999913d4f1a5` +- restart → actionTypeId: `e874242e-5acb-4d98-94c7-0a70db65150c` + +--- + +### socket + +- ThingClassId: `4e7261af-a27b-4446-8346-914ea59f7547` + +#### States + +- power (Bool) → stateTypeId: `018038d7-1d02-4b17-8fe3-babca044b087` + +#### Actions + +- power → actionTypeId: `018038d7-1d02-4b17-8fe3-babca044b087` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "018038d7-1d02-4b17-8fe3-babca044b087", + "params": { + "power": "" + } + } + } + + +--- + +### shelly1l + +- ThingClassId: `20754114-1591-48b5-af2f-8c9966adb7c4` + +#### States + +- power (Bool) → stateTypeId: `94276bb9-ef68-47ab-8e74-34ebe54b411f` +- connected (Bool) → stateTypeId: `2a333f45-2bba-4643-b973-1bb47d56306a` +- signalStrength (Uint) → stateTypeId: `cce7906d-fdef-4804-b118-b5abefa6c6ed` +- updateStatus (String) → stateTypeId: `0e47815d-0084-4a30-957a-f73ed100bed5` +- currentVersion (String) → stateTypeId: `2303ffb7-8de4-4993-b3ac-95e4c035b790` +- availableVersion (String) → stateTypeId: `5f357a69-6096-4f31-9b5b-b2d5478739da` +- totalEnergyConsumed (Double) → stateTypeId: `0f879e7b-2124-4d98-9828-e5bbd1b344ce` +- currentPower (Double) → stateTypeId: `194f4f1b-86a7-4c04-abf0-2459ae7e2821` + +#### Actions + +- power → actionTypeId: `94276bb9-ef68-47ab-8e74-34ebe54b411f` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "94276bb9-ef68-47ab-8e74-34ebe54b411f", + "params": { + "power": "" + } + } + } + +- reboot → actionTypeId: `5a05c09a-c6a0-4141-aeeb-86afdb49ffaf` +- performUpdate → actionTypeId: `fa6a52fa-6a57-4d65-8c41-1e61b545dd9b` + +--- + +### lumiWaterSensor + +- ThingClassId: `e8e18bbe-27bb-4fd7-98fc-f5cef3b5f213` + +#### States + +- connected (Bool) → stateTypeId: `03fc0e4d-dcd9-41dc-8aac-dbe735f11ef7` +- signalStrength (Uint) → stateTypeId: `b3bba018-b9d0-47a8-a2cf-d8d2d6fcecce` +- version (String) → stateTypeId: `bae1014f-67f5-4dcc-b36f-e15eb43afd6e` +- waterDetected (Bool) → stateTypeId: `e43532a7-cbee-446e-9e4a-aff88026ad1a` +- batteryCritical (Bool) → stateTypeId: `72aa617c-88cc-4992-a1a2-400b5e19106e` + + +--- + +### sonoff_dimmer + +- ThingClassId: `4fb65caa-7f84-4496-91f6-1cd35574cc2e` + +#### States + +- connected (Bool) → stateTypeId: `1078dd25-b5bd-4005-8c1f-005ddca7ea21` +- signalStrength (Uint) → stateTypeId: `662d99de-bfce-4cf0-8029-108e9911866c` +- power (Bool) → stateTypeId: `c8ec62d4-024b-4770-b893-6288b64f0dfe` +- brightness (Int) → stateTypeId: `5cd8d0df-1188-4da1-9a87-bff991d3b2af` + +#### Actions + +- power → actionTypeId: `c8ec62d4-024b-4770-b893-6288b64f0dfe` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c8ec62d4-024b-4770-b893-6288b64f0dfe", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `5cd8d0df-1188-4da1-9a87-bff991d3b2af` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5cd8d0df-1188-4da1-9a87-bff991d3b2af", + "params": { + "brightness": "" + } + } + } + + +--- + +### lightSensor + +- ThingClassId: `2c35236c-bc5c-4736-beb6-d8dfd0c6bc40` + +#### States + +- lightIntensity (Double) → stateTypeId: `241629dd-15e4-4698-bb56-f4a16b82d6fa` +- batteryCritical (Bool) → stateTypeId: `235a87fd-524c-4177-a707-7ec004d94f54` +- connected (Bool) → stateTypeId: `1415b7dc-8339-4022-99fa-e1b4c42ef591` +- signalStrength (Uint) → stateTypeId: `2ec0dc23-d665-469d-b7b1-2205a6056783` +- version (String) → stateTypeId: `c71e2426-69f3-45d2-acde-4870f010071e` + + +--- + +### presenceSensor + +- ThingClassId: `339a0c54-4086-404f-8d36-bcf20621b785` + +#### States + +- isPresent (Bool) → stateTypeId: `22c1eac6-9bb5-4cc1-ac0d-e3e1499edd3c` +- lastSeenTime (Int) → stateTypeId: `be4842cb-140c-425f-9630-8bb19fdb943e` + +#### Actions + +- isPresent → actionTypeId: `22c1eac6-9bb5-4cc1-ac0d-e3e1499edd3c` + - Parameters: + - isPresent (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "22c1eac6-9bb5-4cc1-ac0d-e3e1499edd3c", + "params": { + "isPresent": "" + } + } + } + + +--- + +### shellyRoller + +- ThingClassId: `d681a4cb-481a-4469-a49a-e6bbb11eb9c9` + +#### States + +- connected (Bool) → stateTypeId: `d446719d-628e-477d-882c-a84210c85869` +- signalStrength (Uint) → stateTypeId: `f46c52ce-58dd-4d07-bb69-e8b8719c41bc` +- totalEnergyConsumed (Double) → stateTypeId: `a7d88654-7503-474d-9a7c-02150d61a6dc` +- currentPower (Double) → stateTypeId: `0d7cb1cf-3fff-4d0b-96c2-c02e9a92af57` +- moving (Bool) → stateTypeId: `2729d4e0-c38c-47b8-a0e8-26959090fe74` +- percentage (Int) → stateTypeId: `86270b8b-bce4-4d8a-9bc9-d72af36b991c` + +#### Actions + +- percentage → actionTypeId: `86270b8b-bce4-4d8a-9bc9-d72af36b991c` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "86270b8b-bce4-4d8a-9bc9-d72af36b991c", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `b96a8f85-c39e-499b-abbd-40b18788e907` +- close → actionTypeId: `87eb0290-615e-4c98-9ec8-a21104fcf05d` +- stop → actionTypeId: `2266303c-df0c-4eae-b15e-6a86e73c9699` +- calibrate → actionTypeId: `4e2d8a7b-821e-4ee8-9f9b-f774d631845f` + +--- + +### gwa1521Actuator + +- ThingClassId: `6bce244f-b93c-474e-b8eb-65e44ad96329` + +#### States + +- connected (Bool) → stateTypeId: `5d23d473-f063-49dd-b675-d31741d6976b` +- signalStrength (Uint) → stateTypeId: `3e3dba24-37d5-4c4b-99b1-b33ad612a817` +- relay (Bool) → stateTypeId: `3d4993c4-9142-409a-8389-3377eeae0ad6` + +#### Actions + +- relay → actionTypeId: `3d4993c4-9142-409a-8389-3377eeae0ad6` + - Parameters: + - relay (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "3d4993c4-9142-409a-8389-3377eeae0ad6", + "params": { + "relay": "" + } + } + } + + +--- + +### colorTemperatureLight + +- ThingClassId: `498815c1-a6a3-48e9-9c9b-bff974694b26` + +#### States + +- connected (Bool) → stateTypeId: `dd4eb1fe-4ddd-42fa-97bf-df690728c866` +- signalStrength (Uint) → stateTypeId: `45e5b606-1e4d-42b8-9ee1-0442751247ef` +- version (String) → stateTypeId: `477a1531-5f87-4f21-9b32-01161be93cd2` +- power (Bool) → stateTypeId: `a8c56366-5b2d-4f4b-b910-38a87851c484` +- brightness (Int) → stateTypeId: `b72177f9-b673-49b5-864a-345936e5c821` +- colorTemperature (Int) → stateTypeId: `69e94f88-a664-4bb9-ba04-2c3ea6cd7569` + +#### Actions + +- power → actionTypeId: `a8c56366-5b2d-4f4b-b910-38a87851c484` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a8c56366-5b2d-4f4b-b910-38a87851c484", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `b72177f9-b673-49b5-864a-345936e5c821` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b72177f9-b673-49b5-864a-345936e5c821", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `69e94f88-a664-4bb9-ba04-2c3ea6cd7569` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "69e94f88-a664-4bb9-ba04-2c3ea6cd7569", + "params": { + "colorTemperature": "" + } + } + } + +- alert → actionTypeId: `4f8a38f4-652f-40e1-86dd-028dcd64349c` +- removeFromNetwork → actionTypeId: `a3e8d1c7-81c7-4255-b410-3bc4d5c7b4e9` + +--- + +### lumiButtonSensor + +- ThingClassId: `42c1edba-cc5f-4eb9-84f8-1b0d47a6f95e` + +#### States + +- connected (Bool) → stateTypeId: `f0da4762-4778-4b3b-ba68-466ff504a3d3` +- signalStrength (Uint) → stateTypeId: `6e9de8ee-cb28-4f7d-a0f6-fe9e64df0463` +- version (String) → stateTypeId: `11d03ab4-7450-4caf-81ec-0b2b73e56b08` + + +--- + +### today + +- ThingClassId: `fbf665fb-9aca-423f-a5f2-924e50ebe6ca` + +#### States + +- timeZone (String) → stateTypeId: `ab16997c-be29-438e-b588-2507d723d264` +- city (String) → stateTypeId: `65d2a5ff-bcab-43a8-b043-f88cf01586f4` +- country (String) → stateTypeId: `a534bd8b-6826-4d71-b9f9-df1433964b94` +- day (Int) → stateTypeId: `eb5231ea-6a1b-4d7e-a95f-d49e7b25122e` +- month (Int) → stateTypeId: `fcd8ec96-4488-438a-8b30-58bfe2a7fae2` +- monthName (String) → stateTypeId: `a37acc9c-5cfb-4687-adce-e56beb32586f` +- year (Int) → stateTypeId: `79d4ae9b-ea27-4346-8229-1d90f1ddfc9d` +- weekday (Int) → stateTypeId: `452c0388-7fa1-414e-aeb2-8c7c385824b4` +- weekdayName (String) → stateTypeId: `f627d052-cee6-4727-b9c6-0e935d41e04a` +- weekend (Bool) → stateTypeId: `4de5b57b-bb1a-4d66-9ce3-22bb280b075d` +- duskTime (Int) → stateTypeId: `44a99419-fbcd-4d8e-9441-897848b8f77c` +- sunriseTime (Int) → stateTypeId: `3a08824d-285b-412e-a515-9664b491a85c` +- noonTime (Int) → stateTypeId: `d92be29a-929c-4240-91a0-30153850f838` +- dawnTime (Int) → stateTypeId: `a5779b11-0499-4a6d-a7bd-8143dcc546b4` +- sunsetTime (Int) → stateTypeId: `377f04a7-df58-42ad-a234-e9e23bdc2f85` +- daylight (Bool) → stateTypeId: `1c3d6179-3b00-456c-841a-2d26ce960c25` + + +--- + +### motionSensor + +- ThingClassId: `43844f3d-c620-44ab-b1fa-741b79dfc289` + +#### States + +- connected (Bool) → stateTypeId: `8b16ee46-0132-409a-857e-863d20e68a77` +- signalStrength (Uint) → stateTypeId: `12334fb5-5ea4-44d3-8c60-f187097702db` +- isPresent (Bool) → stateTypeId: `b84574b4-43c9-49c4-a05a-92265bb044d7` +- lightIntensity (Double) → stateTypeId: `25568c64-b904-4099-8d5c-452c3130e130` +- batteryLevel (Int) → stateTypeId: `763dabb7-f1fb-4202-a31a-7af9f63f09e1` +- batteryCritical (Bool) → stateTypeId: `323d801e-a563-4680-8e58-f96e148c2ad1` + + +--- + +### energyMeter + +- ThingClassId: `7bba50d7-e18a-41a8-8267-7aa4876ec475` + +#### States + +- currentPower (Double) → stateTypeId: `d5f3fb79-3654-4aaf-ae30-3a761fe2dfd8` +- totalEnergyConsumed (Double) → stateTypeId: `db36a37d-7c48-4208-8b6e-a1b93acb827f` +- totalEnergyProduced (Double) → stateTypeId: `e73d72f3-b172-4db0-9120-0f713e210bdf` +- currentPhaseA (Double) → stateTypeId: `e493ec25-fb8a-4e36-84d9-4430418b3b6f` +- currentPhaseB (Double) → stateTypeId: `37097a51-063e-4b04-aa7b-67ddda8a3c81` +- currentPhaseC (Double) → stateTypeId: `6c3497fd-9894-4485-a295-15b0d829d023` +- currentPowerPhaseA (Double) → stateTypeId: `91e82743-2d97-41e9-8bf2-cb6034818079` +- currentPowerPhaseB (Double) → stateTypeId: `7ecbec82-71ec-4df3-b298-837e7f37aa4b` +- currentPowerPhaseC (Double) → stateTypeId: `eded281b-217b-48f5-8b91-b5142ea87505` +- voltagePhaseA (Double) → stateTypeId: `03deaf24-e515-4649-8979-ef8ae8ee7c02` +- voltagePhaseB (Double) → stateTypeId: `7e1514fb-7e69-4849-90c4-8f27dbd6453a` +- voltagePhaseC (Double) → stateTypeId: `b6e69a07-a362-4eef-87b7-5a670e332919` + +#### Actions + +- currentPower → actionTypeId: `d5f3fb79-3654-4aaf-ae30-3a761fe2dfd8` + - Parameters: + - currentPower (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d5f3fb79-3654-4aaf-ae30-3a761fe2dfd8", + "params": { + "currentPower": "" + } + } + } + +- totalEnergyConsumed → actionTypeId: `db36a37d-7c48-4208-8b6e-a1b93acb827f` + - Parameters: + - totalEnergyConsumed (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "db36a37d-7c48-4208-8b6e-a1b93acb827f", + "params": { + "totalEnergyConsumed": "" + } + } + } + +- totalEnergyProduced → actionTypeId: `e73d72f3-b172-4db0-9120-0f713e210bdf` + - Parameters: + - totalEnergyProduced (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e73d72f3-b172-4db0-9120-0f713e210bdf", + "params": { + "totalEnergyProduced": "" + } + } + } + +- currentPhaseA → actionTypeId: `e493ec25-fb8a-4e36-84d9-4430418b3b6f` + - Parameters: + - currentPhaseA (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e493ec25-fb8a-4e36-84d9-4430418b3b6f", + "params": { + "currentPhaseA": "" + } + } + } + +- currentPhaseB → actionTypeId: `37097a51-063e-4b04-aa7b-67ddda8a3c81` + - Parameters: + - currentPhaseB (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "37097a51-063e-4b04-aa7b-67ddda8a3c81", + "params": { + "currentPhaseB": "" + } + } + } + +- currentPhaseC → actionTypeId: `6c3497fd-9894-4485-a295-15b0d829d023` + - Parameters: + - currentPhaseC (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "6c3497fd-9894-4485-a295-15b0d829d023", + "params": { + "currentPhaseC": "" + } + } + } + +- currentPowerPhaseA → actionTypeId: `91e82743-2d97-41e9-8bf2-cb6034818079` + - Parameters: + - currentPowerPhaseA (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "91e82743-2d97-41e9-8bf2-cb6034818079", + "params": { + "currentPowerPhaseA": "" + } + } + } + +- currentPowerPhaseB → actionTypeId: `7ecbec82-71ec-4df3-b298-837e7f37aa4b` + - Parameters: + - currentPowerPhaseB (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7ecbec82-71ec-4df3-b298-837e7f37aa4b", + "params": { + "currentPowerPhaseB": "" + } + } + } + +- currentPowerPhaseC → actionTypeId: `eded281b-217b-48f5-8b91-b5142ea87505` + - Parameters: + - currentPowerPhaseC (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "eded281b-217b-48f5-8b91-b5142ea87505", + "params": { + "currentPowerPhaseC": "" + } + } + } + +- voltagePhaseA → actionTypeId: `03deaf24-e515-4649-8979-ef8ae8ee7c02` + - Parameters: + - voltagePhaseA (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "03deaf24-e515-4649-8979-ef8ae8ee7c02", + "params": { + "voltagePhaseA": "" + } + } + } + +- voltagePhaseB → actionTypeId: `7e1514fb-7e69-4849-90c4-8f27dbd6453a` + - Parameters: + - voltagePhaseB (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7e1514fb-7e69-4849-90c4-8f27dbd6453a", + "params": { + "voltagePhaseB": "" + } + } + } + +- voltagePhaseC → actionTypeId: `b6e69a07-a362-4eef-87b7-5a670e332919` + - Parameters: + - voltagePhaseC (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b6e69a07-a362-4eef-87b7-5a670e332919", + "params": { + "voltagePhaseC": "" + } + } + } + + +--- + +### car + +- ThingClassId: `dbe0a9ff-94ba-4a94-ae52-51da3f05c717` + +#### States + +- capacity (Double) → stateTypeId: `363a2a39-61b6-4109-9cd9-aca7367d12c7` +- batteryCritical (Bool) → stateTypeId: `d33982d6-6467-4281-b448-68c1b1db088d` +- batteryLevel (Int) → stateTypeId: `3f1cca10-8988-4ec6-b937-0775653cde12` +- minChargingCurrent (Uint) → stateTypeId: `20faf2b8-2b40-4bee-b228-97dbaf0cdffc` +- maxChargingCurrent (Uint) → stateTypeId: `ad17e812-ba07-47a8-99a4-eefb8b54fc85` +- phaseCount (Uint) → stateTypeId: `c886c062-bf1a-46c5-8e54-aed804a22d57` + +#### Actions + +- batteryLevel → actionTypeId: `3f1cca10-8988-4ec6-b937-0775653cde12` + - Parameters: + - batteryLevel (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "3f1cca10-8988-4ec6-b937-0775653cde12", + "params": { + "batteryLevel": "" + } + } + } + + +--- + +### shellyButton1 + +- ThingClassId: `3eba6b29-f634-4ade-80a3-2159803373cc` + +#### States + +- connected (Bool) → stateTypeId: `d23e25a1-f723-4de1-806a-83fb073f01f4` +- signalStrength (Uint) → stateTypeId: `fff3aa51-ec42-40c7-b603-cbd2d58d781e` +- batteryLevel (Int) → stateTypeId: `338355e5-9506-48b1-be86-757d69b34755` +- batteryCritical (Bool) → stateTypeId: `18edddee-1b30-48e4-b233-1e3b68bd6ff1` +- updateStatus (String) → stateTypeId: `aa3cbd93-192a-4035-8f46-c5ff68fe331b` +- currentVersion (String) → stateTypeId: `b17a7df2-952b-4cdd-8d28-a8e8582b49d4` +- availableVersion (String) → stateTypeId: `46f33cf8-82bf-4798-9100-69f54aabd9e0` + +#### Actions + +- performUpdate → actionTypeId: `87b24064-5db7-4590-a9d8-f6d8fd02ed6e` + +--- + +### kasaPlug100 + +- ThingClassId: `48f981ba-3836-4810-9744-a349088f4545` + +#### States + +- connected (Bool) → stateTypeId: `79bcdd81-2e9d-4312-a4a7-85f808d046ef` +- signalStrength (Uint) → stateTypeId: `1de7fac2-87f1-4c2b-9286-1b0895c5ac49` +- power (Bool) → stateTypeId: `a8991ea0-89f0-477b-97fb-414dd7d185b3` + +#### Actions + +- power → actionTypeId: `a8991ea0-89f0-477b-97fb-414dd7d185b3` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a8991ea0-89f0-477b-97fb-414dd7d185b3", + "params": { + "power": "" + } + } + } + + +--- + +### doorSensor + +- ThingClassId: `2d936f56-48ee-4be1-9b3e-28a335ad8085` + +#### States + +- closed (Bool) → stateTypeId: `7f5fdc2b-7916-4e90-9c24-558162304f71` + +#### Actions + +- closed → actionTypeId: `7f5fdc2b-7916-4e90-9c24-558162304f71` + - Parameters: + - closed (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7f5fdc2b-7916-4e90-9c24-558162304f71", + "params": { + "closed": "" + } + } + } + + +--- + +### colorLight + +- ThingClassId: `0edba26c-96ab-44fb-a6a2-c0574d19630e` + +#### States + +- connected (Bool) → stateTypeId: `19bb8d10-1b28-4ba3-99b7-a634138dcfde` +- power (Bool) → stateTypeId: `90aaffe5-6a76-47d2-a14a-550f60390245` +- colorTemperature (Int) → stateTypeId: `c0f4206f-f219-4f06-93c4-4ca515a56f79` +- color (Color) → stateTypeId: `d25423e7-b924-4b20-80b6-77eecc65d089` +- brightness (Int) → stateTypeId: `90e91f64-a208-468c-a5a2-7f47e08859e2` +- effect (String) → stateTypeId: `0b7cdd8d-4db8-4183-abe2-f3c01d1c9afc` + +#### Actions + +- power → actionTypeId: `90aaffe5-6a76-47d2-a14a-550f60390245` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "90aaffe5-6a76-47d2-a14a-550f60390245", + "params": { + "power": "" + } + } + } + +- colorTemperature → actionTypeId: `c0f4206f-f219-4f06-93c4-4ca515a56f79` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c0f4206f-f219-4f06-93c4-4ca515a56f79", + "params": { + "colorTemperature": "" + } + } + } + +- color → actionTypeId: `d25423e7-b924-4b20-80b6-77eecc65d089` + - Parameters: + - color (Color) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d25423e7-b924-4b20-80b6-77eecc65d089", + "params": { + "color": "" + } + } + } + +- brightness → actionTypeId: `90e91f64-a208-468c-a5a2-7f47e08859e2` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "90e91f64-a208-468c-a5a2-7f47e08859e2", + "params": { + "brightness": "" + } + } + } + +- effect → actionTypeId: `0b7cdd8d-4db8-4183-abe2-f3c01d1c9afc` + - Parameters: + - effect (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "0b7cdd8d-4db8-4183-abe2-f3c01d1c9afc", + "params": { + "effect": "" + } + } + } + +- alert → actionTypeId: `d25dcfbc-d28c-4905-80e3-300ffb1248f5` + - Parameters: + - alert (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d25dcfbc-d28c-4905-80e3-300ffb1248f5", + "params": { + "alert": "" + } + } + } + + +--- + +### outdoorSensor + +- ThingClassId: `32dc6390-600f-4eb4-b349-cc2d6796a82a` + +#### States + +- connected (Bool) → stateTypeId: `9fe43e6b-3c29-43a9-bb96-3b80eacc10db` +- batteryLevel (Int) → stateTypeId: `19b18531-61e5-4998-89d1-765d740e24eb` +- batteryCritical (Bool) → stateTypeId: `617aa352-789c-46e7-bf55-7455b1e5018e` +- temperature (Double) → stateTypeId: `88f5b708-65bb-41a7-885f-01be46074713` +- lightIntensity (Double) → stateTypeId: `4fb12c06-981c-4c42-b55c-46bdfe68681a` +- isPresent (Bool) → stateTypeId: `680f79cf-c17c-4ffd-96fa-a5b286e2c117` +- lastSeenTime (Int) → stateTypeId: `6fa16fb2-053c-4c3c-a39b-9548c1b15089` + + +--- + +### impulseGaragedooor + +- ThingClassId: `d6699a12-f4a6-4c50-951c-f4f1cd0501dc` + +#### States + +- impulse (Bool) → stateTypeId: `5ccaf0aa-01a4-441f-b6ca-18940da096a5` + +#### Actions + +- triggerImpulse → actionTypeId: `ff5461c6-70fc-435e-8424-96fa59ed321e` + +--- + +### smartMeterConsumer + +- ThingClassId: `c26478b3-dd64-445f-9859-8ef816025cb9` + +#### States + +- currentPower (Double) → stateTypeId: `5a083458-e476-487d-ab8f-75e92cf16489` +- totalEnergyConsumed (Double) → stateTypeId: `ba10ef2c-e41f-4de2-a620-dff2ec5f025a` + +#### Actions + +- currentPower → actionTypeId: `5a083458-e476-487d-ab8f-75e92cf16489` + - Parameters: + - currentPower (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5a083458-e476-487d-ab8f-75e92cf16489", + "params": { + "currentPower": "" + } + } + } + +- totalEnergyConsumed → actionTypeId: `ba10ef2c-e41f-4de2-a620-dff2ec5f025a` + - Parameters: + - totalEnergyConsumed (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ba10ef2c-e41f-4de2-a620-dff2ec5f025a", + "params": { + "totalEnergyConsumed": "" + } + } + } + + +--- + +### gpioInputRpi + +- ThingClassId: `6aff228b-0410-4ef9-9593-51e8639aacea` + +#### States + +- power (Bool) → stateTypeId: `57f1b7cc-26c8-434b-ba04-d3077dc886c8` + + +--- + +### rollerShade + +- ThingClassId: `df32f5d9-25f0-41ff-924a-586ec0e983d6` + +#### States + +- connected (Bool) → stateTypeId: `de078e37-e94c-45c3-a2e9-ed249a4ab92a` +- signalStrength (Uint) → stateTypeId: `4817e1d2-583f-42c4-8b3c-85cfcb9ddb8c` +- moving (Bool) → stateTypeId: `407e7db4-7257-4657-9aa5-04b243f8f601` +- percentage (Int) → stateTypeId: `03bd4eb3-485c-4676-9901-a29dd5a61867` +- batteryLevel (Int) → stateTypeId: `c3e68496-da84-450c-8e1e-e26d9ac6c807` +- batteryCritical (Bool) → stateTypeId: `179a9d7c-ee22-4aaa-98b2-faa3d69058b8` + +#### Actions + +- percentage → actionTypeId: `03bd4eb3-485c-4676-9901-a29dd5a61867` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "03bd4eb3-485c-4676-9901-a29dd5a61867", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `847e271e-428c-45ce-aced-203de9a79662` +- close → actionTypeId: `72d6a77d-1b8b-41f2-bf95-6798106a6b2e` +- stop → actionTypeId: `777dd1ec-06de-49d8-979c-e48737313b6c` + +--- + +### shellyPro3EM + +- ThingClassId: `d7962c7c-82fe-4d2c-8e79-0b9ff2ee5573` + +#### States + +- connected (Bool) → stateTypeId: `a29300d0-cfde-465b-9aca-9f48f15360bc` +- signalStrength (Uint) → stateTypeId: `837618f5-cb59-40c1-a7b7-c036d9d8772f` +- totalEnergyConsumed (Double) → stateTypeId: `c09b5307-b0f8-4cc3-95f2-544513424623` +- totalEnergyProduced (Double) → stateTypeId: `8e6ddedc-7764-470d-b319-36b39c9ff62e` +- currentPower (Double) → stateTypeId: `eec71598-e307-4917-abb3-53a2b8c14625` +- currentPowerPhaseA (Double) → stateTypeId: `a2577f97-70c5-406c-90df-63228c6ce30b` +- currentPhaseA (Double) → stateTypeId: `821e323f-0f51-4a81-a1c4-c31b8f41fa19` +- voltagePhaseA (Double) → stateTypeId: `134e412f-5a2e-4e65-b4f2-e8f0698e7000` +- energyConsumedPhaseA (Double) → stateTypeId: `0cce4d7b-c673-401b-a654-b2e3ab27bd61` +- energyProducedPhaseA (Double) → stateTypeId: `9042012f-64e7-4594-a900-599f635f93b1` +- currentPowerPhaseB (Double) → stateTypeId: `0852caaa-6704-4b03-8ba6-c1460c2f023d` +- currentPhaseB (Double) → stateTypeId: `f1ea6d35-c74a-43e3-8f06-8387a4595b51` +- voltagePhaseB (Double) → stateTypeId: `37bcd9a2-1f98-45e1-83bc-e9bfb40d0353` +- energyConsumedPhaseB (Double) → stateTypeId: `aef8d193-75c6-431f-b013-0a5c08d6225d` +- energyProducedPhaseB (Double) → stateTypeId: `74c234fd-22c9-4eab-ab8f-e0ba17b7403a` +- currentPowerPhaseC (Double) → stateTypeId: `0c615174-562b-428a-9879-687cfeb5a9bd` +- currentPhaseC (Double) → stateTypeId: `b75373ed-acd5-4980-a0f1-565db2f1351c` +- voltagePhaseC (Double) → stateTypeId: `f6d5128a-305f-488b-b586-b52ba163c8a7` +- energyConsumedPhaseC (Double) → stateTypeId: `cf1761b5-09b5-4688-8875-40627fa945bc` +- energyProducedPhaseC (Double) → stateTypeId: `6a30cfcf-601d-4fdc-9465-f58b5d0caab8` +- updateStatus (String) → stateTypeId: `839f3192-1841-4293-b60f-8e7976510d36` +- currentVersion (String) → stateTypeId: `a8c8e190-ab9f-49f7-9690-f12fb49920cb` +- availableVersion (String) → stateTypeId: `2acba99c-9c4a-40bb-850a-036312995e8b` +- power (Bool) → stateTypeId: `f8621a0a-5b03-4a78-be48-934472b82900` + +#### Actions + +- power → actionTypeId: `f8621a0a-5b03-4a78-be48-934472b82900` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f8621a0a-5b03-4a78-be48-934472b82900", + "params": { + "power": "" + } + } + } + +- performUpdate → actionTypeId: `9b268961-5aa4-4a59-a533-aeaf8c376919` +- reset → actionTypeId: `b0043a22-21e4-4dfc-a813-2a11908a6c04` + +--- + +### waterSensor + +- ThingClassId: `20c843dc-b60e-4d06-8f96-be7950a98fc6` + +#### States + +- connected (Bool) → stateTypeId: `6e26a196-6ecd-4971-a36c-0dcbd508e557` +- signalStrength (Uint) → stateTypeId: `9d92c9c7-901b-4a99-84d0-3d19c8be1635` +- version (String) → stateTypeId: `a59bb290-0c3e-48d8-933b-2f0783cc5615` +- waterDetected (Bool) → stateTypeId: `ff751a4f-ea4e-4706-ad4f-627c327a3d6a` +- temperature (Double) → stateTypeId: `98d4f3a5-539f-4f75-a86e-88d4ab4b026f` +- batteryCritical (Bool) → stateTypeId: `b5eb9897-eabf-455b-9958-91db6b1c4868` +- updateStatus (String) → stateTypeId: `74a82258-5a7c-44f5-af98-3aa3afcbe08e` +- currentVersion (String) → stateTypeId: `16ff5d40-77f0-46fa-bda0-1ef35eae12fc` +- availableVersion (String) → stateTypeId: `a4fdb89d-230f-454b-a4b4-12bc84a19e8c` +- updateProgress (Uint) → stateTypeId: `9dcde658-9048-41da-b4ac-3cbe62a8609e` + +#### Actions + +- performUpdate → actionTypeId: `4d40f75d-fb8a-47af-9a03-98f828765887` + +--- + +### button + +- ThingClassId: `a3a73bf2-ebe4-47fa-8a0a-dc91927c6ce3` + +#### Actions + +- Press → actionTypeId: `3a7bda8e-b92c-454b-8ea2-b798fcec8e4b` + +--- + +### lightPanels + +- ThingClassId: `d44ee383-9fa5-4751-babd-1129ac20896a` + +#### States + +- connected (Bool) → stateTypeId: `a3102107-a825-4ec8-a9ec-b2c2a9fb5c89` +- power (Bool) → stateTypeId: `44bee9ec-513d-4834-991a-ee9ae69d9f2a` +- colorTemperature (Int) → stateTypeId: `41248127-844b-40be-87e6-38aee48b6687` +- color (Color) → stateTypeId: `d4a52cdc-93b2-44fc-a36c-ae65f1d98f2e` +- brightness (Int) → stateTypeId: `4e5d6460-d42e-4b7c-a8f3-6e953451c1ef` +- colorMode (String) → stateTypeId: `bdd2ea1e-9ef9-4967-9678-2c601b826199` +- effectName (String) → stateTypeId: `57f9831e-1b98-41c1-a21c-6073ff327237` + +#### Actions + +- power → actionTypeId: `44bee9ec-513d-4834-991a-ee9ae69d9f2a` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "44bee9ec-513d-4834-991a-ee9ae69d9f2a", + "params": { + "power": "" + } + } + } + +- colorTemperature → actionTypeId: `41248127-844b-40be-87e6-38aee48b6687` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "41248127-844b-40be-87e6-38aee48b6687", + "params": { + "colorTemperature": "" + } + } + } + +- color → actionTypeId: `d4a52cdc-93b2-44fc-a36c-ae65f1d98f2e` + - Parameters: + - color (Color) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d4a52cdc-93b2-44fc-a36c-ae65f1d98f2e", + "params": { + "color": "" + } + } + } + +- brightness → actionTypeId: `4e5d6460-d42e-4b7c-a8f3-6e953451c1ef` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4e5d6460-d42e-4b7c-a8f3-6e953451c1ef", + "params": { + "brightness": "" + } + } + } + +- alert → actionTypeId: `47a6a1a1-fb90-4f24-be8c-b4dba0aaaa84` + +--- + +### indoorModule + +- ThingClassId: `a6706b11-325b-4be3-b0d1-c09e027955b4` + +#### States + +- updateTime (Int) → stateTypeId: `024eb4d2-ed0b-428b-b5c4-ce9aba1fee1e` +- temperature (Double) → stateTypeId: `33957a0c-75b7-45d0-8e07-731c7c20df0e` +- temperatureMin (Double) → stateTypeId: `2f9e4042-b699-4036-be69-a84e561ac38c` +- temperatureMax (Double) → stateTypeId: `304472e3-56fc-4ee6-96df-aeb4b570a1d1` +- humidity (Double) → stateTypeId: `e39c6ea6-8d53-42c7-bfce-e9e4aa3dfec9` +- co2 (Double) → stateTypeId: `a3fe53a3-0940-4fcb-915d-0297ae584917` +- pressure (Double) → stateTypeId: `9d2c409e-0d4f-4e03-89ad-fe0cad776e66` +- signalStrength (Uint) → stateTypeId: `36fd51d9-7693-42ee-b0ae-b623e219d950` +- connected (Bool) → stateTypeId: `5b819dbf-698d-49ae-aeb5-a15db9ef515a` +- batteryLevel (Int) → stateTypeId: `d9fe5e52-8f42-41fd-aa5f-fd157ad6a6be` +- batteryCritical (Bool) → stateTypeId: `7cde2c79-2b90-4ced-97ac-2653d314cf73` + + +--- + +### heosPlayer + +- ThingClassId: `fce5247f-4c6d-408f-ac62-e5973dc6adfa` + +#### States + +- connected (Bool) → stateTypeId: `9a4e527e-057c-4b19-8a02-605cc8349f5e` +- mute (Bool) → stateTypeId: `fcc89c7c-b793-4b6f-a3dc-0e0e3a86748f` +- volume (Int) → stateTypeId: `6d4886a1-fa5d-4889-96c5-7a1c206f59be` +- playbackStatus (String) → stateTypeId: `6db3b484-4cd4-477b-b822-275865d308db` +- shuffle (Bool) → stateTypeId: `4b581237-acf5-4d8f-9e83-9b24e9ac900a` +- repeat (String) → stateTypeId: `4e60cd17-5845-4351-aa2c-2504610e1532` +- source (String) → stateTypeId: `eee22722-3ee5-48f7-8af8-275dc04b21eb` +- artist (String) → stateTypeId: `0a9183a4-b633-4773-ba7a-f4266895157e` +- collection (String) → stateTypeId: `9cd60864-f141-4e03-a85b-357690cad1b8` +- title (String) → stateTypeId: `bbeecf30-6feb-48d5-ade3-57b2a4eea05f` +- artwork (String) → stateTypeId: `a7f0ba95-383a-4efd-adc5-a36e50a04018` +- playerType (String) → stateTypeId: `c59835ac-ee6e-4e6c-aa20-aeb3501937c5` + +#### Actions + +- mute → actionTypeId: `fcc89c7c-b793-4b6f-a3dc-0e0e3a86748f` + - Parameters: + - mute (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "fcc89c7c-b793-4b6f-a3dc-0e0e3a86748f", + "params": { + "mute": "" + } + } + } + +- volume → actionTypeId: `6d4886a1-fa5d-4889-96c5-7a1c206f59be` + - Parameters: + - volume (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "6d4886a1-fa5d-4889-96c5-7a1c206f59be", + "params": { + "volume": "" + } + } + } + +- playbackStatus → actionTypeId: `6db3b484-4cd4-477b-b822-275865d308db` + - Parameters: + - playbackStatus (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "6db3b484-4cd4-477b-b822-275865d308db", + "params": { + "playbackStatus": "" + } + } + } + +- shuffle → actionTypeId: `4b581237-acf5-4d8f-9e83-9b24e9ac900a` + - Parameters: + - shuffle (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4b581237-acf5-4d8f-9e83-9b24e9ac900a", + "params": { + "shuffle": "" + } + } + } + +- repeat → actionTypeId: `4e60cd17-5845-4351-aa2c-2504610e1532` + - Parameters: + - repeat (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4e60cd17-5845-4351-aa2c-2504610e1532", + "params": { + "repeat": "" + } + } + } + +- alert → actionTypeId: `db8e001a-fcae-4c41-9811-325e14c06109` +- skipBack → actionTypeId: `a718f7e9-0b54-4403-b661-49f7b0d13085` +- stop → actionTypeId: `c4b29c09-e3b3-4843-b6d9-e032f3fc1d78` +- play → actionTypeId: `c64964e4-cea0-468a-a9bf-8f69657b74e9` +- pause → actionTypeId: `21c1cbe6-278f-4688-a65f-6620be1ee5ea` +- skipNext → actionTypeId: `57697e9c-ce5e-4b8f-b42e-16662829ceb2` +- increaseVolume → actionTypeId: `ebdc35f8-24a2-4984-855e-4c1a158289b7` + - Parameters: + - step (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ebdc35f8-24a2-4984-855e-4c1a158289b7", + "params": { + "step": "" + } + } + } + +- decreaseVolume → actionTypeId: `e19cc4e0-00ef-4df4-8314-85902017d095` + - Parameters: + - step (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e19cc4e0-00ef-4df4-8314-85902017d095", + "params": { + "step": "" + } + } + } + + +--- + +### vibrationSensor + +- ThingClassId: `6fb1f16f-ffb2-43e7-92ee-20b1f8137e17` + +#### States + +- connected (Bool) → stateTypeId: `9ecf841f-e542-4f24-b135-458683a43e92` +- signalStrength (Uint) → stateTypeId: `b21adc6e-3c6e-4793-b49c-326e220b6059` +- batteryLevel (Int) → stateTypeId: `1990fbc3-c122-424d-96f3-187867d75b82` +- batteryCritical (Bool) → stateTypeId: `ab8d043e-88d7-47e3-b157-a52543ae542a` + + +--- + +### motionSensor + +- ThingClassId: `6cbf86ea-0d31-4ce7-b0fd-02ff707d3553` + +#### States + +- connected (Bool) → stateTypeId: `1c109b37-f002-4fb4-8667-2ee62bba2626` +- signalStrength (Uint) → stateTypeId: `bbd0eef3-b2cd-4fcf-bd2a-e76295d0b232` +- version (String) → stateTypeId: `1060399a-3e15-44ce-8bdc-4b7fd6f1e194` +- tampered (Bool) → stateTypeId: `5ed06626-db36-4520-8c09-b0224df570f8` +- isPresent (Bool) → stateTypeId: `80bb5618-2115-4909-a6ea-be0ccdaeffbd` +- temperature (Double) → stateTypeId: `d7d096fe-8937-4fcf-a54c-8eb4a9aa830b` +- lightIntensity (Double) → stateTypeId: `5368431e-a622-4d36-b1c0-61a456744ea8` +- batteryCritical (Bool) → stateTypeId: `0a9d580f-70e6-42f9-9d77-d7aeb245ee84` +- updateStatus (String) → stateTypeId: `5ccd02af-b646-4dcf-867c-867b0d5011f9` +- currentVersion (String) → stateTypeId: `0e864bc8-45d0-4cf3-9ad9-cee15a4e2311` +- availableVersion (String) → stateTypeId: `187dd962-4f44-4d1b-9b34-7e491c71d951` +- updateProgress (Uint) → stateTypeId: `0736ac21-0f21-4d50-ade5-90cd18f64a1c` + +#### Actions + +- performUpdate → actionTypeId: `915dccbb-4220-45d0-b074-9446079b47e6` + +--- + +### speedwireBattery + +- ThingClassId: `b459dad2-f78b-4a87-a7f3-22f3147b83d8` + +#### States + +- connected (Bool) → stateTypeId: `7f242169-c01a-4c9a-ac71-4f9fa5409875` +- voltage (Double) → stateTypeId: `d2144cad-e507-433b-a9d3-2ab9cf0c1014` +- current (Double) → stateTypeId: `541c110d-2f56-44bb-8f7e-de55759b942d` +- temperature (Double) → stateTypeId: `6a146a40-84da-4392-8466-4176b21280d2` +- currentPower (Double) → stateTypeId: `f0f69109-83a4-4b2a-9e16-66aa33c2e169` +- capacity (Double) → stateTypeId: `38a413cd-3d09-482d-8d25-b602db3b6540` +- batteryCritical (Bool) → stateTypeId: `d815aedf-e836-4274-9b51-2f0128420c46` +- batteryLevel (Int) → stateTypeId: `ec534954-8ee4-46f4-94b6-b48b375b1d7d` +- chargingState (String) → stateTypeId: `93310fa3-8237-423b-9062-62e0626e8c70` + + +--- + +### shellyPlug + +- ThingClassId: `22229a6d-2af8-44e0-bea9-310a0f2769ef` + +#### States + +- connected (Bool) → stateTypeId: `584b3558-5fb5-40a9-81ad-dc71ba68fd45` +- signalStrength (Uint) → stateTypeId: `0b0a73a5-d732-47eb-a075-8e22810eea55` +- power (Bool) → stateTypeId: `d813b35f-e11e-4783-b3b3-dbecb956ffb5` +- totalEnergyConsumed (Double) → stateTypeId: `962fec29-6be0-452e-87c5-5ff71435c40f` +- currentPower (Double) → stateTypeId: `202ea409-650e-48b2-9aae-d4ebe9d505fd` +- updateStatus (String) → stateTypeId: `ccec3806-cc48-42cf-94d7-811ff569d407` +- currentVersion (String) → stateTypeId: `5b286e92-ec05-4a70-8813-646b63995213` +- availableVersion (String) → stateTypeId: `ccf9d5e9-e89d-4dda-ae99-2f3e9c4e7948` + +#### Actions + +- power → actionTypeId: `d813b35f-e11e-4783-b3b3-dbecb956ffb5` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d813b35f-e11e-4783-b3b3-dbecb956ffb5", + "params": { + "power": "" + } + } + } + +- reboot → actionTypeId: `7dc03565-d7cb-4add-ba08-b751ce0821d5` +- performUpdate → actionTypeId: `140026a6-2d16-4a0c-9ba9-dea0740584fd` + +--- + +### spirit + +- ThingClassId: `57ce4f62-d5a3-4e79-8352-96942c6e4425` + +#### States + +- targetTemperature (Double) → stateTypeId: `20e9006f-09ec-43ea-a249-46e4894698d2` +- temperature (Double) → stateTypeId: `68230bfe-ed04-49d6-b2ed-731fdfc35df2` +- heatingOn (Bool) → stateTypeId: `e52ad2fd-ef3e-4e99-8854-4db07281e658` +- connected (Bool) → stateTypeId: `ebd54153-68ec-4e3c-a370-5b0dca35741b` +- signalStrength (Uint) → stateTypeId: `3bd33c04-37ca-4c26-b583-b6caf58b443d` +- batteryLevel (Int) → stateTypeId: `a6129509-e3dd-448f-8964-1817ca4c3888` +- batteryCritical (Bool) → stateTypeId: `78e2e1b5-0de6-49f7-9b90-63d6922234af` +- boost (Bool) → stateTypeId: `daeb8f1e-4637-406c-8b09-e441f2f53c9c` +- windowOpen (Bool) → stateTypeId: `ddde7d49-19d4-4196-b09f-f614e04220b2` +- mirrorDisplay (Bool) → stateTypeId: `89cdbb14-d4b1-444a-a193-e760d6b6bd87` +- childLock (Bool) → stateTypeId: `e31bb876-cc60-4127-bb6b-7d3a4b07fa11` +- updateStatus (String) → stateTypeId: `89c21b2c-0007-4da6-9bbf-4170b716858d` +- currentVersion (String) → stateTypeId: `9a3987df-87d5-4b97-9f31-1e0b0a6468ad` + +#### Actions + +- targetTemperature → actionTypeId: `20e9006f-09ec-43ea-a249-46e4894698d2` + - Parameters: + - targetTemperature (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "20e9006f-09ec-43ea-a249-46e4894698d2", + "params": { + "targetTemperature": "" + } + } + } + +- boost → actionTypeId: `daeb8f1e-4637-406c-8b09-e441f2f53c9c` + - Parameters: + - boost (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "daeb8f1e-4637-406c-8b09-e441f2f53c9c", + "params": { + "boost": "" + } + } + } + +- windowOpen → actionTypeId: `ddde7d49-19d4-4196-b09f-f614e04220b2` + - Parameters: + - windowOpen (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ddde7d49-19d4-4196-b09f-f614e04220b2", + "params": { + "windowOpen": "" + } + } + } + +- mirrorDisplay → actionTypeId: `89cdbb14-d4b1-444a-a193-e760d6b6bd87` + - Parameters: + - mirrorDisplay (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "89cdbb14-d4b1-444a-a193-e760d6b6bd87", + "params": { + "mirrorDisplay": "" + } + } + } + +- childLock → actionTypeId: `e31bb876-cc60-4127-bb6b-7d3a4b07fa11` + - Parameters: + - childLock (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e31bb876-cc60-4127-bb6b-7d3a4b07fa11", + "params": { + "childLock": "" + } + } + } + +- performUpdate → actionTypeId: `9dfcb8ce-298f-45c0-9abf-714c9ece9357` + +--- + +### speedwireMeter + +- ThingClassId: `0c5097af-e136-4430-9fb4-0ccbb30c3e1c` + +#### States + +- connected (Bool) → stateTypeId: `35733d27-4fe0-439a-be71-7c1597481659` +- voltagePhaseA (Double) → stateTypeId: `44ee2491-8376-41cd-a21d-185c736152ec` +- voltagePhaseB (Double) → stateTypeId: `56ae3555-f874-4c2d-8833-17573dce477a` +- voltagePhaseC (Double) → stateTypeId: `51cbb29b-29f0-480a-9d7d-b8f4e6a205ae` +- currentPhaseA (Double) → stateTypeId: `45bbdbef-1832-4870-bff5-299e580fb4da` +- currentPhaseB (Double) → stateTypeId: `b3a4fdd2-b6b8-4c58-9da3-2084ad414022` +- currentPhaseC (Double) → stateTypeId: `b3655188-3854-4336-ae3c-61d3bda6fc4d` +- currentPower (Double) → stateTypeId: `d4ac7f37-e30a-44e4-93cb-ad16df18b8f1` +- currentPowerPhaseA (Double) → stateTypeId: `c5d09c63-7461-4fb8-a6fe-bc7aa919be30` +- currentPowerPhaseB (Double) → stateTypeId: `c52d4422-b521-4804-a7a7-c4398e91e760` +- currentPowerPhaseC (Double) → stateTypeId: `555e892c-3ca7-4100-9832-6ac13b87eb04` +- totalEnergyConsumed (Double) → stateTypeId: `4fb0a4c1-18ed-4d02-b6d0-c07e9b96a56d` +- totalEnergyProduced (Double) → stateTypeId: `76ca68d8-6781-4d2a-8663-440aec40b4de` +- energyConsumedPhaseA (Double) → stateTypeId: `b4ff2c71-f81d-4904-bbac-0c0c6e8a5a33` +- energyConsumedPhaseB (Double) → stateTypeId: `c4e5f569-ac5d-4761-a898-888880bfd59f` +- energyConsumedPhaseC (Double) → stateTypeId: `aabc02d7-8dc3-4637-8bf2-dc2e0e737ad3` +- energyProducedPhaseA (Double) → stateTypeId: `754c3b67-768a-47f7-99d8-f66c198f0835` +- energyProducedPhaseB (Double) → stateTypeId: `7eb08c45-24cf-40ce-be28-f3564f087672` +- energyProducedPhaseC (Double) → stateTypeId: `1eb2bf01-5ec6-42e5-b348-ac1e95199d14` +- firmwareVersion (String) → stateTypeId: `a685393c-8b7e-42c5-bb41-f9907c074626` + + +--- + +### waterSensor + +- ThingClassId: `22a389b6-1b2b-4b88-a47a-d9fd16c8ab2c` + +#### States + +- waterDetected (Bool) → stateTypeId: `d5657846-3f19-4e94-841b-12681bbe4f8e` +- batteryCritical (Bool) → stateTypeId: `75ce3761-24fa-48e1-9a86-94d67c80b7e8` +- connected (Bool) → stateTypeId: `c677bdd4-e319-4c7b-ba76-3851a69ad3df` +- signalStrength (Uint) → stateTypeId: `48d7361e-c99a-4eab-8143-dfccfd4a16da` +- version (String) → stateTypeId: `326dc29b-355d-4d31-bf2f-8b570c342af1` + + +--- + +### kasaPlug110 + +- ThingClassId: `32830124-9efb-4614-8227-ee269b1889b0` + +#### States + +- connected (Bool) → stateTypeId: `b66825ec-9f1b-48da-af18-f36913291c0e` +- signalStrength (Uint) → stateTypeId: `cb16cfb0-6608-486f-abe5-264aa652704d` +- power (Bool) → stateTypeId: `f1a5fda4-87a6-46f6-9499-16811a5f4f4d` +- totalEnergyConsumed (Double) → stateTypeId: `a3533121-69ee-44fd-8394-13373e8f960e` +- currentPower (Double) → stateTypeId: `ccb52b57-5800-4f03-b7fa-f36dcebe1d4e` + +#### Actions + +- power → actionTypeId: `f1a5fda4-87a6-46f6-9499-16811a5f4f4d` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f1a5fda4-87a6-46f6-9499-16811a5f4f4d", + "params": { + "power": "" + } + } + } + + +--- + +### flsAirlink4 + +- ThingClassId: `38693f57-004b-4d0b-aea3-df1ba7ca244e` + +#### States + +- connected (Bool) → stateTypeId: `07cf64a6-f0b4-4c7b-ac26-9388900e6cdc` +- signalStrength (Uint) → stateTypeId: `40313883-bb05-40a6-b98e-6d31f89352db` +- batteryLevel (Int) → stateTypeId: `21b3af55-a149-4844-94f2-49f7f63336c4` +- batteryCritical (Bool) → stateTypeId: `352e2b5b-e9d9-4df5-a482-c771966bb0f5` + + +--- + +### shellyPro1Pm + +- ThingClassId: `d21a9182-2f5b-47c1-9a27-6dd8ebd50b5f` + +#### States + +- power (Bool) → stateTypeId: `9942b350-9033-4491-8a99-538c042a9251` +- connected (Bool) → stateTypeId: `4913d3fd-f6b4-4a23-b495-ae83df8473c8` +- signalStrength (Uint) → stateTypeId: `903a1744-5551-4298-bacd-13066acc16a9` +- updateStatus (String) → stateTypeId: `93ab8203-cc26-4ae9-a61e-d8f0182221b0` +- currentVersion (String) → stateTypeId: `1dd09d4c-33e4-4496-8dc9-27b62a4092b0` +- availableVersion (String) → stateTypeId: `07ca990a-96c7-4213-9af6-d69cb946cc46` +- totalEnergyConsumed (Double) → stateTypeId: `be8ca18d-7417-4e5b-a2b2-2d1c87a5ed34` +- currentPower (Double) → stateTypeId: `d5fd6531-defb-4dac-9025-62a35a20e2c6` + +#### Actions + +- power → actionTypeId: `9942b350-9033-4491-8a99-538c042a9251` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9942b350-9033-4491-8a99-538c042a9251", + "params": { + "power": "" + } + } + } + +- reboot → actionTypeId: `faae305a-fa7d-46b9-9ef8-6a7f12455380` +- performUpdate → actionTypeId: `89504849-9284-466d-b9d5-498e5f193c50` + +--- + +### dimmableLight + +- ThingClassId: `4fa568ef-7a3a-422b-b0c0-206d37cb4eed` + +#### States + +- connected (Bool) → stateTypeId: `57f80677-745e-4cb1-b894-87d8542a7e8c` +- power (Bool) → stateTypeId: `5995ecb7-b5e5-4f6a-b4d6-33c93497e5fb` +- brightness (Int) → stateTypeId: `2f062912-1159-423b-8143-48a8e69b9348` + +#### Actions + +- power → actionTypeId: `5995ecb7-b5e5-4f6a-b4d6-33c93497e5fb` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5995ecb7-b5e5-4f6a-b4d6-33c93497e5fb", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `2f062912-1159-423b-8143-48a8e69b9348` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "2f062912-1159-423b-8143-48a8e69b9348", + "params": { + "brightness": "" + } + } + } + +- alert → actionTypeId: `ab30a83a-539e-4b3a-860a-434e87ca165f` + - Parameters: + - alert (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ab30a83a-539e-4b3a-860a-434e87ca165f", + "params": { + "alert": "" + } + } + } + + +--- + +### airPurifier + +- ThingClassId: `1580b37e-9f4f-474a-9a38-a40060f93861` + +#### States + +- connected (Bool) → stateTypeId: `31565f01-0287-4f82-9dbf-894c20e06f69` +- signalStrength (Uint) → stateTypeId: `ad88fa3d-eebf-42e2-98f4-e58281da03e0` +- power (Bool) → stateTypeId: `7bcce1da-fc9c-4972-8df2-f17baee95023` +- auto (Bool) → stateTypeId: `15ae0037-e85a-406f-878a-907bcf5bea63` +- flowRate (Int) → stateTypeId: `7ad8ce8c-36ab-41b8-8768-4f765a1fa291` +- filterRuntime (Uint) → stateTypeId: `7b1a33b8-6f81-46c2-b1f1-a1a46fffd990` +- replaceFilter (Bool) → stateTypeId: `d01b170d-8985-4b33-b907-1c7e0a35bff6` +- lightPower (Bool) → stateTypeId: `c71f3fb0-7cd1-4868-846d-a261c24627c2` +- pm25 (Double) → stateTypeId: `a71956ec-af44-4dab-86b1-dd7a2baece1c` +- childLock (Bool) → stateTypeId: `d8e6ff6d-5b0e-4071-a749-1e2f19175e4d` +- currentVersion (String) → stateTypeId: `d7bea835-e91b-4a04-826a-aaacf7233faa` +- updateStatus (String) → stateTypeId: `5636514d-40a9-464e-bdfb-5877b22b3e69` +- availableVersion (String) → stateTypeId: `676491ec-2c20-4a05-a75d-c515f4f4bd18` +- updateProgress (Uint) → stateTypeId: `acbac78e-d65e-4698-bed7-9b15057cbf44` + +#### Actions + +- power → actionTypeId: `7bcce1da-fc9c-4972-8df2-f17baee95023` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7bcce1da-fc9c-4972-8df2-f17baee95023", + "params": { + "power": "" + } + } + } + +- auto → actionTypeId: `15ae0037-e85a-406f-878a-907bcf5bea63` + - Parameters: + - auto (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "15ae0037-e85a-406f-878a-907bcf5bea63", + "params": { + "auto": "" + } + } + } + +- flowRate → actionTypeId: `7ad8ce8c-36ab-41b8-8768-4f765a1fa291` + - Parameters: + - flowRate (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7ad8ce8c-36ab-41b8-8768-4f765a1fa291", + "params": { + "flowRate": "" + } + } + } + +- lightPower → actionTypeId: `c71f3fb0-7cd1-4868-846d-a261c24627c2` + - Parameters: + - lightPower (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c71f3fb0-7cd1-4868-846d-a261c24627c2", + "params": { + "lightPower": "" + } + } + } + +- childLock → actionTypeId: `d8e6ff6d-5b0e-4071-a749-1e2f19175e4d` + - Parameters: + - childLock (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d8e6ff6d-5b0e-4071-a749-1e2f19175e4d", + "params": { + "childLock": "" + } + } + } + +- performUpdate → actionTypeId: `5f195fde-2b76-4789-9c7f-8f335a5b450a` + +--- + +### insta + +- ThingClassId: `f81ad8c0-29e3-4284-ad3a-393e11c2cc37` + +#### States + +- connected (Bool) → stateTypeId: `bf6d6426-a967-4084-86bf-4edd2d074316` +- signalStrength (Uint) → stateTypeId: `3859cc17-b534-4e00-be3b-6fbdb67ed0fe` +- updateStatus (String) → stateTypeId: `50196581-9dfe-4371-bb97-ba6498ca4ffc` +- currentVersion (String) → stateTypeId: `6e5285d5-1a80-47b8-a9b5-e951a4236477` +- availableVersion (String) → stateTypeId: `81d7f41e-e09d-40cc-8a18-6f19c0877f5b` +- updateProgress (Uint) → stateTypeId: `a39bef41-5aae-4bdf-8e47-23417b214bcf` + +#### Actions + +- performUpdate → actionTypeId: `299bfa23-da89-495d-85b0-d8233481ced3` + +--- + +### lumiRemote + +- ThingClassId: `f8aa2ba1-ce74-4691-b97d-85427f4cf8bd` + +#### States + +- connected (Bool) → stateTypeId: `d1afa3ba-f3bd-47e5-90fa-9d80dcce91d8` +- signalStrength (Uint) → stateTypeId: `a764dbfb-7b86-439b-94ea-aec742dcb13e` +- version (String) → stateTypeId: `8164c1d0-657e-4347-99fb-f3fdc07af6de` + + +--- + +### phSensor + +- ThingClassId: `e2934fa1-59c3-4de8-82f2-66181136085c` + +#### States + +- ph (Double) → stateTypeId: `743514b1-8018-4525-b87a-c5f414146ff2` +- input (Double) → stateTypeId: `614a039b-9ed9-4b62-9c74-01ba4ac42f16` + +#### Actions + +- ph → actionTypeId: `743514b1-8018-4525-b87a-c5f414146ff2` + - Parameters: + - ph (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "743514b1-8018-4525-b87a-c5f414146ff2", + "params": { + "ph": "" + } + } + } + +- input → actionTypeId: `614a039b-9ed9-4b62-9c74-01ba4ac42f16` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "614a039b-9ed9-4b62-9c74-01ba4ac42f16", + "params": { + "input": "" + } + } + } + + +--- + +### motionSensor + +- ThingClassId: `031c45d1-e782-4f91-9f05-259d6b81c7ef` + +#### States + +- connected (Bool) → stateTypeId: `0d0a5ee1-41f2-4b5a-a3c0-7c8cca1c064d` +- signalStrength (Uint) → stateTypeId: `d4f85c34-896a-4bab-af71-8b80d9889815` +- batteryLevel (Int) → stateTypeId: `00a4450b-d2fe-4e2b-92c8-1ab3a98d1628` +- batteryCritical (Bool) → stateTypeId: `9341f65a-b0aa-4648-82eb-e8400779f817` +- isPresent (Bool) → stateTypeId: `66e3b840-4f4c-4f4a-a71a-69fb751f2a3b` +- lastSeenTime (Int) → stateTypeId: `128777a9-75e7-4cc6-b196-691d2ffddbc9` +- lightIntensity (Double) → stateTypeId: `8077e335-1d18-4e3f-9b5e-6f71af4a33b1` +- temperature (Double) → stateTypeId: `978f069c-57c0-4e73-a81b-c593bc2e7624` +- updateStatus (String) → stateTypeId: `0bf7e6dd-4fa6-45da-a404-c35af88fe74c` +- currentVersion (String) → stateTypeId: `d79ca86e-124a-4d0b-b1fc-c032b6383b87` +- availableVersion (String) → stateTypeId: `6d205b65-a53c-4cdd-9a7c-2e02fe8c0a16` +- updateProgress (Uint) → stateTypeId: `feeb0630-dcfb-4b41-a269-eedf2936c500` + +#### Actions + +- performUpdate → actionTypeId: `01b2e79f-ede7-49c1-8c38-3923513c1329` + +--- + +### kodi + +- ThingClassId: `d09953e3-c5bd-415b-973b-0d0bf2be3f69` + +#### States + +- connected (Bool) → stateTypeId: `09dfbd40-c97c-4a20-9ecd-f80e389a4864` +- mute (Bool) → stateTypeId: `bc98cdb0-4d0e-48ca-afc7-922e49bb7813` +- volume (Int) → stateTypeId: `9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9` +- playbackStatus (String) → stateTypeId: `2dd512b7-40c2-488e-8d4f-6519edaa6f74` +- playerType (String) → stateTypeId: `0af58b87-4e45-4f0a-9ef2-0ade74c7c22c` +- title (String) → stateTypeId: `f2209fec-cceb-46ad-8189-4caf42166e6b` +- artist (String) → stateTypeId: `8cb920a3-3bf1-4231-92d4-8ac27e7b3d65` +- collection (String) → stateTypeId: `ce399eec-9f6a-4903-9916-0e90e38b255e` +- artwork (String) → stateTypeId: `44304c82-c2f6-433b-b62b-815382617d0b` +- shuffle (Bool) → stateTypeId: `5913aa2a-629d-4de5-bf44-a4a1f130c118` +- repeat (String) → stateTypeId: `bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e` + +#### Actions + +- mute → actionTypeId: `bc98cdb0-4d0e-48ca-afc7-922e49bb7813` + - Parameters: + - mute (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bc98cdb0-4d0e-48ca-afc7-922e49bb7813", + "params": { + "mute": "" + } + } + } + +- volume → actionTypeId: `9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9` + - Parameters: + - volume (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9", + "params": { + "volume": "" + } + } + } + +- playbackStatus → actionTypeId: `2dd512b7-40c2-488e-8d4f-6519edaa6f74` + - Parameters: + - playbackStatus (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "2dd512b7-40c2-488e-8d4f-6519edaa6f74", + "params": { + "playbackStatus": "" + } + } + } + +- shuffle → actionTypeId: `5913aa2a-629d-4de5-bf44-a4a1f130c118` + - Parameters: + - shuffle (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5913aa2a-629d-4de5-bf44-a4a1f130c118", + "params": { + "shuffle": "" + } + } + } + +- repeat → actionTypeId: `bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e` + - Parameters: + - repeat (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e", + "params": { + "repeat": "" + } + } + } + +- skipBack → actionTypeId: `a180807d-1265-4831-9d86-a421767418dd` +- fastRewind → actionTypeId: `7e70b47b-7e79-4521-be34-04a3c427e5b1` +- stop → actionTypeId: `ae3cbe03-ee3e-410e-abbd-efabc2402198` +- play → actionTypeId: `4d2ee668-a2e3-4795-8b96-0c800b703b46` +- pause → actionTypeId: `3cf341cb-fe63-40bc-a450-9678d18e91e3` +- fastForward → actionTypeId: `6985250e-1188-4e44-b9dd-93303b5738a1` +- skipNext → actionTypeId: `85d7126a-b123-4a28-aeb4-d84bcfb4d14f` +- increaseVolume → actionTypeId: `3ec57983-01e7-4cc4-b266-8de86dfca82d` +- decreaseVolume → actionTypeId: `54497942-9bf8-492a-8f9c-9820a03e754e` +- notify → actionTypeId: `dc0aa3b5-4eae-4e58-a4ac-d4c124da53f1` + - Parameters: + - title (String) + - body (String) + - type (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "dc0aa3b5-4eae-4e58-a4ac-d4c124da53f1", + "params": { + "title": "", + "body": "", + "type": "" + } + } + } + +- navigate → actionTypeId: `28060803-aa85-44a4-9dec-ee669dfb629f` + - Parameters: + - to (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "28060803-aa85-44a4-9dec-ee669dfb629f", + "params": { + "to": "" + } + } + } + +- system → actionTypeId: `8d51cd64-ecef-44f8-85b0-697bef252ce5` + - Parameters: + - systemCommand (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8d51cd64-ecef-44f8-85b0-697bef252ce5", + "params": { + "systemCommand": "" + } + } + } + + +--- + +### fireSensor + +- ThingClassId: `6b49bd7e-4331-4e1b-bc1b-7860906fda15` + +#### States + +- fireDetected (Bool) → stateTypeId: `d139200e-a6b8-4dcd-a891-35a448461fcb` +- batteryCritical (Bool) → stateTypeId: `6d0a6178-5e86-4bb5-b1a2-929a6d732195` +- connected (Bool) → stateTypeId: `0b393a8a-3d4c-47fe-aeea-c9e201841901` +- signalStrength (Uint) → stateTypeId: `80dfad41-ecdf-4f4d-a63f-77611b107818` +- version (String) → stateTypeId: `7cd6219c-a7af-4789-a174-ce1167d97164` + +#### Actions + +- alarm → actionTypeId: `f19e752b-03d9-4848-9dd1-e92c9c21b749` + - Parameters: + - duration (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f19e752b-03d9-4848-9dd1-e92c9c21b749", + "params": { + "duration": "" + } + } + } + + +--- + +### wallSwitchModule + +- ThingClassId: `1a81dffb-42e9-48f4-8fc5-b5917a7548b4` + +#### States + +- connected (Bool) → stateTypeId: `d36454c9-a90e-415a-870a-5488ba981006` +- signalStrength (Uint) → stateTypeId: `ce55dd06-6d27-49f4-ad40-4a85bc126c2d` +- batteryLevel (Int) → stateTypeId: `6a5f652c-5fa1-4477-a68c-ec1f2a3c1f91` +- batteryCritical (Bool) → stateTypeId: `2e4453a3-b8de-4494-b49e-f09ca855ff77` +- updateStatus (String) → stateTypeId: `cd5f93c5-858c-41e2-b8af-1c23dc968636` +- currentVersion (String) → stateTypeId: `9b00b4fd-700f-4bb4-aa45-c3801cd11557` +- availableVersion (String) → stateTypeId: `6ab24ea7-2af6-4999-8033-9e84d95150c0` +- updateProgress (Uint) → stateTypeId: `454e6350-d58d-4dd0-ae9a-cfae25f5a8b9` + +#### Actions + +- performUpdate → actionTypeId: `a2706922-67da-4b83-8e5e-00627e607290` + +--- + +### powerSocket + +- ThingClassId: `760ecd1b-7365-4142-993b-9e4a3dc6f83f` + +#### States + +- connected (Bool) → stateTypeId: `d4e2983a-f4a3-401f-853e-8b0e2f1d245e` +- signalStrength (Uint) → stateTypeId: `0d200118-f5fc-4c88-851f-6c9440830b21` +- power (Bool) → stateTypeId: `799129a5-8f4f-4836-822f-d2f26465288b` +- currentPower (Double) → stateTypeId: `e98e7f15-31b1-44cd-ab9d-cce14a2d2df9` +- totalEnergyConsumed (Double) → stateTypeId: `dd36b0be-f34f-406b-be27-0fc374b333f9` + +#### Actions + +- power → actionTypeId: `799129a5-8f4f-4836-822f-d2f26465288b` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "799129a5-8f4f-4836-822f-d2f26465288b", + "params": { + "power": "" + } + } + } + + +--- + +### gpioButtonBbb + +- ThingClassId: `4a4b79b9-7e43-4fd7-840f-31108bef0ee2` + + +--- + +### htlcdSensor + +- ThingClassId: `036d0b38-8d5b-497b-8534-9d1dd555c376` + +#### States + +- connected (Bool) → stateTypeId: `69bde74d-4ef5-49f0-958c-0609687883e8` +- signalStrength (Uint) → stateTypeId: `dc4292ba-1d75-40dd-b55a-1e0d9aaf02ef` +- temperature (Double) → stateTypeId: `c7eef19a-d5c8-4f2c-8161-9545eb123ed6` +- humidity (Double) → stateTypeId: `3c256135-07ee-4e77-b3a5-91f05e977798` +- batteryLevel (Int) → stateTypeId: `45260385-cd14-4018-bf6e-d8df88a1b0b4` +- batteryCritical (Bool) → stateTypeId: `72ce81f9-57c8-4b43-afa2-3ecee459c409` + + +--- + +### openweathermap + +- ThingClassId: `985195aa-17ad-4530-88a4-cdd753d747d7` + +#### States + +- weatherCondition (String) → stateTypeId: `f16891f3-1174-44f6-a940-cffc8b64bdc1` +- updateTime (Int) → stateTypeId: `36b2f09b-7d77-4fbc-a68f-23d735dda0b1` +- temperature (Double) → stateTypeId: `6013402f-b5b1-46b3-8490-f0c20d62fe61` +- temperatureMin (Double) → stateTypeId: `14ec2781-cb04-4bbf-b097-7d01ef982630` +- temperatureMax (Double) → stateTypeId: `fefe5563-452f-4833-b5cf-49c3cc67c772` +- humidity (Int) → stateTypeId: `6f32ec73-3240-4630-ada9-1c10b8e98123` +- pressure (Double) → stateTypeId: `4a42eea9-00eb-440b-915e-dbe42180f83b` +- windSpeed (Double) → stateTypeId: `2bf63430-e9e2-4fbf-88e6-6f1b4770f287` +- windDirection (Int) → stateTypeId: `589e2ea5-65b2-4afd-9b72-e3708a589a12` +- cloudiness (Int) → stateTypeId: `798553bc-45c7-42eb-9105-430bddb5d9b7` +- visibility (Int) → stateTypeId: `1e10d129-cb88-48b0-9244-e3e7e7b175d9` +- weatherDescription (String) → stateTypeId: `f9539108-0e0e-4736-a306-6408f8e20a26` +- sunsetTime (Int) → stateTypeId: `af155e94-9492-44e1-8608-7d0ee8b5d50d` +- sunriseTime (Int) → stateTypeId: `a1dddc3d-549f-4f20-b78b-be850548f286` +- daylight (Bool) → stateTypeId: `e0a14b66-c8e1-49fb-8eff-b48e5dce80de` + +#### Actions + +- refreshWeather → actionTypeId: `cfbc6504-d86f-4856-8dfa-97b6fbb385e4` + +--- + +### motionSensor + +- ThingClassId: `25b79fff-4b88-4af8-b06c-2fe246238790` + +#### States + +- connected (Bool) → stateTypeId: `19c28b69-a9c2-4908-8255-7681f72c2d92` +- batteryLevel (Int) → stateTypeId: `ac463b30-24af-4352-84da-19a3ffc906bd` +- batteryCritical (Bool) → stateTypeId: `d7c4e143-6f03-411e-a12e-dd22806270fd` +- temperature (Double) → stateTypeId: `63ee79f7-702b-48c1-86cf-8ddebb78bae6` +- lightIntensity (Double) → stateTypeId: `064f48c1-f86d-4a0a-bdae-3420123dff3f` +- isPresent (Bool) → stateTypeId: `e38ee39c-c77f-40b5-b122-4efc411da0ed` +- lastSeenTime (Int) → stateTypeId: `ef2e564e-2443-448f-bcd9-f85a1126ee6a` + + +--- + +### powerSwitch + +- ThingClassId: `57daa147-dd6f-4673-a757-d8f01a2054c7` + +#### States + +- power (Bool) → stateTypeId: `08087af6-6a3b-4e4a-ac6d-56f23ce63edf` + +#### Actions + +- power → actionTypeId: `08087af6-6a3b-4e4a-ac6d-56f23ce63edf` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "08087af6-6a3b-4e4a-ac6d-56f23ce63edf", + "params": { + "power": "" + } + } + } + + +--- + +### lumiMotionSensor + +- ThingClassId: `b5530192-0891-4934-88a2-7338b069be24` + +#### States + +- connected (Bool) → stateTypeId: `007e2fe5-80d5-4f98-941d-b458b555965a` +- signalStrength (Uint) → stateTypeId: `c5913170-e377-484b-a330-c5d5b590fee2` +- version (String) → stateTypeId: `d1337b3b-0dfb-4505-90f1-e5b2b45be9bd` +- isPresent (Bool) → stateTypeId: `fed7582b-c057-42ab-b7c0-d562a2e7917c` +- lastSeenTime (Int) → stateTypeId: `021ce190-a775-40e0-b19b-c6307c73e343` +- lightIntensity (Double) → stateTypeId: `eb3fb43e-a9bb-4498-880b-464cbb752ff6` + + +--- + +### sonoff_tri + +- ThingClassId: `e1073af2-f207-4dc9-8caa-e933421885db` + +#### States + +- connected (Bool) → stateTypeId: `e6439ea4-4373-4ac1-a790-748604cf2830` +- signalStrength (Uint) → stateTypeId: `08b4ec84-1aec-4e68-a3b4-ae251b8cbe6d` +- powerCH1 (Bool) → stateTypeId: `27bdb42d-ef95-4905-ac3d-925bcc8a1ba1` +- powerCH2 (Bool) → stateTypeId: `705d8277-896a-4d56-b9ff-0a614ecfd39c` +- powerCH3 (Bool) → stateTypeId: `156f285d-e474-43d9-9a9d-17b3bcaef893` + +#### Actions + +- powerCH1 → actionTypeId: `27bdb42d-ef95-4905-ac3d-925bcc8a1ba1` + - Parameters: + - powerCH1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "27bdb42d-ef95-4905-ac3d-925bcc8a1ba1", + "params": { + "powerCH1": "" + } + } + } + +- powerCH2 → actionTypeId: `705d8277-896a-4d56-b9ff-0a614ecfd39c` + - Parameters: + - powerCH2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "705d8277-896a-4d56-b9ff-0a614ecfd39c", + "params": { + "powerCH2": "" + } + } + } + +- powerCH3 → actionTypeId: `156f285d-e474-43d9-9a9d-17b3bcaef893` + - Parameters: + - powerCH3 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "156f285d-e474-43d9-9a9d-17b3bcaef893", + "params": { + "powerCH3": "" + } + } + } + + +--- + +### energyStorage + +- ThingClassId: `81418556-cae3-4803-aa0c-9c4b3304a3eb` + +#### States + +- currentPower (Double) → stateTypeId: `8d1c43f9-4528-4797-8f6a-f7b91fbb91d0` +- batteryLevel (Int) → stateTypeId: `d37eed4a-befc-40d4-b435-40a761f99314` +- charging (Bool) → stateTypeId: `a61c0328-b982-46a5-9cc0-b4fa4d0ab84d` +- batteryCritical (Bool) → stateTypeId: `e95dc037-002d-40a2-8c15-cd5489bd354a` +- capacity (Double) → stateTypeId: `bf076970-20fe-46f7-b4bc-fe34ec833829` + +#### Actions + +- currentPower → actionTypeId: `8d1c43f9-4528-4797-8f6a-f7b91fbb91d0` + - Parameters: + - currentPower (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8d1c43f9-4528-4797-8f6a-f7b91fbb91d0", + "params": { + "currentPower": "" + } + } + } + +- batteryLevel → actionTypeId: `d37eed4a-befc-40d4-b435-40a761f99314` + - Parameters: + - batteryLevel (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d37eed4a-befc-40d4-b435-40a761f99314", + "params": { + "batteryLevel": "" + } + } + } + +- charging → actionTypeId: `a61c0328-b982-46a5-9cc0-b4fa4d0ab84d` + - Parameters: + - charging (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a61c0328-b982-46a5-9cc0-b4fa4d0ab84d", + "params": { + "charging": "" + } + } + } + + +--- + +### extendedAwning + +- ThingClassId: `be9ffcc5-28b9-4db9-aaec-d6e758776a60` + +#### States + +- openingOutput (Bool) → stateTypeId: `43c174e2-31d2-4256-a81f-09997ec1c0a3` +- closingOutput (Bool) → stateTypeId: `4992092c-d765-4764-a3d5-658171a74093` +- status (String) → stateTypeId: `c24f6229-91df-4ca5-8555-d6d5d948062c` +- moving (Bool) → stateTypeId: `010d3f47-7c05-4e71-a2f9-3f53958e8095` +- percentage (Int) → stateTypeId: `ce82e5d1-dbb8-4916-a966-a2ab85e4cda7` + +#### Actions + +- openingOutput → actionTypeId: `43c174e2-31d2-4256-a81f-09997ec1c0a3` + - Parameters: + - openingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "43c174e2-31d2-4256-a81f-09997ec1c0a3", + "params": { + "openingOutput": "" + } + } + } + +- closingOutput → actionTypeId: `4992092c-d765-4764-a3d5-658171a74093` + - Parameters: + - closingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4992092c-d765-4764-a3d5-658171a74093", + "params": { + "closingOutput": "" + } + } + } + +- percentage → actionTypeId: `ce82e5d1-dbb8-4916-a966-a2ab85e4cda7` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ce82e5d1-dbb8-4916-a966-a2ab85e4cda7", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `4ee66b18-0c2b-4578-9ae1-34d816e84563` +- stop → actionTypeId: `48ae5686-7bd6-4f10-a6a4-2ac502aafa5f` +- close → actionTypeId: `6e71e4a1-af8b-4a93-a66c-ef1782e03621` + +--- + +### colorBulb + +- ThingClassId: `12907c9c-e7f0-47f2-bd58-39d52ffdf24e` + +#### States + +- connected (Bool) → stateTypeId: `dc4c1640-90f3-4fe0-af9b-db7fa105f18a` +- power (Bool) → stateTypeId: `12de3f8f-2454-4057-aa12-9290296fdbdd` +- colorTemperature (Int) → stateTypeId: `dd7d7e70-5552-4531-8789-2d0f750488be` +- color (Color) → stateTypeId: `a47d8164-5023-4ffb-8298-73293e93e7f6` +- brightness (Int) → stateTypeId: `8bd20350-0e79-45dc-b68a-84da99356863` +- effect (String) → stateTypeId: `65f88396-2958-480e-b0be-c4695400a343` + +#### Actions + +- power → actionTypeId: `12de3f8f-2454-4057-aa12-9290296fdbdd` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "12de3f8f-2454-4057-aa12-9290296fdbdd", + "params": { + "power": "" + } + } + } + +- colorTemperature → actionTypeId: `dd7d7e70-5552-4531-8789-2d0f750488be` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "dd7d7e70-5552-4531-8789-2d0f750488be", + "params": { + "colorTemperature": "" + } + } + } + +- color → actionTypeId: `a47d8164-5023-4ffb-8298-73293e93e7f6` + - Parameters: + - color (Color) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a47d8164-5023-4ffb-8298-73293e93e7f6", + "params": { + "color": "" + } + } + } + +- brightness → actionTypeId: `8bd20350-0e79-45dc-b68a-84da99356863` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8bd20350-0e79-45dc-b68a-84da99356863", + "params": { + "brightness": "" + } + } + } + +- effect → actionTypeId: `65f88396-2958-480e-b0be-c4695400a343` + - Parameters: + - effect (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "65f88396-2958-480e-b0be-c4695400a343", + "params": { + "effect": "" + } + } + } + + +--- + +### shelly2 + +- ThingClassId: `f277d3a3-62e0-49c1-90b2-4108578e80bf` + +#### States + +- connected (Bool) → stateTypeId: `966ddc70-aa75-4c86-a75e-c1a010698d93` +- signalStrength (Uint) → stateTypeId: `ed8d3275-4d47-406b-9adf-0355a9bff31e` +- updateStatus (String) → stateTypeId: `8f544e5f-f200-47aa-82c4-46aa9838c96e` +- currentVersion (String) → stateTypeId: `b38b19da-4403-40a2-8aa3-81518d092505` +- availableVersion (String) → stateTypeId: `6f081a46-df7d-43df-acb0-a7f226c0fd71` +- channel1 (Bool) → stateTypeId: `e3179799-96ca-47a4-8771-888f523247ac` +- channel2 (Bool) → stateTypeId: `0e50c443-786a-4067-b1df-2b183434a546` + +#### Actions + +- channel1 → actionTypeId: `e3179799-96ca-47a4-8771-888f523247ac` + - Parameters: + - channel1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e3179799-96ca-47a4-8771-888f523247ac", + "params": { + "channel1": "" + } + } + } + +- channel2 → actionTypeId: `0e50c443-786a-4067-b1df-2b183434a546` + - Parameters: + - channel2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "0e50c443-786a-4067-b1df-2b183434a546", + "params": { + "channel2": "" + } + } + } + +- reboot → actionTypeId: `f444ff28-07b1-40fe-b450-c373a6341411` +- performUpdate → actionTypeId: `4ca44813-1ee3-4aee-89c7-a667fe1c8ddc` + +--- + +### countdown + +- ThingClassId: `805c8948-e663-4ba6-aa67-df7446ed7098` + +#### States + +- running (Bool) → stateTypeId: `b21ccd53-1ebd-41a0-a2a3-662874e79837` + +#### Actions + +- start → actionTypeId: `436e9923-6eff-444e-bde7-a61228a4d748` +- stop → actionTypeId: `bf4d1def-4159-4254-a76d-fd31aaa84e2d` +- restart → actionTypeId: `14aad613-b972-411f-93c9-f00bfd254285` + +--- + +### sonoff_dual + +- ThingClassId: `425ab191-833c-4618-8ac8-aff02370b99d` + +#### States + +- connected (Bool) → stateTypeId: `e2f55332-e706-412e-beb6-abf76b3bcff3` +- signalStrength (Uint) → stateTypeId: `3d6a567f-d266-4711-bcf1-3ac1f53abadb` +- powerCH1 (Bool) → stateTypeId: `b8bf3085-8061-4cd6-af1f-f76a03054f46` +- powerCH2 (Bool) → stateTypeId: `4fbcaeb6-9242-4aa6-b462-a214fb38bcc9` + +#### Actions + +- powerCH1 → actionTypeId: `b8bf3085-8061-4cd6-af1f-f76a03054f46` + - Parameters: + - powerCH1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b8bf3085-8061-4cd6-af1f-f76a03054f46", + "params": { + "powerCH1": "" + } + } + } + +- powerCH2 → actionTypeId: `4fbcaeb6-9242-4aa6-b462-a214fb38bcc9` + - Parameters: + - powerCH2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4fbcaeb6-9242-4aa6-b462-a214fb38bcc9", + "params": { + "powerCH2": "" + } + } + } + + +--- + +### moistureSensor + +- ThingClassId: `33e610cf-ff30-481b-9f0b-d6857bcd41a5` + +#### States + +- moisture (Double) → stateTypeId: `7a62e1d2-92f2-424c-876c-870478a4b2bd` +- input (Double) → stateTypeId: `ce64a425-d990-4fc1-966b-be6de445792b` + +#### Actions + +- moisture → actionTypeId: `7a62e1d2-92f2-424c-876c-870478a4b2bd` + - Parameters: + - moisture (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7a62e1d2-92f2-424c-876c-870478a4b2bd", + "params": { + "moisture": "" + } + } + } + +- input → actionTypeId: `ce64a425-d990-4fc1-966b-be6de445792b` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ce64a425-d990-4fc1-966b-be6de445792b", + "params": { + "input": "" + } + } + } + + +--- + +### extendedStatefulGaragedoor + +- ThingClassId: `7341e689-4495-4422-851a-3e7c790394b8` + +#### States + +- state (String) → stateTypeId: `0cc74edb-7116-47cf-953a-409933f26557` +- moving (Bool) → stateTypeId: `963bed3d-2ccb-4dd0-b609-c7e9f25d32d6` +- percentage (Int) → stateTypeId: `f9244c14-0bc9-49ce-90a5-437e66245594` +- openingOutput (Bool) → stateTypeId: `ecc799c7-4d74-4d1f-94e5-2d74e77493ae` +- closingOutput (Bool) → stateTypeId: `e1c14bcd-6131-494b-8dd1-46738e9c8f5e` + +#### Actions + +- percentage → actionTypeId: `f9244c14-0bc9-49ce-90a5-437e66245594` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f9244c14-0bc9-49ce-90a5-437e66245594", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `4a3a3b88-47e9-436f-86be-b5955f3fc2f7` +- close → actionTypeId: `2420fcdb-03d3-4edb-aa89-e3b93c7d6d18` +- stop → actionTypeId: `109c3eaf-26a0-4121-8be2-1363253178fd` + +--- + +### gpioInputBbb + +- ThingClassId: `ffd2aa29-55cc-4824-ba95-c311784f7824` + +#### States + +- power (Bool) → stateTypeId: `22440876-417a-4d57-8e01-efe26ef9f235` + + +--- + +### orpSensor + +- ThingClassId: `3edeec39-ab9d-4697-90cc-0bba089384cf` + +#### States + +- orp (Double) → stateTypeId: `e5ed3535-2e5d-412e-85f8-782cbccd7731` +- input (Double) → stateTypeId: `020ff04f-a157-4925-9c55-2b45389208fc` + +#### Actions + +- orp → actionTypeId: `e5ed3535-2e5d-412e-85f8-782cbccd7731` + - Parameters: + - orp (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e5ed3535-2e5d-412e-85f8-782cbccd7731", + "params": { + "orp": "" + } + } + } + +- input → actionTypeId: `020ff04f-a157-4925-9c55-2b45389208fc` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "020ff04f-a157-4925-9c55-2b45389208fc", + "params": { + "input": "" + } + } + } + + +--- + +### waterSensor + +- ThingClassId: `09b9cb86-f551-4efe-9a7d-2f7624e9510f` + +#### States + +- waterDetected (Bool) → stateTypeId: `b2427b85-1f62-4635-b546-1961191426ef` + +#### Actions + +- waterDetected → actionTypeId: `b2427b85-1f62-4635-b546-1961191426ef` + - Parameters: + - waterDetected (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b2427b85-1f62-4635-b546-1961191426ef", + "params": { + "waterDetected": "" + } + } + } + + +--- + +### onOffLight + +- ThingClassId: `f720f31d-9523-4a74-9f10-19cbc9edeb58` + +#### States + +- connected (Bool) → stateTypeId: `111a5a4a-63d4-4d1d-ac72-b5b5a29fd0aa` +- power (Bool) → stateTypeId: `5dc5e71b-789e-4c68-abb6-1534c8af019e` + +#### Actions + +- power → actionTypeId: `5dc5e71b-789e-4c68-abb6-1534c8af019e` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5dc5e71b-789e-4c68-abb6-1534c8af019e", + "params": { + "power": "" + } + } + } + + +--- + +### powerMeterChannel + +- ThingClassId: `805487dd-768b-47d5-a0a9-c7021bbec6ff` + +#### States + +- connected (Bool) → stateTypeId: `f268fa63-e17f-41ab-9536-ec2e21a9164c` +- signalStrength (Uint) → stateTypeId: `5ef7fb87-901f-4f1f-8db0-1aa0e0ee633e` +- currentPower (Double) → stateTypeId: `bcd91dba-d063-445a-9680-32d64da29fc0` +- totalEnergyConsumed (Double) → stateTypeId: `ebd82e2f-4d23-451a-a26d-9c95fd3c00be` + + +--- + +### shelly1pm + +- ThingClassId: `30e74e9f-57f4-4bbc-b0df-f2c4f28b2f06` + +#### States + +- power (Bool) → stateTypeId: `ff44d332-52c3-4142-83e3-01d56c2eb42e` +- connected (Bool) → stateTypeId: `df23a5ea-5f54-42ac-ab6b-aea8f71224f0` +- signalStrength (Uint) → stateTypeId: `58531cb9-933e-457e-af07-7c6c22c28e51` +- updateStatus (String) → stateTypeId: `a290c9ad-356c-4387-9d82-2bf522643e16` +- currentVersion (String) → stateTypeId: `681f3a7e-d981-4cb2-a7dc-b889a9393276` +- availableVersion (String) → stateTypeId: `bd77d5f6-4958-4a8a-98f5-25931333a5d3` +- totalEnergyConsumed (Double) → stateTypeId: `23594959-1cd4-4e23-a7ae-b0b7fbd29daa` +- currentPower (Double) → stateTypeId: `3ec03053-7cf5-44fb-ad92-041eed9edd9a` + +#### Actions + +- power → actionTypeId: `ff44d332-52c3-4142-83e3-01d56c2eb42e` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ff44d332-52c3-4142-83e3-01d56c2eb42e", + "params": { + "power": "" + } + } + } + +- reboot → actionTypeId: `3133cf3d-729d-4f36-9a6d-1eeecb07edde` +- performUpdate → actionTypeId: `edc735dd-8c6b-4f76-b05b-32c934b4fe3b` + +--- + +### modbusSolarInverter + +- ThingClassId: `12e0429e-e8ce-48bd-a11c-faaf0bd71856` + +#### States + +- connected (Bool) → stateTypeId: `3c60e2a7-31f3-4b0b-a3f9-ede042e82f22` +- voltagePhaseA (Double) → stateTypeId: `5a717aff-6bdb-4679-94d6-ec1bce7fa2af` +- voltagePhaseB (Double) → stateTypeId: `34eb5b54-7683-42ff-8320-9b2527d6381c` +- voltagePhaseC (Double) → stateTypeId: `2bd0a069-9d16-4d58-9f78-df682d92005d` +- currentPhaseA (Double) → stateTypeId: `48d4a7b7-b09a-4255-83dd-9eab8ea3a51c` +- currentPhaseB (Double) → stateTypeId: `479b27c4-01fc-45ef-a462-b8d8499b3422` +- currentPhaseC (Double) → stateTypeId: `f82bbba1-c68a-4c43-a3e5-10b00ed924d7` +- currentPower (Double) → stateTypeId: `225beb67-95ca-495c-aca8-cd3fd4efedd5` +- currentPowerPhaseA (Double) → stateTypeId: `9283d5a9-b185-4678-beb1-1c6ce6f76930` +- currentPowerPhaseB (Double) → stateTypeId: `8a87319c-f6ab-4eb1-bb17-a65f80289a56` +- currentPowerPhaseC (Double) → stateTypeId: `1f930456-5947-476c-b74b-480f1e81a799` +- totalEnergyProduced (Double) → stateTypeId: `5e0ed108-7e93-4724-a831-319109d9daf8` +- energyProducedToday (Double) → stateTypeId: `b8fb66fa-46b5-4ed7-82a7-29fe5257caa9` +- firmwareVersion (String) → stateTypeId: `3f290cbc-0578-479a-ab98-d89b5549184d` + + +--- + +### htSensor + +- ThingClassId: `3976d3fc-6bd3-4574-8c5b-90c9a07c6440` + +#### States + +- temperature (Double) → stateTypeId: `bb6ee147-2e36-4445-b3e9-449a5dfa9923` +- humidity (Double) → stateTypeId: `5cc739a8-b84a-49e4-af01-08eea0815abb` +- batteryCritical (Bool) → stateTypeId: `c12ee882-9e4e-4b62-b317-4a5a6162b00a` +- connected (Bool) → stateTypeId: `b15bc020-d6fd-4e0e-b3ce-6b7828416e02` +- signalStrength (Uint) → stateTypeId: `4b045aba-366c-49b5-a87e-389805319efe` +- version (String) → stateTypeId: `67cc511f-ef3f-47e9-a60d-4cb8b881703d` + + +--- + +### venetianblind + +- ThingClassId: `c7160205-d864-4194-b418-060fff60f0cb` + +#### States + +- percentage (Int) → stateTypeId: `77ca50db-42a7-4434-83e2-8b5fc4438924` +- angle (Int) → stateTypeId: `079c7a80-8a1c-4fd7-b40c-6800120c70fb` +- moving (Bool) → stateTypeId: `48d5de0a-11ab-4801-94e4-a1dd458c341d` +- signalStrength (Uint) → stateTypeId: `aee4f4e3-3445-441d-bdbb-631b0c5db942` +- connected (Bool) → stateTypeId: `57361115-edbe-49fb-9847-408b571d3108` + +#### Actions + +- percentage → actionTypeId: `77ca50db-42a7-4434-83e2-8b5fc4438924` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "77ca50db-42a7-4434-83e2-8b5fc4438924", + "params": { + "percentage": "" + } + } + } + +- angle → actionTypeId: `079c7a80-8a1c-4fd7-b40c-6800120c70fb` + - Parameters: + - angle (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "079c7a80-8a1c-4fd7-b40c-6800120c70fb", + "params": { + "angle": "" + } + } + } + +- open → actionTypeId: `004e7294-59e6-498b-a0aa-e58eaeefdf2b` +- stop → actionTypeId: `31b07407-65ef-4fd1-880b-b5d9f69a9d07` +- close → actionTypeId: `1a9707e7-9d64-4237-b150-234edcfed12a` + +--- + +### wallbox + +- ThingClassId: `6f453eaa-7594-4be8-a92d-14878193071a` + +#### States + +- maxChargingCurrent (Double) → stateTypeId: `1e0890e5-065a-455a-a068-10b0231897f4` +- power (Bool) → stateTypeId: `51c7b606-1eb0-418a-8203-3f0fb9d6e454` +- pluggedIn (Bool) → stateTypeId: `e9cc633d-35a6-4a86-8e97-14b12ba06d8e` +- charging (Bool) → stateTypeId: `b5d43614-7ed0-4c6e-b48a-f74aa9884769` +- phaseCount (Uint) → stateTypeId: `08fbe34e-735d-4ce5-81c7-ea1c7b07877b` +- desiredPhaseCount (Uint) → stateTypeId: `68239a43-c627-4b31-bc48-e8a814066cc5` +- currentPower (Double) → stateTypeId: `596a002d-77f4-410c-8ca9-3a4bb8051328` +- totalEnergyConsumed (Double) → stateTypeId: `c3b4303f-7267-4401-b2da-2378d39d762d` + +#### Actions + +- maxChargingCurrent → actionTypeId: `1e0890e5-065a-455a-a068-10b0231897f4` + - Parameters: + - maxChargingCurrent (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1e0890e5-065a-455a-a068-10b0231897f4", + "params": { + "maxChargingCurrent": "" + } + } + } + +- power → actionTypeId: `51c7b606-1eb0-418a-8203-3f0fb9d6e454` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "51c7b606-1eb0-418a-8203-3f0fb9d6e454", + "params": { + "power": "" + } + } + } + +- pluggedIn → actionTypeId: `e9cc633d-35a6-4a86-8e97-14b12ba06d8e` + - Parameters: + - pluggedIn (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e9cc633d-35a6-4a86-8e97-14b12ba06d8e", + "params": { + "pluggedIn": "" + } + } + } + +- charging → actionTypeId: `b5d43614-7ed0-4c6e-b48a-f74aa9884769` + - Parameters: + - charging (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b5d43614-7ed0-4c6e-b48a-f74aa9884769", + "params": { + "charging": "" + } + } + } + +- phaseCount → actionTypeId: `08fbe34e-735d-4ce5-81c7-ea1c7b07877b` + - Parameters: + - phaseCount (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "08fbe34e-735d-4ce5-81c7-ea1c7b07877b", + "params": { + "phaseCount": "" + } + } + } + +- desiredPhaseCount → actionTypeId: `68239a43-c627-4b31-bc48-e8a814066cc5` + - Parameters: + - desiredPhaseCount (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "68239a43-c627-4b31-bc48-e8a814066cc5", + "params": { + "desiredPhaseCount": "" + } + } + } + +- currentPower → actionTypeId: `596a002d-77f4-410c-8ca9-3a4bb8051328` + - Parameters: + - currentPower (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "596a002d-77f4-410c-8ca9-3a4bb8051328", + "params": { + "currentPower": "" + } + } + } + +- totalEnergyConsumed → actionTypeId: `c3b4303f-7267-4401-b2da-2378d39d762d` + - Parameters: + - totalEnergyConsumed (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c3b4303f-7267-4401-b2da-2378d39d762d", + "params": { + "totalEnergyConsumed": "" + } + } + } + + +--- + +### cookTop + +- ThingClassId: `6ab99f5b-c8b6-4391-84d3-2e258a529174` + +#### States + +- connected (Bool) → stateTypeId: `d8113d26-045d-4fd5-a2f5-f202968408e0` + + +--- + +### tapDial + +- ThingClassId: `58e579b4-f917-478c-9006-f1f8d4df2ded` + +#### States + +- connected (Bool) → stateTypeId: `7c81af92-3643-4211-9d62-407cbc596619` +- batteryLevel (Int) → stateTypeId: `9d0d190f-2898-4c9a-a423-ec7187bfcb5e` +- batteryCritical (Bool) → stateTypeId: `79efe477-2757-4457-bdfb-a3fbeb198e7a` +- level (Uint) → stateTypeId: `23528402-b98f-49b8-90cf-7b68f251ad59` + + +--- + +### netPwrCtlPro + +- ThingClassId: `1492f911-1c09-42ce-b920-084548a689ea` + +#### States + +- connected (Bool) → stateTypeId: `820c54bd-0d4f-4e13-8160-a8efa77c9db5` +- temperature (Double) → stateTypeId: `2973ec1e-9c26-45ad-a97b-dd5eccbf650a` + + +--- + +### simpleGaragedoor + +- ThingClassId: `572403b1-bc22-4620-8170-53147a546033` + +#### States + +- openingOutput (Bool) → stateTypeId: `fcd421eb-54f2-4195-bdef-ffa69e9dcc57` +- closingOutput (Bool) → stateTypeId: `44ef060a-e6fc-4f33-84d2-b24ac7d31ff1` + +#### Actions + +- open → actionTypeId: `3edb25af-ad51-495b-9ac9-ab97669339b7` +- close → actionTypeId: `1111c0ed-69b6-480c-9fd5-15292600d4f4` +- stop → actionTypeId: `f346766f-44ee-452b-bb9c-e89ec0f56016` + +--- + +### keba + +- ThingClassId: `900dacec-cae7-4a37-95ba-501846368ea2` + +#### States + +- connected (Bool) → stateTypeId: `ce813458-d7d8-4f40-9648-dba4c41e92f0` +- power (Bool) → stateTypeId: `83ed0774-2a91-434d-b03c-d920d02f2981` +- systemEnabled (Bool) → stateTypeId: `e5631593-f486-47cb-9951-b7597d0b769b` +- phaseCount (Uint) → stateTypeId: `6713b2e7-41b3-4596-a304-3065726bdbe4` +- activity (String) → stateTypeId: `539e5602-6dd9-465d-9705-3bb59bcf8982` +- plugState (String) → stateTypeId: `3b4d29f3-3101-47ad-90fd-269b6348783b` +- pluggedIn (Bool) → stateTypeId: `6c227717-f420-4dcd-bd52-49973715603b` +- charging (Bool) → stateTypeId: `c9785626-2501-478d-8c18-c42ad5d9a269` +- maxChargingCurrent (Double) → stateTypeId: `593656f0-babf-4308-8767-68f34e10fb15` +- maxChargingCurrentPercent (Uint) → stateTypeId: `3c7b83a0-0e42-47bf-9788-dde6aab5ceea` +- maxChargingCurrentHardware (Uint) → stateTypeId: `33e2ed95-f01e-44db-8156-34d124a8ecc8` +- voltagePhaseA (Int) → stateTypeId: `4a2d75d8-a3a0-4b40-9ca7-e8b6f11d0ef9` +- voltagePhaseB (Int) → stateTypeId: `c8344ca5-21ac-4cd1-8f4b-e5ed202c5862` +- voltagePhaseC (Int) → stateTypeId: `5f01e86c-0943-4849-a01a-db441916ebd5` +- currentPhaseA (Double) → stateTypeId: `31ec17b0-11e3-4332-92b0-fea821cf024f` +- currentPhaseB (Double) → stateTypeId: `cdc7e10a-0d0a-4e93-ad2c-d34ffca45c97` +- currentPhaseC (Double) → stateTypeId: `da838dc8-85f0-4e55-b4b5-cb93a43b373d` +- currentPower (Double) → stateTypeId: `7af9e93b-099d-4d9d-a480-9c0f66aecd8b` +- powerFactor (Double) → stateTypeId: `889c3c9a-96b4-4408-bd9a-d79e36ed9296` +- sessionId (Uint) → stateTypeId: `1d30ce60-2ea0-450f-817e-5c88f59ebfbf` +- sessionTime (Int) → stateTypeId: `a6f35ea0-aaea-438b-b818-6d161762611e` +- sessionEnergy (Double) → stateTypeId: `8e277efe-21ef-4536-bfc0-901b32d44d7c` +- totalEnergyConsumed (Double) → stateTypeId: `41e179b3-29a2-43ec-b537-023a527081e8` +- outputX2 (Bool) → stateTypeId: `96b2d176-6460-4109-8824-3af4679c6573` +- input (Bool) → stateTypeId: `ba600276-8b36-4404-b8ec-415245e5bc15` +- uptime (Int) → stateTypeId: `3421ecf9-c95f-4dc1-ad0c-144e9b6ae056` +- error1 (Int) → stateTypeId: `b44bc948-1234-4f87-9a22-bfb6de09df4d` +- error2 (Int) → stateTypeId: `afca201a-5213-43fe-bfec-cae6ce7509d2` +- failsafeMode (Bool) → stateTypeId: `f1758c5c-2c02-41cb-93ec-b778a3c78d28` +- firmware (String) → stateTypeId: `e941ace5-fb7f-4dc2-b3f2-188233f4e934` +- hostAddress (String) → stateTypeId: `11501a4b-8b83-4b92-be3c-a714d507f158` + +#### Actions + +- power → actionTypeId: `83ed0774-2a91-434d-b03c-d920d02f2981` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "83ed0774-2a91-434d-b03c-d920d02f2981", + "params": { + "power": "" + } + } + } + +- maxChargingCurrent → actionTypeId: `593656f0-babf-4308-8767-68f34e10fb15` + - Parameters: + - maxChargingCurrent (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "593656f0-babf-4308-8767-68f34e10fb15", + "params": { + "maxChargingCurrent": "" + } + } + } + +- outputX2 → actionTypeId: `96b2d176-6460-4109-8824-3af4679c6573` + - Parameters: + - outputX2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "96b2d176-6460-4109-8824-3af4679c6573", + "params": { + "outputX2": "" + } + } + } + +- failsafeMode → actionTypeId: `f1758c5c-2c02-41cb-93ec-b778a3c78d28` + - Parameters: + - failsafeMode (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f1758c5c-2c02-41cb-93ec-b778a3c78d28", + "params": { + "failsafeMode": "" + } + } + } + +- display → actionTypeId: `158b1a8f-fde9-4191-bf42-4ece5fe582e6` + - Parameters: + - message (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "158b1a8f-fde9-4191-bf42-4ece5fe582e6", + "params": { + "message": "" + } + } + } + + +--- + +### signalRepeater + +- ThingClassId: `ac51f426-195e-472a-837f-4ba7e4666e6e` + +#### States + +- connected (Bool) → stateTypeId: `7415ea93-9b72-4740-b3b1-a2ebb73d1db5` +- signalStrength (Uint) → stateTypeId: `05758f08-33a8-485b-8572-f87021e3af36` +- currentVersion (String) → stateTypeId: `05d9a4f4-5d7e-474b-b57c-445f795a0d90` +- updateStatus (String) → stateTypeId: `7cf5dbb5-672f-4c17-ab52-bd62a4289f44` +- availableVersion (String) → stateTypeId: `b092b5e3-496d-44a2-a15b-00cb6b7462f4` +- updateProgress (Uint) → stateTypeId: `3ff0a3ab-f3fe-4dac-8b1a-d30676fde7f3` + +#### Actions + +- performUpdate → actionTypeId: `4e6544cc-0f99-460f-92aa-f00c77f8131a` + +--- + +### airHousekeeper + +- ThingClassId: `bed2680c-ebce-49ab-86cc-7c3c69e34372` + +#### States + +- connected (Bool) → stateTypeId: `984b266b-e8b9-4566-a6ef-cc2aaf41333e` +- signalStrength (Uint) → stateTypeId: `cf87d713-bdb6-4768-ad48-92b1ce5835ce` +- temperature (Double) → stateTypeId: `2cb06847-a98e-4440-ab5a-990a4073f7e6` +- humidity (Double) → stateTypeId: `021ad175-3e09-4f9c-a457-231b71681699` +- voc (Uint) → stateTypeId: `0e5d6b08-d415-43e2-9314-e97e526e105d` +- pm25 (Double) → stateTypeId: `1f9460ba-8495-4a00-a3ac-de4efcb40c1c` +- co2 (Double) → stateTypeId: `f0621e7f-46b0-40a6-8bce-54164e8518ae` +- formaldehyd (Double) → stateTypeId: `2a8353ca-b1aa-4d7b-8951-e24febe87bbc` +- batteryLevel (Int) → stateTypeId: `24c68257-5e33-493f-acee-6c3cdce1bbf1` +- batteryCritical (Bool) → stateTypeId: `1cadb85c-3c1b-4cd4-8878-d32c71234758` + + +--- + +### heos + +- ThingClassId: `28bbf4c6-dfd8-4d9d-aa27-5daf2c25d63c` + +#### States + +- connected (Bool) → stateTypeId: `4d1790bf-28c6-4c1f-8892-ba1a0ef140f5` +- loggedIn (Bool) → stateTypeId: `ab689a6e-eb71-4a41-a267-ba1afe7e2f56` +- userDisplayName (String) → stateTypeId: `77756132-5fa4-409e-969e-d23bcee72356` + +#### Actions + +- reboot → actionTypeId: `4f8b7fe8-7a18-483a-859d-ed5acb0b9a20` + +--- + +### kebaSimple + +- ThingClassId: `c5bca9d2-2a17-40c4-8bb2-ba89783a6dd1` + +#### States + +- connected (Bool) → stateTypeId: `995f2ccf-2082-434e-a46d-c506862e6d6a` +- power (Bool) → stateTypeId: `63f84293-62aa-420d-bc0d-cc48618c6526` +- systemEnabled (Bool) → stateTypeId: `8ade4b68-e44e-425c-87ea-a35d176f337d` +- phaseCount (Uint) → stateTypeId: `2473e39b-9641-4236-be56-e706d7797161` +- activity (String) → stateTypeId: `955ffd64-42f6-4000-94c5-c7f862daa438` +- plugState (String) → stateTypeId: `82aa0d67-eea6-4a5e-b7ab-2848a4012490` +- pluggedIn (Bool) → stateTypeId: `faf68cc9-f014-4db5-94fa-0f10a0b85fb1` +- charging (Bool) → stateTypeId: `38affdf2-f62e-458c-b738-8db81aa13790` +- maxChargingCurrent (Double) → stateTypeId: `2a72ad9e-96bd-4281-afb7-ce4f5c6f5052` +- maxChargingCurrentPercent (Uint) → stateTypeId: `33631b7f-a675-4625-8095-31e09e03a010` +- maxChargingCurrentHardware (Uint) → stateTypeId: `f94a2381-28a8-478e-ac44-0902a5be8885` +- outputX2 (Bool) → stateTypeId: `043ea799-4348-44f9-985d-bee2ba280957` +- input (Bool) → stateTypeId: `0ca0921d-5516-44fb-9483-242d9bb7a2d0` +- uptime (Int) → stateTypeId: `2cffff03-63b2-468d-b2ef-a4741401d7c8` +- error1 (Int) → stateTypeId: `8380c340-84ee-4d62-84b0-7c5738ab66bc` +- error2 (Int) → stateTypeId: `afe287a2-35e2-4762-a6bf-79d7c31d32ab` +- failsafeMode (Bool) → stateTypeId: `bfad6a1a-40e0-4b32-9f42-09efd5a7e94c` +- firmware (String) → stateTypeId: `d473770e-c5b4-4845-8215-0dea304ea202` +- hostAddress (String) → stateTypeId: `eef1d569-f383-4980-8cb8-06ccc5069b0b` + +#### Actions + +- power → actionTypeId: `63f84293-62aa-420d-bc0d-cc48618c6526` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "63f84293-62aa-420d-bc0d-cc48618c6526", + "params": { + "power": "" + } + } + } + +- maxChargingCurrent → actionTypeId: `2a72ad9e-96bd-4281-afb7-ce4f5c6f5052` + - Parameters: + - maxChargingCurrent (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "2a72ad9e-96bd-4281-afb7-ce4f5c6f5052", + "params": { + "maxChargingCurrent": "" + } + } + } + +- outputX2 → actionTypeId: `043ea799-4348-44f9-985d-bee2ba280957` + - Parameters: + - outputX2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "043ea799-4348-44f9-985d-bee2ba280957", + "params": { + "outputX2": "" + } + } + } + +- failsafeMode → actionTypeId: `bfad6a1a-40e0-4b32-9f42-09efd5a7e94c` + - Parameters: + - failsafeMode (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bfad6a1a-40e0-4b32-9f42-09efd5a7e94c", + "params": { + "failsafeMode": "" + } + } + } + +- display → actionTypeId: `e756c842-bec5-42ee-a28b-280d48e834b1` + - Parameters: + - message (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e756c842-bec5-42ee-a28b-280d48e834b1", + "params": { + "message": "" + } + } + } + + +--- + +### lumiMotionSensor2 + +- ThingClassId: `6e9c7ced-cfc6-4ea3-9a68-b3820c9b0030` + +#### States + +- connected (Bool) → stateTypeId: `e80bb10c-953b-4845-8c61-2f51e84f9cfe` +- signalStrength (Uint) → stateTypeId: `7e736041-29a7-4f7f-82b6-3e17d01b3943` +- version (String) → stateTypeId: `2081fea2-8fac-4541-b414-3f5584aed67c` +- isPresent (Bool) → stateTypeId: `c70a2674-5b91-4a48-b696-ae9e80cc6e3a` +- lastSeenTime (Int) → stateTypeId: `bdaab055-8a1d-42cd-95e4-d77ab065292a` +- lightIntensity (Double) → stateTypeId: `bb34c29b-1519-453a-a19b-57d024977d49` + + +--- + +### irrigation + +- ThingClassId: `d013b980-20d5-4791-9c4f-b411c39241d7` + +#### States + +- power (Bool) → stateTypeId: `0212a287-c5ae-4644-8803-adfdd8caeb9a` + +#### Actions + +- power → actionTypeId: `0212a287-c5ae-4644-8803-adfdd8caeb9a` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "0212a287-c5ae-4644-8803-adfdd8caeb9a", + "params": { + "power": "" + } + } + } + + +--- + +### blind + +- ThingClassId: `17ee3657-6ad8-4ae2-8959-3cf66cec8d13` + +#### States + +- openingOutput (Bool) → stateTypeId: `b2dbf25c-27e5-4f7e-a57d-2ef6d087fa2b` +- closingOutput (Bool) → stateTypeId: `9b673430-572d-4a9c-85d3-dafadbe541cd` +- status (String) → stateTypeId: `5fdec1e0-51f6-48b9-b743-ba572504b2c1` + +#### Actions + +- openingOutput → actionTypeId: `b2dbf25c-27e5-4f7e-a57d-2ef6d087fa2b` + - Parameters: + - openingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "b2dbf25c-27e5-4f7e-a57d-2ef6d087fa2b", + "params": { + "openingOutput": "" + } + } + } + +- closingOutput → actionTypeId: `9b673430-572d-4a9c-85d3-dafadbe541cd` + - Parameters: + - closingOutput (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9b673430-572d-4a9c-85d3-dafadbe541cd", + "params": { + "closingOutput": "" + } + } + } + +- open → actionTypeId: `120dc265-dbbb-4f19-9d31-c372c23479c0` +- stop → actionTypeId: `1a924c9a-5dcb-4b1c-8fd6-ab101098e007` +- close → actionTypeId: `86e9cf21-7487-47c4-b4be-4a940d7235fb` + +--- + +### doorSensor + +- ThingClassId: `fd43b442-1764-4005-acaf-9075e6d11e3a` + +#### States + +- closed (Bool) → stateTypeId: `2fb8e0a0-52f2-4c1d-b1c9-c7a295a83b44` +- batteryLevel (Int) → stateTypeId: `3c120c1c-0093-4c5e-8d7e-8892e4ce21b3` +- batteryCritical (Bool) → stateTypeId: `9628450e-5580-4f30-8af7-f1c3093dcfb7` +- connected (Bool) → stateTypeId: `4fae59a7-fe89-4bc7-bc04-fc18e94b5c3e` +- signalStrength (Uint) → stateTypeId: `a1bf9c90-6e12-4513-a82a-a1d15351f140` + + +--- + +### motionSensor + +- ThingClassId: `fe7e6f2f-5ba2-4c39-b4c4-36d69e7c4738` + +#### States + +- connected (Bool) → stateTypeId: `56a58de9-fc2d-4ba4-b986-6494468c1297` +- signalStrength (Uint) → stateTypeId: `4d9dc0ee-4a91-48d0-8fad-bb1a88a30aef` +- isPresent (Bool) → stateTypeId: `baebd40c-a942-4228-a8cf-2bfbd5599cb3` +- batteryCritical (Bool) → stateTypeId: `b777b208-8cb1-457e-b3c0-52ec7e29bd4a` +- batteryLevel (Int) → stateTypeId: `209c5af4-d13e-4411-92db-e204aae3a34a` +- tampered (Bool) → stateTypeId: `044c823e-e4da-4a69-91fe-c4a94d774493` +- temperature (Double) → stateTypeId: `29207d04-0a34-4200-b933-a6bb3653fc56` +- lightIntensity (Double) → stateTypeId: `278c9d59-8948-4435-a94c-0eecc756b676` +- seismicIntensity (Double) → stateTypeId: `b69041c8-5262-45b8-b3bd-a0a7cbc8f3a2` + + +--- + +### smartMeterProducer + +- ThingClassId: `986acf96-3cdd-4a8d-8f5c-2ffe12fef1c9` + +#### States + +- currentPower (Double) → stateTypeId: `8fd67ad4-322d-46d7-a0fd-20fdbfc12bc5` +- totalEnergyProduced (Double) → stateTypeId: `58a1212c-ab6e-4631-b08d-712cdde295c7` + +#### Actions + +- currentPower → actionTypeId: `8fd67ad4-322d-46d7-a0fd-20fdbfc12bc5` + - Parameters: + - currentPower (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8fd67ad4-322d-46d7-a0fd-20fdbfc12bc5", + "params": { + "currentPower": "" + } + } + } + +- totalEnergyProduced → actionTypeId: `58a1212c-ab6e-4631-b08d-712cdde295c7` + - Parameters: + - totalEnergyProduced (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "58a1212c-ab6e-4631-b08d-712cdde295c7", + "params": { + "totalEnergyProduced": "" + } + } + } + + +--- + +### telegram + +- ThingClassId: `f71bac7a-90e1-4810-9c31-531ac5f596fb` + +#### Actions + +- notify → actionTypeId: `36b4ddf9-1a05-46c6-b0c9-2c3b8c835d42` + - Parameters: + - title (String) + - body (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "36b4ddf9-1a05-46c6-b0c9-2c3b8c835d42", + "params": { + "title": "", + "body": "" + } + } + } + + +--- + +### netPwrCtlAdv + +- ThingClassId: `99987919-d32d-4d8f-938c-bcf9683003b6` + +#### States + +- connected (Bool) → stateTypeId: `d143b775-e004-4119-a317-6c508686d473` +- temperature (Double) → stateTypeId: `aed7464a-6c36-4858-adb7-776d97c5498e` + + +--- + +### garagedoor + +- ThingClassId: `cb206d74-b13c-4466-98c6-070b19ebd23a` + +#### States + +- percentage (Int) → stateTypeId: `284816aa-842b-4a86-bb4e-ef5353b76762` +- moving (Bool) → stateTypeId: `07175175-f95d-4cd9-a398-9aab8232c2a9` +- signalStrength (Uint) → stateTypeId: `0a194091-3073-4912-9d84-f1d52c8534bd` +- connected (Bool) → stateTypeId: `5a32cbd3-bc1c-4724-ae53-9f36cb75bf84` +- state (String) → stateTypeId: `12af28f1-475e-4d05-9bbb-adbb86dcd69c` + +#### Actions + +- percentage → actionTypeId: `284816aa-842b-4a86-bb4e-ef5353b76762` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "284816aa-842b-4a86-bb4e-ef5353b76762", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `5738edd9-a1d1-4031-8505-85a919afe6f7` +- stop → actionTypeId: `75e345b8-0a25-4ba6-ba83-f2611252f87f` +- close → actionTypeId: `1e6552e3-8eb0-4070-b9cf-13fd13671eef` + +--- + +### smokeSensor + +- ThingClassId: `f41ea8de-6df0-40b6-8fc1-95334659a964` + +#### States + +- connected (Bool) → stateTypeId: `67df8dca-5da0-4909-84d0-684cdda5340a` +- signalStrength (Uint) → stateTypeId: `fc21bb2f-b35f-4847-a459-8db0ce66107c` +- version (String) → stateTypeId: `f4275d7b-5911-4422-8a97-a7a01300f281` +- fireDetected (Bool) → stateTypeId: `9ab61466-0ead-4d95-a6d5-c54951445bfb` +- temperature (Double) → stateTypeId: `3bcabb7b-8545-447b-98ba-761a1112f72b` +- batteryCritical (Bool) → stateTypeId: `d34ecef2-ceea-4e6f-8cd7-06f54593d594` +- updateStatus (String) → stateTypeId: `b3cdd902-dc00-4a6f-9ed0-c97347726397` +- currentVersion (String) → stateTypeId: `9170282f-eb7e-40ca-a6a6-cd51f7f3d2bb` +- availableVersion (String) → stateTypeId: `b7e5325d-640c-4781-91f0-68ce669cf873` +- updateProgress (Uint) → stateTypeId: `ac365d01-b58a-4974-a6c0-57472fd2553a` + +#### Actions + +- alarm → actionTypeId: `dc28424e-7414-4cba-b48d-e16a4e2cc1ec` + - Parameters: + - duration (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "dc28424e-7414-4cba-b48d-e16a4e2cc1ec", + "params": { + "duration": "" + } + } + } + +- performUpdate → actionTypeId: `2860002a-4d15-450a-b973-8877da4ad3ad` + +--- + +### vibrationSensor + +- ThingClassId: `3e03b237-a098-442c-a226-d51468bdbecc` + +#### Actions + +- triggerVibrationAlert → actionTypeId: `f6710702-5f1a-4819-8cc8-2ddb53134870` + +--- + +### heating + +- ThingClassId: `392854c4-3d14-4cf8-96cd-d933526bd197` + +#### States + +- power (Bool) → stateTypeId: `409b635e-a754-4b5c-b3f0-d1c5a0fb3f03` + +#### Actions + +- power → actionTypeId: `409b635e-a754-4b5c-b3f0-d1c5a0fb3f03` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "409b635e-a754-4b5c-b3f0-d1c5a0fb3f03", + "params": { + "power": "" + } + } + } + + +--- + +### storage + +- ThingClassId: `b00139fa-7386-48b1-8697-2fdd21a57ced` + +#### States + +- connected (Bool) → stateTypeId: `2f7e1267-b0be-4b78-9aa3-832b86c4efad` +- chargingState (String) → stateTypeId: `7a045257-d829-4e58-a769-047b3aeec7c5` +- currentPower (Double) → stateTypeId: `5a89cd3f-3abf-4f51-ab2b-4039f1d211d9` +- capacity (Double) → stateTypeId: `3b163deb-67a2-41d1-8441-b2d53ad846ef` +- batteryLevel (Int) → stateTypeId: `5c6da672-9662-41bc-8c8c-aa0f32481251` +- cellTemperature (Double) → stateTypeId: `4417499c-1757-4309-868a-be5cf3455c4a` +- batteryCritical (Bool) → stateTypeId: `e5396312-b50e-4d6f-b628-5b51448971d3` + + +--- + +### shelly3EM + +- ThingClassId: `c4428100-b270-4d95-91ae-492da8176311` + +#### States + +- connected (Bool) → stateTypeId: `3da67c4e-0a70-423b-a3bf-c6fb035ece0c` +- signalStrength (Uint) → stateTypeId: `a199035a-ede2-4b7e-8bbc-4346bddfc8ef` +- totalEnergyConsumed (Double) → stateTypeId: `1c3cf72d-46e8-47b7-b80b-312d23a16311` +- totalEnergyProduced (Double) → stateTypeId: `a7a74cfa-ade2-4527-af7e-1475fff5b88f` +- currentPower (Double) → stateTypeId: `a49564b6-71e6-4765-9758-af61898632c1` +- currentPowerPhaseA (Double) → stateTypeId: `687b3de6-7f02-45d2-ae23-015b8341be0b` +- currentPhaseA (Double) → stateTypeId: `0a5e4116-f486-49a8-bb49-2d911ff64fd8` +- voltagePhaseA (Double) → stateTypeId: `a17fc5ba-7250-4c29-85eb-06491925b3ce` +- energyConsumedPhaseA (Double) → stateTypeId: `39533108-28d9-4ec5-af17-b42c95dd73bc` +- energyProducedPhaseA (Double) → stateTypeId: `962bc7d3-d80f-461d-b08e-c01f23af3197` +- currentPowerPhaseB (Double) → stateTypeId: `549a50bf-11a0-47dd-99bc-8dcca9c31989` +- currentPhaseB (Double) → stateTypeId: `eb475aad-faf4-4c75-bc1a-b301176604bb` +- voltagePhaseB (Double) → stateTypeId: `b0dcc6d0-5449-4716-9dbe-859513349b64` +- energyConsumedPhaseB (Double) → stateTypeId: `6f238eb1-9c4f-4beb-889a-73aa95a837ff` +- energyProducedPhaseB (Double) → stateTypeId: `b3c78052-4d92-4103-9ab3-f23e256e92a3` +- currentPowerPhaseC (Double) → stateTypeId: `aae6fcb0-d6ca-4b51-a913-5f2134c14026` +- currentPhaseC (Double) → stateTypeId: `89ba2b3a-4fc7-4266-812b-7738d5b4c33d` +- voltagePhaseC (Double) → stateTypeId: `3ea8e4cf-c1ad-4843-b2de-a3196231224e` +- energyConsumedPhaseC (Double) → stateTypeId: `38f76e32-46b0-46bc-8dd3-93a422996584` +- energyProducedPhaseC (Double) → stateTypeId: `3d0c568d-d478-4f1f-83df-1e07eb57d04b` +- updateStatus (String) → stateTypeId: `d667bec3-e0a2-48fc-86be-2da1ff487bb3` +- currentVersion (String) → stateTypeId: `3f08799c-74ff-415a-86fd-d89d29dc8f10` +- availableVersion (String) → stateTypeId: `d742d57b-4b60-484a-ae3b-ba1730e6bc45` +- power (Bool) → stateTypeId: `d8505ed8-f7cc-4bfd-939a-90f99aaa242b` + +#### Actions + +- power → actionTypeId: `d8505ed8-f7cc-4bfd-939a-90f99aaa242b` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d8505ed8-f7cc-4bfd-939a-90f99aaa242b", + "params": { + "power": "" + } + } + } + +- performUpdate → actionTypeId: `971a7849-f5b1-496c-9f7c-0f61a6c5182b` +- reset → actionTypeId: `f4e2db2b-3832-4ffb-bd75-60e180fc59dd` + +--- + +### connection + +- ThingClassId: `4fd79fed-42f1-4df9-be64-3df7b2e0bda2` + +#### States + +- connected (Bool) → stateTypeId: `98e4476f-e745-4a7f-b795-19269cb70c40` +- version (String) → stateTypeId: `8fd0c0ed-af89-4887-bf0f-040b13c25268` + + +--- + +### daylightSensor + +- ThingClassId: `1d43d0ed-efe2-46ab-a567-af632e550931` + +#### States + +- daylight (Bool) → stateTypeId: `6e7bc630-a19c-41ec-b6a3-2e0cbcc4fadf` +- sunriseTime (Int) → stateTypeId: `d7c1f356-1efe-4ab7-ad4b-e7ab12cb53b7` +- sunsetTime (Int) → stateTypeId: `6d064789-b9c3-44c8-a5ea-b722fc2f56b7` + + +--- + +### onOffSwitch + +- ThingClassId: `2007e8ae-4849-47f6-98d6-ea6769c8ebd9` + +#### States + +- connected (Bool) → stateTypeId: `b5abd47e-95f1-4e35-94fa-be87c396073a` +- signalStrength (Uint) → stateTypeId: `21889797-32c0-4f1b-903d-8af71981882b` +- batteryLevel (Int) → stateTypeId: `103fba1d-79a6-4b48-b7a1-f91090f1c699` +- batteryCritical (Bool) → stateTypeId: `a47e27ce-f443-4c9a-96fc-d59ec4989b49` +- currentVersion (String) → stateTypeId: `41c74445-4d2d-46dc-8a63-c98f1df8e742` +- updateStatus (String) → stateTypeId: `69495a25-e6da-4fb3-956e-5218a925db93` +- availableVersion (String) → stateTypeId: `86759c02-7007-4cb6-a349-c63c851f9849` +- updateProgress (Uint) → stateTypeId: `743113cd-d2bc-4279-bcaa-cee2483b072a` + +#### Actions + +- performUpdate → actionTypeId: `4760aeee-c8ec-4645-b676-344d427b40ed` + +--- + +### gpioButtonRpi + +- ThingClassId: `1abd4dad-0757-4160-8df1-75c45bd61e6e` + + +--- + +### motionSensor + +- ThingClassId: `30a1090e-8058-4a5b-aee3-4ba112ba3ba7` + +#### States + +- connected (Bool) → stateTypeId: `6bf470bb-4756-43fa-bddf-5e6ce002caa3` +- signalStrength (Uint) → stateTypeId: `0a54036e-ca25-40fd-8f24-3516c5141c0b` +- batteryLevel (Int) → stateTypeId: `e2e414c1-5f21-4244-942a-ee17cb25f1c0` +- batteryCritical (Bool) → stateTypeId: `21e7c58e-595e-4b7d-bd21-c0a424c876dc` +- isPresent (Bool) → stateTypeId: `16ee7fe2-1a86-40e9-aae5-610f712ca155` +- lastSeenTime (Int) → stateTypeId: `12041993-c731-4cc1-8010-904b5655d920` +- currentVersion (String) → stateTypeId: `09704fdb-f2da-4d1c-bddd-f85f85847e29` +- updateStatus (String) → stateTypeId: `8ff400f3-0b53-401e-b330-1a419f078734` +- availableVersion (String) → stateTypeId: `d634f289-e6d6-4685-8636-64c41481adb2` +- updateProgress (Uint) → stateTypeId: `15e02d98-badf-4961-a3db-b70d515d064c` + +#### Actions + +- performUpdate → actionTypeId: `aea08384-f841-4d46-97c6-d9803632a476` + +--- + +### dimmableLight + +- ThingClassId: `3068324d-d5cd-4943-a3cd-95668b09cbc8` + +#### States + +- connected (Bool) → stateTypeId: `892dd19a-c47f-41a4-9b0b-40f43b58c7f9` +- signalStrength (Uint) → stateTypeId: `c2ce2865-bab3-44ef-84f1-06b60d1bb514` +- power (Bool) → stateTypeId: `d40ac497-3716-4ec4-a7b3-21cecf751241` +- brightness (Int) → stateTypeId: `76ef975e-6713-497b-8e4b-a0ebae8b1f87` +- updateStatus (String) → stateTypeId: `5fce38cd-07a7-4071-b020-fe405033fb98` +- currentVersion (String) → stateTypeId: `8893cd94-f5e1-409f-baca-4d3eb173844e` +- availableVersion (String) → stateTypeId: `b4fe0394-0df0-475f-b24c-19470067070a` +- updateProgress (Uint) → stateTypeId: `ab7905f3-b202-4646-82f4-3db5d8fd1418` + +#### Actions + +- power → actionTypeId: `d40ac497-3716-4ec4-a7b3-21cecf751241` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d40ac497-3716-4ec4-a7b3-21cecf751241", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `76ef975e-6713-497b-8e4b-a0ebae8b1f87` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "76ef975e-6713-497b-8e4b-a0ebae8b1f87", + "params": { + "brightness": "" + } + } + } + +- alert → actionTypeId: `cc0cfcfa-97e2-4d7f-92f1-dbd0b8d479d2` +- performUpdate → actionTypeId: `6fe8bfd5-4f8d-428d-a67c-3d88ab910128` + +--- + +### networkDevice + +- ThingClassId: `bd216356-f1ec-4324-9785-6982d2174e17` + +#### States + +- address (String) → stateTypeId: `acee9260-4d01-471a-85c5-4d6116b35ff1` +- hostName (String) → stateTypeId: `29c65dcf-090e-4316-8554-68f038a8416f` +- macManufacturerName (String) → stateTypeId: `395623b2-5b25-4582-803e-61cd6d40844c` +- networkInterface (String) → stateTypeId: `412f0e24-26e7-450b-8e60-bfaf938ea23e` +- isPresent (Bool) → stateTypeId: `cb43e1b5-4f61-4538-bfa2-c33055c542cf` +- lastSeenTime (Int) → stateTypeId: `b51d54c9-cce1-43f0-a35d-52fc2d8d302c` + +#### Actions + +- ping → actionTypeId: `e98793b6-2dad-4090-91db-77f8493b4e45` +- arpRequest → actionTypeId: `2ca3f99f-7315-4f17-b48d-99f0c151a62c` +- lookupHost → actionTypeId: `9797dac5-d99a-4bcf-a99a-5b9356bbce76` + +--- + +### dimmerSwitch2 + +- ThingClassId: `60836676-c87b-499b-9802-a72b788ef00b` + +#### States + +- connected (Bool) → stateTypeId: `0e35957c-bfdf-4b00-9cb2-ecc663f67d55` +- signalStrength (Uint) → stateTypeId: `a20e79de-4710-4295-a582-3e63eedd19fa` +- batteryLevel (Int) → stateTypeId: `a182b72c-4fc5-4ae4-87c0-8b1eb3de00d4` +- batteryCritical (Bool) → stateTypeId: `3a446876-a960-43c5-b7bc-6e06a071391a` +- updateStatus (String) → stateTypeId: `b47a5b4d-f10e-4d6f-965f-b2a1347fcab6` +- currentVersion (String) → stateTypeId: `f4442612-970e-4233-9242-b4f2873702ee` +- availableVersion (String) → stateTypeId: `373848e9-cad7-4986-a9a5-0982f58efb71` +- updateProgress (Uint) → stateTypeId: `fd232036-9b2f-4c20-a6de-6227f3c8b947` + +#### Actions + +- performUpdate → actionTypeId: `2d8b7527-f8a3-41a7-aef2-706f8dd25fb1` + +--- + +### colorLight + +- ThingClassId: `b11a3f24-8011-42ca-939c-ab110c5f350e` + +#### States + +- connected (Bool) → stateTypeId: `e78b8264-d888-4cbd-bf90-2eaec0c83ee0` +- signalStrength (Uint) → stateTypeId: `84990224-7579-4d99-8a19-e98b62381881` +- power (Bool) → stateTypeId: `c3c02756-6cc7-455a-ae59-dd97b9e9a1e6` +- brightness (Int) → stateTypeId: `e81e7c79-96a4-4e80-ae85-d33278c75de0` +- colorTemperature (Int) → stateTypeId: `d78650c5-68d3-4d08-991c-cb054cdcf6fd` +- color (Color) → stateTypeId: `9e49f581-eed3-499f-8927-270dfde472e9` +- updateStatus (String) → stateTypeId: `8e6ff7a1-d1d7-4aaf-a719-7bb35c3b0f89` +- currentVersion (String) → stateTypeId: `54bfb270-59bf-434b-ac5c-539d05aaa4a6` +- availableVersion (String) → stateTypeId: `5201e76b-2cc2-4de3-a0f2-43aee3d5fad7` +- updateProgress (Uint) → stateTypeId: `01c7f30d-108b-4fe6-b9cc-6a0dca7e5c2f` + +#### Actions + +- power → actionTypeId: `c3c02756-6cc7-455a-ae59-dd97b9e9a1e6` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "c3c02756-6cc7-455a-ae59-dd97b9e9a1e6", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `e81e7c79-96a4-4e80-ae85-d33278c75de0` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e81e7c79-96a4-4e80-ae85-d33278c75de0", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `d78650c5-68d3-4d08-991c-cb054cdcf6fd` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d78650c5-68d3-4d08-991c-cb054cdcf6fd", + "params": { + "colorTemperature": "" + } + } + } + +- color → actionTypeId: `9e49f581-eed3-499f-8927-270dfde472e9` + - Parameters: + - color (Color) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9e49f581-eed3-499f-8927-270dfde472e9", + "params": { + "color": "" + } + } + } + +- alert → actionTypeId: `b0175457-b763-45d6-89fd-573f279c40b3` +- performUpdate → actionTypeId: `c7c24bb7-9ad1-4584-bc4d-96ce848918da` + +--- + +### rollershutter + +- ThingClassId: `6b187fe0-a987-462d-90ac-c48efc0d0fc0` + +#### States + +- percentage (Int) → stateTypeId: `f954ffc7-a6aa-4d30-aee0-0484631c3344` +- moving (Bool) → stateTypeId: `fa9446ba-da30-4d49-8fb6-f410ecc7dba0` +- signalStrength (Uint) → stateTypeId: `67594d96-47a2-4360-a1b8-79e4f22f9ed0` +- connected (Bool) → stateTypeId: `7a49865d-5ea5-43be-b61f-4e454c48e87e` + +#### Actions + +- percentage → actionTypeId: `f954ffc7-a6aa-4d30-aee0-0484631c3344` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "f954ffc7-a6aa-4d30-aee0-0484631c3344", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `a0460180-e799-4bc6-83ba-11731ef124a3` +- stop → actionTypeId: `cbccf714-1188-4ac9-9c91-17fe2c99acb3` +- close → actionTypeId: `baf377c6-9fba-44cf-9f14-af0101f874b5` + +--- + +### dimmerSwitch2 + +- ThingClassId: `2b40aea0-e0f3-4cde-b034-3ae8a69a5d9d` + +#### States + +- connected (Bool) → stateTypeId: `45f75511-7d72-410e-aed0-5720cc497bf8` +- batteryLevel (Int) → stateTypeId: `cb6e045c-e305-4950-9cd4-fb3989912156` +- batteryCritical (Bool) → stateTypeId: `88cc3794-3e83-47d4-8889-0b3246336bf7` + + +--- + +### indoor + +- ThingClassId: `1c809049-04f2-4710-99f5-6ed379a2934f` + +#### States + +- updateTime (Int) → stateTypeId: `50da9f6b-c350-401c-a72e-2e4036f3975d` +- temperature (Double) → stateTypeId: `3cb25538-e463-40ae-92f9-8f34f0c06b92` +- temperatureMin (Double) → stateTypeId: `ae8bb713-8805-4efd-89a1-bca44a1f1690` +- temperatureMax (Double) → stateTypeId: `dd30507e-037b-4c74-bcca-e04b94c7c5fe` +- humidity (Double) → stateTypeId: `e2db5f01-196a-48d1-8874-6b8cbfe0d8c9` +- pressure (Double) → stateTypeId: `03b0a7b7-987d-4d3b-b3f0-21d9f92ad326` +- noise (Double) → stateTypeId: `906cea9d-1daf-4e9c-90b9-e40f43052a34` +- co2 (Double) → stateTypeId: `e5710bd1-79fa-4bd4-9052-8416aae909b9` +- signalStrength (Uint) → stateTypeId: `6ea906d4-5740-454d-a730-6fdb9fa0d624` +- connected (Bool) → stateTypeId: `d84ba5d7-5202-4786-b983-958b594c341f` + + +--- + +### shellyPlus1pm + +- ThingClassId: `4c497fe1-c399-463a-9a73-0c5f4ebac100` + +#### States + +- power (Bool) → stateTypeId: `bc425ba1-7776-4004-ba67-b256db7c511d` +- connected (Bool) → stateTypeId: `1b0ecbb2-5ed6-439e-81fb-5788ed8679e2` +- signalStrength (Uint) → stateTypeId: `bffa3472-a09f-4e85-9d31-0b966e415cd2` +- updateStatus (String) → stateTypeId: `c9515efd-f16a-4a29-97e1-516d1d5a6a93` +- currentVersion (String) → stateTypeId: `e3859bc0-f96d-4fa1-958b-0e087a39a0e6` +- availableVersion (String) → stateTypeId: `0dda20f7-e13e-494d-8351-c4401ded6c1e` +- totalEnergyConsumed (Double) → stateTypeId: `76e87d1f-bc65-4f63-b692-106861827633` +- currentPower (Double) → stateTypeId: `40e63755-7220-4c7c-9c6a-fe5d7e230a35` + +#### Actions + +- power → actionTypeId: `bc425ba1-7776-4004-ba67-b256db7c511d` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bc425ba1-7776-4004-ba67-b256db7c511d", + "params": { + "power": "" + } + } + } + +- reboot → actionTypeId: `b18211d8-528b-4bff-93c2-ce6a8b55759e` +- performUpdate → actionTypeId: `0cabc075-9abc-49be-a50d-e8a8d7637d03` + +--- + +### shellySmoke + +- ThingClassId: `7317eb8a-fa6d-41a3-9ff5-0da3feacc960` + +#### States + +- fireDetected (Bool) → stateTypeId: `a16585f7-7cc6-49b0-848c-d7da2237ba77` +- temperature (Double) → stateTypeId: `3e3606ba-8c2d-41b0-a434-171dccd97795` +- connected (Bool) → stateTypeId: `a1d0350f-d71d-4bd2-b5c7-f928d9c561bb` +- signalStrength (Uint) → stateTypeId: `dd7205f4-2431-4ed5-8127-d31800c442a7` +- batteryLevel (Int) → stateTypeId: `61090a03-b3ff-4b21-a5b8-2ad27bbdf1a5` +- batteryCritical (Bool) → stateTypeId: `1ce8e795-65a7-4e10-815d-0cb8e9f2ec7e` +- updateStatus (String) → stateTypeId: `34b839d7-0043-44c9-8bf9-136059141ff9` +- currentVersion (String) → stateTypeId: `4750db5f-6380-4528-9a5e-216c32dc1709` +- availableVersion (String) → stateTypeId: `0633052d-5b6c-480b-8208-23b25018c11f` + +#### Actions + +- performUpdate → actionTypeId: `09dc2e58-149c-4131-bd1b-e039a5133f72` + +--- + +### colorTemperatureLight + +- ThingClassId: `be811592-6fe7-41be-b924-4a0a7e33295b` + +#### States + +- connected (Bool) → stateTypeId: `95c072ba-516a-43b5-8d68-a4712c5989b6` +- signalStrength (Uint) → stateTypeId: `c6d12225-e5bb-4cc7-a69f-601b8ea07e70` +- power (Bool) → stateTypeId: `d815fd02-ebe2-456a-ba3f-6d649b90a094` +- brightness (Int) → stateTypeId: `7c4b6949-46ab-41f7-8a78-09e4eaf2a01f` +- colorTemperature (Int) → stateTypeId: `889f758f-f0b9-40ba-abe2-e2100188b86e` +- updateStatus (String) → stateTypeId: `99aa4d81-cd35-478c-88b8-cfa9e26bf8ae` +- currentVersion (String) → stateTypeId: `2bf3f759-4793-426b-ad05-bf4eb199e6de` +- availableVersion (String) → stateTypeId: `a5dc8a78-f818-461e-b0a7-97c6d2cdbd3c` +- updateProgress (Uint) → stateTypeId: `a2279a96-8c72-455e-a0c4-38db3fe76f17` + +#### Actions + +- power → actionTypeId: `d815fd02-ebe2-456a-ba3f-6d649b90a094` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d815fd02-ebe2-456a-ba3f-6d649b90a094", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `7c4b6949-46ab-41f7-8a78-09e4eaf2a01f` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7c4b6949-46ab-41f7-8a78-09e4eaf2a01f", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `889f758f-f0b9-40ba-abe2-e2100188b86e` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "889f758f-f0b9-40ba-abe2-e2100188b86e", + "params": { + "colorTemperature": "" + } + } + } + +- alert → actionTypeId: `a1677c81-a68a-4268-a289-1d62b31605e3` +- performUpdate → actionTypeId: `7aaa9757-3b78-4dd2-86a6-07b72883e0fa` + +--- + +### dishwasher + +- ThingClassId: `bb0fcd0b-9594-4368-99d9-3ad5e5a8136b` + +#### States + +- connected (Bool) → stateTypeId: `7c056989-d91b-492c-9206-ef77fb81b0c8` +- closed (Bool) → stateTypeId: `8cbb3746-7e04-4fc8-93eb-b774b606a057` +- operationState (String) → stateTypeId: `2b45fbfc-d3d7-4dd4-91f8-4a789405246e` +- remoteControlActivationState (Bool) → stateTypeId: `c8bf60d2-e8e3-44dd-9cea-c7bcbe17c2b1` +- remoteStartAllowanceState (Bool) → stateTypeId: `a8ce4a4e-fae3-4100-ad05-7c390b774b4a` +- progress (Int) → stateTypeId: `f0484744-a180-4a14-9c84-f49a489e3510` +- selectedProgram (String) → stateTypeId: `692ea106-557c-4870-b569-ab82a4909b2c` +- endTime (String) → stateTypeId: `f61cd171-2e8e-434c-98f9-e7fc7df1c928` + +#### Actions + +- start → actionTypeId: `7dc1e238-cdc2-42e8-9a2a-e93d497966d9` + - Parameters: + - startTime (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "7dc1e238-cdc2-42e8-9a2a-e93d497966d9", + "params": { + "startTime": "" + } + } + } + +- stop → actionTypeId: `c2c7e1bd-bf0f-4ded-93e0-e4d770f03f6f` + +--- + +### temperatureSensor + +- ThingClassId: `ff9657f3-4076-41b9-ae7d-537866fd0ddc` + +#### States + +- batteryCritical (Bool) → stateTypeId: `cf20355b-1640-4eda-b7e7-e3363c02bed6` +- connected (Bool) → stateTypeId: `13d91dce-cba3-452c-9618-3c505a56fbc2` +- signalStrength (Uint) → stateTypeId: `8f77c980-a1e0-4f4b-a042-1272a8fe3459` +- temperature (Double) → stateTypeId: `1ca9594f-fa48-4ea3-be0e-d8aea3e5ad0a` + + +--- + +### meter + +- ThingClassId: `c3cb53a4-32dd-434d-9d9c-aada41f8129c` + +#### States + +- connected (Bool) → stateTypeId: `b70b61a4-54cb-47ec-b62a-b498eb1f650e` +- currentPower (Double) → stateTypeId: `e5056ea1-88a2-410b-9c5e-6322aca4cb17` +- voltagePhaseA (Double) → stateTypeId: `267bc59f-1113-4aff-a502-4618a591aa16` +- voltagePhaseB (Double) → stateTypeId: `bbcedb80-30f1-493e-81f0-5f77f2847353` +- voltagePhaseC (Double) → stateTypeId: `8037557b-40dc-411b-8937-bcd1695f898a` +- currentPhaseA (Double) → stateTypeId: `a9673688-d84a-4848-8583-a70739130252` +- currentPhaseB (Double) → stateTypeId: `15632e49-95f9-496d-830c-53a31ca6d98e` +- currentPhaseC (Double) → stateTypeId: `10a24ba9-a57a-48a9-98f3-52671c09e855` +- totalEnergyProduced (Double) → stateTypeId: `ca14cca5-d9f0-49c5-a8f7-907d4c0825f0` +- totalEnergyConsumed (Double) → stateTypeId: `f3451818-48d2-42a5-94fd-ad094c06967f` +- currentPowerPhaseA (Double) → stateTypeId: `6dbbb062-447b-47d6-b2e4-dceac9aff795` +- currentPowerPhaseB (Double) → stateTypeId: `f230e78e-15b0-47a4-b494-bae65be00755` +- currentPowerPhaseC (Double) → stateTypeId: `56b5d550-d902-4c33-9288-8ee972735a75` +- frequency (Double) → stateTypeId: `9ff64b29-e023-4395-abd4-b6c366acfd9e` + + +--- + +### colorTemperatureLight + +- ThingClassId: `8a91f8e7-8162-437e-a664-9ed999e44e62` + +#### States + +- connected (Bool) → stateTypeId: `be8617fb-174f-4008-b60d-6a748b72c509` +- signalStrength (Uint) → stateTypeId: `e666efcb-564e-41a1-8585-d0d99665c8c0` +- power (Bool) → stateTypeId: `5f7c7a38-5dc0-44f2-ae25-576dd4b7740b` +- brightness (Int) → stateTypeId: `30643f4e-9f1a-4848-abb6-7ce4081f1878` +- colorTemperature (Int) → stateTypeId: `18f2b025-e638-4296-ade4-3dde89ffc5ab` +- updateStatus (String) → stateTypeId: `91464b14-5989-48d0-98bf-31dd61429cd6` +- currentVersion (String) → stateTypeId: `3fb91687-1cb1-4a86-817c-1c69be2bea1d` +- availableVersion (String) → stateTypeId: `c53a4c3d-0889-47c9-ac88-ca7ed92b28b8` +- updateProgress (Uint) → stateTypeId: `45c7b068-e19a-4d44-81eb-6d116496f1c9` + +#### Actions + +- power → actionTypeId: `5f7c7a38-5dc0-44f2-ae25-576dd4b7740b` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5f7c7a38-5dc0-44f2-ae25-576dd4b7740b", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `30643f4e-9f1a-4848-abb6-7ce4081f1878` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "30643f4e-9f1a-4848-abb6-7ce4081f1878", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `18f2b025-e638-4296-ade4-3dde89ffc5ab` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "18f2b025-e638-4296-ade4-3dde89ffc5ab", + "params": { + "colorTemperature": "" + } + } + } + +- alert → actionTypeId: `b6c75191-fd7d-475c-9ed0-40fe7bdfbc28` +- performUpdate → actionTypeId: `b805feb6-2920-4204-a4be-49f5890a7114` + +--- + +### doorSensor + +- ThingClassId: `adc6d53a-34a9-486e-a501-34b84395201d` + +#### States + +- closed (Bool) → stateTypeId: `99bfe225-cfca-4fe6-ab86-b50a4dba0345` +- batteryLevel (Int) → stateTypeId: `4d3fdaee-eca3-42c1-8aa8-f315d6aed6e5` +- batteryCritical (Bool) → stateTypeId: `56c95d21-11da-436a-9631-9f667d433076` +- connected (Bool) → stateTypeId: `564245ee-34b8-4af3-9ede-8661c5c8bf7e` +- signalStrength (Uint) → stateTypeId: `d2ae9d3b-fad0-412a-9c0b-f31bbf0658d2` + + +--- + +### lumiRelay + +- ThingClassId: `8e381cb1-2caa-4261-be77-e76a538bf67a` + +#### States + +- connected (Bool) → stateTypeId: `b12d1765-0b2e-4e95-b5ef-780d27fdda44` +- signalStrength (Uint) → stateTypeId: `bc22b220-003f-4f19-9aef-21c4049c5a0e` +- version (String) → stateTypeId: `ca1a8d08-4423-4401-bca7-d52b11e54ed9` +- relay1 (Bool) → stateTypeId: `486e0df0-cbda-4b67-b844-6f70e5af6891` +- relay2 (Bool) → stateTypeId: `2caa4f0f-661e-4b59-83e5-8417058e48fd` + +#### Actions + +- relay1 → actionTypeId: `486e0df0-cbda-4b67-b844-6f70e5af6891` + - Parameters: + - relay1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "486e0df0-cbda-4b67-b844-6f70e5af6891", + "params": { + "relay1": "" + } + } + } + +- relay2 → actionTypeId: `2caa4f0f-661e-4b59-83e5-8417058e48fd` + - Parameters: + - relay2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "2caa4f0f-661e-4b59-83e5-8417058e48fd", + "params": { + "relay2": "" + } + } + } + + +--- + +### lumiHTSensor + +- ThingClassId: `dfabab0e-d483-43f8-82c6-720899e70c86` + +#### States + +- connected (Bool) → stateTypeId: `eb09e3f4-44ea-4ca9-9eac-9a693595fe37` +- signalStrength (Uint) → stateTypeId: `0cb72e84-01c4-4041-9aee-1dabf26a062e` +- version (String) → stateTypeId: `968ff8bb-b852-48d8-bde2-28cfa810b20e` +- temperature (Double) → stateTypeId: `152b475e-6bd8-4e6f-8765-0636c0bc8e9d` +- humidity (Double) → stateTypeId: `e6559d9e-2c64-485d-bb2b-8a9aec0ac656` +- batteryLevel (Int) → stateTypeId: `4091259a-f1db-435e-9296-9eeb17b6f835` +- batteryCritical (Bool) → stateTypeId: `2c59a1f8-f33e-4dab-83fe-46b95d107fed` + + +--- + +### zone + +- ThingClassId: `1a7bb944-fb9c-490a-8a4c-794b27282292` + +#### States + +- connected (Bool) → stateTypeId: `9f45a703-6a15-447c-a77a-0df731cda48e` +- mode (String) → stateTypeId: `4cecf87c-8a5d-4bc4-a4ba-d2ee6103714b` +- tadoMode (String) → stateTypeId: `8b800998-5c2d-4940-9d0e-036979cf49ca` +- power (Bool) → stateTypeId: `e886377d-34b7-4908-ad0d-ed463fc6181d` +- windowOpenDetected (Bool) → stateTypeId: `c7a04e26-bb22-406e-b117-262bdb8b9c0e` +- temperature (Double) → stateTypeId: `80098178-7d92-43dd-a216-23704cc0eaa2` +- targetTemperature (Double) → stateTypeId: `684fcc62-f12b-4669-988e-4b79f153b0f2` +- humidity (Double) → stateTypeId: `0faaaff1-2a33-44ec-b68d-d8855f584b02` + +#### Actions + +- mode → actionTypeId: `4cecf87c-8a5d-4bc4-a4ba-d2ee6103714b` + - Parameters: + - mode (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4cecf87c-8a5d-4bc4-a4ba-d2ee6103714b", + "params": { + "mode": "" + } + } + } + +- power → actionTypeId: `e886377d-34b7-4908-ad0d-ed463fc6181d` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e886377d-34b7-4908-ad0d-ed463fc6181d", + "params": { + "power": "" + } + } + } + +- targetTemperature → actionTypeId: `684fcc62-f12b-4669-988e-4b79f153b0f2` + - Parameters: + - targetTemperature (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "684fcc62-f12b-4669-988e-4b79f153b0f2", + "params": { + "targetTemperature": "" + } + } + } + + +--- + +### lifxAccount + +- ThingClassId: `387c87f6-3e5b-4d6a-ba4d-372d0efad79f` + +#### States + +- loggedIn (Bool) → stateTypeId: `0db34069-5de0-4233-baec-27f039228524` +- userDisplayName (String) → stateTypeId: `554afd9b-a2ec-4d28-9065-2b9ab3a9e3b2` +- connected (Bool) → stateTypeId: `3e7b358b-d7de-4db4-8a3a-b9860eae186f` + + +--- + +### sonoff_quad + +- ThingClassId: `ae845ec9-be61-4bdf-9015-4c156f937da7` + +#### States + +- connected (Bool) → stateTypeId: `5b422d28-9f60-4ea9-ab23-42a0ec605b9e` +- signalStrength (Uint) → stateTypeId: `d80d8f37-f3c0-4364-998b-312339fd1fa8` +- powerCH1 (Bool) → stateTypeId: `e8fd95c3-2323-40d8-89cf-40e0068977d8` +- powerCH2 (Bool) → stateTypeId: `baf0ca62-7f09-45ea-aea1-6de34764e6cb` +- powerCH3 (Bool) → stateTypeId: `8b939d15-3e45-40aa-bb53-9b3fb47f3cb3` +- powerCH4 (Bool) → stateTypeId: `4060baa0-2b11-4905-908c-b6f1c3b6a892` + +#### Actions + +- powerCH1 → actionTypeId: `e8fd95c3-2323-40d8-89cf-40e0068977d8` + - Parameters: + - powerCH1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e8fd95c3-2323-40d8-89cf-40e0068977d8", + "params": { + "powerCH1": "" + } + } + } + +- powerCH2 → actionTypeId: `baf0ca62-7f09-45ea-aea1-6de34764e6cb` + - Parameters: + - powerCH2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "baf0ca62-7f09-45ea-aea1-6de34764e6cb", + "params": { + "powerCH2": "" + } + } + } + +- powerCH3 → actionTypeId: `8b939d15-3e45-40aa-bb53-9b3fb47f3cb3` + - Parameters: + - powerCH3 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "8b939d15-3e45-40aa-bb53-9b3fb47f3cb3", + "params": { + "powerCH3": "" + } + } + } + +- powerCH4 → actionTypeId: `4060baa0-2b11-4905-908c-b6f1c3b6a892` + - Parameters: + - powerCH4 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4060baa0-2b11-4905-908c-b6f1c3b6a892", + "params": { + "powerCH4": "" + } + } + } + + +--- + +### shellyPlusSmoke + +- ThingClassId: `8013cb36-2375-4d52-b042-4b61a290be3b` + +#### States + +- fireDetected (Bool) → stateTypeId: `12cf10d4-c74f-49e3-ac5a-3647ffb0cc64` +- mute (Bool) → stateTypeId: `724cd341-95b3-4bc6-b9c9-d8e85c0f8b7a` +- connected (Bool) → stateTypeId: `8e5095d7-ab1c-42ba-934d-8e6c290f6b49` +- signalStrength (Uint) → stateTypeId: `bc08e45b-8976-45da-9f26-80a0cdf92a3d` +- batteryLevel (Int) → stateTypeId: `201dc87b-7fd3-4252-9bc8-e3cc3ac88f77` +- batteryCritical (Bool) → stateTypeId: `735eca96-b388-49f5-8e38-41361a4b85ad` +- updateStatus (String) → stateTypeId: `7626bcf4-5a16-400a-bc00-6deb64b699c1` +- currentVersion (String) → stateTypeId: `ce6114c9-d422-4e32-bfc3-4f3435915da5` +- availableVersion (String) → stateTypeId: `39a37cb7-9485-4895-842f-348770c9cdc3` + +#### Actions + +- mute → actionTypeId: `724cd341-95b3-4bc6-b9c9-d8e85c0f8b7a` + - Parameters: + - mute (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "724cd341-95b3-4bc6-b9c9-d8e85c0f8b7a", + "params": { + "mute": "" + } + } + } + +- performUpdate → actionTypeId: `ac36efdb-1929-4e13-befd-b981439eaeab` + +--- + +### fridge + +- ThingClassId: `6cbf309d-bde8-4e6e-ad6d-b85c8fc1843f` + +#### States + +- connected (Bool) → stateTypeId: `16931afd-44f6-4b13-bd3e-f6d30ac54ea0` +- closed (Bool) → stateTypeId: `99bba70c-5ead-4076-8b71-720a931668a4` +- fridgeTemperature (Int) → stateTypeId: `bc13977e-0ea1-4804-af00-311ae62c6c06` +- fridgeTemperatureSetting (Int) → stateTypeId: `5a1a8665-835b-4909-8f79-42874c5c4643` +- freezerTemperature (Int) → stateTypeId: `523adac4-a98a-49b5-96d4-d506831aeab7` +- freezerTemperatureSetting (Int) → stateTypeId: `081ceedc-7c09-4cd9-8015-13a59ce653bf` + + +--- + +### tasmotaBlinds + +- ThingClassId: `70ae35db-68bf-42d7-872a-85582d27d128` + +#### States + +- connected (Bool) → stateTypeId: `686ad054-0ee5-4135-8f2d-dda993532262` +- signalStrength (Uint) → stateTypeId: `dc58b863-1e84-4469-b226-cd4349d82050` + +#### Actions + +- open → actionTypeId: `df8025a0-3553-413b-9986-61248d7a8440` +- close → actionTypeId: `b548fde8-1fdc-4605-9507-964076437ffb` +- stop → actionTypeId: `f985c1ce-3ddd-415d-a10b-060fc0fa995c` + +--- + +### shellyTrv + +- ThingClassId: `52932a47-38cd-4dce-b338-88122ce4ab8a` + +#### States + +- temperature (Double) → stateTypeId: `d9a26a08-5735-403a-ab02-7638bd0a471f` +- targetTemperature (Double) → stateTypeId: `9800babf-a6cc-4eda-b42e-8f5481b61aea` +- valvePosition (Uint) → stateTypeId: `e442ca7a-ee17-482b-aae4-579915029abf` +- heatingOn (Bool) → stateTypeId: `1935b7fa-72a5-4aee-877e-d656cd79d688` +- boost (Bool) → stateTypeId: `ef74da4d-70f4-49cd-9697-a8e2bf25dee1` +- windowOpen (Bool) → stateTypeId: `a5944856-6b0f-4b45-9d9f-fe0f3c2de8aa` +- connected (Bool) → stateTypeId: `92fa20b0-2b66-4d68-8819-6eeb43f1c0fb` +- signalStrength (Uint) → stateTypeId: `42e080f3-c00c-49d2-b046-7bd26331b8f0` +- batteryLevel (Int) → stateTypeId: `f45dff98-41ac-43bb-a005-24294973611b` +- batteryCritical (Bool) → stateTypeId: `48c3a619-331e-44eb-b080-877fdcfd03f6` +- updateStatus (String) → stateTypeId: `113625e0-e171-48e6-a9ca-6a13b75b9234` +- currentVersion (String) → stateTypeId: `ad5cdb22-42ce-4592-ad72-61a854981f69` +- availableVersion (String) → stateTypeId: `f3e00825-cd05-45e6-bc99-457bf74255c5` + +#### Actions + +- targetTemperature → actionTypeId: `9800babf-a6cc-4eda-b42e-8f5481b61aea` + - Parameters: + - targetTemperature (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9800babf-a6cc-4eda-b42e-8f5481b61aea", + "params": { + "targetTemperature": "" + } + } + } + +- valvePosition → actionTypeId: `e442ca7a-ee17-482b-aae4-579915029abf` + - Parameters: + - valvePosition (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "e442ca7a-ee17-482b-aae4-579915029abf", + "params": { + "valvePosition": "" + } + } + } + +- boost → actionTypeId: `ef74da4d-70f4-49cd-9697-a8e2bf25dee1` + - Parameters: + - boost (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ef74da4d-70f4-49cd-9697-a8e2bf25dee1", + "params": { + "boost": "" + } + } + } + +- performUpdate → actionTypeId: `27e4c7f5-1828-443c-a18d-6d79382e001d` +- reboot → actionTypeId: `4cef8e3a-853b-4313-8f70-d22122e7bb04` + +--- + +### speedwireInverter + +- ThingClassId: `b63a0669-f2ac-4769-abea-e14cafb2309a` + +#### States + +- connected (Bool) → stateTypeId: `aaff72c3-c70a-4a2f-bed1-89f38cebe442` +- voltagePhaseA (Double) → stateTypeId: `6ef4eb16-a3d6-4bc9-972d-5e7cb81173a5` +- voltagePhaseB (Double) → stateTypeId: `d9a5768b-1bf5-4933-810d-84dd7a688f71` +- voltagePhaseC (Double) → stateTypeId: `fc168dc6-eecf-40b4-b214-3e28da0dbb12` +- currentPhaseA (Double) → stateTypeId: `2a6c59ca-853a-47d6-96fb-0c85edf32f52` +- currentPhaseB (Double) → stateTypeId: `4db96fec-737c-4c4b-bf07-5ef2fd62508a` +- currentPhaseC (Double) → stateTypeId: `0f23fb0e-a440-4ac2-9aff-896bc65feb2c` +- currentPower (Double) → stateTypeId: `d7ceb482-5df8-4c0c-82bd-62ce7ba22c43` +- currentPowerMpp1 (Double) → stateTypeId: `b366f680-6134-488b-8362-b1b824a8daca` +- currentPowerMpp2 (Double) → stateTypeId: `87d9b654-5558-47a3-9db9-ffd7c23b4774` +- totalEnergyProduced (Double) → stateTypeId: `51cadd66-2cf1-485a-a2a9-191d11abfbd1` +- energyProducedToday (Double) → stateTypeId: `e8bc8f81-e5c5-4900-b429-93fcaa262fcb` +- frequency (Double) → stateTypeId: `fdccf5de-7413-4480-9ca0-1151665dede8` +- firmwareVersion (String) → stateTypeId: `6d76cc7b-9e00-4561-be7b-4e2a6b8f7b66` + + +--- + +### foh + +- ThingClassId: `692bc4be-07b8-4b77-ab0b-a36185b17d76` + +#### States + +- connected (Bool) → stateTypeId: `840b220c-656b-4f56-bbaa-ce818cffad64` + + +--- + +### cleaningRobot + +- ThingClassId: `a7bfe39f-14d1-481a-a255-eea7f40e0c07` + +#### States + +- connected (Bool) → stateTypeId: `f0f81c21-b10e-44ef-8606-600ebaf646e0` +- operationState (String) → stateTypeId: `ac2b896e-d7ff-4b17-affa-ad5bdc486640` + + +--- + +### colorLight + +- ThingClassId: `886a856d-1373-4fff-ac34-dbdfa5531c2a` + +#### States + +- power (Bool) → stateTypeId: `1a366728-e67c-4767-b125-bec5dd6515f5` +- brightness (Int) → stateTypeId: `392e418c-d1e0-45ae-ba90-0fbc53227d70` +- colorTemperature (Int) → stateTypeId: `4db6a6d9-f7f4-4dca-85c4-4f5f8e57c897` +- color (Color) → stateTypeId: `ecce80e5-c992-49cd-bd67-7721d2efad2b` + +#### Actions + +- power → actionTypeId: `1a366728-e67c-4767-b125-bec5dd6515f5` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1a366728-e67c-4767-b125-bec5dd6515f5", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `392e418c-d1e0-45ae-ba90-0fbc53227d70` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "392e418c-d1e0-45ae-ba90-0fbc53227d70", + "params": { + "brightness": "" + } + } + } + +- colorTemperature → actionTypeId: `4db6a6d9-f7f4-4dca-85c4-4f5f8e57c897` + - Parameters: + - colorTemperature (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4db6a6d9-f7f4-4dca-85c4-4f5f8e57c897", + "params": { + "colorTemperature": "" + } + } + } + +- color → actionTypeId: `ecce80e5-c992-49cd-bd67-7721d2efad2b` + - Parameters: + - color (Color) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "ecce80e5-c992-49cd-bd67-7721d2efad2b", + "params": { + "color": "" + } + } + } + + +--- + +### shellyEm3 + +- ThingClassId: `ba293550-d2af-4463-b973-e1812ab67b96` + +#### States + +- connected (Bool) → stateTypeId: `08bd7743-af98-4328-bbca-64280afc5a87` +- signalStrength (Uint) → stateTypeId: `0f147c29-aefd-4926-a979-35dfeaec12c0` +- totalEnergyConsumed (Double) → stateTypeId: `67050a5a-cc78-4d11-a7d9-a9db528029ff` +- totalEnergyProduced (Double) → stateTypeId: `088cb7df-9187-4206-ae5b-18a00e4f1969` +- currentPower (Double) → stateTypeId: `3fc2a87f-cd33-4d1f-b7a6-75ffcb4e7cc4` +- currentPowerPhaseA (Double) → stateTypeId: `432ba180-936d-4700-907e-766264bfdd35` +- powerFactorPhaseA (Double) → stateTypeId: `50be490b-ba5d-4b1f-806c-9e15b915c1eb` +- currentPhaseA (Double) → stateTypeId: `5fa79319-756b-4b2c-87b1-59ff996b8435` +- voltagePhaseA (Double) → stateTypeId: `5977ffab-cdcf-409c-940b-aa0a59de84a5` +- energyConsumedPhaseA (Double) → stateTypeId: `ba25ef68-bb52-4e96-a8fb-137aae966104` +- energyProducedPhaseA (Double) → stateTypeId: `34562cd3-b178-4f68-903d-a01e20d0ad76` +- currentPowerPhaseB (Double) → stateTypeId: `02edeedb-8a93-41f8-8bc5-09031b7d2d4d` +- powerFactorPhaseB (Double) → stateTypeId: `f56504bb-0c6c-4425-831c-771b23aadf19` +- currentPhaseB (Double) → stateTypeId: `a4151601-fe77-418a-a2c1-6376e32da3bd` +- voltagePhaseB (Double) → stateTypeId: `7c846993-fb06-48ef-987c-7b35d9671070` +- energyConsumedPhaseB (Double) → stateTypeId: `6636e6a0-e3ca-4654-9506-4302c4e8eed7` +- energyProducedPhaseB (Double) → stateTypeId: `d70a0d1a-cac1-4250-85fa-4859ad2dc947` +- currentPowerPhaseC (Double) → stateTypeId: `82277a4e-49cc-45f4-8b29-470ce99333b6` +- powerFactorPhaseC (Double) → stateTypeId: `2e2c622f-1575-4d0b-a0c0-78bc03748c1e` +- currentPhaseC (Double) → stateTypeId: `ab78aa9c-aa73-4f5d-8d21-38c83c5e9e7c` +- voltagePhaseC (Double) → stateTypeId: `cd7af1b2-d5f0-4c2e-b85c-84f23ae1fbb9` +- energyConsumedPhaseC (Double) → stateTypeId: `452c2159-aa2f-4217-80e5-4b492b69671e` +- energyProducedPhaseC (Double) → stateTypeId: `de248e26-b617-4d22-9175-752e2d695274` +- updateStatus (String) → stateTypeId: `8e25bbc2-54d8-4aa1-8ca5-f61b5f17a03b` +- currentVersion (String) → stateTypeId: `f9ddb9f1-1251-484e-bdce-531d584d8f6a` +- availableVersion (String) → stateTypeId: `27f1e394-642f-4a90-88bf-1ef9ba88b10b` +- power (Bool) → stateTypeId: `639dda4c-e354-43ca-a785-fbe6806986e2` + +#### Actions + +- power → actionTypeId: `639dda4c-e354-43ca-a785-fbe6806986e2` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "639dda4c-e354-43ca-a785-fbe6806986e2", + "params": { + "power": "" + } + } + } + +- performUpdate → actionTypeId: `f230d689-53f8-4542-9b20-9993b1c2eb27` +- reset → actionTypeId: `87772e43-1bf7-496b-b8be-46db39f71700` + +--- + +### cooling + +- ThingClassId: `09edbc07-d382-48a4-9b16-99992014aff9` + +#### States + +- power (Bool) → stateTypeId: `918cfd2c-6692-4faa-acc6-18ebf93611ec` + +#### Actions + +- power → actionTypeId: `918cfd2c-6692-4faa-acc6-18ebf93611ec` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "918cfd2c-6692-4faa-acc6-18ebf93611ec", + "params": { + "power": "" + } + } + } + + +--- + +### gpioOutputRpi + +- ThingClassId: `3885c520-e202-4435-88f6-3c35c362b2e6` + +#### States + +- power (Bool) → stateTypeId: `06843766-358e-44b0-8d52-2b46ef98459a` + +#### Actions + +- power → actionTypeId: `06843766-358e-44b0-8d52-2b46ef98459a` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "06843766-358e-44b0-8d52-2b46ef98459a", + "params": { + "power": "" + } + } + } + + +--- + +### counterBbb + +- ThingClassId: `3e311ef1-60c4-4b0e-a2fb-186bff9bd792` + +#### States + +- counter (Int) → stateTypeId: `fb5181d0-644b-4ab7-afa0-b7ddc8951526` + + +--- + +### netatmoConnection + +- ThingClassId: `728d5a67-27a3-400e-b83c-2765f5196f69` + +#### States + +- connected (Bool) → stateTypeId: `2f79bc1d-27ed-480a-b583-728363c83ea6` +- loggedIn (Bool) → stateTypeId: `d1ca8579-5d5a-4372-9139-4b083efead2e` +- username (String) → stateTypeId: `b9c98ae6-3687-4279-8fda-bc02c7b7ea38` + + +--- + +### fyrtur + +- ThingClassId: `0d2286dd-23aa-4fba-b905-c833f0c7d486` + +#### States + +- connected (Bool) → stateTypeId: `c44b7fb4-d87b-4fd0-b4c6-5131f3156751` +- signalStrength (Uint) → stateTypeId: `af6e5985-c185-4fe0-a976-a41f7040f4f4` +- moving (Bool) → stateTypeId: `01ade6d2-f778-49e9-8585-3bc8e8391364` +- percentage (Int) → stateTypeId: `51e6dd8a-769f-4096-8839-ad691ee85424` +- currentVersion (String) → stateTypeId: `da474607-f49c-4a07-9310-33d93e890647` +- updateStatus (String) → stateTypeId: `04bd682b-e1b9-491b-b771-22ba44ddc703` +- availableVersion (String) → stateTypeId: `bca2f9c8-5bd9-4c8b-a57d-92dda2c10bc5` +- updateProgress (Uint) → stateTypeId: `eeae6626-d53d-42ad-99e2-6f04bd8770b2` + +#### Actions + +- percentage → actionTypeId: `51e6dd8a-769f-4096-8839-ad691ee85424` + - Parameters: + - percentage (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "51e6dd8a-769f-4096-8839-ad691ee85424", + "params": { + "percentage": "" + } + } + } + +- open → actionTypeId: `9c4074bc-fc91-42da-acba-003ad4bf9db6` +- close → actionTypeId: `9bf470ff-8afa-4595-969d-fddf458d266f` +- stop → actionTypeId: `03a0253f-a2b7-412a-933e-f55028e310ab` +- performUpdate → actionTypeId: `c2f10178-976e-4eba-b191-202bfc0bf95b` + +--- + +### smartButton + +- ThingClassId: `1e34a056-9f37-4741-b249-a5eca7a4ab4e` + +#### States + +- connected (Bool) → stateTypeId: `b449cca5-19a0-483f-b4bd-b9b43b4f8ed4` +- batteryLevel (Int) → stateTypeId: `a0a1b480-6822-49bc-b1b1-50c39764d255` +- batteryCritical (Bool) → stateTypeId: `7c1fd7c1-f322-4be7-9c22-7d14d0ec38ea` + + +--- + +### doorSensor + +- ThingClassId: `714e2bd2-c100-4f2a-b13e-c9d5c87f7adb` + +#### States + +- connected (Bool) → stateTypeId: `fd09cac9-e98a-4161-80c5-d63d813e466e` +- signalStrength (Uint) → stateTypeId: `70f6e8c9-3d4c-4b03-879b-9a469f2f3b58` +- version (String) → stateTypeId: `68862900-b07c-4bd7-be85-64b2ce5384f9` +- closed (Bool) → stateTypeId: `279e7781-19cf-4628-a9da-efbe51c6e439` +- temperature (Double) → stateTypeId: `be94e9a8-b225-4610-9a49-686967e84a28` +- batteryCritical (Bool) → stateTypeId: `14907cf7-0acf-4dcb-b397-bd7bd3055479` +- updateStatus (String) → stateTypeId: `a59533d3-6974-47a1-aca7-a2483981a134` +- currentVersion (String) → stateTypeId: `5ca4251c-4f35-405c-bf16-373c3f791ada` +- availableVersion (String) → stateTypeId: `a3ec91c5-5348-4eb5-99a1-f0303227bee5` +- updateProgress (Uint) → stateTypeId: `9e4b4603-470c-4bea-ae5c-0dbeaf6da570` + +#### Actions + +- performUpdate → actionTypeId: `51d98b39-9d88-4947-be46-72c7ebde2a79` + +--- + +### soundtouch + +- ThingClassId: `f9b7a3f5-6353-48b1-afc1-66f914412f82` + +#### States + +- connected (Bool) → stateTypeId: `09dfbd40-c97c-4a20-9ecd-f80e389a4864` +- power (Bool) → stateTypeId: `5bac4ad7-f55c-4301-8d72-f2783d9909ff` +- mute (Bool) → stateTypeId: `bc98cdb0-4d0e-48ca-afc7-922e49bb7813` +- volume (Int) → stateTypeId: `9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9` +- playerType (String) → stateTypeId: `f784072d-b8da-4c8f-9497-dccf38aa9b16` +- playbackStatus (String) → stateTypeId: `2dd512b7-40c2-488e-8d4f-6519edaa6f74` +- title (String) → stateTypeId: `f2209fec-cceb-46ad-8189-4caf42166e6b` +- artist (String) → stateTypeId: `8cb920a3-3bf1-4231-92d4-8ac27e7b3d65` +- collection (String) → stateTypeId: `ce399eec-9f6a-4903-9916-0e90e38b255e` +- artwork (String) → stateTypeId: `44304c82-c2f6-433b-b62b-815382617d0b` +- shuffle (Bool) → stateTypeId: `5913aa2a-629d-4de5-bf44-a4a1f130c118` +- repeat (String) → stateTypeId: `bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e` +- source (String) → stateTypeId: `f4684de8-ff5f-41f3-a5c3-f5e5754519d2` +- bass (Int) → stateTypeId: `91bc53ec-4f3b-438d-8e32-129b7c27aae4` + +#### Actions + +- power → actionTypeId: `5bac4ad7-f55c-4301-8d72-f2783d9909ff` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5bac4ad7-f55c-4301-8d72-f2783d9909ff", + "params": { + "power": "" + } + } + } + +- mute → actionTypeId: `bc98cdb0-4d0e-48ca-afc7-922e49bb7813` + - Parameters: + - mute (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bc98cdb0-4d0e-48ca-afc7-922e49bb7813", + "params": { + "mute": "" + } + } + } + +- volume → actionTypeId: `9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9` + - Parameters: + - volume (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9", + "params": { + "volume": "" + } + } + } + +- playbackStatus → actionTypeId: `2dd512b7-40c2-488e-8d4f-6519edaa6f74` + - Parameters: + - playbackStatus (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "2dd512b7-40c2-488e-8d4f-6519edaa6f74", + "params": { + "playbackStatus": "" + } + } + } + +- shuffle → actionTypeId: `5913aa2a-629d-4de5-bf44-a4a1f130c118` + - Parameters: + - shuffle (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5913aa2a-629d-4de5-bf44-a4a1f130c118", + "params": { + "shuffle": "" + } + } + } + +- repeat → actionTypeId: `bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e` + - Parameters: + - repeat (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e", + "params": { + "repeat": "" + } + } + } + +- bass → actionTypeId: `91bc53ec-4f3b-438d-8e32-129b7c27aae4` + - Parameters: + - bass (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "91bc53ec-4f3b-438d-8e32-129b7c27aae4", + "params": { + "bass": "" + } + } + } + +- skipBack → actionTypeId: `a180807d-1265-4831-9d86-a421767418dd` +- stop → actionTypeId: `ae3cbe03-ee3e-410e-abbd-efabc2402198` +- play → actionTypeId: `4d2ee668-a2e3-4795-8b96-0c800b703b46` +- pause → actionTypeId: `3cf341cb-fe63-40bc-a450-9678d18e91e3` +- skipNext → actionTypeId: `85d7126a-b123-4a28-aeb4-d84bcfb4d14f` +- savePreset → actionTypeId: `6c47e736-e2e0-47d4-9b96-7f56d2342b4d` + - Parameters: + - presetNumber (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "6c47e736-e2e0-47d4-9b96-7f56d2342b4d", + "params": { + "presetNumber": "" + } + } + } + +- alert → actionTypeId: `de24c5ec-1e36-4149-bfaa-71fb05264aa3` + - Parameters: + - sound (String) + - message (String) + - volume (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "de24c5ec-1e36-4149-bfaa-71fb05264aa3", + "params": { + "sound": "", + "message": "", + "volume": "" + } + } + } + +- increaseVolume → actionTypeId: `d0169ff4-f5a5-4db2-8ef0-b819d3022bde` + - Parameters: + - step (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d0169ff4-f5a5-4db2-8ef0-b819d3022bde", + "params": { + "step": "" + } + } + } + +- decreaseVolume → actionTypeId: `30873274-7662-42ec-ac31-2ef709e430ca` + - Parameters: + - step (Uint) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "30873274-7662-42ec-ac31-2ef709e430ca", + "params": { + "step": "" + } + } + } + + +--- + +### fireSensor + +- ThingClassId: `14e458d8-0480-4d2f-8e8b-2371cd4136f2` + +#### States + +- fireDetected (Bool) → stateTypeId: `4bb41637-8469-4aea-ad46-6cef3ba3afa3` + +#### Actions + +- fireDetected → actionTypeId: `4bb41637-8469-4aea-ad46-6cef3ba3afa3` + - Parameters: + - fireDetected (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "4bb41637-8469-4aea-ad46-6cef3ba3afa3", + "params": { + "fireDetected": "" + } + } + } + + +--- + +### lumiWeatherSensor + +- ThingClassId: `0b582616-0b05-4ac9-8b59-51b66079b571` + +#### States + +- connected (Bool) → stateTypeId: `003f7e37-326b-455d-828b-5a9493b56a69` +- signalStrength (Uint) → stateTypeId: `684f642e-08ed-4912-b7a9-597baef400c0` +- version (String) → stateTypeId: `cc644362-19ca-489d-8122-4d1bc55f100f` +- temperature (Double) → stateTypeId: `b1641cec-3bf6-4654-b9c0-b81acb3b4481` +- humidity (Double) → stateTypeId: `27a1e85a-f654-48d8-905d-05b3e2bc499e` +- pressure (Double) → stateTypeId: `7c3861f3-a9db-407e-9459-90a511d7f797` +- batteryLevel (Int) → stateTypeId: `706eb697-4265-440d-a79a-11df3f6db335` +- batteryCritical (Bool) → stateTypeId: `dc419970-7bb4-404f-8146-232b46668778` + + +--- + +### customMail + +- ThingClassId: `f4844c97-7ca6-4349-904e-ff9749a9fe74` + +#### Actions + +- notify → actionTypeId: `054613b0-3666-4dad-9252-e0ebca187edc` + - Parameters: + - title (String) + - body (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "054613b0-3666-4dad-9252-e0ebca187edc", + "params": { + "title": "", + "body": "" + } + } + } + + +--- + +### waterLevelSensor + +- ThingClassId: `f1576df0-fb45-4bf0-89fa-a83c4118c326` + +#### States + +- waterLevel (Double) → stateTypeId: `07563165-e42d-4d0f-ac60-31cdd19170f2` +- input (Double) → stateTypeId: `d344887d-da5d-4742-83bd-608754b2d0aa` + +#### Actions + +- input → actionTypeId: `d344887d-da5d-4742-83bd-608754b2d0aa` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d344887d-da5d-4742-83bd-608754b2d0aa", + "params": { + "input": "" + } + } + } + + +--- + +### shellyPowerMeterChannel + +- ThingClassId: `e2d2f11b-922f-4ff0-81e1-6fbf4c965521` + +#### States + +- connected (Bool) → stateTypeId: `1524dc63-7df8-47fc-a466-69ca896db361` +- signalStrength (Uint) → stateTypeId: `c3d6a520-dad3-463e-b321-91fa1dff6e07` +- totalEnergyConsumed (Double) → stateTypeId: `670b966c-f882-4846-86ce-54db7da68917` +- currentPower (Double) → stateTypeId: `9d6a6965-3024-424d-b71b-cf1358a2ece1` + + +--- + +### coSensor + +- ThingClassId: `262a29b2-b5df-4ee2-822c-e672f50d97b6` + +#### States + +- co (Double) → stateTypeId: `9eebe9d2-b34b-4847-bc25-109e2b8cab24` +- input (Double) → stateTypeId: `cf3ec5ec-7098-47c5-9666-b3c52eba1b1d` + +#### Actions + +- co → actionTypeId: `9eebe9d2-b34b-4847-bc25-109e2b8cab24` + - Parameters: + - co (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9eebe9d2-b34b-4847-bc25-109e2b8cab24", + "params": { + "co": "" + } + } + } + +- input → actionTypeId: `cf3ec5ec-7098-47c5-9666-b3c52eba1b1d` + - Parameters: + - input (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "cf3ec5ec-7098-47c5-9666-b3c52eba1b1d", + "params": { + "input": "" + } + } + } + + +--- + +### dimmableLight + +- ThingClassId: `b2eeb554-ca5c-46b5-a897-bc443fb186ea` + +#### States + +- connected (Bool) → stateTypeId: `2dc93a53-c506-41a5-9242-b5d045f51c40` +- signalStrength (Uint) → stateTypeId: `ab75980d-12f5-4ddc-be2d-dc54514a3b75` +- version (String) → stateTypeId: `9390d2a6-7a17-4b42-8b35-cdb8b3d4d723` +- power (Bool) → stateTypeId: `19d82a60-0009-4cff-966d-3b1c4fe358e1` +- brightness (Int) → stateTypeId: `6376376f-3221-4e6b-bce3-41872a6fc98a` + +#### Actions + +- power → actionTypeId: `19d82a60-0009-4cff-966d-3b1c4fe358e1` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "19d82a60-0009-4cff-966d-3b1c4fe358e1", + "params": { + "power": "" + } + } + } + +- brightness → actionTypeId: `6376376f-3221-4e6b-bce3-41872a6fc98a` + - Parameters: + - brightness (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "6376376f-3221-4e6b-bce3-41872a6fc98a", + "params": { + "brightness": "" + } + } + } + +- alert → actionTypeId: `a04d9e2b-e854-4361-bb34-2da74f8f028f` + +--- + +### ventilationFlow + +- ThingClassId: `a7eec5f7-3cc3-4edb-baa7-1f6b6f935bf8` + +#### States + +- power (Bool) → stateTypeId: `adf9a8dd-da13-4070-a3bd-9d4be26ebcd1` +- flowRate (Int) → stateTypeId: `5a273bba-0bef-49fb-870a-7f2df8fc14b6` + +#### Actions + +- power → actionTypeId: `adf9a8dd-da13-4070-a3bd-9d4be26ebcd1` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "adf9a8dd-da13-4070-a3bd-9d4be26ebcd1", + "params": { + "power": "" + } + } + } + +- flowRate → actionTypeId: `5a273bba-0bef-49fb-870a-7f2df8fc14b6` + - Parameters: + - flowRate (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5a273bba-0bef-49fb-870a-7f2df8fc14b6", + "params": { + "flowRate": "" + } + } + } + + +--- + +### lumiMagnetSensor + +- ThingClassId: `b3e30f37-7467-4c66-8694-9fe624aebd10` + +#### States + +- connected (Bool) → stateTypeId: `76f6c739-73e0-4a36-97c9-043af5854af5` +- signalStrength (Uint) → stateTypeId: `7fef2f25-91ac-4818-bc7a-e427bdeff438` +- version (String) → stateTypeId: `ac0e4cd1-553b-4e43-b08a-6dd8d617e765` +- closed (Bool) → stateTypeId: `6fad76ec-9d36-408d-bbf1-00e5d18bf6b0` +- batteryLevel (Int) → stateTypeId: `c2dbbf61-109d-4267-a9ad-904bc0f3e8ca` +- batteryCritical (Bool) → stateTypeId: `da0cb4d6-4d72-4163-93fe-a63cabf1adf0` + + +--- + +### remote + +- ThingClassId: `19ee3f56-f958-4b04-8ea3-747b72d7c7d6` + +#### States + +- connected (Bool) → stateTypeId: `9d5d116c-f742-4766-baf9-e7662f5003a9` +- signalStrength (Uint) → stateTypeId: `b87d310a-28ba-4546-9f47-822e5182836c` +- batteryLevel (Int) → stateTypeId: `4a72d569-44be-4689-bda6-addc0c6351d4` +- batteryCritical (Bool) → stateTypeId: `87b60c83-d980-48f5-bc31-0daa241d727e` +- currentVersion (String) → stateTypeId: `66c95514-6c23-4029-a3de-79f69f30cddb` +- updateStatus (String) → stateTypeId: `73f99785-7a4b-4cd3-96e7-fc2deef92227` +- availableVersion (String) → stateTypeId: `f6979f9f-0f41-4520-899d-8dc52905cbaf` +- updateProgress (Uint) → stateTypeId: `a0fa549a-12c3-47fb-88b5-373c4f81794b` + +#### Actions + +- performUpdate → actionTypeId: `28f2ae38-a592-4a7c-8f2a-58e1c3f43ac0` + +--- + +### tasmotaShutter + +- ThingClassId: `c63b02f2-3695-4e8c-9789-1b8a705f3a53` + +#### States + +- connected (Bool) → stateTypeId: `7bbf0bbf-abb3-487e-b5e9-077f7b00d8ef` +- signalStrength (Uint) → stateTypeId: `1de7fac2-87f1-4c2b-9286-1b0895c5ac49` + +#### Actions + +- open → actionTypeId: `8e7fb2f4-2819-4d14-a5ae-95624b097bf7` +- close → actionTypeId: `efbe9290-affd-4902-abb7-dd4ea74ccd1b` +- stop → actionTypeId: `c9c9c569-e224-4f63-abed-782cba04d61b` + +--- + +### powerMeterSocket + +- ThingClassId: `22feafcc-40cb-4699-91dd-0903693287b9` + +#### States + +- connected (Bool) → stateTypeId: `34ffc41b-5596-499f-90b9-f39f8220a7f0` +- signalStrength (Uint) → stateTypeId: `738ae904-d28c-46b0-b2db-0dc82e14245c` +- power (Bool) → stateTypeId: `a0bc7583-2600-4b6f-ae89-252029dda249` +- currentPower (Double) → stateTypeId: `d486ccbf-0803-4ac8-bbde-db26116a4754` +- totalEnergyConsumed (Double) → stateTypeId: `6583f3ff-838c-4dfd-98e4-2d7113f0824e` + +#### Actions + +- power → actionTypeId: `a0bc7583-2600-4b6f-ae89-252029dda249` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "a0bc7583-2600-4b6f-ae89-252029dda249", + "params": { + "power": "" + } + } + } + + +--- + +### sonosGroup + +- ThingClassId: `72d9332b-2b25-4136-87a6-e534eae4cc80` + +#### States + +- connected (Bool) → stateTypeId: `09dfbd40-c97c-4a20-9ecd-f80e389a4864` +- mute (Bool) → stateTypeId: `bc98cdb0-4d0e-48ca-afc7-922e49bb7813` +- volume (Int) → stateTypeId: `9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9` +- playbackStatus (String) → stateTypeId: `2dd512b7-40c2-488e-8d4f-6519edaa6f74` +- title (String) → stateTypeId: `f2209fec-cceb-46ad-8189-4caf42166e6b` +- artist (String) → stateTypeId: `8cb920a3-3bf1-4231-92d4-8ac27e7b3d65` +- collection (String) → stateTypeId: `ce399eec-9f6a-4903-9916-0e90e38b255e` +- artwork (String) → stateTypeId: `44304c82-c2f6-433b-b62b-815382617d0b` +- shuffle (Bool) → stateTypeId: `5913aa2a-629d-4de5-bf44-a4a1f130c118` +- repeat (String) → stateTypeId: `bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e` +- playerType (String) → stateTypeId: `addbd4ee-019b-4756-a59a-6412116105e9` + +#### Actions + +- mute → actionTypeId: `bc98cdb0-4d0e-48ca-afc7-922e49bb7813` + - Parameters: + - mute (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bc98cdb0-4d0e-48ca-afc7-922e49bb7813", + "params": { + "mute": "" + } + } + } + +- volume → actionTypeId: `9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9` + - Parameters: + - volume (Int) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "9dfe5d78-4c3f-497c-bab1-bb9fdf7e93a9", + "params": { + "volume": "" + } + } + } + +- playbackStatus → actionTypeId: `2dd512b7-40c2-488e-8d4f-6519edaa6f74` + - Parameters: + - playbackStatus (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "2dd512b7-40c2-488e-8d4f-6519edaa6f74", + "params": { + "playbackStatus": "" + } + } + } + +- shuffle → actionTypeId: `5913aa2a-629d-4de5-bf44-a4a1f130c118` + - Parameters: + - shuffle (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "5913aa2a-629d-4de5-bf44-a4a1f130c118", + "params": { + "shuffle": "" + } + } + } + +- repeat → actionTypeId: `bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e` + - Parameters: + - repeat (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "bc02c28e-3f5d-4de4-b9b5-c0b1576c6e7e", + "params": { + "repeat": "" + } + } + } + +- skipBack → actionTypeId: `a180807d-1265-4831-9d86-a421767418dd` +- fastRewind → actionTypeId: `7e70b47b-7e79-4521-be34-04a3c427e5b1` +- stop → actionTypeId: `ae3cbe03-ee3e-410e-abbd-efabc2402198` +- play → actionTypeId: `4d2ee668-a2e3-4795-8b96-0c800b703b46` +- pause → actionTypeId: `3cf341cb-fe63-40bc-a450-9678d18e91e3` +- skipNext → actionTypeId: `85d7126a-b123-4a28-aeb4-d84bcfb4d14f` +- increaseVolume → actionTypeId: `02abbda5-d23c-4fde-84cf-09782f319804` +- decreaseVolume → actionTypeId: `7f71d0f7-3950-46fb-a785-f16f9c3fd85f` + +--- + +### shellyHT + +- ThingClassId: `cc75be5c-8e34-4f72-a55d-c96e4c85d4be` + +#### States + +- temperature (Double) → stateTypeId: `507e7ca7-e1ab-4e7c-8097-4aedf924f797` +- humidity (Double) → stateTypeId: `18a3c71b-f4ef-45d8-a5db-58f533fb6e19` +- connected (Bool) → stateTypeId: `b35ace90-8afb-49f1-924d-899bf1c03c3a` +- signalStrength (Uint) → stateTypeId: `f6a09411-4efa-49e0-9cac-1c8e550e9cb6` +- batteryLevel (Int) → stateTypeId: `15914ad5-816b-471c-996b-00160100f2bc` +- batteryCritical (Bool) → stateTypeId: `56053726-92dc-4a80-b05e-a9a857c02bc1` +- updateStatus (String) → stateTypeId: `fdda809d-0807-4495-9d50-f9e2a12894ac` +- currentVersion (String) → stateTypeId: `5655b88c-f852-4efe-955f-cf5f88e8ba6b` +- availableVersion (String) → stateTypeId: `770b6b3a-3815-4ba3-8a2d-3fb949c914de` + +#### Actions + +- performUpdate → actionTypeId: `e32aaff9-b2f8-437e-b7b4-5b519d9e5e21` + +--- + +### rainGauge + +- ThingClassId: `33a7230b-588f-471c-895d-4a1ddd417c2a` + +#### States + +- updateTime (Int) → stateTypeId: `3c87cbf7-73ad-4673-9abd-188e1f4facfb` +- rainfallLastHour (Uint) → stateTypeId: `6c55bcd5-b1b3-4ea2-8b4c-2689941d43bb` +- rainfallLastDay (Uint) → stateTypeId: `3f475b34-ad5f-4821-8452-2f6869ef46b4` +- signalStrength (Uint) → stateTypeId: `d44a1e64-c5e5-4dae-944b-bce23192f610` +- connected (Bool) → stateTypeId: `d726cd1e-75c5-4d50-adbd-962301ea9b91` +- batteryLevel (Int) → stateTypeId: `e06955c4-963b-4f8f-9c0c-975c1cd75edb` +- batteryCritical (Bool) → stateTypeId: `dd8f8620-fcca-408b-835f-2c257e18aee2` + + +--- + +### shellySwitch + +- ThingClassId: `6de35a17-0f54-4397-894d-4321b64c53d1` + +#### States + +- connected (Bool) → stateTypeId: `0c233312-7b8f-4ca3-880d-523cab9b3ccb` +- signalStrength (Uint) → stateTypeId: `5088cd2d-8f71-4cfb-a120-4a2d4a84355d` +- power (Bool) → stateTypeId: `20f74d88-0683-4d3a-9513-6b29b5112b7b` + + +--- + +### doorLock + +- ThingClassId: `f5f60f66-215a-492b-9088-ef8e2b58c802` + +#### States + +- connected (Bool) → stateTypeId: `6fc8b1ad-5eb0-4038-8a65-847343c5a432` +- signalStrength (Uint) → stateTypeId: `02af2c5f-87ec-4f86-8784-3a089d5928e9` +- batteryLevel (Int) → stateTypeId: `b0a977d8-a789-4bc9-ad11-afb372b15e69` +- batteryCritical (Bool) → stateTypeId: `ba8147de-d38b-4295-a694-952a28c3e9d7` +- state (String) → stateTypeId: `9e1ce33e-ab39-4fce-8b68-54dfa970fea4` + +#### Actions + +- lock → actionTypeId: `72c23e40-e6f9-4e21-9e8f-d9a56711054c` +- unlock → actionTypeId: `6ff7d9d2-8169-4dd0-befc-9c4f0b4c110d` + +--- + +### remoteControl + +- ThingClassId: `ea5d0123-266e-4879-98f9-ecd4e2603e15` + +#### States + +- connected (Bool) → stateTypeId: `33394ace-3c4f-44b0-959f-5eb4721ec982` +- signalStrength (Uint) → stateTypeId: `dfb91a2d-04f3-4dce-a822-e14f802e5416` +- batteryLevel (Int) → stateTypeId: `fc61ac93-8c85-4d2a-80ca-47070be0777b` +- batteryCritical (Bool) → stateTypeId: `3bb7a2c8-d1e7-4ce6-a409-910d13f7d839` + + +--- + +### thermostat + +- ThingClassId: `6a34ba99-e5ec-4fc9-a61f-695ed8573fa1` + +#### States + +- temperature (Double) → stateTypeId: `0f808803-0e63-47df-b024-9685998ba663` +- targetTemperature (Double) → stateTypeId: `60169ebf-c1e3-41ed-a1bb-4b858e93ec50` +- heatingOn (Bool) → stateTypeId: `1f6a0c39-4417-4e31-86db-9926cf81c345` +- coolingOn (Bool) → stateTypeId: `cab7d4bd-f612-4d12-b3a4-0649e189810f` + +#### Actions + +- temperature → actionTypeId: `0f808803-0e63-47df-b024-9685998ba663` + - Parameters: + - temperature (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "0f808803-0e63-47df-b024-9685998ba663", + "params": { + "temperature": "" + } + } + } + +- targetTemperature → actionTypeId: `60169ebf-c1e3-41ed-a1bb-4b858e93ec50` + - Parameters: + - targetTemperature (Double) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "60169ebf-c1e3-41ed-a1bb-4b858e93ec50", + "params": { + "targetTemperature": "" + } + } + } + +- heatingOn → actionTypeId: `1f6a0c39-4417-4e31-86db-9926cf81c345` + - Parameters: + - heatingOn (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1f6a0c39-4417-4e31-86db-9926cf81c345", + "params": { + "heatingOn": "" + } + } + } + +- coolingOn → actionTypeId: `cab7d4bd-f612-4d12-b3a4-0649e189810f` + - Parameters: + - coolingOn (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "cab7d4bd-f612-4d12-b3a4-0649e189810f", + "params": { + "coolingOn": "" + } + } + } + + +--- + +### alarm + +- ThingClassId: `3f3c7ecc-9915-4e4e-95a1-e11f4f9d174d` + + +--- + +### oven + +- ThingClassId: `96845b7d-4c20-43a0-a810-ec505df3ee88` + +#### States + +- connected (Bool) → stateTypeId: `e0a6c618-d849-4206-9e3c-cd01352664e7` +- closed (Bool) → stateTypeId: `e892ca9e-5b31-41f5-a568-44474091f0f6` +- operationState (String) → stateTypeId: `c9f9bd33-513f-4834-a504-c2c1611fb4be` +- localControlState (Bool) → stateTypeId: `8843a1ce-796a-40c3-ab24-cf97b821d45c` +- remoteControlActivationState (Bool) → stateTypeId: `6afd574a-3c22-46cd-bc28-4dfcba01c51d` +- remoteStartAllowanceState (Bool) → stateTypeId: `9f9cb8ea-8527-48c9-8bf2-f5148d5b53f1` +- targetTemperature (Int) → stateTypeId: `f3f5f257-5887-4d64-b61a-8179424912b3` +- currentTemperature (Int) → stateTypeId: `1dcf634c-04c1-4415-9656-06f5b61bde17` +- duration (Int) → stateTypeId: `3527a28d-e4df-481b-a8b6-88717b77c7a6` +- progress (Int) → stateTypeId: `85a333dc-0e0b-454c-9c9a-d14dd6484275` +- selectedProgram (String) → stateTypeId: `2e6f27bb-371a-44a4-b057-51f765bdeb86` +- endTime (String) → stateTypeId: `6e828e48-3634-4d92-9dee-2c03a51c7189` + + +--- + +### openUv + +- ThingClassId: `37e17c00-91e1-4276-a1e3-12283d2cae4c` + +#### States + +- connected (Bool) → stateTypeId: `47c7dd57-3592-4d05-af4c-1034268223e1` +- uv (Int) → stateTypeId: `1d63cee1-3e28-4e90-ad4f-acbc2081ea8c` +- uvTime (Int) → stateTypeId: `35c799a1-d4b5-4d26-8b63-d884cf96ff2c` +- uvMax (Int) → stateTypeId: `59fe2255-3b61-44f0-84eb-afa6eea838c2` +- uvMaxTime (Int) → stateTypeId: `4abd1745-c290-4685-bed4-108d31721b67` +- ozone (Int) → stateTypeId: `48e51a7c-edbb-499e-95a0-6789bf51437c` +- ozoneTime (Int) → stateTypeId: `27a48154-218f-4a27-aefb-41d943ecf7e8` +- safeExposureTimeSt1 (Int) → stateTypeId: `13bc0387-acfe-4461-85c8-46f5e93ee0aa` +- safeExposureTimeSt2 (Int) → stateTypeId: `0a60b028-97c9-4231-90a4-95ace8c6cf28` +- safeExposureTimeSt3 (Int) → stateTypeId: `fb9c63aa-8ec6-479d-bd87-75865b8fcd77` +- safeExposureTimeSt4 (Int) → stateTypeId: `31fc498f-1f17-4443-b0f8-65aff70bbf1c` +- safeExposureTimeSt5 (Int) → stateTypeId: `268637f0-73a9-4945-ace9-fc2bfc250675` +- safeExposureTimeSt6 (Int) → stateTypeId: `fd98313c-a6fb-4cff-8478-7399d33e7794` + + +--- + +### sgReady + +- ThingClassId: `83cf138d-02dc-4015-9b03-6360c2f3cfb1` + +#### States + +- relay1 (Bool) → stateTypeId: `d080466e-7271-441f-9916-1199a6668545` +- relay2 (Bool) → stateTypeId: `caf22937-fdf7-41e1-a87b-d11e66c4f4c6` +- sgReadyMode (String) → stateTypeId: `1e694bc2-12e1-4e1d-a0ec-70af2c7b16ab` +- operatingModeDescription (String) → stateTypeId: `b421d098-f6e9-40e2-b536-58acdb3a49fe` + +#### Actions + +- relay1 → actionTypeId: `d080466e-7271-441f-9916-1199a6668545` + - Parameters: + - relay1 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "d080466e-7271-441f-9916-1199a6668545", + "params": { + "relay1": "" + } + } + } + +- relay2 → actionTypeId: `caf22937-fdf7-41e1-a87b-d11e66c4f4c6` + - Parameters: + - relay2 (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "caf22937-fdf7-41e1-a87b-d11e66c4f4c6", + "params": { + "relay2": "" + } + } + } + +- sgReadyMode → actionTypeId: `1e694bc2-12e1-4e1d-a0ec-70af2c7b16ab` + - Parameters: + - sgReadyMode (String) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "1e694bc2-12e1-4e1d-a0ec-70af2c7b16ab", + "params": { + "sgReadyMode": "" + } + } + } + + +--- + +### switch + +- ThingClassId: `27dc49c0-58cd-4d5f-a95b-0c437dd828cf` + +#### States + +- connected (Bool) → stateTypeId: `8864755d-4e6a-4e45-b2db-3eb5d4f3d53d` +- signalStrength (Uint) → stateTypeId: `71723ea3-d2a1-48c4-9a2c-532d938e5022` +- power (Bool) → stateTypeId: `717f2593-1544-483b-aac8-f9800b299e4d` +- totalEnergyConsumed (Double) → stateTypeId: `a3533121-69ee-44fd-8394-13373e8f960e` +- currentPower (Double) → stateTypeId: `ccb52b57-5800-4f03-b7fa-f36dcebe1d4e` + +#### Actions + +- power → actionTypeId: `717f2593-1544-483b-aac8-f9800b299e4d` + - Parameters: + - power (Bool) + + Example: + + { + "id": 1, + "method": "Integrations.ExecuteAction", + "params": { + "thingId": "", + "actionTypeId": "717f2593-1544-483b-aac8-f9800b299e4d", + "params": { + "power": "" + } + } + } + + +--- + +### doorLock + +- ThingClassId: `34cb3d09-dd9f-4b95-95d0-30a1cd94adac` + +#### States + +- connected (Bool) → stateTypeId: `206b0508-b477-4aa2-b420-aba2259fb6e6` +- signalStrength (Uint) → stateTypeId: `6c8f8db5-464c-408a-9c65-4e8096663019` +- version (String) → stateTypeId: `9e27850b-99d8-40df-9bc7-4b3c7c01faf8` +- batteryLevel (Int) → stateTypeId: `568e5bdd-47f3-4ccb-a1d8-ff3a5ea87ad8` +- batteryCritical (Bool) → stateTypeId: `89abea26-b772-4258-9b56-e026b80c2028` + +#### Actions + +- open → actionTypeId: `6e112e3b-080f-47e4-8e2b-453029f0eacb` +- close → actionTypeId: `c26e1908-25d0-4475-8f82-5aaf034640f1` + +--- + diff --git a/ios/.gitignore b/ios/.gitignore new file mode 100644 index 0000000..7a7f987 --- /dev/null +++ b/ios/.gitignore @@ -0,0 +1,34 @@ +**/dgph +*.mode1v3 +*.mode2v3 +*.moved-aside +*.pbxuser +*.perspectivev3 +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. +!default.mode1v3 +!default.mode2v3 +!default.pbxuser +!default.perspectivev3 diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist new file mode 100644 index 0000000..391a902 --- /dev/null +++ b/ios/Flutter/AppFrameworkInfo.plist @@ -0,0 +1,24 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + App + CFBundleIdentifier + io.flutter.flutter.app + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + App + CFBundlePackageType + FMWK + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Debug.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig new file mode 100644 index 0000000..592ceee --- /dev/null +++ b/ios/Flutter/Release.xcconfig @@ -0,0 +1 @@ +#include "Generated.xcconfig" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..6396007 --- /dev/null +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,620 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXBuildFile section */ + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; }; + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; }; + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 97C146E61CF9000F007C117D /* Project object */; + proxyType = 1; + remoteGlobalIDString = 97C146ED1CF9000F007C117D; + remoteInfo = Runner; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 9705A1C41CF9048500538489 /* Embed Frameworks */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Embed Frameworks"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; }; + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; }; + 331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; + 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; }; + 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 97C146EB1CF9000F007C117D /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C8082294A63A400263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C807B294A618700263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 9740EEB11CF90186004384FC /* Flutter */ = { + isa = PBXGroup; + children = ( + 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 9740EEB31CF90195004384FC /* Generated.xcconfig */, + ); + name = Flutter; + sourceTree = ""; + }; + 97C146E51CF9000F007C117D = { + isa = PBXGroup; + children = ( + 9740EEB11CF90186004384FC /* Flutter */, + 97C146F01CF9000F007C117D /* Runner */, + 97C146EF1CF9000F007C117D /* Products */, + 331C8082294A63A400263BE5 /* RunnerTests */, + ); + sourceTree = ""; + }; + 97C146EF1CF9000F007C117D /* Products */ = { + isa = PBXGroup; + children = ( + 97C146EE1CF9000F007C117D /* Runner.app */, + 331C8081294A63A400263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 97C146F01CF9000F007C117D /* Runner */ = { + isa = PBXGroup; + children = ( + 97C146FA1CF9000F007C117D /* Main.storyboard */, + 97C146FD1CF9000F007C117D /* Assets.xcassets */, + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */, + 97C147021CF9000F007C117D /* Info.plist */, + 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */, + 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */, + 74858FAE1ED2DC5600515810 /* AppDelegate.swift */, + 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */, + 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */, + ); + path = Runner; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C8080294A63A400263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C807D294A63A400263BE5 /* Sources */, + 331C807F294A63A400263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C8086294A63A400263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 97C146ED1CF9000F007C117D /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 9740EEB61CF901F6004384FC /* Run Script */, + 97C146EA1CF9000F007C117D /* Sources */, + 97C146EB1CF9000F007C117D /* Frameworks */, + 97C146EC1CF9000F007C117D /* Resources */, + 9705A1C41CF9048500538489 /* Embed Frameworks */, + 3B06AD1E1E4923F5004D2608 /* Thin Binary */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Runner; + productName = Runner; + productReference = 97C146EE1CF9000F007C117D /* Runner.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 97C146E61CF9000F007C117D /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C8080294A63A400263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 97C146ED1CF9000F007C117D; + }; + 97C146ED1CF9000F007C117D = { + CreatedOnToolsVersion = 7.3.1; + LastSwiftMigration = 1100; + }; + }; + }; + buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 97C146E51CF9000F007C117D; + productRefGroup = 97C146EF1CF9000F007C117D /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 97C146ED1CF9000F007C117D /* Runner */, + 331C8080294A63A400263BE5 /* RunnerTests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C807F294A63A400263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EC1CF9000F007C117D /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */, + 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */, + 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */, + 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}", + ); + name = "Thin Binary"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin"; + }; + 9740EEB61CF901F6004384FC /* Run Script */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + name = "Run Script"; + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C807D294A63A400263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 97C146EA1CF9000F007C117D /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, + 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, + 7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C8086294A63A400263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 97C146ED1CF9000F007C117D /* Runner */; + targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 97C146FA1CF9000F007C117D /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C146FB1CF9000F007C117D /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 97C147001CF9000F007C117D /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 249021D3217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Profile; + }; + 249021D4217E4FDB00AE95B9 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Profile; + }; + 331C8088294A63A400263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Debug; + }; + 331C8089294A63A400263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Release; + }; + 331C808A294A63A400263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner"; + }; + name = Profile; + }; + 97C147031CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 97C147041CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SUPPORTED_PLATFORMS = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + TARGETED_DEVICE_FAMILY = "1,2"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 97C147061CF9000F007C117D /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Debug; + }; + 97C147071CF9000F007C117D /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; + ENABLE_BITCODE = NO; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; + SWIFT_VERSION = 5.0; + VERSIONING_SYSTEM = "apple-generic"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C8088294A63A400263BE5 /* Debug */, + 331C8089294A63A400263BE5 /* Release */, + 331C808A294A63A400263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147031CF9000F007C117D /* Debug */, + 97C147041CF9000F007C117D /* Release */, + 249021D3217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 97C147061CF9000F007C117D /* Debug */, + 97C147071CF9000F007C117D /* Release */, + 249021D4217E4FDB00AE95B9 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 97C146E61CF9000F007C117D /* Project object */; +} diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..e3773d4 --- /dev/null +++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/ios/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings new file mode 100644 index 0000000..f9b0d7c --- /dev/null +++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings @@ -0,0 +1,8 @@ + + + + + PreviewsEnabled + + + diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift new file mode 100644 index 0000000..c30b367 --- /dev/null +++ b/ios/Runner/AppDelegate.swift @@ -0,0 +1,16 @@ +import Flutter +import UIKit + +@main +@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate { + override func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? + ) -> Bool { + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..d36b1fa --- /dev/null +++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,122 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "Icon-App-20x20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "Icon-App-29x29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "Icon-App-40x40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "Icon-App-60x60@3x.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@1x.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "Icon-App-20x20@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@1x.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "Icon-App-29x29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@1x.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "Icon-App-40x40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@1x.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "Icon-App-76x76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "Icon-App-83.5x83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "Icon-App-1024x1024@1x.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png new file mode 100644 index 0000000..dc9ada4 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png new file mode 100644 index 0000000..7353c41 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png new file mode 100644 index 0000000..6ed2d93 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png new file mode 100644 index 0000000..4cd7b00 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png new file mode 100644 index 0000000..fe73094 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png new file mode 100644 index 0000000..321773c Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png new file mode 100644 index 0000000..797d452 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png new file mode 100644 index 0000000..502f463 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png new file mode 100644 index 0000000..0ec3034 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png new file mode 100644 index 0000000..e9f5fea Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png new file mode 100644 index 0000000..84ac32a Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png new file mode 100644 index 0000000..8953cba Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png differ diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png new file mode 100644 index 0000000..0467bf1 Binary files /dev/null and b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json new file mode 100644 index 0000000..0bedcf2 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchImage.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "LaunchImage@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@2x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png new file mode 100644 index 0000000..9da19ea Binary files /dev/null and b/ios/Runner/Assets.xcassets/LaunchImage.imageset/LaunchImage@3x.png differ diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md new file mode 100644 index 0000000..89c2725 --- /dev/null +++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md @@ -0,0 +1,5 @@ +# Launch Screen Assets + +You can customize the launch screen with your own desired assets by replacing the image files in this directory. + +You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images. \ No newline at end of file diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard new file mode 100644 index 0000000..f2e259c --- /dev/null +++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard new file mode 100644 index 0000000..f3c2851 --- /dev/null +++ b/ios/Runner/Base.lproj/Main.storyboard @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist new file mode 100644 index 0000000..6524dbe --- /dev/null +++ b/ios/Runner/Info.plist @@ -0,0 +1,70 @@ + + + + + CADisableMinimumFrameDurationOnPhone + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + Etm Powersync App + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + etm_powersync_app + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleSignature + ???? + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSRequiresIPhoneOS + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + $(PRODUCT_MODULE_NAME).SceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + + UILaunchStoryboardName + LaunchScreen + UIMainStoryboardFile + Main + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h new file mode 100644 index 0000000..308a2a5 --- /dev/null +++ b/ios/Runner/Runner-Bridging-Header.h @@ -0,0 +1 @@ +#import "GeneratedPluginRegistrant.h" diff --git a/ios/Runner/SceneDelegate.swift b/ios/Runner/SceneDelegate.swift new file mode 100644 index 0000000..b9ce8ea --- /dev/null +++ b/ios/Runner/SceneDelegate.swift @@ -0,0 +1,6 @@ +import Flutter +import UIKit + +class SceneDelegate: FlutterSceneDelegate { + +} diff --git a/ios/RunnerTests/RunnerTests.swift b/ios/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..86a7c3b --- /dev/null +++ b/ios/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Flutter +import UIKit +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/lib/main.dart b/lib/main.dart new file mode 100644 index 0000000..5154688 --- /dev/null +++ b/lib/main.dart @@ -0,0 +1,168 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; + +import 'services/nymea_service.dart'; +import 'screens/dashboard_screen.dart'; +import 'screens/energy_screen.dart'; +import 'screens/things_screen.dart'; +import 'screens/ac_screen.dart'; +import 'screens/favorites_screen.dart'; +import 'theme/app_theme.dart'; + +void main() { + WidgetsFlutterBinding.ensureInitialized(); + SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]); + SystemChrome.setSystemUIOverlayStyle( + const SystemUiOverlayStyle( + statusBarColor: Colors.transparent, + statusBarIconBrightness: Brightness.dark, + ), + ); + + runApp( + ChangeNotifierProvider( + create: (_) => NymeaService(), + child: const NymeaEnergyApp(), + ), + ); +} + +class NymeaEnergyApp extends StatelessWidget { + const NymeaEnergyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + title: 'Nymea Energy', + debugShowCheckedModeBanner: false, + theme: AppTheme.theme, + home: const MainShell(), + ); + } +} + +class MainShell extends StatefulWidget { + const MainShell({super.key}); + + @override + State createState() => _MainShellState(); +} + +class _MainShellState extends State { + int _currentIndex = 0; + + final List _screens = const [ + DashboardScreen(), + EnergyScreen(), + ThingsScreen(), + ACScreen(), + FavoritesScreen(), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + body: IndexedStack( + index: _currentIndex, + children: _screens, + ), + bottomNavigationBar: _BottomNav( + currentIndex: _currentIndex, + onTap: (i) => setState(() => _currentIndex = i), + ), + ); + } +} + +class _BottomNav extends StatelessWidget { + final int currentIndex; + final ValueChanged onTap; + + const _BottomNav({required this.currentIndex, required this.onTap}); + + @override + Widget build(BuildContext context) { + final items = [ + _NavItem(icon: Icons.home_rounded, label: 'Dashboard'), + _NavItem(icon: Icons.bar_chart_rounded, label: 'Énergie'), + _NavItem(icon: Icons.device_hub_rounded, label: 'Things'), + _NavItem(icon: Icons.ac_unit_rounded, label: 'A/C'), + _NavItem(icon: Icons.star_rounded, label: 'Favoris'), + ]; + + return Container( + decoration: BoxDecoration( + color: Colors.white, + boxShadow: [ + BoxShadow( + color: Colors.black.withValues(alpha:0.08), + blurRadius: 12, + offset: const Offset(0, -2), + ), + ], + ), + child: SafeArea( + child: SizedBox( + height: 62, + child: Row( + children: items.asMap().entries.map((e) { + final i = e.key; + final item = e.value; + final isSelected = currentIndex == i; + + return Expanded( + child: GestureDetector( + onTap: () => onTap(i), + behavior: HitTestBehavior.opaque, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + AnimatedContainer( + duration: const Duration(milliseconds: 200), + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 4), + decoration: BoxDecoration( + color: isSelected + ? AppTheme.primaryGreen.withValues(alpha:0.12) + : Colors.transparent, + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + item.icon, + color: isSelected + ? AppTheme.primaryGreen + : AppTheme.textLight, + size: 22, + ), + ), + const SizedBox(height: 2), + Text( + item.label, + style: TextStyle( + fontSize: 10, + color: isSelected + ? AppTheme.primaryGreen + : AppTheme.textLight, + fontWeight: isSelected + ? FontWeight.bold + : FontWeight.normal, + ), + ), + ], + ), + ), + ); + }).toList(), + ), + ), + ), + ); + } +} + +class _NavItem { + final IconData icon; + final String label; + const _NavItem({required this.icon, required this.label}); +} diff --git a/lib/models/energy_data.dart b/lib/models/energy_data.dart new file mode 100644 index 0000000..89a41f7 --- /dev/null +++ b/lib/models/energy_data.dart @@ -0,0 +1,101 @@ +class EnergyData { + final double pvPower; // Watts - production solaire + final double homePower; // Watts - consommation maison + final double batteryPower; // Watts - puissance batterie (+ charge, - décharge) + final double gridPower; // Watts - réseau (+ injection, - soutif) + final double batterySOC; // % - état de charge batterie + final double temperature; // °C + final String weatherIcon; + + // Journée + final double dayProductionWh; + final double daySelfConsumptionWh; + final double dayGridInjectionWh; + final double selfConsumptionRate; // % + final double autonomyRate; // % + final double dayGains; // € + + // Borne de recharge + final ChargingMode chargingMode; + final double chargingPower; // kW + final double solarSourcePercent; // % + final bool gridLimitOk; + + const EnergyData({ + this.pvPower = 0, + this.homePower = 0, + this.batteryPower = 0, + this.gridPower = 0, + this.batterySOC = 0, + this.temperature = 0, + this.weatherIcon = 'cloud_snow', + this.dayProductionWh = 0, + this.daySelfConsumptionWh = 0, + this.dayGridInjectionWh = 0, + this.selfConsumptionRate = 0, + this.autonomyRate = 0, + this.dayGains = 0, + this.chargingMode = ChargingMode.pv, + this.chargingPower = 3.6, + this.solarSourcePercent = 82, + this.gridLimitOk = true, + }); + + EnergyData copyWith({ + double? pvPower, + double? homePower, + double? batteryPower, + double? gridPower, + double? batterySOC, + double? temperature, + String? weatherIcon, + double? dayProductionWh, + double? daySelfConsumptionWh, + double? dayGridInjectionWh, + double? selfConsumptionRate, + double? autonomyRate, + double? dayGains, + ChargingMode? chargingMode, + double? chargingPower, + double? solarSourcePercent, + bool? gridLimitOk, + }) { + return EnergyData( + pvPower: pvPower ?? this.pvPower, + homePower: homePower ?? this.homePower, + batteryPower: batteryPower ?? this.batteryPower, + gridPower: gridPower ?? this.gridPower, + batterySOC: batterySOC ?? this.batterySOC, + temperature: temperature ?? this.temperature, + weatherIcon: weatherIcon ?? this.weatherIcon, + dayProductionWh: dayProductionWh ?? this.dayProductionWh, + daySelfConsumptionWh: daySelfConsumptionWh ?? this.daySelfConsumptionWh, + dayGridInjectionWh: dayGridInjectionWh ?? this.dayGridInjectionWh, + selfConsumptionRate: selfConsumptionRate ?? this.selfConsumptionRate, + autonomyRate: autonomyRate ?? this.autonomyRate, + dayGains: dayGains ?? this.dayGains, + chargingMode: chargingMode ?? this.chargingMode, + chargingPower: chargingPower ?? this.chargingPower, + solarSourcePercent: solarSourcePercent ?? this.solarSourcePercent, + gridLimitOk: gridLimitOk ?? this.gridLimitOk, + ); + } +} + +enum ChargingMode { pv, minPv, boost } + +class HistoryPoint { + final DateTime time; + final double pvWh; + final double homeWh; + final double gridWh; + final double batteryWh; + + const HistoryPoint({ + required this.time, + this.pvWh = 0, + this.homeWh = 0, + this.gridWh = 0, + this.batteryWh = 0, + }); +} \ No newline at end of file diff --git a/lib/models/nymea_models.dart b/lib/models/nymea_models.dart new file mode 100644 index 0000000..6c36730 --- /dev/null +++ b/lib/models/nymea_models.dart @@ -0,0 +1,247 @@ +// ── Thing models ────────────────────────────────────────────────────────────── + +class NymeaThing { + final String id; + final String name; + final String thingClassId; + final String setupStatus; + final List> paramValues; + final List states; + + const NymeaThing({ + required this.id, + required this.name, + required this.thingClassId, + required this.setupStatus, + required this.paramValues, + this.states = const [], + }); + + factory NymeaThing.fromJson(Map j) { + return NymeaThing( + id: j['id'] as String? ?? '', + name: j['name'] as String? ?? 'Unknown', + thingClassId: j['thingClassId'] as String? ?? '', + setupStatus: j['setupStatus'] as String? ?? '', + paramValues: List>.from(j['paramValues'] ?? []), + states: (j['states'] as List? ?? []) + .map((s) => NymeaStateValue.fromJson(s)) + .toList(), + ); + } + + NymeaThing copyWith({String? name, List? states}) => NymeaThing( + id: id, + name: name ?? this.name, + thingClassId: thingClassId, + setupStatus: setupStatus, + paramValues: paramValues, + states: states ?? this.states, + ); + + dynamic settingValue(String settingTypeId) { + try { + return paramValues + .firstWhere((p) => p['paramTypeId'] == settingTypeId)['value']; + } catch (_) { + return null; + } + } + + dynamic stateValue(String stateTypeId) { + try { + return states.firstWhere((s) => s.stateTypeId == stateTypeId).value; + } catch (_) { + return null; + } + } + + bool get isSetupComplete => setupStatus == 'ThingSetupStatusComplete'; +} + +class NymeaStateValue { + final String stateTypeId; + final dynamic value; + + const NymeaStateValue({required this.stateTypeId, required this.value}); + + factory NymeaStateValue.fromJson(Map j) => NymeaStateValue( + stateTypeId: j['stateTypeId'] as String? ?? '', + value: j['value'], + ); +} + +// ── State type definition (from GetThingClasses) ────────────────────────────── +class NymeaStateType { + final String id; + final String name; + final String displayName; + final String type; // "Double", "Bool", "Int", "String" + final String unit; // "W", "V", "A", "Percentage", "" + final dynamic defaultValue; + final bool writable; + + const NymeaStateType({ + required this.id, + required this.name, + required this.displayName, + required this.type, + required this.unit, + this.defaultValue, + this.writable = false, + }); + + factory NymeaStateType.fromJson(Map j) => NymeaStateType( + id: j['id'] as String? ?? '', + name: j['name'] as String? ?? '', + displayName: j['displayName'] as String? ?? j['name'] as String? ?? '', + type: j['type'] as String? ?? 'String', + unit: j['unit'] as String? ?? '', + defaultValue: j['defaultValue'], + writable: j['writable'] as bool? ?? false, + ); + + String formatValue(dynamic value) { + if (value == null) return '—'; + switch (unit) { + case 'W': return '${_fmt(value)} W'; + case 'kW': return '${_fmt(value)} kW'; + case 'Wh': return '${_fmt(value)} Wh'; + case 'kWh': return '${_fmt(value)} kWh'; + case 'V': return '${_fmt(value)} V'; + case 'A': return '${_fmt(value)} A'; + case 'Percentage': return '${_fmt(value)} %'; + case 'Celsius': return '${_fmt(value)} °C'; + case 'Hz': return '${_fmt(value)} Hz'; + case 'VoltAmpereReactive': return '${_fmt(value)} VAr'; + case 'KiloVoltAmpereHour': return '${_fmt(value)} kVAh'; + case 'Rpm': return '${_fmt(value)} rpm'; + default: + if (type == 'Bool') return (value == true || value == 'true') ? 'Oui' : 'Non'; + return value.toString(); + } + } + + String _fmt(dynamic value) { + if (value is double) { + if (value.abs() >= 1000) return value.toStringAsFixed(0); + if (value.abs() >= 10) return value.toStringAsFixed(1); + return value.toStringAsFixed(2); + } + return value.toString(); + } +} + +// ── Action type definition ───────────────────────────────────────────────────── +class NymeaActionType { + final String id; + final String name; + final String displayName; + final List> paramTypes; + + const NymeaActionType({ + required this.id, + required this.name, + required this.displayName, + this.paramTypes = const [], + }); + + factory NymeaActionType.fromJson(Map j) => NymeaActionType( + id: j['id'] as String? ?? '', + name: j['name'] as String? ?? '', + displayName: j['displayName'] as String? ?? j['name'] as String? ?? '', + paramTypes: List>.from(j['paramTypes'] ?? []), + ); +} + +class NymeaThingClass { + final String id; + final String name; + final String displayName; + final List interfaces; // ← clé pour la catégorisation + final List stateTypes; + final List actionTypes; + final List> paramTypes; + final List settingsTypes; + + const NymeaThingClass({ + required this.id, + required this.name, + required this.displayName, + this.interfaces = const [], + this.stateTypes = const [], + this.actionTypes = const [], + this.paramTypes = const [], + this.settingsTypes = const [], + }); + + factory NymeaThingClass.fromJson(Map j) => NymeaThingClass( + id: j['id'] as String? ?? '', + name: j['name'] as String? ?? '', + displayName: j['displayName'] as String? ?? '', + interfaces: List.from(j['interfaces'] ?? []), + stateTypes: (j['stateTypes'] as List? ?? []) + .map((s) => NymeaStateType.fromJson(s as Map)) + .toList(), + actionTypes: (j['actionTypes'] as List? ?? []) + .map((a) => NymeaActionType.fromJson(a as Map)) + .toList(), + paramTypes: List>.from(j['paramTypes'] ?? []), + settingsTypes: (j['settingsTypes'] as List? ?? []) + .map((s) => NymeaStateType.fromJson(s as Map)) + .toList(), + ); + + /// Retourne la stateType par son id + NymeaStateType? stateTypeById(String id) { + try { return stateTypes.firstWhere((s) => s.id == id); } + catch (_) { return null; } + } + + /// Retourne la stateType "principale" à afficher sur la card + NymeaStateType? get primaryStateType { + // Priorité : power → energy → temperature → connected → on/off → premier + const priority = [ + 'currentPower', 'power', 'totalEnergyConsumed', 'totalEnergyProduced', + 'temperature', 'batterylevel', 'soc', 'connected', 'on', + ]; + for (final p in priority) { + final found = stateTypes.where( + (s) => s.name.toLowerCase() == p.toLowerCase() + ); + if (found.isNotEmpty) return found.first; + } + return stateTypes.isNotEmpty ? stateTypes.first : null; + } +} + +// ── Favorite Widgets ────────────────────────────────────────────────────────── + +enum FavoriteType { + pvPower, + homePower, + batterySOC, + gridPower, + rates, + evCharger, + thingState, + chart, +} + +class FavoriteWidget { + final String id; + final FavoriteType type; + final String title; + final String? thingId; + final String? stateTypeId; + final Map extra; + + const FavoriteWidget({ + required this.id, + required this.type, + required this.title, + this.thingId, + this.stateTypeId, + this.extra = const {}, + }); +} diff --git a/lib/models/thing_category.dart b/lib/models/thing_category.dart new file mode 100644 index 0000000..f7390c7 --- /dev/null +++ b/lib/models/thing_category.dart @@ -0,0 +1,187 @@ +import 'package:flutter/material.dart'; +import '../theme/app_theme.dart'; +import 'nymea_models.dart'; + +// ───────────────────────────────────────────────────────────────────────────── +// Catégories affichées dans le Things screen +// ───────────────────────────────────────────────────────────────────────────── + +enum ThingCategory { + energy, // smartmeter, energymeter, powersocket + solar, // solarinverter, solarpanel + battery, // battery, energystorage + evCharger, // evcharger + hvac, // thermostat, heatingzone, ac, pump + lighting, // light, dimmablelight, colorlight + sensors, // sensor, temperaturesensor, humiditysensor, motionsensor + network, // networkdevice, gateway + notifications, // pushnotification, email, sms + media, // mediadevice, mediaplayer + weather, // weather + other, // tout le reste +} + +class ThingCategoryInfo { + final ThingCategory category; + final String label; + final IconData icon; + final Color color; + + const ThingCategoryInfo({ + required this.category, + required this.label, + required this.icon, + required this.color, + }); +} + +// ───────────────────────────────────────────────────────────────────────────── +// Mapping interface nymea → catégorie +// ───────────────────────────────────────────────────────────────────────────── + +const Map interfaceToCategoryMap = { + 'smartmeter': ThingCategory.energy, + 'electricmeter': ThingCategory.energy, + 'energymeter': ThingCategory.energy, + 'smartenergymeter': ThingCategory.energy, + 'extendedsmartmeter': ThingCategory.energy, + 'powersocket': ThingCategory.energy, + 'smartplug': ThingCategory.energy, + 'solarinverter': ThingCategory.solar, + 'solarpanel': ThingCategory.solar, + 'inverter': ThingCategory.solar, + 'battery': ThingCategory.battery, + 'energystorage': ThingCategory.battery, + 'batterymonitor': ThingCategory.battery, + 'evcharger': ThingCategory.evCharger, + 'wallbox': ThingCategory.evCharger, + 'thermostat': ThingCategory.hvac, + 'heatingzone': ThingCategory.hvac, + 'ac': ThingCategory.hvac, + 'airconditioner': ThingCategory.hvac, + 'pump': ThingCategory.hvac, + 'heatpump': ThingCategory.hvac, + 'ventilation': ThingCategory.hvac, + 'boiler': ThingCategory.hvac, + 'light': ThingCategory.lighting, + 'dimmablelight': ThingCategory.lighting, + 'colorlight': ThingCategory.lighting, + 'colortemperaturelight': ThingCategory.lighting, + 'sensor': ThingCategory.sensors, + 'temperaturesensor': ThingCategory.sensors, + 'humiditysensor': ThingCategory.sensors, + 'pressuresensor': ThingCategory.sensors, + 'motionsensor': ThingCategory.sensors, + 'doorsensor': ThingCategory.sensors, + 'windowsensor': ThingCategory.sensors, + 'smokesensor': ThingCategory.sensors, + 'co2sensor': ThingCategory.sensors, + 'lightsensor': ThingCategory.sensors, + 'networkdevice': ThingCategory.network, + 'gateway': ThingCategory.network, + 'router': ThingCategory.network, + 'pushnotification': ThingCategory.notifications, + 'notificationservice': ThingCategory.notifications, + 'notification': ThingCategory.notifications, + 'email': ThingCategory.notifications, + 'sms': ThingCategory.notifications, + 'weather': ThingCategory.weather, + 'weatherstation': ThingCategory.weather, + 'mediadevice': ThingCategory.media, + 'mediaplayer': ThingCategory.media, +}; + +// ───────────────────────────────────────────────────────────────────────────── +// Infos visuelles par catégorie +// ───────────────────────────────────────────────────────────────────────────── + +const Map categoryInfoMap = { + ThingCategory.energy: ThingCategoryInfo( + category: ThingCategory.energy, + label: 'Compteurs & Prises', + icon: Icons.electrical_services_rounded, + color: AppTheme.gridGray, + ), + ThingCategory.solar: ThingCategoryInfo( + category: ThingCategory.solar, + label: 'Solaire', + icon: Icons.solar_power_rounded, + color: AppTheme.solarYellow, + ), + ThingCategory.battery: ThingCategoryInfo( + category: ThingCategory.battery, + label: 'Stockage', + icon: Icons.battery_charging_full_rounded, + color: AppTheme.batteryGreen, + ), + ThingCategory.evCharger: ThingCategoryInfo( + category: ThingCategory.evCharger, + label: 'Chargeurs EV', + icon: Icons.electric_car_rounded, + color: AppTheme.minPvBlue, + ), + ThingCategory.hvac: ThingCategoryInfo( + category: ThingCategory.hvac, + label: 'Chauffage & Climatisation', + icon: Icons.thermostat_rounded, + color: Color(0xFFFF7043), + ), + ThingCategory.lighting: ThingCategoryInfo( + category: ThingCategory.lighting, + label: 'Éclairage', + icon: Icons.lightbulb_rounded, + color: Color(0xFFFFCA28), + ), + ThingCategory.sensors: ThingCategoryInfo( + category: ThingCategory.sensors, + label: 'Capteurs', + icon: Icons.sensors_rounded, + color: Color(0xFF26C6DA), + ), + ThingCategory.network: ThingCategoryInfo( + category: ThingCategory.network, + label: 'Réseau & Passerelles', + icon: Icons.router_rounded, + color: Color(0xFF7C4DFF), + ), + ThingCategory.notifications: ThingCategoryInfo( + category: ThingCategory.notifications, + label: 'Services de notification', + icon: Icons.notifications_rounded, + color: Color(0xFFEC407A), + ), + ThingCategory.weather: ThingCategoryInfo( + category: ThingCategory.weather, + label: 'Météo', + icon: Icons.wb_cloudy_rounded, + color: Color(0xFF42A5F5), + ), + ThingCategory.media: ThingCategoryInfo( + category: ThingCategory.media, + label: 'Multimédia', + icon: Icons.speaker_rounded, + color: Color(0xFFAB47BC), + ), + ThingCategory.other: ThingCategoryInfo( + category: ThingCategory.other, + label: 'Autres', + icon: Icons.device_hub_rounded, + color: Color(0xFF78909C), + ), +}; + +// ───────────────────────────────────────────────────────────────────────────── +// Extension utilitaire sur NymeaThingClass +// ───────────────────────────────────────────────────────────────────────────── + +extension ThingClassCategoryExt on NymeaThingClass { + ThingCategory get category { + for (final iface in interfaces) { + final cat = interfaceToCategoryMap[iface.toLowerCase()]; + if (cat != null) return cat; + } + return ThingCategory.other; + } + + ThingCategoryInfo get categoryDetails => categoryInfoMap[category]!; +} \ No newline at end of file diff --git a/lib/screens/ac_screen.dart b/lib/screens/ac_screen.dart new file mode 100644 index 0000000..2e691c5 --- /dev/null +++ b/lib/screens/ac_screen.dart @@ -0,0 +1,333 @@ +import 'package:flutter/material.dart'; +import '../theme/app_theme.dart'; + +class ACScreen extends StatefulWidget { + const ACScreen({super.key}); + + @override + State createState() => _ACScreenState(); +} + +class _ACScreenState extends State { + final List<_ACZone> _zones = [ + _ACZone(name: 'Salon', currentTemp: 19.5, targetTemp: 21, mode: ACMode.heat, isOn: true), + _ACZone(name: 'Chambre', currentTemp: 18.0, targetTemp: 19, mode: ACMode.cool, isOn: false), + _ACZone(name: 'Bureau', currentTemp: 20.0, targetTemp: 22, mode: ACMode.heat, isOn: true), + _ACZone(name: 'Cuisine', currentTemp: 21.5, targetTemp: 21, mode: ACMode.auto, isOn: false), + ]; + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: AppTheme.backgroundGray, + appBar: AppBar( + backgroundColor: AppTheme.backgroundGray, + elevation: 0, + title: const Text( + 'Climatisation / Chauffage', + style: TextStyle(fontWeight: FontWeight.bold, color: AppTheme.textDark), + ), + actions: [ + IconButton( + icon: const Icon(Icons.schedule, color: AppTheme.textDark), + onPressed: () {}, + ), + ], + ), + body: ListView.separated( + padding: const EdgeInsets.all(16), + itemCount: _zones.length, + separatorBuilder: (_, _) => const SizedBox(height: 12), + itemBuilder: (context, index) { + return _ZoneCard( + zone: _zones[index], + onChanged: (updated) { + setState(() => _zones[index] = updated); + }, + ); + }, + ), + ); + } +} + +enum ACMode { heat, cool, auto, fan } + +class _ACZone { + final String name; + final double currentTemp; + final double targetTemp; + final ACMode mode; + final bool isOn; + + const _ACZone({ + required this.name, + required this.currentTemp, + required this.targetTemp, + required this.mode, + required this.isOn, + }); + + _ACZone copyWith({ + double? targetTemp, + ACMode? mode, + bool? isOn, + }) => + _ACZone( + name: name, + currentTemp: currentTemp, + targetTemp: targetTemp ?? this.targetTemp, + mode: mode ?? this.mode, + isOn: isOn ?? this.isOn, + ); +} + +class _ZoneCard extends StatelessWidget { + final _ACZone zone; + final ValueChanged<_ACZone> onChanged; + + const _ZoneCard({required this.zone, required this.onChanged}); + + Color get _modeColor { + switch (zone.mode) { + case ACMode.heat: + return Colors.orange; + case ACMode.cool: + return Colors.cyan; + case ACMode.auto: + return AppTheme.primaryGreen; + case ACMode.fan: + return Colors.blueGrey; + } + } + + IconData get _modeIcon { + switch (zone.mode) { + case ACMode.heat: + return Icons.whatshot_rounded; + case ACMode.cool: + return Icons.ac_unit_rounded; + case ACMode.auto: + return Icons.autorenew_rounded; + case ACMode.fan: + return Icons.air_rounded; + } + } + + String get _modeLabel { + switch (zone.mode) { + case ACMode.heat: + return 'Chauffage'; + case ACMode.cool: + return 'Clim'; + case ACMode.auto: + return 'Auto'; + case ACMode.fan: + return 'Ventilation'; + } + } + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + // Header row + Row( + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + color: zone.isOn + ? _modeColor.withValues(alpha:0.15) + : Colors.grey.shade100, + borderRadius: BorderRadius.circular(12), + ), + child: Icon( + _modeIcon, + color: zone.isOn ? _modeColor : Colors.grey, + size: 26, + ), + ), + const SizedBox(width: 14), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(zone.name, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + fontSize: 16)), + Text( + zone.isOn ? _modeLabel : 'Éteint', + style: TextStyle( + fontSize: 12, + color: + zone.isOn ? _modeColor : AppTheme.textLight), + ), + ], + ), + ), + Switch( + value: zone.isOn, + onChanged: (v) => onChanged(zone.copyWith(isOn: v)), + activeThumbColor: _modeColor, + ), + ], + ), + + if (zone.isOn) ...[ + const Divider(height: 20), + + // Temperature + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + children: [ + const Text('Actuelle', + style: TextStyle( + fontSize: 12, color: AppTheme.textLight)), + Text( + '${zone.currentTemp.toStringAsFixed(1)}°C', + style: const TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + ], + ), + Icon(Icons.arrow_forward_rounded, + color: Colors.grey.shade400), + Column( + children: [ + const Text('Cible', + style: TextStyle( + fontSize: 12, color: AppTheme.textLight)), + Row( + children: [ + IconButton( + icon: Icon(Icons.remove_circle_outline, + color: _modeColor), + onPressed: () => onChanged(zone.copyWith( + targetTemp: zone.targetTemp - 0.5)), + ), + Text( + '${zone.targetTemp.toStringAsFixed(1)}°C', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: _modeColor, + ), + ), + IconButton( + icon: Icon(Icons.add_circle_outline, + color: _modeColor), + onPressed: () => onChanged(zone.copyWith( + targetTemp: zone.targetTemp + 0.5)), + ), + ], + ), + ], + ), + ], + ), + + // Mode selector + const SizedBox(height: 8), + Row( + children: ACMode.values.map((m) { + final selected = zone.mode == m; + final color = _modeColorFor(m); + final icon = _modeIconFor(m); + final label = _modeLabelFor(m); + return Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: GestureDetector( + onTap: () => onChanged(zone.copyWith(mode: m)), + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + padding: const EdgeInsets.symmetric(vertical: 8), + decoration: BoxDecoration( + color: selected + ? color.withValues(alpha:0.15) + : Colors.grey.shade100, + borderRadius: BorderRadius.circular(10), + border: selected + ? Border.all(color: color, width: 1.5) + : null, + ), + child: Column( + children: [ + Icon(icon, + size: 18, + color: selected ? color : Colors.grey), + const SizedBox(height: 2), + Text(label, + style: TextStyle( + fontSize: 10, + color: + selected ? color : AppTheme.textLight, + fontWeight: selected + ? FontWeight.bold + : FontWeight.normal)), + ], + ), + ), + ), + ), + ); + }).toList(), + ), + ], + ], + ), + ), + ); + } + + Color _modeColorFor(ACMode m) { + switch (m) { + case ACMode.heat: + return Colors.orange; + case ACMode.cool: + return Colors.cyan; + case ACMode.auto: + return AppTheme.primaryGreen; + case ACMode.fan: + return Colors.blueGrey; + } + } + + IconData _modeIconFor(ACMode m) { + switch (m) { + case ACMode.heat: + return Icons.whatshot_rounded; + case ACMode.cool: + return Icons.ac_unit_rounded; + case ACMode.auto: + return Icons.autorenew_rounded; + case ACMode.fan: + return Icons.air_rounded; + } + } + + String _modeLabelFor(ACMode m) { + switch (m) { + case ACMode.heat: + return 'Chauf.'; + case ACMode.cool: + return 'Clim'; + case ACMode.auto: + return 'Auto'; + case ACMode.fan: + return 'Vent.'; + } + } +} \ No newline at end of file diff --git a/lib/screens/dashboard_screen.dart b/lib/screens/dashboard_screen.dart new file mode 100644 index 0000000..e7d9e77 --- /dev/null +++ b/lib/screens/dashboard_screen.dart @@ -0,0 +1,556 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../services/nymea_service.dart'; +import '../theme/app_theme.dart'; +import '../widgets/energy_flow_widget.dart'; +import '../widgets/production_card.dart'; +import '../widgets/ev_charging_card.dart'; +import '../widgets/gains_card.dart'; + +class DashboardScreen extends StatefulWidget { + const DashboardScreen({super.key}); + + @override + State createState() => _DashboardScreenState(); +} + +class _DashboardScreenState extends State { + @override + void initState() { + super.initState(); + // Start simulation on first load + WidgetsBinding.instance.addPostFrameCallback((_) { + final service = context.read(); + if (!service.connected) { + service.startSimulation(); + } + }); + } + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, service, _) { + final data = service.energyData; + + return Scaffold( + backgroundColor: AppTheme.backgroundGray, + body: RefreshIndicator( + onRefresh: () async { + service.startSimulation(); + }, + color: AppTheme.primaryGreen, + child: CustomScrollView( + slivers: [ + // App bar + SliverAppBar( + floating: true, + backgroundColor: AppTheme.backgroundGray, + elevation: 0, + title: Row( + children: [ + Container( + width: 36, + height: 36, + decoration: BoxDecoration( + color: AppTheme.primaryGreen, + borderRadius: BorderRadius.circular(10), + ), + child: const Icon(Icons.bolt, color: Colors.white, size: 22), + ), + const SizedBox(width: 10), + const Text( + 'Nymea Energy', + style: TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + fontSize: 18, + ), + ), + ], + ), + actions: [ + // Connection status + Padding( + padding: const EdgeInsets.only(right: 8), + child: IconButton( + icon: Icon( + service.connected + ? Icons.wifi_rounded + : Icons.wifi_off_rounded, + color: service.connected + ? AppTheme.primaryGreen + : Colors.red, + ), + onPressed: () => _showConnectionDialog(context, service), + ), + ), + Padding( + padding: const EdgeInsets.only(right: 12), + child: IconButton( + icon: const Icon(Icons.notifications_outlined, + color: AppTheme.textDark), + onPressed: () {}, + ), + ), + ], + ), + + SliverPadding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + sliver: SliverList( + delegate: SliverChildListDelegate([ + // Energy flow + EnergyFlowWidget(data: data), + const SizedBox(height: 12), + + // Self-consumption rates + _RatesRow(data: data), + const SizedBox(height: 12), + + // Production card + ProductionCard(data: data), + const SizedBox(height: 12), + + // Gains + GainsCard(data: data), + const SizedBox(height: 12), + + // EV Charging + EVChargingCard(data: data, service: service), + const SizedBox(height: 16), + ]), + ), + ), + ], + ), + ), + ); + }, + ); + } + + void _showConnectionDialog(BuildContext context, NymeaService service) { + showDialog( + context: context, + builder: (ctx) => _ConnectionDialog(service: service), + ); + } +} + +class _RatesRow extends StatelessWidget { + final dynamic data; + + const _RatesRow({required this.data}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: _RateCard( + label: 'Autoconsommation', + value: data.selfConsumptionRate, + icon: Icons.wb_sunny_rounded, + color: AppTheme.solarYellow, + ), + ), + const SizedBox(width: 12), + Expanded( + child: _RateCard( + label: 'Autonomie', + value: data.autonomyRate, + icon: Icons.home_rounded, + color: AppTheme.homeBlue, + ), + ), + ], + ); + } +} + +class _RateCard extends StatelessWidget { + final String label; + final double value; + final IconData icon; + final Color color; + + const _RateCard({ + required this.label, + required this.value, + required this.icon, + required this.color, + }); + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(14), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(icon, color: color, size: 18), + const SizedBox(width: 6), + Expanded( + child: Text( + label, + style: const TextStyle( + fontSize: 12, color: AppTheme.textLight), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + const SizedBox(height: 8), + Text( + '${value.toStringAsFixed(1)}%', + style: TextStyle( + fontSize: 26, + fontWeight: FontWeight.bold, + color: color, + ), + ), + const SizedBox(height: 6), + ClipRRect( + borderRadius: BorderRadius.circular(4), + child: LinearProgressIndicator( + value: (value / 100).clamp(0, 1), + backgroundColor: color.withValues(alpha:0.15), + valueColor: AlwaysStoppedAnimation(color), + minHeight: 6, + ), + ), + ], + ), + ), + ); + } +} + +// ═══════════════════════════════════════════════════════════════════════════ +// Dialog de connexion avec sélection du protocole TCP / WebSocket +// ═══════════════════════════════════════════════════════════════════════════ + +class _ConnectionDialog extends StatefulWidget { + final NymeaService service; + const _ConnectionDialog({required this.service}); + + @override + State<_ConnectionDialog> createState() => _ConnectionDialogState(); +} + +class _ConnectionDialogState extends State<_ConnectionDialog> { + late TextEditingController _hostCtrl; + late TextEditingController _portCtrl; + late TextEditingController _userCtrl; + late TextEditingController _passCtrl; + late NymeaProtocol _protocol; + bool _connecting = false; + bool _verbose = false; + + // Ports par défaut selon protocole + static const _defaultPorts = { + NymeaProtocol.tcpRaw: 2222, + NymeaProtocol.webSocket: 4444, + }; + + @override + void initState() { + super.initState(); + _protocol = widget.service.protocol; + _hostCtrl = TextEditingController(text: widget.service.host); + _portCtrl = TextEditingController(text: widget.service.port.toString()); + _userCtrl = TextEditingController(text: widget.service.username); + _passCtrl = TextEditingController(text: widget.service.password); + _verbose = widget.service.verboseLog; + } + + @override + void dispose() { + _hostCtrl.dispose(); + _portCtrl.dispose(); + _userCtrl.dispose(); + _passCtrl.dispose(); + super.dispose(); + } + + void _onProtocolChanged(NymeaProtocol p) { + setState(() { + _protocol = p; + // Mettre à jour le port par défaut si l'utilisateur n'a pas changé + final currentPort = int.tryParse(_portCtrl.text) ?? 0; + final otherDefault = _defaultPorts[_protocol == NymeaProtocol.tcpRaw + ? NymeaProtocol.webSocket + : NymeaProtocol.tcpRaw]!; + if (currentPort == otherDefault || currentPort == 0) { + _portCtrl.text = _defaultPorts[p]!.toString(); + } + }); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Row( + children: [ + Container( + width: 36, height: 36, + decoration: BoxDecoration( + color: AppTheme.primaryGreen.withValues(alpha:0.12), + borderRadius: BorderRadius.circular(10), + ), + child: const Icon(Icons.router_rounded, + color: AppTheme.primaryGreen, size: 20), + ), + const SizedBox(width: 10), + const Text('Connexion Nymea'), + ], + ), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // ── Sélecteur de protocole ───────────────────────────────────── + const Text('Protocole', + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.w600, + color: AppTheme.textLight)), + const SizedBox(height: 8), + Container( + decoration: BoxDecoration( + color: Colors.grey.shade100, + borderRadius: BorderRadius.circular(10), + ), + child: Row( + children: [ + _ProtoTab( + label: 'TCP brut', + subtitle: 'port 2222', + icon: Icons.cable_rounded, + selected: _protocol == NymeaProtocol.tcpRaw, + onTap: () => _onProtocolChanged(NymeaProtocol.tcpRaw), + ), + _ProtoTab( + label: 'WebSocket', + subtitle: 'port 4444', + icon: Icons.wifi_rounded, + selected: _protocol == NymeaProtocol.webSocket, + onTap: () => _onProtocolChanged(NymeaProtocol.webSocket), + ), + ], + ), + ), + const SizedBox(height: 6), + // Info protocole + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: AppTheme.primaryGreen.withValues(alpha:0.07), + borderRadius: BorderRadius.circular(8), + ), + child: Text( + _protocol == NymeaProtocol.tcpRaw + ? '💡 TCP brut : nymea envoie un message de bienvenue dès la connexion. Utilisé par l\'app nymea officielle.' + : '💡 WebSocket : le client envoie JSONRPC.Hello en premier. Activez-le dans nymea → Paramètres → Serveur WebSocket.', + style: const TextStyle(fontSize: 11, color: AppTheme.textLight), + ), + ), + const SizedBox(height: 14), + + // ── Hôte ────────────────────────────────────────────────────── + TextField( + controller: _hostCtrl, + decoration: const InputDecoration( + labelText: 'Adresse IP / Hôte', + prefixIcon: Icon(Icons.dns_outlined), + border: OutlineInputBorder(), + isDense: true, + ), + ), + const SizedBox(height: 10), + + // ── Port ────────────────────────────────────────────────────── + TextField( + controller: _portCtrl, + keyboardType: TextInputType.number, + decoration: const InputDecoration( + labelText: 'Port', + prefixIcon: Icon(Icons.settings_ethernet), + border: OutlineInputBorder(), + isDense: true, + ), + ), + const SizedBox(height: 10), + + // ── Identifiants ────────────────────────────────────────── + TextField( + controller: _userCtrl, + decoration: const InputDecoration( + labelText: 'Utilisateur', + prefixIcon: Icon(Icons.person_outline), + border: OutlineInputBorder(), + isDense: true, + ), + ), + const SizedBox(height: 10), + TextField( + controller: _passCtrl, + obscureText: true, + decoration: const InputDecoration( + labelText: 'Mot de passe', + prefixIcon: Icon(Icons.lock_outline), + border: OutlineInputBorder(), + isDense: true, + ), + ), + + // ── Debug verbose ───────────────────────────────────────── + const SizedBox(height: 8), + Row( + children: [ + const Icon(Icons.terminal_rounded, size: 16, + color: AppTheme.textLight), + const SizedBox(width: 8), + const Expanded( + child: Text('Logs JSON verbose', + style: TextStyle(fontSize: 13, color: AppTheme.textDark)), + ), + Switch( + value: _verbose, + activeThumbColor: AppTheme.primaryGreen, + onChanged: (v) { + setState(() => _verbose = v); + widget.service.verboseLog = v; + }, + ), + ], + ), + + // ── Erreur ──────────────────────────────────────────────────── + if (widget.service.connectionError != null) ...[ + const SizedBox(height: 8), + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: Colors.red.shade50, + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Icon(Icons.error_outline, color: Colors.red, size: 16), + const SizedBox(width: 6), + Expanded( + child: Text( + widget.service.connectionError!, + style: const TextStyle(color: Colors.red, fontSize: 11), + ), + ), + ], + ), + ), + ], + ], + ), + actions: [ + // Mode démo + TextButton.icon( + icon: const Icon(Icons.science_outlined, size: 16), + label: const Text('Mode démo'), + onPressed: () { + widget.service.startSimulation(); + Navigator.pop(context); + }, + ), + // Connecter + ElevatedButton.icon( + icon: _connecting + ? const SizedBox( + width: 14, height: 14, + child: CircularProgressIndicator( + strokeWidth: 2, color: Colors.white)) + : const Icon(Icons.link_rounded, size: 16), + label: const Text('Connecter'), + onPressed: _connecting + ? null + : () async { + setState(() => _connecting = true); + final ok = await widget.service.connect( + _hostCtrl.text.trim(), + int.tryParse(_portCtrl.text.trim()) ?? + _defaultPorts[_protocol]!, + protocol: _protocol, + username: _userCtrl.text.trim(), + password: _passCtrl.text, + ); + if (ok && context.mounted) Navigator.pop(context); + if (mounted) setState(() => _connecting = false); + }, + style: ElevatedButton.styleFrom( + backgroundColor: AppTheme.primaryGreen, + foregroundColor: Colors.white, + ), + ), + ], + ); + } +} + +class _ProtoTab extends StatelessWidget { + final String label; + final String subtitle; + final IconData icon; + final bool selected; + final VoidCallback onTap; + + const _ProtoTab({ + required this.label, + required this.subtitle, + required this.icon, + required this.selected, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return Expanded( + child: GestureDetector( + onTap: onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + margin: const EdgeInsets.all(4), + padding: const EdgeInsets.symmetric(vertical: 10), + decoration: BoxDecoration( + color: selected ? Colors.white : Colors.transparent, + borderRadius: BorderRadius.circular(8), + boxShadow: selected + ? [BoxShadow( + color: Colors.black.withValues(alpha:0.08), + blurRadius: 4, offset: const Offset(0, 1))] + : null, + ), + child: Column( + children: [ + Icon(icon, + size: 20, + color: selected ? AppTheme.primaryGreen : AppTheme.textLight), + const SizedBox(height: 4), + Text(label, + style: TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: selected ? AppTheme.primaryGreen : AppTheme.textLight)), + Text(subtitle, + style: const TextStyle( + fontSize: 10, color: AppTheme.textLight)), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/energy_screen.dart b/lib/screens/energy_screen.dart new file mode 100644 index 0000000..01e39fa --- /dev/null +++ b/lib/screens/energy_screen.dart @@ -0,0 +1,403 @@ +import 'package:flutter/material.dart'; +import 'package:fl_chart/fl_chart.dart'; +import 'package:provider/provider.dart'; +import '../services/nymea_service.dart'; +import '../theme/app_theme.dart'; + +class EnergyScreen extends StatefulWidget { + const EnergyScreen({super.key}); + + @override + State createState() => _EnergyScreenState(); +} + +class _EnergyScreenState extends State { + String _period = 'Jour'; + final List _periods = ['Jour', 'Semaine', 'Mois', 'Année']; + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, service, _) { + final points = service.historyPoints; + + return Scaffold( + backgroundColor: AppTheme.backgroundGray, + appBar: AppBar( + backgroundColor: AppTheme.backgroundGray, + elevation: 0, + title: const Text( + 'Énergie', + style: TextStyle( + fontWeight: FontWeight.bold, color: AppTheme.textDark), + ), + actions: [ + IconButton( + icon: const Icon(Icons.file_download_outlined, + color: AppTheme.textDark), + onPressed: () {}, + ), + ], + ), + body: SingleChildScrollView( + padding: const EdgeInsets.all(16), + child: Column( + children: [ + // Period selector + Card( + child: Padding( + padding: const EdgeInsets.all(4), + child: Row( + children: _periods.map((p) { + final selected = _period == p; + return Expanded( + child: GestureDetector( + onTap: () => setState(() => _period = p), + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + padding: const EdgeInsets.symmetric(vertical: 8), + decoration: BoxDecoration( + color: selected + ? AppTheme.primaryGreen + : Colors.transparent, + borderRadius: BorderRadius.circular(10), + ), + child: Text( + p, + textAlign: TextAlign.center, + style: TextStyle( + color: selected + ? Colors.white + : AppTheme.textLight, + fontWeight: selected + ? FontWeight.bold + : FontWeight.normal, + fontSize: 13, + ), + ), + ), + ), + ); + }).toList(), + ), + ), + ), + const SizedBox(height: 12), + + // Summary cards + _SummaryRow(service: service), + const SizedBox(height: 12), + + // Production chart + Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Production & Consommation', + style: TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + fontSize: 15)), + const SizedBox(height: 4), + const _Legend(), + const SizedBox(height: 16), + SizedBox( + height: 200, + child: points.isEmpty + ? const Center(child: CircularProgressIndicator()) + : BarChart( + BarChartData( + alignment: BarChartAlignment.spaceAround, + maxY: 5000, + barTouchData: BarTouchData(enabled: true), + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 24, + getTitlesWidget: (value, meta) { + final idx = value.toInt(); + if (idx % 3 != 0 || + idx >= points.length) { + return const SizedBox(); + } + return Text( + '${points[idx].time.hour}h', + style: const TextStyle( + fontSize: 10, + color: AppTheme.textLight), + ); + }, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 40, + getTitlesWidget: (value, meta) => Text( + '${(value / 1000).toStringAsFixed(1)}k', + style: const TextStyle( + fontSize: 9, + color: AppTheme.textLight), + ), + ), + ), + rightTitles: const AxisTitles( + sideTitles: + SideTitles(showTitles: false)), + topTitles: const AxisTitles( + sideTitles: + SideTitles(showTitles: false)), + ), + borderData: FlBorderData(show: false), + gridData: FlGridData( + show: true, + drawVerticalLine: false, + getDrawingHorizontalLine: (value) => + FlLine( + color: Colors.grey.shade100, + strokeWidth: 1, + ), + ), + barGroups: points + .asMap() + .entries + .map( + (e) => BarChartGroupData( + x: e.key, + barsSpace: 2, + barRods: [ + BarChartRodData( + toY: e.value.pvWh, + color: AppTheme.solarYellow, + width: 5, + borderRadius: + const BorderRadius.vertical( + top: Radius.circular(3)), + ), + BarChartRodData( + toY: e.value.homeWh, + color: AppTheme.homeBlue, + width: 5, + borderRadius: + const BorderRadius.vertical( + top: Radius.circular(3)), + ), + ], + ), + ) + .toList(), + ), + ), + ), + ], + ), + ), + ), + const SizedBox(height: 12), + + // Grid line chart + Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Import/Export réseau', + style: TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + fontSize: 15)), + const SizedBox(height: 16), + SizedBox( + height: 160, + child: points.isEmpty + ? const Center(child: CircularProgressIndicator()) + : LineChart( + LineChartData( + minY: -2000, + maxY: 3000, + lineTouchData: + LineTouchData(enabled: true), + titlesData: FlTitlesData( + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 22, + getTitlesWidget: (value, meta) { + final idx = value.toInt(); + if (idx % 4 != 0 || + idx >= points.length) { + return const SizedBox(); + } + return Text( + '${points[idx].time.hour}h', + style: const TextStyle( + fontSize: 10, + color: AppTheme.textLight), + ); + }, + ), + ), + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 42, + getTitlesWidget: (v, _) => Text( + '${v.toStringAsFixed(0)} W', + style: const TextStyle( + fontSize: 9, + color: AppTheme.textLight), + ), + ), + ), + rightTitles: const AxisTitles( + sideTitles: + SideTitles(showTitles: false)), + topTitles: const AxisTitles( + sideTitles: + SideTitles(showTitles: false)), + ), + borderData: FlBorderData(show: false), + gridData: FlGridData( + drawVerticalLine: false, + getDrawingHorizontalLine: (v) => FlLine( + color: v == 0 + ? Colors.grey.shade400 + : Colors.grey.shade100, + strokeWidth: v == 0 ? 1.5 : 1), + ), + lineBarsData: [ + LineChartBarData( + spots: points + .asMap() + .entries + .map((e) => FlSpot( + e.key.toDouble(), + e.value.gridWh)) + .toList(), + isCurved: true, + color: Colors.orange, + barWidth: 2, + belowBarData: BarAreaData( + show: true, + color: Colors.orange.withValues(alpha:0.1), + ), + dotData: const FlDotData(show: false), + ), + ], + ), + ), + ), + ], + ), + ), + ), + const SizedBox(height: 16), + ], + ), + ), + ); + }, + ); + } +} + +class _Legend extends StatelessWidget { + const _Legend(); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + _dot(AppTheme.solarYellow), + const SizedBox(width: 4), + const Text('Production', style: TextStyle(fontSize: 12, color: AppTheme.textLight)), + const SizedBox(width: 16), + _dot(AppTheme.homeBlue), + const SizedBox(width: 4), + const Text('Consommation', style: TextStyle(fontSize: 12, color: AppTheme.textLight)), + ], + ); + } + + Widget _dot(Color c) => Container( + width: 10, + height: 10, + decoration: BoxDecoration(color: c, shape: BoxShape.circle), + ); +} + +class _SummaryRow extends StatelessWidget { + final NymeaService service; + + const _SummaryRow({required this.service}); + + @override + Widget build(BuildContext context) { + final d = service.energyData; + return Row( + children: [ + _SummaryCard( + label: 'Production', + value: '${(d.dayProductionWh / 1000).toStringAsFixed(2)} kWh', + color: AppTheme.solarYellow, + icon: Icons.wb_sunny_rounded), + const SizedBox(width: 8), + _SummaryCard( + label: 'Consommation', + value: '${(d.daySelfConsumptionWh / 1000).toStringAsFixed(2)} kWh', + color: AppTheme.homeBlue, + icon: Icons.home_rounded), + const SizedBox(width: 8), + _SummaryCard( + label: 'Gains', + value: '${d.dayGains.toStringAsFixed(2)} €', + color: Colors.amber, + icon: Icons.euro_rounded), + ], + ); + } +} + +class _SummaryCard extends StatelessWidget { + final String label; + final String value; + final Color color; + final IconData icon; + + const _SummaryCard({ + required this.label, + required this.value, + required this.color, + required this.icon, + }); + + @override + Widget build(BuildContext context) { + return Expanded( + child: Card( + child: Padding( + padding: const EdgeInsets.all(12), + child: Column( + children: [ + Icon(icon, color: color, size: 20), + const SizedBox(height: 6), + Text(value, + style: TextStyle( + fontWeight: FontWeight.bold, + color: color, + fontSize: 13)), + const SizedBox(height: 2), + Text(label, + style: const TextStyle( + fontSize: 10, color: AppTheme.textLight)), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/screens/favorites_screen.dart b/lib/screens/favorites_screen.dart new file mode 100644 index 0000000..d86a8d3 --- /dev/null +++ b/lib/screens/favorites_screen.dart @@ -0,0 +1,706 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../models/energy_data.dart'; +import '../models/nymea_models.dart'; +import '../services/nymea_service.dart'; +import '../theme/app_theme.dart'; + +class FavoritesScreen extends StatelessWidget { + const FavoritesScreen({super.key}); + + @override + Widget build(BuildContext context) { + return Consumer( + builder: (context, service, _) { + final favs = service.favoriteWidgets; + + return Scaffold( + backgroundColor: AppTheme.backgroundGray, + appBar: AppBar( + backgroundColor: AppTheme.backgroundGray, + elevation: 0, + title: const Text('Favoris', + style: TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark)), + actions: [ + IconButton( + icon: const Icon(Icons.add_circle_outline, + color: AppTheme.primaryGreen), + onPressed: () => _showAddFavorite(context, service), + ), + ], + ), + body: favs.isEmpty + ? _EmptyState(onAdd: () => _showAddFavorite(context, service)) + : ReorderableListView.builder( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + itemCount: favs.length, + onReorder: service.reorderFavorites, + proxyDecorator: (child, index, animation) => Material( + elevation: 6, + borderRadius: BorderRadius.circular(16), + child: child, + ), + itemBuilder: (context, index) { + final fav = favs[index]; + return Padding( + key: ValueKey(fav.id), + padding: const EdgeInsets.only(bottom: 12), + child: _FavoriteCard( + fav: fav, + service: service, + onRemove: () => service.removeFavorite(fav.id), + ), + ); + }, + ), + ); + }, + ); + } + + void _showAddFavorite(BuildContext context, NymeaService service) { + showModalBottomSheet( + context: context, + isScrollControlled: true, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20))), + builder: (_) => _AddFavoriteSheet(service: service), + ); + } +} + +// ── Favorite Card ───────────────────────────────────────────────────────────── + +class _FavoriteCard extends StatelessWidget { + final FavoriteWidget fav; + final NymeaService service; + final VoidCallback onRemove; + + const _FavoriteCard({ + required this.fav, + required this.service, + required this.onRemove, + }); + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header with drag handle + title + remove + Row( + children: [ + const Icon(Icons.drag_handle, color: AppTheme.textLight), + const SizedBox(width: 8), + Expanded( + child: Text(fav.title, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + fontSize: 15)), + ), + IconButton( + icon: const Icon(Icons.close, size: 18, color: AppTheme.textLight), + onPressed: onRemove, + padding: EdgeInsets.zero, + constraints: const BoxConstraints(), + ), + ], + ), + const SizedBox(height: 10), + // Content based on type + _buildContent(context), + ], + ), + ), + ); + } + + Widget _buildContent(BuildContext context) { + final d = service.energyData; + switch (fav.type) { + case FavoriteType.pvPower: + return _BigMetric( + value: _fmt(d.pvPower), + unit: d.pvPower >= 1000 ? 'kW' : 'W', + label: 'Production solaire', + icon: Icons.wb_sunny_rounded, + color: AppTheme.solarYellow, + trend: d.pvPower > 100 ? '↑ En production' : 'Pas de production', + ); + + case FavoriteType.homePower: + return _BigMetric( + value: _fmt(d.homePower), + unit: d.homePower >= 1000 ? 'kW' : 'W', + label: 'Consommation maison', + icon: Icons.home_rounded, + color: AppTheme.homeBlue, + trend: 'Dont ${d.selfConsumptionRate.toStringAsFixed(0)}% solaire', + ); + + case FavoriteType.batterySOC: + return _BatteryWidget(data: d); + + case FavoriteType.gridPower: + return _BigMetric( + value: _fmt(d.gridPower.abs()), + unit: d.gridPower.abs() >= 1000 ? 'kW' : 'W', + label: d.gridPower >= 0 ? 'Import réseau' : 'Export réseau', + icon: Icons.electrical_services_rounded, + color: d.gridPower >= 0 ? Colors.orange : AppTheme.primaryGreen, + trend: d.gridPower >= 0 ? '↓ Achat réseau' : '↑ Vente réseau', + ); + + case FavoriteType.rates: + return _RatesWidget(data: d); + + case FavoriteType.evCharger: + return _EVWidget(data: d, service: service); + + case FavoriteType.thingState: + return _ThingStateWidget(fav: fav, service: service); + + case FavoriteType.chart: + return _MiniChart(historyPoints: service.historyPoints); + } + } + + String _fmt(double w) { + if (w >= 1000) return (w / 1000).toStringAsFixed(1); + return w.toStringAsFixed(0); + } +} + +// ── Sub-widgets ─────────────────────────────────────────────────────────────── + +class _BigMetric extends StatelessWidget { + final String value; + final String unit; + final String label; + final IconData icon; + final Color color; + final String trend; + + const _BigMetric({ + required this.value, + required this.unit, + required this.label, + required this.icon, + required this.color, + required this.trend, + }); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + color: color.withValues(alpha:0.12), + borderRadius: BorderRadius.circular(14), + ), + child: Icon(icon, color: color, size: 30), + ), + const SizedBox(width: 16), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Text(value, + style: TextStyle( + fontSize: 34, + fontWeight: FontWeight.bold, + color: color)), + const SizedBox(width: 4), + Padding( + padding: const EdgeInsets.only(bottom: 4), + child: Text(unit, + style: const TextStyle( + fontSize: 16, color: AppTheme.textLight)), + ), + ], + ), + Text(label, + style: const TextStyle( + fontSize: 12, color: AppTheme.textLight)), + const SizedBox(height: 2), + Text(trend, + style: TextStyle( + fontSize: 11, + color: color, + fontWeight: FontWeight.w500)), + ], + ), + ], + ); + } +} + +class _BatteryWidget extends StatelessWidget { + final EnergyData data; + const _BatteryWidget({required this.data}); + + @override + Widget build(BuildContext context) { + final soc = data.batterySOC; + final isCharging = data.batteryPower > 0; + final color = soc > 50 + ? AppTheme.batteryGreen + : soc > 20 + ? Colors.orange + : Colors.red; + + return Row( + children: [ + Stack( + alignment: Alignment.center, + children: [ + SizedBox( + width: 80, + height: 80, + child: CircularProgressIndicator( + value: soc / 100, + strokeWidth: 8, + backgroundColor: color.withValues(alpha:0.15), + valueColor: AlwaysStoppedAnimation(color), + ), + ), + Column( + children: [ + Text('${soc.toStringAsFixed(0)}%', + style: TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: color)), + Icon( + isCharging + ? Icons.bolt + : Icons.battery_std_rounded, + size: 14, + color: color), + ], + ), + ], + ), + const SizedBox(width: 20), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('État de charge', + style: const TextStyle( + fontSize: 13, color: AppTheme.textLight)), + const SizedBox(height: 4), + Text( + isCharging + ? '⚡ En charge ${_fmt(data.batteryPower)} W' + : data.batteryPower < -10 + ? '↓ Décharge ${_fmt(data.batteryPower.abs())} W' + : '○ Standby', + style: TextStyle( + fontSize: 13, + color: color, + fontWeight: FontWeight.w600), + ), + ], + ), + ], + ); + } + + String _fmt(double w) => w >= 1000 + ? '${(w / 1000).toStringAsFixed(1)} kW' + : '${w.toStringAsFixed(0)} W'; +} + +class _RatesWidget extends StatelessWidget { + final EnergyData data; + const _RatesWidget({required this.data}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Expanded( + child: _RateItem( + label: 'Autoconsommation', + value: data.selfConsumptionRate, + color: AppTheme.solarYellow)), + const SizedBox(width: 16), + Expanded( + child: _RateItem( + label: 'Autonomie', + value: data.autonomyRate, + color: AppTheme.homeBlue)), + ], + ); + } +} + +class _RateItem extends StatelessWidget { + final String label; + final double value; + final Color color; + const _RateItem( + {required this.label, required this.value, required this.color}); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Text('${value.toStringAsFixed(1)}%', + style: TextStyle( + fontSize: 28, + fontWeight: FontWeight.bold, + color: color)), + const SizedBox(height: 4), + ClipRRect( + borderRadius: BorderRadius.circular(4), + child: LinearProgressIndicator( + value: (value / 100).clamp(0, 1), + backgroundColor: color.withValues(alpha:0.15), + valueColor: AlwaysStoppedAnimation(color), + minHeight: 7, + ), + ), + const SizedBox(height: 4), + Text(label, + style: const TextStyle(fontSize: 11, color: AppTheme.textLight), + textAlign: TextAlign.center), + ], + ); + } +} + +class _EVWidget extends StatelessWidget { + final EnergyData data; + final NymeaService service; + const _EVWidget({required this.data, required this.service}); + + @override + Widget build(BuildContext context) { + final modeColors = { + ChargingMode.pv: AppTheme.pvGreen, + ChargingMode.minPv: AppTheme.minPvBlue, + ChargingMode.boost: AppTheme.boostRed, + }; + final modeLabels = { + ChargingMode.pv: 'PV', + ChargingMode.minPv: 'Min+PV', + ChargingMode.boost: 'Boost', + }; + final color = modeColors[data.chargingMode]!; + + return Row( + children: [ + Container( + width: 52, + height: 52, + decoration: BoxDecoration( + color: color.withValues(alpha:0.12), + borderRadius: BorderRadius.circular(14)), + child: Icon(Icons.electric_car_rounded, color: color, size: 28), + ), + const SizedBox(width: 14), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('${data.chargingPower.toStringAsFixed(1)} kW', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: color)), + Text('Mode : ${modeLabels[data.chargingMode]}', + style: TextStyle(fontSize: 12, color: color)), + Text( + '${data.solarSourcePercent.toStringAsFixed(0)}% solaire · Réseau ${data.gridLimitOk ? "OK" : "!"}', + style: const TextStyle( + fontSize: 11, color: AppTheme.textLight)), + ], + ), + ), + // Quick mode toggle + Column( + children: ChargingMode.values.map((m) { + final c = modeColors[m]!; + return GestureDetector( + onTap: () => service.setChargingMode(m), + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + width: 8, + height: 8, + margin: const EdgeInsets.symmetric(vertical: 3), + decoration: BoxDecoration( + color: data.chargingMode == m ? c : c.withValues(alpha:0.3), + shape: BoxShape.circle, + ), + ), + ); + }).toList(), + ), + ], + ); + } +} + +class _ThingStateWidget extends StatelessWidget { + final FavoriteWidget fav; + final NymeaService service; + const _ThingStateWidget( + {required this.fav, required this.service}); + + @override + Widget build(BuildContext context) { + final thing = service.things.firstWhere( + (t) => t.id == fav.thingId, + orElse: () => NymeaThing( + id: '', name: 'Introuvable', thingClassId: '', + setupStatus: '', paramValues: [])); + + final value = fav.stateTypeId != null + ? thing.stateValue(fav.stateTypeId!) + : null; + + return Row( + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + color: AppTheme.primaryGreen.withValues(alpha:0.12), + borderRadius: BorderRadius.circular(12)), + child: const Icon(Icons.device_hub_rounded, + color: AppTheme.primaryGreen, size: 26), + ), + const SizedBox(width: 14), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(thing.name, + style: const TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + fontSize: 14)), + const SizedBox(height: 4), + Text(value?.toString() ?? '—', + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: AppTheme.primaryGreen)), + ], + ), + ], + ); + } +} + +class _MiniChart extends StatelessWidget { + final List historyPoints; + const _MiniChart({required this.historyPoints}); + + @override + Widget build(BuildContext context) { + if (historyPoints.isEmpty) { + return const SizedBox( + height: 60, + child: Center(child: Text('Pas de données', style: TextStyle(color: AppTheme.textLight)))); + } + final max = historyPoints.map((p) => p.pvWh).reduce((a, b) => a > b ? a : b); + + return SizedBox( + height: 60, + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: historyPoints.map((p) { + final h = max > 0 ? (p.pvWh / max) * 50 : 0.0; + return Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 1), + child: Container( + height: h.clamp(2, 50), + decoration: BoxDecoration( + color: AppTheme.solarYellow.withValues(alpha:0.7), + borderRadius: const BorderRadius.vertical( + top: Radius.circular(3)), + ), + ), + ), + ); + }).toList(), + ), + ); + } +} + +// ── Empty state ─────────────────────────────────────────────────────────────── + +class _EmptyState extends StatelessWidget { + final VoidCallback onAdd; + const _EmptyState({required this.onAdd}); + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 90, + height: 90, + decoration: BoxDecoration( + color: AppTheme.primaryGreen.withValues(alpha:0.1), + shape: BoxShape.circle, + ), + child: const Icon(Icons.star_outline_rounded, + color: AppTheme.primaryGreen, size: 48), + ), + const SizedBox(height: 16), + const Text('Aucun favori', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 18, + color: AppTheme.textDark)), + const SizedBox(height: 8), + const Text('Ajoutez des widgets pour un accès rapide', + style: TextStyle(color: AppTheme.textLight)), + const SizedBox(height: 24), + ElevatedButton.icon( + onPressed: onAdd, + icon: const Icon(Icons.add), + label: const Text('Ajouter un widget'), + style: ElevatedButton.styleFrom( + backgroundColor: AppTheme.primaryGreen, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12)), + padding: + const EdgeInsets.symmetric(horizontal: 24, vertical: 12), + ), + ), + ], + ), + ); + } +} + +// ── Add favorite sheet ──────────────────────────────────────────────────────── + +class _AddFavoriteSheet extends StatelessWidget { + final NymeaService service; + const _AddFavoriteSheet({required this.service}); + + @override + Widget build(BuildContext context) { + final options = [ + _FavOption(FavoriteType.pvPower, '☀️ Production PV', + 'Puissance solaire instantanée', Icons.wb_sunny_rounded, + AppTheme.solarYellow), + _FavOption(FavoriteType.homePower, '🏠 Consommation', + 'Puissance consommée', Icons.home_rounded, AppTheme.homeBlue), + _FavOption(FavoriteType.batterySOC, '🔋 Batterie', + 'État de charge', Icons.battery_charging_full_rounded, + AppTheme.batteryGreen), + _FavOption(FavoriteType.gridPower, '⚡ Réseau', + 'Import / Export réseau', Icons.electrical_services_rounded, + AppTheme.gridGray), + _FavOption(FavoriteType.rates, '📊 Taux', + 'Autoconsommation & autonomie', Icons.pie_chart_rounded, + Colors.deepPurple), + _FavOption(FavoriteType.evCharger, '🚗 Borne EV', + 'Recharge véhicule', Icons.electric_car_rounded, + AppTheme.minPvBlue), + _FavOption(FavoriteType.chart, '📈 Graphique', + 'Production journalière', Icons.bar_chart_rounded, + Colors.teal), + ]; + + return DraggableScrollableSheet( + initialChildSize: 0.6, + maxChildSize: 0.9, + minChildSize: 0.4, + expand: false, + builder: (_, controller) => Column( + children: [ + Container( + margin: const EdgeInsets.only(top: 8, bottom: 16), + width: 40, + height: 4, + decoration: BoxDecoration( + color: Colors.grey.shade300, + borderRadius: BorderRadius.circular(2)), + ), + const Padding( + padding: EdgeInsets.symmetric(horizontal: 20), + child: Text('Ajouter un widget', + style: TextStyle( + fontSize: 18, fontWeight: FontWeight.bold)), + ), + const SizedBox(height: 12), + Expanded( + child: ListView( + controller: controller, + padding: const EdgeInsets.symmetric(horizontal: 16), + children: options.map((opt) { + final alreadyAdded = service.favoriteWidgets + .any((f) => f.type == opt.type); + return Card( + margin: const EdgeInsets.only(bottom: 8), + child: ListTile( + leading: Container( + width: 44, + height: 44, + decoration: BoxDecoration( + color: opt.color.withValues(alpha:0.12), + borderRadius: BorderRadius.circular(12)), + child: Icon(opt.icon, color: opt.color), + ), + title: Text(opt.title, + style: const TextStyle( + fontWeight: FontWeight.bold)), + subtitle: Text(opt.subtitle, + style: const TextStyle(fontSize: 12)), + trailing: alreadyAdded + ? const Icon(Icons.check_circle, + color: AppTheme.primaryGreen) + : const Icon(Icons.add_circle_outline, + color: AppTheme.primaryGreen), + onTap: alreadyAdded + ? null + : () { + service.addFavorite(FavoriteWidget( + id: 'fw_${opt.type.name}_${DateTime.now().millisecondsSinceEpoch}', + type: opt.type, + title: opt.title.split(' ').skip(1).join(' '), + )); + Navigator.pop(context); + }, + ), + ); + }).toList(), + ), + ), + ], + ), + ); + } +} + +class _FavOption { + final FavoriteType type; + final String title; + final String subtitle; + final IconData icon; + final Color color; + const _FavOption( + this.type, this.title, this.subtitle, this.icon, this.color); +} diff --git a/lib/screens/thing_detail_screen.dart b/lib/screens/thing_detail_screen.dart new file mode 100644 index 0000000..cae969e --- /dev/null +++ b/lib/screens/thing_detail_screen.dart @@ -0,0 +1,655 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../models/nymea_models.dart'; +import '../models/thing_category.dart'; +import '../services/nymea_service.dart'; +import '../theme/app_theme.dart'; + +// ───────────────────────────────────────────────────────────────────────────── +// ThingDetailScreen — fiche complète d'un appareil +// ───────────────────────────────────────────────────────────────────────────── + +class ThingDetailScreen extends StatelessWidget { + final NymeaThing thing; + + const ThingDetailScreen({super.key, required this.thing}); + + @override + Widget build(BuildContext context) { + final service = context.watch(); + + // Récupérer le thing à jour (les états sont mis à jour en temps réel) + final liveThing = service.things.firstWhere( + (t) => t.id == thing.id, + orElse: () => thing, + ); + + NymeaThingClass? cls; + try { + cls = service.thingClasses.firstWhere((c) => c.id == thing.thingClassId); + } catch (_) {} + + final catInfo = cls != null + ? categoryInfoMap[cls.category] ?? categoryInfoMap[ThingCategory.other]! + : categoryInfoMap[ThingCategory.other]!; + + // Grouper les états par thème + final stateGroups = _groupStates(cls?.stateTypes ?? [], liveThing); + + return Scaffold( + backgroundColor: AppTheme.backgroundGray, + body: CustomScrollView( + slivers: [ + // ── SliverAppBar avec header coloré ───────────────────────────── + SliverAppBar( + expandedHeight: 160, + pinned: true, + backgroundColor: catInfo.color, + foregroundColor: Colors.white, + actions: [ + if (!service.isSimulation) + IconButton( + icon: const Icon(Icons.edit_outlined, color: Colors.white), + onPressed: () => + _showRenameDialog(context, service, liveThing), + ), + ], + flexibleSpace: FlexibleSpaceBar( + background: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [ + catInfo.color, + catInfo.color.withValues(alpha: 0.7), + ], + ), + ), + child: SafeArea( + child: Padding( + padding: const EdgeInsets.fromLTRB(20, 56, 20, 16), + child: Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Container( + width: 56, height: 56, + decoration: BoxDecoration( + color: Colors.white.withValues(alpha: 0.2), + borderRadius: BorderRadius.circular(16), + ), + child: Icon(catInfo.icon, + color: Colors.white, size: 30), + ), + const SizedBox(width: 14), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(liveThing.name, + style: const TextStyle( + color: Colors.white, + fontSize: 20, + fontWeight: FontWeight.bold), + maxLines: 1, + overflow: TextOverflow.ellipsis), + const SizedBox(height: 2), + Text( + cls?.displayName ?? catInfo.label, + style: TextStyle( + color: Colors.white.withValues(alpha: 0.8), + fontSize: 13), + ), + ], + ), + ), + _OnlineBadge(thing: liveThing, thingClass: cls), + ], + ), + ), + ), + ), + ), + ), + + // ── Contenu ────────────────────────────────────────────────────── + SliverPadding( + padding: const EdgeInsets.all(16), + sliver: SliverList( + delegate: SliverChildListDelegate([ + // Actions rapides (si la classe en a) + if (cls != null && cls.actionTypes.isNotEmpty) ...[ + _ActionsSection(thing: liveThing, thingClass: cls), + const SizedBox(height: 16), + ], + + // États groupés + ...stateGroups.entries.map((entry) => Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionHeader(title: entry.key), + const SizedBox(height: 8), + Card( + child: Column( + children: entry.value.asMap().entries.map((e) { + final isLast = e.key == entry.value.length - 1; + return _StateRow( + stateType: e.value, + value: liveThing.stateValue(e.value.id), + isLast: isLast, + color: catInfo.color, + ); + }).toList(), + ), + ), + const SizedBox(height: 16), + ], + )), + + // Interfaces nymea + if (cls != null && cls.interfaces.isNotEmpty) ...[ + _SectionHeader(title: 'Interfaces'), + const SizedBox(height: 8), + Wrap( + spacing: 8, runSpacing: 6, + children: cls.interfaces.map((iface) => Chip( + label: Text(iface, + style: const TextStyle(fontSize: 12)), + backgroundColor: catInfo.color.withValues(alpha: 0.1), + side: BorderSide(color: catInfo.color.withValues(alpha: 0.3)), + padding: const EdgeInsets.symmetric(horizontal: 4), + )).toList(), + ), + const SizedBox(height: 16), + ], + + // Section Réglages + if (cls != null && cls.settingsTypes.isNotEmpty) ...[ + const _SectionHeader(title: 'Réglages'), + const SizedBox(height: 8), + Card( + child: Column( + children: cls.settingsTypes.asMap().entries.map((e) { + final isLast = e.key == cls!.settingsTypes.length - 1; + final current = liveThing.settingValue(e.value.id); + return _SettingRow( + settingType: e.value, + value: current, + isLast: isLast, + onEdit: (newVal) => service.setThingSettings( + liveThing.id, e.value.id, newVal), + ); + }).toList(), + ), + ), + const SizedBox(height: 16), + ], + + // Info technique + _SectionHeader(title: 'Informations'), + const SizedBox(height: 8), + Card( + child: Column(children: [ + _InfoRow('ID', liveThing.id, isLast: false), + _InfoRow('Classe', liveThing.thingClassId, isLast: false), + _InfoRow('Statut setup', liveThing.setupStatus + .replaceAll('ThingSetupStatus', ''), isLast: true), + ]), + ), + const SizedBox(height: 16), + + // Section Gestion + if (!service.isSimulation) ...[ + const _SectionHeader(title: 'Gestion'), + const SizedBox(height: 8), + Card( + child: Column(children: [ + ListTile( + leading: const Icon(Icons.edit_rounded, + color: AppTheme.primaryGreen), + title: const Text('Renommer'), + onTap: () => + _showRenameDialog(context, service, liveThing), + ), + const Divider(height: 1, indent: 16, endIndent: 16), + ListTile( + leading: const Icon(Icons.delete_outline_rounded, + color: Colors.red), + title: const Text('Supprimer', + style: TextStyle(color: Colors.red)), + onTap: () => + _showRemoveDialog(context, service, liveThing), + ), + ]), + ), + const SizedBox(height: 16), + ], + + const SizedBox(height: 60), + ]), + ), + ), + ], + ), + ); + } + + // ── Groupement des états par thème ──────────────────────────────────────── + + Map> _groupStates( + List stateTypes, + NymeaThing thing, + ) { + final Map> groups = {}; + + for (final st in stateTypes) { + final group = _groupName(st.name); + groups.putIfAbsent(group, () => []).add(st); + } + + // Trier : Puissance en premier, puis alphabétique + final ordered = >{}; + const firstGroups = ['Puissance', 'Énergie', 'Mesures électriques', 'État']; + for (final g in firstGroups) { + if (groups.containsKey(g)) ordered[g] = groups[g]!; + } + for (final entry in groups.entries) { + if (!ordered.containsKey(entry.key)) ordered[entry.key] = entry.value; + } + + return ordered; + } + + String _groupName(String stateName) { + final n = stateName.toLowerCase(); + if (n.contains('power') || n.contains('currentpower')) { return 'Puissance'; } + if (n.contains('energy') || n.contains('total')) { return 'Énergie'; } + if (n.contains('voltage') || n.contains('current') || n.contains('frequency') + || n.contains('ampere') || n.contains('volt') || n.contains('hertz') + || n.contains('powerfactor')) { return 'Mesures électriques'; } + if (n.contains('temperature') || n.contains('humidity') || n.contains('pressure') + || n.contains('co2') || n.contains('lux')) { return 'Environnement'; } + if (n.contains('connected') || n.contains('reachable') || n.contains('status') + || n.contains('mode') || n.contains('on')) { return 'État'; } + if (n.contains('soc') || n.contains('battery') || n.contains('charging')) { return 'Batterie'; } + return 'Divers'; + } + + void _showRenameDialog( + BuildContext ctx, NymeaService svc, NymeaThing t) { + final ctrl = TextEditingController(text: t.name); + showDialog( + context: ctx, + builder: (c) => AlertDialog( + title: const Text('Renommer'), + content: TextField( + controller: ctrl, + autofocus: true, + decoration: const InputDecoration(border: OutlineInputBorder()), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(c), + child: const Text('Annuler')), + ElevatedButton( + onPressed: () async { + final name = ctrl.text.trim(); + if (name.isNotEmpty) await svc.renameThing(t.id, name); + if (c.mounted) Navigator.pop(c); + }, + child: const Text('Renommer'), + ), + ], + ), + ); + } + + void _showRemoveDialog( + BuildContext ctx, NymeaService svc, NymeaThing t) { + showDialog( + context: ctx, + builder: (c) => AlertDialog( + title: const Text('Supprimer'), + content: Text('Supprimer "${t.name}" définitivement ?'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(c), + child: const Text('Annuler')), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: Colors.red, foregroundColor: Colors.white), + onPressed: () async { + await svc.removeThing(t.id); + if (c.mounted) { + Navigator.pop(c); + Navigator.pop(ctx); + } + }, + child: const Text('Supprimer'), + ), + ], + ), + ); + } +} + +// ─── Section actions ────────────────────────────────────────────────────────── + +class _ActionsSection extends StatelessWidget { + final NymeaThing thing; + final NymeaThingClass thingClass; + const _ActionsSection({required this.thing, required this.thingClass}); + + @override + Widget build(BuildContext context) { + final service = context.read(); + + return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + const _SectionHeader(title: 'Actions'), + const SizedBox(height: 8), + Wrap( + spacing: 10, runSpacing: 8, + children: thingClass.actionTypes.map((action) => ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: AppTheme.primaryGreen, + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(10)), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + ), + icon: const Icon(Icons.play_arrow_rounded, size: 18), + label: Text(action.displayName, + style: const TextStyle(fontSize: 13, fontWeight: FontWeight.w600)), + onPressed: () => _executeAction(context, service, action), + )).toList(), + ), + ]); + } + + void _executeAction(BuildContext context, NymeaService service, + NymeaActionType action) async { + if (action.paramTypes.isEmpty) { + // Action sans paramètre → exécuter directement + await service.executeAction( + thingId: thing.id, + actionTypeId: action.id, + params: {}, + ); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('Action "${action.displayName}" exécutée'), + backgroundColor: AppTheme.primaryGreen, + duration: const Duration(seconds: 2), + )); + } + } else { + // Action avec paramètres → dialog + _showActionParamDialog(context, service, action); + } + } + + void _showActionParamDialog(BuildContext context, NymeaService service, + NymeaActionType action) { + // Simple pour l'instant : juste afficher les paramètres requis + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: Text(action.displayName), + content: Column( + mainAxisSize: MainAxisSize.min, + children: action.paramTypes.map((p) => ListTile( + dense: true, + title: Text(p['displayName']?.toString() ?? p['name']?.toString() ?? ''), + subtitle: Text('Type: ${p['type']}'), + )).toList(), + ), + actions: [ + TextButton(onPressed: () => Navigator.pop(ctx), + child: const Text('Fermer')), + ], + ), + ); + } +} + +// ─── Widgets utilitaires ────────────────────────────────────────────────────── + +class _SectionHeader extends StatelessWidget { + final String title; + const _SectionHeader({required this.title}); + + @override + Widget build(BuildContext context) => Padding( + padding: const EdgeInsets.only(left: 4), + child: Text(title, + style: const TextStyle( + fontSize: 13, fontWeight: FontWeight.w700, + color: AppTheme.textLight, letterSpacing: 0.5)), + ); +} + +class _StateRow extends StatelessWidget { + final NymeaStateType stateType; + final dynamic value; + final bool isLast; + final Color color; + + const _StateRow({ + required this.stateType, required this.value, + required this.isLast, required this.color, + }); + + @override + Widget build(BuildContext context) { + final formatted = stateType.formatValue(value); + final isBool = stateType.type == 'Bool'; + + return Column(children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 13), + child: Row(children: [ + Expanded( + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(stateType.displayName, + style: const TextStyle( + fontSize: 14, color: AppTheme.textDark, + fontWeight: FontWeight.w500)), + if (stateType.name != stateType.displayName) + Text(stateType.name, + style: const TextStyle( + fontSize: 10, color: AppTheme.textLight)), + ]), + ), + if (isBool) + Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 3), + decoration: BoxDecoration( + color: (value == true || value == 'true') + ? AppTheme.primaryGreen.withValues(alpha: 0.15) + : Colors.grey.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(20), + ), + child: Text(formatted, + style: TextStyle( + fontSize: 12, fontWeight: FontWeight.bold, + color: (value == true || value == 'true') + ? AppTheme.primaryGreen : AppTheme.textLight)), + ) + else + Text(formatted, + style: TextStyle( + fontSize: 15, fontWeight: FontWeight.bold, + color: color)), + ]), + ), + if (!isLast) + const Divider(height: 1, indent: 16, endIndent: 16, + color: Color(0xFFEEEEEE)), + ]); + } +} + +class _InfoRow extends StatelessWidget { + final String label; + final String value; + final bool isLast; + const _InfoRow(this.label, this.value, {required this.isLast}); + + @override + Widget build(BuildContext context) => Column(children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + child: Row(children: [ + Text(label, + style: const TextStyle(fontSize: 13, color: AppTheme.textLight)), + const SizedBox(width: 12), + Expanded( + child: SelectableText(value, + textAlign: TextAlign.end, + style: const TextStyle( + fontSize: 12, fontWeight: FontWeight.w500, + color: AppTheme.textDark)), + ), + ]), + ), + if (!isLast) const Divider(height: 1, indent: 16, endIndent: 16, + color: Color(0xFFEEEEEE)), + ]); +} + +class _SettingRow extends StatelessWidget { + final NymeaStateType settingType; + final dynamic value; + final bool isLast; + final Future Function(dynamic) onEdit; + + const _SettingRow({ + required this.settingType, + required this.value, + required this.isLast, + required this.onEdit, + }); + + @override + Widget build(BuildContext context) { + final formatted = settingType.formatValue(value); + return Column(children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 4), + child: Row(children: [ + Expanded( + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(settingType.displayName, + style: const TextStyle( + fontSize: 14, color: AppTheme.textDark, + fontWeight: FontWeight.w500)), + if (settingType.name != settingType.displayName) + Text(settingType.name, + style: const TextStyle( + fontSize: 10, color: AppTheme.textLight)), + ]), + ), + Text(formatted, + style: const TextStyle( + fontSize: 14, color: AppTheme.textLight)), + const SizedBox(width: 8), + IconButton( + icon: const Icon(Icons.edit_outlined, size: 18, + color: AppTheme.textLight), + onPressed: () => _showEditDialog(context), + ), + ]), + ), + if (!isLast) + const Divider(height: 1, indent: 16, endIndent: 16, + color: Color(0xFFEEEEEE)), + ]); + } + + void _showEditDialog(BuildContext context) { + if (settingType.type == 'Bool') { + final current = value == true || value == 'true'; + onEdit(!current); + return; + } + final ctrl = TextEditingController(text: value?.toString() ?? ''); + showDialog( + context: context, + builder: (c) => AlertDialog( + title: Text(settingType.displayName), + content: TextField( + controller: ctrl, + autofocus: true, + keyboardType: (settingType.type == 'Int' || settingType.type == 'Double') + ? const TextInputType.numberWithOptions(decimal: true) + : TextInputType.text, + decoration: InputDecoration( + border: const OutlineInputBorder(), + suffixText: settingType.unit, + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(c), + child: const Text('Annuler')), + ElevatedButton( + onPressed: () { + dynamic newVal = ctrl.text.trim(); + if (settingType.type == 'Int') { + newVal = int.tryParse(ctrl.text.trim()) ?? value; + } else if (settingType.type == 'Double') { + newVal = double.tryParse(ctrl.text.trim()) ?? value; + } + onEdit(newVal); + Navigator.pop(c); + }, + child: const Text('Enregistrer'), + ), + ], + ), + ); + } +} + +class _OnlineBadge extends StatelessWidget { + final NymeaThing thing; + final NymeaThingClass? thingClass; + const _OnlineBadge({required this.thing, required this.thingClass}); + + bool _isOnline() { + final connType = thingClass?.stateTypes + .where((s) => s.name.toLowerCase() == 'connected'); + if (connType != null && connType.isNotEmpty) { + final val = thing.stateValue(connType.first.id); + return val == true || val == 'true'; + } + return thing.isSetupComplete; + } + + @override + Widget build(BuildContext context) { + final online = _isOnline(); + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: Colors.white.withValues(alpha: 0.2), + borderRadius: BorderRadius.circular(20), + ), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Container( + width: 8, height: 8, + decoration: BoxDecoration( + color: online ? Colors.greenAccent : Colors.grey[300], + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 6), + Text(online ? 'En ligne' : 'Hors ligne', + style: const TextStyle( + color: Colors.white, fontSize: 12, + fontWeight: FontWeight.w600)), + ]), + ); + } +} \ No newline at end of file diff --git a/lib/screens/things_screen.dart b/lib/screens/things_screen.dart new file mode 100644 index 0000000..9385d55 --- /dev/null +++ b/lib/screens/things_screen.dart @@ -0,0 +1,596 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '../models/nymea_models.dart'; +import '../models/thing_category.dart'; +import '../services/nymea_service.dart'; +import '../theme/app_theme.dart'; +import 'thing_detail_screen.dart'; + +class ThingsScreen extends StatefulWidget { + const ThingsScreen({super.key}); + @override + State createState() => _ThingsScreenState(); +} + +class _ThingsScreenState extends State { + final Set _collapsed = {}; + String _searchQuery = ''; + bool _showSearch = false; + + @override + Widget build(BuildContext context) { + final service = context.watch(); + // Garder tous les things avec un id valide (le filtre setupStatus était trop strict) + final things = service.things.where((t) => t.id.isNotEmpty).toList(); + final thingClasses = service.thingClasses; + + final filtered = _searchQuery.isEmpty + ? things + : things.where((t) => + t.name.toLowerCase().contains(_searchQuery.toLowerCase())).toList(); + + final Map> grouped = {}; + for (final thing in filtered) { + final cls = _classFor(thing, thingClasses); + final cat = cls?.category ?? ThingCategory.other; + grouped.putIfAbsent(cat, () => []).add(thing); + } + + const orderedCats = [ + ThingCategory.energy, ThingCategory.solar, ThingCategory.battery, + ThingCategory.evCharger, ThingCategory.hvac, ThingCategory.lighting, + ThingCategory.sensors, ThingCategory.network, ThingCategory.notifications, + ThingCategory.weather, ThingCategory.media, ThingCategory.other, + ]; + final cats = orderedCats.where((c) => grouped.containsKey(c)).toList(); + + return Scaffold( + backgroundColor: AppTheme.backgroundGray, + appBar: _buildAppBar(service, things.length), + body: !service.isConnected + ? _buildDisconnected() + : (things.isEmpty && !service.thingsLoaded) + ? _buildLoading() + : things.isEmpty + ? _buildEmpty() + : cats.isEmpty + // Classes pas encore chargées — afficher things en mode simple + ? _buildThingsSimple(things, service) + : ListView.builder( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 100), + itemCount: cats.length, + itemBuilder: (context, i) { + final cat = cats[i]; + return _CategorySection( + info: categoryInfoMap[cat]!, + things: grouped[cat]!, + thingClasses: thingClasses, + collapsed: _collapsed.contains(cat), + onToggle: () => setState(() { + if (_collapsed.contains(cat)) { + _collapsed.remove(cat); + } else { + _collapsed.add(cat); + } + }), + onTap: (t) => Navigator.push( + context, + MaterialPageRoute( + builder: (_) => ThingDetailScreen(thing: t)), + ), + ); + }, + ), + ); + } + + AppBar _buildAppBar(NymeaService service, int count) { + return AppBar( + backgroundColor: AppTheme.backgroundGray, + elevation: 0, + title: _showSearch + ? TextField( + autofocus: true, + decoration: const InputDecoration( + hintText: 'Rechercher un appareil...', + border: InputBorder.none, + hintStyle: TextStyle(color: AppTheme.textLight), + ), + style: const TextStyle(color: AppTheme.textDark, fontSize: 18), + onChanged: (v) => setState(() => _searchQuery = v), + ) + : Row(children: [ + const Text('Things', + style: TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + fontSize: 20)), + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: AppTheme.primaryGreen.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(10), + ), + child: Text('$count', + style: const TextStyle( + fontSize: 12, + fontWeight: FontWeight.bold, + color: AppTheme.primaryGreen)), + ), + ]), + actions: [ + IconButton( + icon: Icon(_showSearch ? Icons.close : Icons.search, + color: AppTheme.textDark), + onPressed: () => setState(() { + _showSearch = !_showSearch; + _searchQuery = ''; + }), + ), + IconButton( + icon: const Icon(Icons.refresh_rounded, color: AppTheme.textDark), + onPressed: () => service.refresh(), + ), + ], + ); + } + + Widget _buildLoading() => const Center( + child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ + CircularProgressIndicator(color: AppTheme.primaryGreen), + SizedBox(height: 16), + Text('Chargement des appareils...', + style: TextStyle(color: AppTheme.textLight)), + ]), + ); + + Widget _buildDisconnected() => Center( + child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ + Icon(Icons.cloud_off_rounded, size: 64, color: Colors.grey[400]), + const SizedBox(height: 12), + const Text('Non connecté à nymea', + style: TextStyle(color: AppTheme.textLight, fontSize: 16)), + ]), + ); + + /// Affichage simple quand les ThingClasses ne sont pas encore chargées + Widget _buildThingsSimple(List things, NymeaService service) { + return ListView.builder( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 100), + itemCount: things.length, + itemBuilder: (context, i) { + final t = things[i]; + return Card( + margin: const EdgeInsets.only(bottom: 8), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + child: ListTile( + leading: Container( + width: 40, height: 40, + decoration: BoxDecoration( + color: AppTheme.primaryGreen.withValues(alpha: 0.12), + borderRadius: BorderRadius.circular(10), + ), + child: const Icon(Icons.device_hub_rounded, + color: AppTheme.primaryGreen, size: 22), + ), + title: Text(t.name, + style: const TextStyle(fontWeight: FontWeight.w600, fontSize: 14)), + subtitle: Text(t.setupStatus.replaceAll('ThingSetupStatus', ''), + style: const TextStyle(fontSize: 12, color: AppTheme.textLight)), + trailing: t.setupStatus == 'ThingSetupStatusComplete' + ? Container( + width: 8, height: 8, + decoration: const BoxDecoration( + color: AppTheme.primaryGreen, + shape: BoxShape.circle, + ), + ) + : null, + ), + ); + }, + ); + } + + Widget _buildEmpty() => Center( + child: Column(mainAxisAlignment: MainAxisAlignment.center, children: [ + Icon(Icons.search_off_rounded, size: 64, color: Colors.grey[400]), + const SizedBox(height: 12), + Text( + _searchQuery.isEmpty ? 'Aucun appareil' : 'Aucun résultat pour "$_searchQuery"', + style: const TextStyle(color: AppTheme.textLight, fontSize: 16), + ), + ]), + ); + + NymeaThingClass? _classFor(NymeaThing thing, List classes) { + try { return classes.firstWhere((c) => c.id == thing.thingClassId); } + catch (_) { return null; } + } +} + +// ─── Section catégorie ──────────────────────────────────────────────────────── + +class _CategorySection extends StatelessWidget { + final ThingCategoryInfo info; + final List things; + final List thingClasses; + final bool collapsed; + final VoidCallback onToggle; + final void Function(NymeaThing) onTap; + + const _CategorySection({ + required this.info, required this.things, required this.thingClasses, + required this.collapsed, required this.onToggle, required this.onTap, + }); + + NymeaThingClass? _cls(NymeaThing t) { + try { return thingClasses.firstWhere((c) => c.id == t.thingClassId); } + catch (_) { return null; } + } + + @override + Widget build(BuildContext context) { + return Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + // ── Header collapsable ───────────────────────────────────────────────── + InkWell( + onTap: onToggle, + borderRadius: BorderRadius.circular(12), + child: Padding( + padding: const EdgeInsets.symmetric(vertical: 10, horizontal: 4), + child: Row(children: [ + Container( + width: 34, height: 34, + decoration: BoxDecoration( + color: info.color.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(9), + ), + child: Icon(info.icon, color: info.color, size: 19), + ), + const SizedBox(width: 10), + Expanded( + child: Text(info.label, + style: const TextStyle( + fontWeight: FontWeight.w700, fontSize: 13, + color: AppTheme.textDark, letterSpacing: 0.2)), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 2), + decoration: BoxDecoration( + color: info.color.withValues(alpha: 0.12), + borderRadius: BorderRadius.circular(10), + ), + child: Text('${things.length}', + style: TextStyle( + fontSize: 11, fontWeight: FontWeight.bold, + color: info.color)), + ), + const SizedBox(width: 4), + AnimatedRotation( + turns: collapsed ? -0.25 : 0, + duration: const Duration(milliseconds: 200), + child: const Icon(Icons.expand_more, + color: AppTheme.textLight, size: 20), + ), + ]), + ), + ), + + // ── Things ──────────────────────────────────────────────────────────── + AnimatedCrossFade( + duration: const Duration(milliseconds: 220), + crossFadeState: collapsed + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, + firstChild: Column( + children: [ + ...things.map((t) => Padding( + padding: const EdgeInsets.only(bottom: 10), + child: ThingCard( + thing: t, + thingClass: _cls(t), + categoryInfo: info, + onTap: () => onTap(t), + ), + )), + const SizedBox(height: 4), + ], + ), + secondChild: const SizedBox.shrink(), + ), + ]); + } +} + +// ─── ThingCard ──────────────────────────────────────────────────────────────── + +class ThingCard extends StatelessWidget { + final NymeaThing thing; + final NymeaThingClass? thingClass; + final ThingCategoryInfo categoryInfo; + final VoidCallback onTap; + + const ThingCard({ + super.key, required this.thing, required this.thingClass, + required this.categoryInfo, required this.onTap, + }); + + @override + Widget build(BuildContext context) { + final primaryType = thingClass?.primaryStateType; + final primaryValue = primaryType?.formatValue(thing.stateValue(primaryType.id)); + final secondaryStates = _secondaryStates(); + final isOnline = _isOnline(); + + return Card( + child: InkWell( + borderRadius: BorderRadius.circular(16), + onTap: onTap, + child: Padding( + padding: const EdgeInsets.all(14), + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + // Ligne principale + Row(children: [ + Container( + width: 48, height: 48, + decoration: BoxDecoration( + color: categoryInfo.color.withValues(alpha: isOnline ? 0.15 : 0.07), + borderRadius: BorderRadius.circular(13), + ), + child: Icon(categoryInfo.icon, + color: isOnline + ? categoryInfo.color + : categoryInfo.color.withValues(alpha: 0.4), + size: 26), + ), + const SizedBox(width: 12), + Expanded( + child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(thing.name, + style: const TextStyle( + fontWeight: FontWeight.w600, fontSize: 15, + color: AppTheme.textDark), + maxLines: 1, overflow: TextOverflow.ellipsis), + const SizedBox(height: 2), + Text(thingClass?.displayName ?? 'Appareil', + style: const TextStyle(fontSize: 12, color: AppTheme.textLight), + maxLines: 1, overflow: TextOverflow.ellipsis), + ]), + ), + Column(crossAxisAlignment: CrossAxisAlignment.end, children: [ + if (primaryValue != null) + Text(primaryValue, + style: TextStyle( + fontWeight: FontWeight.bold, fontSize: 16, + color: isOnline + ? categoryInfo.color + : AppTheme.textLight)), + const SizedBox(height: 4), + _StatusDot(isOnline: isOnline), + ]), + const SizedBox(width: 2), + _ThingMenu(thing: thing, onDetail: onTap), + ]), + + // Chips états secondaires + if (secondaryStates.isNotEmpty) ...[ + const SizedBox(height: 10), + const Divider(height: 1, color: Color(0xFFEEEEEE)), + const SizedBox(height: 10), + Wrap( + spacing: 7, runSpacing: 6, + children: secondaryStates.map((s) => _StateChip( + label: s.displayName, + value: s.formatValue(thing.stateValue(s.id)), + color: categoryInfo.color, + )).toList(), + ), + ], + ]), + ), + ), + ); + } + + bool _isOnline() { + final connType = thingClass?.stateTypes + .where((s) => s.name.toLowerCase() == 'connected'); + if (connType != null && connType.isNotEmpty) { + final val = thing.stateValue(connType.first.id); + return val == true || val == 'true'; + } + return thing.isSetupComplete; + } + + List _secondaryStates() { + if (thingClass == null) return []; + final primary = thingClass!.primaryStateType; + const interesting = [ + 'voltage', 'current', 'frequency', 'power', + 'totalenergyconsumed', 'totalenergyproduced', + 'temperature', 'humidity', 'soc', + 'chargingmode', 'mode', 'maxchargingcurrent', 'status', + ]; + return thingClass!.stateTypes + .where((s) => + s != primary && + s.name.toLowerCase() != 'connected' && + interesting.any((i) => s.name.toLowerCase().contains(i))) + .take(3) + .toList(); + } +} + +// ─── Widgets utilitaires ────────────────────────────────────────────────────── + +class _StatusDot extends StatelessWidget { + final bool isOnline; + const _StatusDot({required this.isOnline}); + + @override + Widget build(BuildContext context) => Row(mainAxisSize: MainAxisSize.min, children: [ + Container( + width: 7, height: 7, + decoration: BoxDecoration( + color: isOnline ? AppTheme.primaryGreen : Colors.grey[400], + shape: BoxShape.circle, + ), + ), + const SizedBox(width: 4), + Text( + isOnline ? 'En ligne' : 'Hors ligne', + style: TextStyle( + fontSize: 10, + color: isOnline ? AppTheme.primaryGreen : AppTheme.textLight), + ), + ]); +} + +class _StateChip extends StatelessWidget { + final String label; + final String value; + final Color color; + const _StateChip({required this.label, required this.value, required this.color}); + + @override + Widget build(BuildContext context) => Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: color.withValues(alpha: 0.08), + borderRadius: BorderRadius.circular(20), + border: Border.all(color: color.withValues(alpha: 0.2)), + ), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Flexible( + child: Text(label, + overflow: TextOverflow.ellipsis, + style: TextStyle( + fontSize: 11, color: color.withValues(alpha: 0.8), + fontWeight: FontWeight.w500)), + ), + const SizedBox(width: 5), + Flexible( + child: Text(value, + overflow: TextOverflow.ellipsis, + style: TextStyle(fontSize: 11, color: color, fontWeight: FontWeight.bold)), + ), + ]), + ); +} + +// ─── Menu contextuel ────────────────────────────────────────────────────────── + +class _ThingMenu extends StatelessWidget { + final NymeaThing thing; + final VoidCallback onDetail; + const _ThingMenu({required this.thing, required this.onDetail}); + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + icon: const Icon(Icons.more_vert, color: AppTheme.textLight, size: 20), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)), + itemBuilder: (_) => [ + const PopupMenuItem(value: 'detail', + child: Row(children: [ + Icon(Icons.info_outline, size: 18, color: AppTheme.textDark), + SizedBox(width: 10), Text('Détails & États'), + ])), + const PopupMenuItem(value: 'params', + child: Row(children: [ + Icon(Icons.tune, size: 18, color: AppTheme.textDark), + SizedBox(width: 10), Text('Paramètres'), + ])), + const PopupMenuItem(value: 'rename', + child: Row(children: [ + Icon(Icons.edit_outlined, size: 18, color: AppTheme.textDark), + SizedBox(width: 10), Text('Renommer'), + ])), + const PopupMenuItem(value: 'favorite', + child: Row(children: [ + Icon(Icons.star_outline, size: 18, color: AppTheme.textDark), + SizedBox(width: 10), Text('Ajouter aux favoris'), + ])), + ], + onSelected: (value) { + switch (value) { + case 'detail': onDetail(); break; + case 'params': _showParamsSheet(context); break; + case 'rename': _showRenameDialog(context); break; + case 'favorite': + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('${thing.name} ajouté aux favoris'), + backgroundColor: AppTheme.primaryGreen, + duration: const Duration(seconds: 2), + )); + } + }, + ); + } + + void _showParamsSheet(BuildContext context) { + showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20))), + builder: (_) => Padding( + padding: const EdgeInsets.all(20), + child: Column(mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Row(children: [ + const Icon(Icons.tune, color: AppTheme.primaryGreen), + const SizedBox(width: 8), + Expanded(child: Text('Paramètres — ${thing.name}', + style: const TextStyle(fontWeight: FontWeight.bold, + fontSize: 16, color: AppTheme.textDark))), + ]), + const SizedBox(height: 4), + SelectableText('ID: ${thing.id}', + style: const TextStyle(fontSize: 10, color: AppTheme.textLight)), + const Divider(height: 24), + if (thing.paramValues.isEmpty) + const Text('Aucun paramètre configuré.', + style: TextStyle(color: AppTheme.textLight)) + else + ...thing.paramValues.map((p) => Padding( + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row(children: [ + Expanded(child: Text(p['paramTypeId']?.toString() ?? '?', + style: const TextStyle(color: AppTheme.textLight))), + Text(p['value']?.toString() ?? '—', + style: const TextStyle( + fontWeight: FontWeight.w600, color: AppTheme.textDark)), + ]), + )), + const SizedBox(height: 20), + ]), + ), + ); + } + + void _showRenameDialog(BuildContext context) { + final ctrl = TextEditingController(text: thing.name); + showDialog( + context: context, + builder: (ctx) => AlertDialog( + title: const Text('Renommer'), + content: TextField( + controller: ctrl, autofocus: true, + decoration: const InputDecoration(labelText: 'Nouveau nom'), + ), + actions: [ + TextButton(onPressed: () => Navigator.pop(ctx), + child: const Text('Annuler')), + FilledButton( + onPressed: () { + context.read().renameThing(thing.id, ctrl.text.trim()); + Navigator.pop(ctx); + }, + child: const Text('Renommer'), + ), + ], + ), + ); + } +} \ No newline at end of file diff --git a/lib/services/nymea_service.dart b/lib/services/nymea_service.dart new file mode 100644 index 0000000..21f04d3 --- /dev/null +++ b/lib/services/nymea_service.dart @@ -0,0 +1,946 @@ +import 'dart:async'; +import 'dart:developer' as dev; +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; +import 'package:flutter/foundation.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:web_socket_channel/web_socket_channel.dart'; +import '../models/energy_data.dart'; +import '../models/nymea_models.dart'; + +// ── Protocole de connexion ───────────────────────────────────────────────────── +enum NymeaProtocol { + /// TCP brut port 2222 — nymea parle en premier (\n-delimited JSON) + tcpRaw, + /// WebSocket port 4444 — client envoie JSONRPC.Hello en premier + webSocket, +} + +/// Service de communication nymea JSON-RPC 2.0 +/// Supporte TCP brut (port 2222) et WebSocket (port 4444) +class NymeaService extends ChangeNotifier { + // ── Transport ──────────────────────────────────────────────────────────────── + Socket? _socket; // TCP raw + WebSocketChannel? _wsChannel; // WebSocket + StreamSubscription? _wsSub; + NymeaProtocol _protocol = NymeaProtocol.tcpRaw; + + int _requestId = 1; + final Map>> _pendingRequests = {}; + final StringBuffer _buffer = StringBuffer(); // TCP fragment buffer + + // ── State ──────────────────────────────────────────────────────────────────── + bool _connected = false; + bool _connecting = false; + String _host = '192.168.1.106'; + int _port = 2222; + String? _connectionError; + String? _nymeaVersion; + Timer? _heartbeatTimer; + Timer? _simulationTimer; + bool _isSimulation = false; + + // ── Auth ───────────────────────────────────────────────────────────────────── + String _token = ''; + String _username = ''; + String _password = ''; + + // ── Debug verbeux ───────────────────────────────────────────────────────── + bool _verboseLog = false; // activé depuis l'UI ou à la connexion + bool get verboseLog => _verboseLog; + set verboseLog(bool v) { + _verboseLog = v; + _log('🔧 Verbose logging ${v ? "ON" : "OFF"}', force: true); + } + + void _log(String msg, {bool force = false, String? json}) { + if (!force && !_verboseLog) return; + dev.log(msg, name: 'nymea'); + if (json != null && _verboseLog) { + // Formatter le JSON pour lisibilité + try { + final parsed = jsonDecode(json); + final pretty = const JsonEncoder.withIndent(' ').convert(parsed); + dev.log(pretty, name: 'nymea.json'); + } catch (_) { + dev.log(json, name: 'nymea.json'); + } + } + } + + EnergyData _energyData = const EnergyData(); + List _historyPoints = []; + List _things = []; + List _thingClasses = []; + List _favoriteWidgets = []; + + // ── Getters ────────────────────────────────────────────────────────────────── + bool get connected => _connected; + bool get isConnected => _connected; // alias pour les screens + bool get connecting => _connecting; + bool get isSimulation => _isSimulation; + NymeaProtocol get protocol => _protocol; + String get host => _host; + int get port => _port; + String? get connectionError => _connectionError; + String? get nymeaVersion => _nymeaVersion; + String get username => _username; + String get password => _password; + EnergyData get energyData => _energyData; + List get historyPoints => _historyPoints; + List get things => _things; + List get thingClasses => _thingClasses; + List get favoriteWidgets => _favoriteWidgets; + + // ═══════════════════════════════════════════════════════════════════════════ + // CONNEXION — entrée publique + // ═══════════════════════════════════════════════════════════════════════════ + + Future connect( + String host, + int port, { + NymeaProtocol protocol = NymeaProtocol.tcpRaw, + String username = '', + String password = '', + }) async { + if (_connecting) return false; + _host = host; + _port = port; + _protocol = protocol; + _username = username; + _password = password; + _connectionError = null; + _connecting = true; + _isSimulation = false; + _simulationTimer?.cancel(); + _buffer.clear(); + // Charger le token sauvegardé pour cet hôte + final prefs = await SharedPreferences.getInstance(); + _token = prefs.getString('nymea_token_$host') ?? ''; + if (_token.isNotEmpty) { + _log('🔑 Token restauré depuis SharedPreferences', force: true); + } + notifyListeners(); + + try { + if (protocol == NymeaProtocol.tcpRaw) { + return await _connectTcp(host, port); + } else { + return await _connectWs(host, port); + } + } catch (e) { + _connectionError = e.toString(); + _connected = false; + _connecting = false; + notifyListeners(); + return false; + } + } + + // ── TCP brut : nymea parle en PREMIER ──────────────────────────────────────── + Future _connectTcp(String host, int port) async { + _log('TCP → $host:$port'); + _socket = await Socket.connect(host, port, + timeout: const Duration(seconds: 8)); + + final welcomeCompleter = Completer>(); + bool welcomeReceived = false; + + _socket!.cast>().transform(utf8.decoder).listen( + (chunk) { + _buffer.write(chunk); + final raw = _buffer.toString(); + int start = 0; + for (int i = 0; i < raw.length; i++) { + if (raw[i] == '\n') { + final line = raw.substring(start, i).trim(); + if (line.isNotEmpty) { + try { + final data = jsonDecode(line) as Map; + if (!welcomeReceived) { + welcomeReceived = true; + _log('← raw TCP line (${line.length}): ${line.substring(0, line.length.clamp(0, 120))}…', force: _verboseLog); + if (!welcomeCompleter.isCompleted) { + welcomeCompleter.complete(data); + } + } else { + _processMessage(data); + } + } catch (e) { + _log('TCP parse error: $e', force: true); + } + } + start = i + 1; + } + } + _buffer.clear(); + if (start < raw.length) _buffer.write(raw.substring(start)); + }, + onError: (e) { + if (!welcomeCompleter.isCompleted) welcomeCompleter.completeError(e); + _onError(e); + }, + onDone: () { + if (!welcomeCompleter.isCompleted) { + welcomeCompleter.completeError( + Exception('Socket closed before welcome')); + } + _onDone(); + }, + cancelOnError: false, + ); + + // Attendre le message de bienvenue de nymea + final welcome = await welcomeCompleter.future + .timeout(const Duration(seconds: 8)); + + return _finishConnect(welcome); + } + + // ── WebSocket : client parle en PREMIER (JSONRPC.Hello) ────────────────────── + Future _connectWs(String host, int port) async { + _log('WebSocket → ws://$host:$port'); + final uri = Uri.parse('ws://$host:$port'); + _wsChannel = WebSocketChannel.connect(uri); + + // Attendre que la connexion soit établie + try { + await _wsChannel!.ready.timeout(const Duration(seconds: 8)); + } catch (_) { + // some versions don't have .ready — ignore + } + + _wsSub = _wsChannel!.stream.listen( + (raw) { + try { + // nymea peut envoyer String ou binary (Uint8List) + String str; + if (raw is String) { + str = raw; + } else if (raw is List) { + str = utf8.decode(raw); + } else { + _log('⚠️ WS frame type inattendu: ${raw.runtimeType}', force: true); + return; + } + _log('← WS raw (${str.length} chars): ${str.substring(0, str.length.clamp(0, 80))}…'); + final data = jsonDecode(str) as Map; + _processMessage(data); + } catch (e) { + _log('❌ WS parse error: $e raw type: ${raw.runtimeType}', force: true); + } + }, + onError: (e) { + _log('❌ WS stream error: $e', force: true); + _onError(e); + }, + onDone: _onDone, + cancelOnError: false, + ); + + _log('📡 WS listener actif, envoi Hello...', force: true); + + // Sur WebSocket, c'est le CLIENT qui envoie Hello en premier + final hello = await _sendRequest('JSONRPC.Hello', {}) + .timeout(const Duration(seconds: 8)); + + return _finishConnect(hello); + } + + // ── Finalisation commune ───────────────────────────────────────────────────── + Future _finishConnect(Map welcome) async { + final p = welcome['params'] as Map? ?? welcome; + _nymeaVersion = p['version'] as String? + ?? p['serverVersion'] as String? + ?? 'nymea'; + + _log('✅ Connected to nymea $_nymeaVersion' + ' via ${_protocol == NymeaProtocol.tcpRaw ? "TCP" : "WebSocket"}'); + + // Flux auth : si requis ET pas encore authentifié avec token valide + if (p['authenticationRequired'] == true && p['authenticated'] != true) { + if (_token.isNotEmpty) { + _log('🔑 Token existant présent, tentative d\'utilisation...', force: true); + // Le token sera inclus dans les requêtes — on verra si ça marche + } else if (_username.isNotEmpty) { + try { + await _doAuthenticate(); + } catch (e) { + _connectionError = e.toString(); + _connected = false; + _connecting = false; + notifyListeners(); + return false; + } + } + } + + await _setNotificationsEnabled(); + + _connected = true; + _connecting = false; + notifyListeners(); + + await _initialLoad(); + _startHeartbeat(); + return true; + } + + Future _doAuthenticate() async { + _log('🔐 JSONRPC.Authenticate → user=$_username', force: true); + final r = await _sendRequest('JSONRPC.Authenticate', { + 'username': _username, + 'password': _password, + 'deviceName': 'etm-powersync-app', + }); + _token = r['params']?['token'] as String? ?? ''; + if (_token.isNotEmpty) { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('nymea_token_$_host', _token); + _log('✅ Token obtenu et sauvegardé', force: true); + } else { + _log('❌ Authenticate échoué: ${r["params"]}', force: true); + throw Exception('Authentication failed: ${r["params"]}'); + } + } + + Future _setNotificationsEnabled() async { + try { + await _sendRequest('JSONRPC.SetNotificationStatus', {'enabled': true}); + } catch (e) { + _log('SetNotificationStatus: $e'); + } + } + + // ── Déconnexion ────────────────────────────────────────────────────────────── + void disconnect() { + _heartbeatTimer?.cancel(); + _simulationTimer?.cancel(); + _socket?.destroy(); + _socket = null; + _wsSub?.cancel(); + _wsChannel?.sink.close(); + _wsChannel = null; + _connected = false; + _connecting = false; + _isSimulation = false; + _buffer.clear(); + for (final c in _pendingRequests.values) { + c.completeError(Exception('Disconnected')); + } + _pendingRequests.clear(); + notifyListeners(); + } + + // ═══════════════════════════════════════════════════════════════════════════ + // JSON-RPC SEND — \n pour TCP, frame WebSocket pour WS + // ═══════════════════════════════════════════════════════════════════════════ + + Future> _sendRequest( + String method, Map params) async { + if (_socket == null && _wsChannel == null) { + throw Exception('Not connected'); + } + final id = _requestId++; + final completer = Completer>(); + _pendingRequests[id] = completer; + + final msg = jsonEncode({ + 'id': id, 'method': method, 'params': params, + 'token': _token, + }); + _log('→ [$id] $method', force: true, json: msg); + + if (_protocol == NymeaProtocol.tcpRaw) { + _socket!.write('$msg\n'); + } else { + _wsChannel!.sink.add(msg); + } + + // Timeout 15s — évite le blocage si nymea ne répond pas + return completer.future.timeout( + const Duration(seconds: 15), + onTimeout: () { + _pendingRequests.remove(id); + throw TimeoutException('Request $method timed out', const Duration(seconds: 15)); + }, + ); + } + + // ═══════════════════════════════════════════════════════════════════════════ + // MESSAGE PROCESSING (commun TCP + WS) + // ═══════════════════════════════════════════════════════════════════════════ + + void _processMessage(Map data) { + // Réponse à une requête + if (data.containsKey('id')) { + final id = data['id']; + // JSON decode peut retourner num au lieu de int — on normalise + final intId = (id is num) ? id.toInt() : null; + if (intId != null && _pendingRequests.containsKey(intId)) { + _log('← [$intId] réponse status=${data['status'] ?? '?'}', + force: true, json: jsonEncode(data)); + _pendingRequests[intId]!.complete(data); + _pendingRequests.remove(intId); + } else if (intId != null) { + _log('← [$intId] réponse non attendue (déjà timeout?)', force: true); + } + } + // Notification push + if (data.containsKey('notification')) { + final notification = data['notification'] as String; + _log('← push: $notification', force: true, + json: _verboseLog ? jsonEncode(data) : null); + _handleNotification( + notification, + data['params'] as Map? ?? {}, + ); + } + } + + void _handleNotification( + String notification, Map params) { + _log('← push: $notification'); + switch (notification) { + case 'Energy.PowerBalanceChanged': + _parsePowerBalance(params); + break; + case 'Energy.RootMeterChanged': + _parseRootMeter(params); + break; + case 'Integrations.StateChanged': + _handleStateChanged(params); + break; + case 'Integrations.ThingAdded': + final t = params['thing']; + if (t != null) { + _things.add(NymeaThing.fromJson(t as Map)); + notifyListeners(); + } + break; + case 'Integrations.ThingRemoved': + _things.removeWhere((t) => t.id == params['thingId']); + notifyListeners(); + break; + } + } + + void _handleStateChanged(Map params) { + final thingId = params['thingId'] as String?; + final stateTypeId = params['stateTypeId'] as String?; + final value = params['value']; + if (thingId == null || stateTypeId == null) return; + final idx = _things.indexWhere((t) => t.id == thingId); + if (idx >= 0) { + final states = List.from(_things[idx].states); + final si = states.indexWhere((s) => s.stateTypeId == stateTypeId); + if (si >= 0) { + states[si] = NymeaStateValue(stateTypeId: stateTypeId, value: value); + } else { + states.add(NymeaStateValue(stateTypeId: stateTypeId, value: value)); + } + _things[idx] = _things[idx].copyWith(states: states); + notifyListeners(); + } + } + + void _onError(dynamic error) { + _log('❌ Connection error: $error', force: true); + _connectionError = error.toString(); + _connected = false; + for (final c in _pendingRequests.values) { + c.completeError(error); + } + _pendingRequests.clear(); + notifyListeners(); + } + + void _onDone() { + _log('🔌 Connection closed', force: true); + _connected = false; + notifyListeners(); + } + + // ═══════════════════════════════════════════════════════════════════════════ + // HEARTBEAT & INITIAL LOAD + // ═══════════════════════════════════════════════════════════════════════════ + + Future _initialLoad() async { + await Future.wait([ + _loadThings(), + _loadEnergyStatus(), + _loadEnergyHistory(), + ]); + } + + void _startHeartbeat() { + _heartbeatTimer?.cancel(); + // Polling toutes les 5 secondes pour rafraîchir les données énergie + _heartbeatTimer = Timer.periodic(const Duration(seconds: 5), (_) async { + if (!_connected || _isSimulation) return; + try { + await _loadEnergyStatus(); + } catch (_) { + _connected = false; + notifyListeners(); + } + }); + } + + // ═══════════════════════════════════════════════════════════════════════════ + // ENERGY MANAGER + // ═══════════════════════════════════════════════════════════════════════════ + + Future _loadEnergyStatus() async { + try { + final r = await _sendRequest('Energy.GetPowerBalance', {}); + _log('📊 PowerBalance: $r'); + _parsePowerBalance(r); + } catch (e) { _log('GetPowerBalance error: $e'); } + } + + // ── nymea 1.14 Energy.PowerBalanceChanged / Energy.GetPowerBalance ─────────── + // Champs réels confirmés depuis les logs : + // currentPowerProduction : W solaire (NÉGATIF! ex: -1190 = 1190W PV) + // currentPowerConsumption : W maison (positif) + // currentPowerAcquisition : W réseau (positif = import, 0 = export) + // currentPowerStorage : W batterie (+ charge, - décharge) + // totalProduction : kWh PV cumulé + // totalConsumption : kWh maison cumulé + // totalAcquisition : kWh réseau importé cumulé + // totalReturn : kWh réseau exporté cumulé + void _parsePowerBalance(Map response) { + final p = response['params'] as Map? ?? response; + _log('📊 Energy fields: ${p.keys.toList()}'); + + double? n(String k) => (p[k] as num?)?.toDouble(); + + // Production PV est négative dans nymea (convention producteur = négatif) + final rawProd = n('currentPowerProduction'); + final pv = rawProd != null ? rawProd.abs() : 0.0; + + final home = n('currentPowerConsumption') ?? 0.0; + final grid = n('currentPowerAcquisition') ?? 0.0; // + import, 0 si export + final bat = n('currentPowerStorage') ?? 0.0; + + // Totaux cumulés en kWh → convertir en Wh pour l'affichage + final totalProdKwh = n('totalProduction') ?? 0.0; + final totalRetKwh = n('totalReturn') ?? 0.0; + final totalConsoKwh = n('totalConsumption') ?? 0.0; + final totalAcqKwh = n('totalAcquisition') ?? 0.0; + + // Autoconsommation = production - injection réseau + final selfConsoKwh = totalProdKwh - totalRetKwh; + // Taux autoconsommation = autoconso / production * 100 + final selfRate = totalProdKwh > 0 ? (selfConsoKwh / totalProdKwh * 100).clamp(0.0, 100.0) : 0.0; + // Taux autonomie = (production + batterie utilisée) / conso * 100 + final autoRate = totalConsoKwh > 0 ? ((totalConsoKwh - totalAcqKwh) / totalConsoKwh * 100).clamp(0.0, 100.0) : 0.0; + + _energyData = _energyData.copyWith( + pvPower: pv, + homePower: home, + gridPower: grid, + batteryPower: bat, + dayProductionWh: totalProdKwh * 1000, + dayGridInjectionWh: totalRetKwh * 1000, + daySelfConsumptionWh: selfConsoKwh * 1000, + selfConsumptionRate: selfRate, + autonomyRate: autoRate, + dayGains: totalRetKwh * 0.13 + selfConsoKwh * 0.22, // estimation tarifaire + ); + notifyListeners(); + } + + void _parseRootMeter(Map response) { + // Dans nymea 1.14, tout est dans PowerBalance — méthode conservée pour compat + } + + Future refreshEnergy() => _loadEnergyStatus(); + + /// Rafraîchit things + classes + énergie + Future refresh() async { + await Future.wait([_loadThings(), _loadEnergyStatus()]); + } + + Future _loadEnergyHistory() async { + try { + final now = DateTime.now(); + final from = DateTime(now.year, now.month, now.day) + .millisecondsSinceEpoch ~/ 1000; + final to = now.millisecondsSinceEpoch ~/ 1000; + final r = await _sendRequest('Energy.GetEnergyLogs', { + 'sampleRate': 'SampleRateHour', + 'from': from, + 'to': to, + }); + final logs = r['params']?['logs'] as List? ?? []; + _historyPoints = logs.map((l) { + final lm = l as Map; + return HistoryPoint( + time: DateTime.fromMillisecondsSinceEpoch( + (lm['timestamp'] as int) * 1000), + pvWh: (lm['totalEnergyProduced'] as num?)?.toDouble() ?? 0, + homeWh: (lm['totalEnergyConsumed'] as num?)?.toDouble() ?? 0, + gridWh: (lm['totalEnergyReturned'] as num?)?.toDouble() ?? 0, + ); + }).toList(); + notifyListeners(); + } catch (e) { _log('GetEnergyLogs: $e'); } + } + + Future setChargingMode(ChargingMode mode) async { + final modeStr = { + ChargingMode.pv: 'pv', + ChargingMode.minPv: 'minpv', + ChargingMode.boost: 'boost', + }[mode]!; + if (_connected && !_isSimulation) { + try { + await _sendRequest('Energy.SetChargingMode', {'mode': modeStr}); + } catch (e) { _log('SetChargingMode: $e'); } + } + _energyData = _energyData.copyWith(chargingMode: mode); + notifyListeners(); + } + + // ═══════════════════════════════════════════════════════════════════════════ + // THINGS / INTEGRATIONS + // ═══════════════════════════════════════════════════════════════════════════ + + bool _thingsLoaded = false; + bool get thingsLoaded => _thingsLoaded; + + Future _loadThings() async { + // ── Étape 1 : charger les things configurés ────────────────────────────── + try { + _log('📦 GetThings → envoi...', force: true); + final r = await _sendRequest('Integrations.GetThings', {}); + _log('📦 GetThings ← status=${r["status"]} keys=${r.keys.toList()}', force: true); + + final thingsRaw = r['params']?['things'] + ?? r['result']?['things'] + ?? r['things']; + + if (thingsRaw is List) { + _things = thingsRaw + .map((t) => NymeaThing.fromJson(t as Map)) + .where((t) => t.id.isNotEmpty) // exclure entrées invalides + .toList(); + _log('📦 ✅ ${_things.length} things configurés:', force: true); + for (final t in _things) { + _log(' 📱 "${t.name}" | classId=${t.thingClassId.substring(0, 8)}… | ${t.setupStatus}', force: true); + } + } else { + _log('📦 ⚠️ GetThings: clé "things" absente — keys=${r.keys.toList()}', force: true); + } + } catch (e, st) { + _log('📦 ❌ GetThings erreur: $e\n$st', force: true); + } + + // ── Étape 2 : charger UNIQUEMENT les classes des things présents ────────── + // On filtre sur les thingClassIds réellement utilisés → évite les 80+ plugins + if (_things.isNotEmpty) { + try { + final neededClassIds = _things + .map((t) => t.thingClassId) + .where((id) => id.isNotEmpty) + .toSet() + .toList(); + + _log('📦 GetThingClasses pour ${neededClassIds.length} classes...', force: true); + + // nymea supporte un filtre optionnel thingClassIds + final r = await _sendRequest('Integrations.GetThingClasses', { + 'thingClassIds': neededClassIds, + }); + + final classesRaw = r['params']?['thingClasses'] + ?? r['result']?['thingClasses'] + ?? r['thingClasses']; + + if (classesRaw is List && classesRaw.isNotEmpty) { + _thingClasses = classesRaw + .map((c) => NymeaThingClass.fromJson(c as Map)) + .toList(); + _log('📦 ✅ ThingClasses: ${_thingClasses.length}', force: true); + for (final c in _thingClasses) { + _log(' 📋 "${c.name}" | id=${c.id.substring(0, 8)}… | interfaces=${c.interfaces}', force: true); + } + } else { + // Fallback : nymea < 1.6 ne supporte peut-être pas le filtre → tout charger + _log('📦 Filtre non supporté, fallback GetThingClasses sans filtre...', force: true); + await _loadAllThingClassesFiltered(neededClassIds); + } + } catch (e) { + _log('📦 ❌ GetThingClasses erreur: $e', force: true); + // Fallback si le filtre cause une erreur + await _loadAllThingClassesFiltered( + _things.map((t) => t.thingClassId).toSet().toList() + ); + } + } + + _thingsLoaded = true; + notifyListeners(); + } + + /// Fallback : charge toutes les classes puis filtre côté client + Future _loadAllThingClassesFiltered(List neededIds) async { + try { + final r = await _sendRequest('Integrations.GetThingClasses', {}); + final classesRaw = r['params']?['thingClasses'] + ?? r['result']?['thingClasses'] + ?? r['thingClasses']; + + if (classesRaw is List) { + final all = classesRaw + .map((c) => NymeaThingClass.fromJson(c as Map)) + .toList(); + // Garder seulement les classes dont on a besoin + _thingClasses = all + .where((c) => neededIds.contains(c.id)) + .toList(); + _log('📦 Fallback: ${all.length} classes totales → ${_thingClasses.length} utilisées', force: true); + for (final c in _thingClasses) { + _log(' 📋 "${c.name}" interfaces=${c.interfaces}', force: true); + } + } + } catch (e) { + _log('📦 ❌ Fallback GetThingClasses erreur: $e', force: true); + } + } + Future refreshThings() => _loadThings(); + + Future>> discoverThings(String thingClassId) async { + if (_isSimulation) return []; + try { + final r = await _sendRequest( + 'Integrations.DiscoverThings', {'thingClassId': thingClassId}); + return List>.from( + r['params']?['thingDescriptors'] ?? []); + } catch (_) { return []; } + } + + Future addThing({ + required String thingClassId, + required String thingDescriptorId, + required String name, + }) async { + if (_isSimulation) return false; + try { + final r = await _sendRequest('Integrations.AddThing', { + 'thingClassId': thingClassId, + 'name': name, + 'thingDescriptorId': thingDescriptorId, + }); + if (r['status'] == 'success') { await _loadThings(); return true; } + return false; + } catch (_) { return false; } + } + + Future removeThing(String thingId) async { + if (_isSimulation) return false; + try { + final r = await _sendRequest( + 'Integrations.RemoveThing', {'thingId': thingId}); + if (r['status'] == 'success') { + _things.removeWhere((t) => t.id == thingId); + notifyListeners(); + return true; + } + return false; + } catch (_) { return false; } + } + + Future renameThing(String thingId, String newName) async { + if (_isSimulation) return false; + try { + final r = await _sendRequest( + 'Integrations.EditThing', {'thingId': thingId, 'name': newName}); + if (r['status'] == 'success') { + final idx = _things.indexWhere((t) => t.id == thingId); + if (idx >= 0) { + _things[idx] = _things[idx].copyWith(name: newName); + notifyListeners(); + } + return true; + } + return false; + } catch (_) { return false; } + } + + Future setThingSettings( + String thingId, String settingTypeId, dynamic value) async { + if (_isSimulation) return true; + try { + final r = await _sendRequest('Integrations.SetThingSettings', { + 'thingId': thingId, + 'settings': [{'paramTypeId': settingTypeId, 'value': value}], + }); + return r['params']?['thingError'] == 'ThingErrorNoError'; + } catch (e) { + _log('SetThingSettings: $e'); + return false; + } + } + + Future executeAction({ + required String thingId, + required String actionTypeId, + Map params = const {}, + }) async { + if (_isSimulation) return true; + try { + final r = await _sendRequest('Integrations.ExecuteAction', { + 'thingId': thingId, + 'actionTypeId': actionTypeId, + 'params': params.entries + .map((e) => {'paramTypeId': e.key, 'value': e.value}) + .toList(), + }); + return r['status'] == 'success'; + } catch (e) { _log('ExecuteAction: $e'); return false; } + } + + Future getStateValue(String thingId, String stateTypeId) async { + if (_isSimulation) return null; + try { + final r = await _sendRequest('Integrations.GetStateValue', { + 'thingId': thingId, 'stateTypeId': stateTypeId, + }); + return r['params']?['value']; + } catch (_) { return null; } + } + + Future>> getRules() async { + if (_isSimulation) return []; + try { + final r = await _sendRequest('Rules.GetRules', {}); + return List>.from(r['params']?['rules'] ?? []); + } catch (_) { return []; } + } + + // ═══════════════════════════════════════════════════════════════════════════ + // FAVORITES + // ═══════════════════════════════════════════════════════════════════════════ + + void addFavorite(FavoriteWidget widget) { + if (!_favoriteWidgets.any((f) => f.id == widget.id)) { + _favoriteWidgets.add(widget); + notifyListeners(); + } + } + + void removeFavorite(String id) { + _favoriteWidgets.removeWhere((f) => f.id == id); + notifyListeners(); + } + + void reorderFavorites(int oldIndex, int newIndex) { + if (newIndex > oldIndex) newIndex--; + final item = _favoriteWidgets.removeAt(oldIndex); + _favoriteWidgets.insert(newIndex, item); + notifyListeners(); + } + + // ═══════════════════════════════════════════════════════════════════════════ + // SIMULATION + // ═══════════════════════════════════════════════════════════════════════════ + + void startSimulation() { + disconnect(); + _connected = true; + _isSimulation = true; + _nymeaVersion = 'demo 1.8.2'; + _generateSimulatedThings(); + _generateHistory(); + if (_favoriteWidgets.isEmpty) { + _favoriteWidgets = [ + FavoriteWidget(id: 'fw_pv', type: FavoriteType.pvPower, title: 'Production PV'), + FavoriteWidget(id: 'fw_home', type: FavoriteType.homePower, title: 'Consommation'), + FavoriteWidget(id: 'fw_soc', type: FavoriteType.batterySOC, title: 'Batterie'), + FavoriteWidget(id: 'fw_rates', type: FavoriteType.rates, title: 'Taux'), + FavoriteWidget(id: 'fw_ev', type: FavoriteType.evCharger, title: 'Borne EV'), + ]; + } + _simulationTimer?.cancel(); + _simulationTimer = Timer.periodic( + const Duration(seconds: 2), (_) => _simulateData()); + _simulateData(); + notifyListeners(); + } + + void _simulateData() { + final now = DateTime.now(); + final hour = now.hour + now.minute / 60.0; + final rng = Random(); + double pv = 0; + if (hour >= 7 && hour <= 20) { + pv = (3800 * sin((hour - 7) * pi / 13) + rng.nextDouble() * 80 - 40) + .clamp(0, 4500); + } + final home = 200 + rng.nextDouble() * 600; + final battery = pv > home + 200 ? (pv - home - 200).clamp(0.0, 2000.0) : 0.0; + final batDischarge = home > pv + 100 && _energyData.batterySOC > 10 + ? min(home - pv, 1500.0) : 0.0; + final grid = home - pv - battery + batDischarge; + final soc = (_energyData.batterySOC + + (battery > 0 ? 0.1 : batDischarge > 0 ? -0.05 : 0)).clamp(5.0, 100.0); + _energyData = _energyData.copyWith( + pvPower: pv, homePower: home, + batteryPower: battery > 0 ? battery : (batDischarge > 0 ? -batDischarge : 0), + gridPower: grid, batterySOC: soc, temperature: 7, + dayProductionWh: pv * 0.5, daySelfConsumptionWh: home * 0.4, + dayGridInjectionWh: grid < 0 ? -grid * 0.3 : 0, + selfConsumptionRate: pv > 0 ? (min(pv, home) / pv * 100).clamp(0.0, 100.0) : 0.0, + autonomyRate: home > 0 ? ((pv + batDischarge) / home * 100).clamp(0.0, 100.0) : 0.0, + dayGains: (pv * 0.5 / 1000) * 0.13, + ); + notifyListeners(); + } + + void _generateHistory() { + final now = DateTime.now(); + _historyPoints = List.generate(24, (i) { + final h = i.toDouble(); + final pv = (h >= 7 && h <= 20) + ? (3000 * sin((h - 7) * pi / 13)).clamp(0.0, 4500.0) : 0.0; + return HistoryPoint( + time: DateTime(now.year, now.month, now.day, i), + pvWh: pv, homeWh: 200 + Random().nextDouble() * 400, + gridWh: (200 - pv * 0.3).clamp(0, 500), + ); + }); + } + + void _generateSimulatedThings() { + _things = [ + NymeaThing(id: 'sim-inverter', name: 'Onduleur SolarEdge', thingClassId: 'solaredge', + setupStatus: 'ThingSetupStatusComplete', paramValues: [], + states: [NymeaStateValue(stateTypeId: 'power', value: 4200.0)]), + NymeaThing(id: 'sim-battery', name: 'Batterie BYD', thingClassId: 'byd', + setupStatus: 'ThingSetupStatusComplete', paramValues: [], + states: [NymeaStateValue(stateTypeId: 'soc', value: 42.0)]), + NymeaThing(id: 'sim-ev', name: 'Borne Wallbox', thingClassId: 'wallbox', + setupStatus: 'ThingSetupStatusComplete', paramValues: [], + states: [NymeaStateValue(stateTypeId: 'power', value: 3600.0)]), + NymeaThing(id: 'sim-meter', name: 'Compteur Linky', thingClassId: 'linky', + setupStatus: 'ThingSetupStatusComplete', paramValues: [], + states: [NymeaStateValue(stateTypeId: 'power', value: 180.0)]), + NymeaThing(id: 'sim-ac', name: 'Climatiseur Salon', thingClassId: 'mitsubishi', + setupStatus: 'ThingSetupStatusComplete', paramValues: [], + states: [NymeaStateValue(stateTypeId: 'power', value: false)]), + ]; + } + + @override + void dispose() { + _heartbeatTimer?.cancel(); + _simulationTimer?.cancel(); + _socket?.destroy(); + _wsSub?.cancel(); + _wsChannel?.sink.close(); + super.dispose(); + } +} \ No newline at end of file diff --git a/lib/theme/app_theme.dart b/lib/theme/app_theme.dart new file mode 100644 index 0000000..2ee3ac4 --- /dev/null +++ b/lib/theme/app_theme.dart @@ -0,0 +1,36 @@ +import 'package:flutter/material.dart'; + +class AppTheme { + // Colors + static const Color primaryGreen = Color(0xFF4CAF50); + static const Color solarYellow = Color(0xFFF5C842); + static const Color gridGray = Color(0xFF5A6473); + static const Color homeBlue = Color(0xFF5BA4CF); + static const Color batteryGreen = Color(0xFF4CAF50); + static const Color accentOrange = Color(0xFFFF7043); + static const Color backgroundGray = Color(0xFFF0F2F5); + static const Color cardWhite = Color(0xFFFFFFFF); + static const Color textDark = Color(0xFF1A1A2E); + static const Color textLight = Color(0xFF6B7280); + static const Color boostRed = Color(0xFFEF5350); + static const Color pvGreen = Color(0xFF43A047); + static const Color minPvBlue = Color(0xFF42A5F5); + + static ThemeData get theme => ThemeData( + colorScheme: ColorScheme.fromSeed( + seedColor: primaryGreen, + surface: backgroundGray, + ), + scaffoldBackgroundColor: backgroundGray, + cardTheme: CardThemeData( + color: cardWhite, + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + ), + margin: EdgeInsets.zero, + ), + fontFamily: 'Roboto', + useMaterial3: true, + ); +} diff --git a/lib/widgets/energy_flow_widget.dart b/lib/widgets/energy_flow_widget.dart new file mode 100644 index 0000000..7b70dbd --- /dev/null +++ b/lib/widgets/energy_flow_widget.dart @@ -0,0 +1,272 @@ +import 'package:flutter/material.dart'; +import '../models/energy_data.dart'; +import '../theme/app_theme.dart'; + +class EnergyFlowWidget extends StatelessWidget { + final EnergyData data; + + const EnergyFlowWidget({super.key, required this.data}); + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text( + 'Données en temps réel', + style: TextStyle( + fontSize: 17, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + Row( + children: [ + Text( + '${data.temperature.toStringAsFixed(0)}°C', + style: const TextStyle( + fontSize: 15, + fontWeight: FontWeight.w600, + color: AppTheme.textDark, + ), + ), + const SizedBox(width: 4), + const Icon(Icons.cloud, color: Colors.blueGrey, size: 22), + ], + ), + ], + ), + const SizedBox(height: 20), + + // Energy nodes + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + children: [ + _EnergyNode( + icon: Icons.wb_sunny_rounded, + color: AppTheme.solarYellow, + power: data.pvPower, + label: 'Solaire', + ), + _EnergyNode( + icon: Icons.home_rounded, + color: AppTheme.homeBlue, + power: data.homePower, + label: 'Maison', + ), + _EnergyNode( + icon: Icons.battery_charging_full_rounded, + color: AppTheme.batteryGreen, + power: data.batteryPower.abs(), + label: 'Batterie', + badge: '${data.batterySOC.toStringAsFixed(0)}%', + ), + _EnergyNode( + icon: Icons.electrical_services_rounded, + color: AppTheme.gridGray, + power: data.gridPower.abs(), + label: data.gridPower >= 0 ? 'Réseau ↓' : 'Réseau ↑', + ), + ], + ), + const SizedBox(height: 16), + + // Flow diagram + SizedBox( + height: 80, + child: CustomPaint( + painter: _FlowPainter(data: data), + size: Size.infinite, + ), + ), + ], + ), + ), + ); + } +} + +class _EnergyNode extends StatelessWidget { + final IconData icon; + final Color color; + final double power; + final String label; + final String? badge; + + const _EnergyNode({ + required this.icon, + required this.color, + required this.power, + required this.label, + this.badge, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: 64, + height: 64, + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + ), + child: Icon(icon, color: Colors.white, size: 30), + ), + if (badge != null) + Positioned( + bottom: -4, + left: 0, + right: 0, + child: Center( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 1), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: color, width: 1.5), + ), + child: Text( + badge!, + style: TextStyle( + fontSize: 10, + fontWeight: FontWeight.bold, + color: color, + ), + ), + ), + ), + ), + ], + ), + const SizedBox(height: 10), + Text( + _formatPower(power), + style: const TextStyle( + fontSize: 18, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + Text( + _powerUnit(power), + style: const TextStyle( + fontSize: 12, + color: AppTheme.textLight, + ), + ), + Text( + label, + style: const TextStyle( + fontSize: 11, + color: AppTheme.textLight, + ), + ), + ], + ); + } + + String _formatPower(double w) { + if (w >= 1000) return (w / 1000).toStringAsFixed(1); + return w.toStringAsFixed(0); + } + + String _powerUnit(double w) => w >= 1000 ? 'kW' : 'W'; +} + +class _FlowPainter extends CustomPainter { + final EnergyData data; + + _FlowPainter({required this.data}); + + @override + void paint(Canvas canvas, Size size) { + // Draw animated flow lines between nodes + final centerY = size.height * 0.4; + final nodePositions = [ + size.width * 0.125, // PV + size.width * 0.375, // Home + size.width * 0.625, // Battery + size.width * 0.875, // Grid + ]; + + final linePaint = Paint() + ..strokeWidth = 2 + ..style = PaintingStyle.stroke; + + // PV -> Home (always if PV > 0) + if (data.pvPower > 0) { + _drawArrowLine(canvas, Offset(nodePositions[0], centerY), + Offset(nodePositions[1], centerY), AppTheme.solarYellow, linePaint); + } + + // Home -> Battery (if battery charging) + if (data.batteryPower > 0) { + _drawArrowLine(canvas, Offset(nodePositions[1], centerY), + Offset(nodePositions[2], centerY), AppTheme.batteryGreen, linePaint); + } + + // Grid -> Home (if importing) + if (data.gridPower > 0) { + _drawArrowLine(canvas, Offset(nodePositions[3], centerY), + Offset(nodePositions[1], centerY), Colors.orange, linePaint); + } else if (data.gridPower < 0) { + // Exporting + _drawArrowLine(canvas, Offset(nodePositions[2], centerY), + Offset(nodePositions[3], centerY), AppTheme.solarYellow, linePaint); + } + + // Draw node dots + final dotPaint = Paint()..style = PaintingStyle.fill; + for (int i = 0; i < nodePositions.length; i++) { + final colors = [ + AppTheme.solarYellow, + AppTheme.homeBlue, + AppTheme.batteryGreen, + AppTheme.gridGray, + ]; + dotPaint.color = colors[i]; + canvas.drawCircle(Offset(nodePositions[i], centerY), 6, dotPaint); + } + } + + void _drawArrowLine(Canvas canvas, Offset start, Offset end, Color color, + Paint paint) { + paint.color = color.withValues(alpha:0.7); + + final path = Path() + ..moveTo(start.dx, start.dy) + ..lineTo(end.dx, end.dy); + canvas.drawPath(path, paint); + + // Arrow head + final arrowPaint = Paint() + ..color = color + ..style = PaintingStyle.fill; + + final dx = end.dx - start.dx; + final arrowSign = dx > 0 ? 1 : -1; + final arrowTip = Offset(end.dx - arrowSign * 8, end.dy); + + final arrowPath = Path() + ..moveTo(arrowTip.dx + arrowSign * 8, arrowTip.dy) + ..lineTo(arrowTip.dx, arrowTip.dy - 5) + ..lineTo(arrowTip.dx, arrowTip.dy + 5) + ..close(); + canvas.drawPath(arrowPath, arrowPaint); + } + + @override + bool shouldRepaint(_FlowPainter oldDelegate) => true; +} diff --git a/lib/widgets/ev_charging_card.dart b/lib/widgets/ev_charging_card.dart new file mode 100644 index 0000000..36e7426 --- /dev/null +++ b/lib/widgets/ev_charging_card.dart @@ -0,0 +1,425 @@ +import 'package:flutter/material.dart'; +import '../models/energy_data.dart'; +import '../services/nymea_service.dart'; +import '../theme/app_theme.dart'; + +class EVChargingCard extends StatelessWidget { + final EnergyData data; + final NymeaService service; + + const EVChargingCard({ + super.key, + required this.data, + required this.service, + }); + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Recharge du véhicule', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + Text( + _statusLabel(data.chargingMode), + style: const TextStyle( + fontSize: 13, + color: AppTheme.textLight, + ), + ), + ], + ), + IconButton( + icon: const Icon(Icons.settings_outlined), + onPressed: () => _showSettings(context), + color: AppTheme.textLight, + ), + ], + ), + const SizedBox(height: 16), + + // Mode buttons + Row( + children: [ + _ModeButton( + label: 'PV', + icon: Icons.wb_sunny_rounded, + color: AppTheme.pvGreen, + isSelected: data.chargingMode == ChargingMode.pv, + onTap: () => service.setChargingMode(ChargingMode.pv), + ), + const SizedBox(width: 8), + _ModeButton( + label: 'Min + PV', + icon: Icons.bolt, + color: AppTheme.minPvBlue, + isSelected: data.chargingMode == ChargingMode.minPv, + onTap: () => service.setChargingMode(ChargingMode.minPv), + ), + const SizedBox(width: 8), + _ModeButton( + label: 'Boost', + icon: Icons.rocket_launch_rounded, + color: AppTheme.boostRed, + isSelected: data.chargingMode == ChargingMode.boost, + onTap: () => service.setChargingMode(ChargingMode.boost), + ), + ], + ), + const SizedBox(height: 16), + + // Stats + _InfoRow( + label: 'Puissance borne', + value: '${data.chargingPower.toStringAsFixed(1)} kW', + ), + const SizedBox(height: 6), + _InfoRow( + label: 'Source', + value: '${data.solarSourcePercent.toStringAsFixed(0)}% solaire', + valueColor: AppTheme.pvGreen, + ), + const SizedBox(height: 6), + _InfoRow( + label: 'Limite réseau', + value: data.gridLimitOk ? 'OK ✓' : 'Dépassée !', + valueColor: data.gridLimitOk ? AppTheme.primaryGreen : AppTheme.boostRed, + ), + + // Charging indicator + const SizedBox(height: 12), + if (data.chargingMode != ChargingMode.pv || data.pvPower > 0) + _ChargingIndicator( + mode: data.chargingMode, + pvPower: data.pvPower, + chargingPower: data.chargingPower, + ), + ], + ), + ), + ); + } + + String _statusLabel(ChargingMode mode) { + switch (mode) { + case ChargingMode.pv: + return 'Surplus PV disponible'; + case ChargingMode.minPv: + return 'Minimum + surplus PV'; + case ChargingMode.boost: + return 'Charge rapide (réseau)'; + } + } + + void _showSettings(BuildContext context) { + showModalBottomSheet( + context: context, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(20)), + ), + builder: (_) => const _ChargingSettingsSheet(), + ); + } +} + +class _ModeButton extends StatelessWidget { + final String label; + final IconData icon; + final Color color; + final bool isSelected; + final VoidCallback onTap; + + const _ModeButton({ + required this.label, + required this.icon, + required this.color, + required this.isSelected, + required this.onTap, + }); + + @override + Widget build(BuildContext context) { + return Expanded( + child: GestureDetector( + onTap: onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + padding: const EdgeInsets.symmetric(vertical: 12), + decoration: BoxDecoration( + color: isSelected ? color : color.withValues(alpha:0.1), + borderRadius: BorderRadius.circular(30), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(icon, + color: isSelected ? Colors.white : color, size: 16), + const SizedBox(width: 4), + Text( + label, + style: TextStyle( + color: isSelected ? Colors.white : color, + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + ], + ), + ), + ), + ); + } +} + +class _InfoRow extends StatelessWidget { + final String label; + final String value; + final Color? valueColor; + + const _InfoRow({required this.label, required this.value, this.valueColor}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Text(label, + style: const TextStyle(fontSize: 13, color: AppTheme.textLight)), + const Text(' : ', style: TextStyle(color: AppTheme.textLight)), + Text( + value, + style: TextStyle( + fontSize: 13, + fontWeight: FontWeight.bold, + color: valueColor ?? AppTheme.textDark, + ), + ), + ], + ); + } +} + +class _ChargingIndicator extends StatelessWidget { + final ChargingMode mode; + final double pvPower; + final double chargingPower; + + const _ChargingIndicator({ + required this.mode, + required this.pvPower, + required this.chargingPower, + }); + + @override + Widget build(BuildContext context) { + final pvPercent = (pvPower / (chargingPower * 1000)).clamp(0.0, 1.0); + final gridPercent = mode == ChargingMode.boost ? 1.0 : (1 - pvPercent).clamp(0.0, 1.0); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Répartition charge', + style: TextStyle(fontSize: 12, color: AppTheme.textLight)), + const SizedBox(height: 6), + ClipRRect( + borderRadius: BorderRadius.circular(8), + child: SizedBox( + height: 10, + child: Row( + children: [ + Flexible( + flex: (pvPercent * 100).toInt(), + child: Container(color: AppTheme.solarYellow), + ), + Flexible( + flex: (gridPercent * 100).toInt(), + child: Container(color: Colors.orange.shade300), + ), + ], + ), + ), + ), + const SizedBox(height: 4), + Row( + children: [ + _legend(AppTheme.solarYellow, 'Solaire'), + const SizedBox(width: 12), + _legend(Colors.orange.shade300, 'Réseau'), + ], + ), + ], + ); + } + + Widget _legend(Color color, String label) => Row( + children: [ + Container(width: 10, height: 10, color: color), + const SizedBox(width: 4), + Text(label, style: const TextStyle(fontSize: 11, color: AppTheme.textLight)), + ], + ); +} + +class _ChargingSettingsSheet extends StatefulWidget { + const _ChargingSettingsSheet(); + + @override + State<_ChargingSettingsSheet> createState() => _ChargingSettingsSheetState(); +} + +class _ChargingSettingsSheetState extends State<_ChargingSettingsSheet> { + double _minPower = 6; + double _maxPower = 16; + bool _scheduleEnabled = false; + TimeOfDay _startTime = const TimeOfDay(hour: 22, minute: 0); + TimeOfDay _endTime = const TimeOfDay(hour: 6, minute: 0); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(20), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text('Paramètres de charge', + style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)), + const SizedBox(height: 20), + const Text('Courant minimum (A)', + style: TextStyle(fontWeight: FontWeight.w500)), + Slider( + value: _minPower, + min: 6, + max: 16, + divisions: 10, + label: '${_minPower.toStringAsFixed(0)} A', + onChanged: (v) => setState(() => _minPower = v), + activeColor: AppTheme.primaryGreen, + ), + const Text('Courant maximum (A)', + style: TextStyle(fontWeight: FontWeight.w500)), + Slider( + value: _maxPower, + min: 6, + max: 32, + divisions: 26, + label: '${_maxPower.toStringAsFixed(0)} A', + onChanged: (v) => setState(() => _maxPower = v), + activeColor: AppTheme.primaryGreen, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const Text('Programmation horaire', + style: TextStyle(fontWeight: FontWeight.w500)), + Switch( + value: _scheduleEnabled, + onChanged: (v) => setState(() => _scheduleEnabled = v), + activeThumbColor: AppTheme.primaryGreen, + ), + ], + ), + if (_scheduleEnabled) ...[ + Row( + children: [ + Expanded( + child: _TimePicker( + label: 'Début', + time: _startTime, + onChanged: (t) => setState(() => _startTime = t), + ), + ), + const SizedBox(width: 16), + Expanded( + child: _TimePicker( + label: 'Fin', + time: _endTime, + onChanged: (t) => setState(() => _endTime = t), + ), + ), + ], + ), + ], + const SizedBox(height: 16), + SizedBox( + width: double.infinity, + child: ElevatedButton( + onPressed: () => Navigator.pop(context), + style: ElevatedButton.styleFrom( + backgroundColor: AppTheme.primaryGreen, + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12)), + ), + child: const Text('Enregistrer'), + ), + ), + ], + ), + ); + } +} + +class _TimePicker extends StatelessWidget { + final String label; + final TimeOfDay time; + final ValueChanged onChanged; + + const _TimePicker({ + required this.label, + required this.time, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () async { + final picked = await showTimePicker(context: context, initialTime: time); + if (picked != null) onChanged(picked); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + decoration: BoxDecoration( + border: Border.all(color: Colors.grey.shade300), + borderRadius: BorderRadius.circular(8), + ), + child: Row( + children: [ + const Icon(Icons.access_time, size: 16, color: AppTheme.textLight), + const SizedBox(width: 8), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, + style: const TextStyle( + fontSize: 11, color: AppTheme.textLight)), + Text( + '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}', + style: const TextStyle( + fontWeight: FontWeight.bold, + color: AppTheme.textDark), + ), + ], + ), + ], + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/gains_card.dart b/lib/widgets/gains_card.dart new file mode 100644 index 0000000..a35b38a --- /dev/null +++ b/lib/widgets/gains_card.dart @@ -0,0 +1,63 @@ +import 'package:flutter/material.dart'; +import '../models/energy_data.dart'; +import '../theme/app_theme.dart'; + +class GainsCard extends StatelessWidget { + final EnergyData data; + + const GainsCard({super.key, required this.data}); + + @override + Widget build(BuildContext context) { + return Card( + child: InkWell( + borderRadius: BorderRadius.circular(16), + onTap: () {}, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 14), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: Colors.amber.shade50, + shape: BoxShape.circle, + ), + child: const Icon(Icons.euro_rounded, + color: Colors.amber, size: 22), + ), + const SizedBox(width: 12), + const Text( + 'Gains', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w600, + color: AppTheme.textDark, + ), + ), + ], + ), + Row( + children: [ + Text( + '${data.dayGains.toStringAsFixed(2)} €', + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + const Icon(Icons.chevron_right, color: AppTheme.textLight), + ], + ), + ], + ), + ), + ), + ); + } +} \ No newline at end of file diff --git a/lib/widgets/production_card.dart b/lib/widgets/production_card.dart new file mode 100644 index 0000000..af5f1bc --- /dev/null +++ b/lib/widgets/production_card.dart @@ -0,0 +1,177 @@ +import 'package:flutter/material.dart'; +import 'package:percent_indicator/percent_indicator.dart'; +import '../models/energy_data.dart'; +import '../theme/app_theme.dart'; + +class ProductionCard extends StatelessWidget { + final EnergyData data; + + const ProductionCard({super.key, required this.data}); + + @override + Widget build(BuildContext context) { + return Card( + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Header + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const Text( + 'Production du jour', + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + Text( + '${_formatEnergy(data.dayProductionWh)} Wh', + style: const TextStyle( + fontSize: 22, + fontWeight: FontWeight.bold, + color: AppTheme.textDark, + ), + ), + ], + ), + CircularPercentIndicator( + radius: 35, + lineWidth: 6, + percent: (data.selfConsumptionRate / 100).clamp(0, 1), + center: Text( + '${data.selfConsumptionRate.toStringAsFixed(0)}%', + style: const TextStyle( + fontWeight: FontWeight.bold, + fontSize: 13, + ), + ), + progressColor: AppTheme.primaryGreen, + backgroundColor: Colors.grey.shade200, + ), + ], + ), + const Divider(height: 24), + + // Self-consumption + _StatRow( + icon: Icons.home_rounded, + iconColor: AppTheme.solarYellow, + label: 'Usage personnel', + value: '${_formatEnergy(data.daySelfConsumptionWh)} Wh', + subLabel: 'Autoconsommation', + percent: data.selfConsumptionRate, + color: AppTheme.solarYellow, + ), + const SizedBox(height: 12), + + // Grid injection + _StatRow( + icon: Icons.electrical_services_rounded, + iconColor: AppTheme.gridGray, + label: 'Vers réseau', + value: '${_formatEnergy(data.dayGridInjectionWh)} Wh', + subLabel: 'Autonomie', + percent: data.autonomyRate, + color: AppTheme.homeBlue, + ), + ], + ), + ), + ); + } + + String _formatEnergy(double wh) { + if (wh >= 1000) return '${(wh / 1000).toStringAsFixed(2)} k'; + return wh.toStringAsFixed(0); + } +} + +class _StatRow extends StatelessWidget { + final IconData icon; + final Color iconColor; + final String label; + final String value; + final String subLabel; + final double percent; + final Color color; + + const _StatRow({ + required this.icon, + required this.iconColor, + required this.label, + required this.value, + required this.subLabel, + required this.percent, + required this.color, + }); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + Row( + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: iconColor.withValues(alpha:0.15), + shape: BoxShape.circle, + ), + child: Icon(icon, color: iconColor, size: 20), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text(label, + style: const TextStyle( + fontSize: 14, color: AppTheme.textLight)), + Text(value, + style: const TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: AppTheme.textDark)), + ], + ), + const SizedBox(height: 4), + Row( + children: [ + Text( + '$subLabel : ${percent.toStringAsFixed(0)}%', + style: TextStyle(fontSize: 11, color: color), + ), + const SizedBox(width: 8), + Expanded( + child: ClipRRect( + borderRadius: BorderRadius.circular(4), + child: LinearProgressIndicator( + value: (percent / 100).clamp(0, 1), + backgroundColor: Colors.grey.shade200, + valueColor: AlwaysStoppedAnimation(color), + minHeight: 5, + ), + ), + ), + ], + ), + ], + ), + ), + ], + ), + ], + ); + } +} \ No newline at end of file diff --git a/linux/.gitignore b/linux/.gitignore new file mode 100644 index 0000000..d3896c9 --- /dev/null +++ b/linux/.gitignore @@ -0,0 +1 @@ +flutter/ephemeral diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 0000000..c416dcc --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,128 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "etm_powersync_app") +# The unique GTK application identifier for this application. See: +# https://wiki.gnome.org/HowDoI/ChooseApplicationID +set(APPLICATION_ID "com.example.etm_powersync_app") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(SET CMP0063 NEW) + +# Load bundled libraries from the lib/ directory relative to the binary. +set(CMAKE_INSTALL_RPATH "$ORIGIN/lib") + +# Root filesystem for cross-building. +if(FLUTTER_TARGET_PLATFORM_SYSROOT) + set(CMAKE_SYSROOT ${FLUTTER_TARGET_PLATFORM_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH ${CMAKE_SYSROOT}) + set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) + set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) + set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +endif() + +# Define build configuration options. +if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") +endif() + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_14) + target_compile_options(${TARGET} PRIVATE -Wall -Werror) + target_compile_options(${TARGET} PRIVATE "$<$>:-O3>") + target_compile_definitions(${TARGET} PRIVATE "$<$>:NDEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) + +# Only the install-generated bundle's copy of the executable will launch +# correctly, since the resources must in the right relative locations. To avoid +# people trying to run the unbundled copy, put it in a subdirectory instead of +# the default top-level location. +set_target_properties(${BINARY_NAME} + PROPERTIES + RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/intermediates_do_not_run" +) + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# By default, "installing" just makes a relocatable bundle in the build +# directory. +set(BUILD_BUNDLE_DIR "${PROJECT_BINARY_DIR}/bundle") +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +# Start with a clean build bundle directory every time. +install(CODE " + file(REMOVE_RECURSE \"${BUILD_BUNDLE_DIR}/\") + " COMPONENT Runtime) + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}/lib") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +foreach(bundled_library ${PLUGIN_BUNDLED_LIBRARIES}) + install(FILES "${bundled_library}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endforeach(bundled_library) + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/linux/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +if(NOT CMAKE_BUILD_TYPE MATCHES "Debug") + install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() diff --git a/linux/flutter/CMakeLists.txt b/linux/flutter/CMakeLists.txt new file mode 100644 index 0000000..d5bd016 --- /dev/null +++ b/linux/flutter/CMakeLists.txt @@ -0,0 +1,88 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.10) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. + +# Serves the same purpose as list(TRANSFORM ... PREPEND ...), +# which isn't available in 3.10. +function(list_prepend LIST_NAME PREFIX) + set(NEW_LIST "") + foreach(element ${${LIST_NAME}}) + list(APPEND NEW_LIST "${PREFIX}${element}") + endforeach(element) + set(${LIST_NAME} "${NEW_LIST}" PARENT_SCOPE) +endfunction() + +# === Flutter Library === +# System-level dependencies. +find_package(PkgConfig REQUIRED) +pkg_check_modules(GTK REQUIRED IMPORTED_TARGET gtk+-3.0) +pkg_check_modules(GLIB REQUIRED IMPORTED_TARGET glib-2.0) +pkg_check_modules(GIO REQUIRED IMPORTED_TARGET gio-2.0) + +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/libflutter_linux_gtk.so") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/lib/libapp.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "fl_basic_message_channel.h" + "fl_binary_codec.h" + "fl_binary_messenger.h" + "fl_dart_project.h" + "fl_engine.h" + "fl_json_message_codec.h" + "fl_json_method_codec.h" + "fl_message_codec.h" + "fl_method_call.h" + "fl_method_channel.h" + "fl_method_codec.h" + "fl_method_response.h" + "fl_plugin_registrar.h" + "fl_plugin_registry.h" + "fl_standard_message_codec.h" + "fl_standard_method_codec.h" + "fl_string_codec.h" + "fl_value.h" + "fl_view.h" + "flutter_linux.h" +) +list_prepend(FLUTTER_LIBRARY_HEADERS "${EPHEMERAL_DIR}/flutter_linux/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}") +target_link_libraries(flutter INTERFACE + PkgConfig::GTK + PkgConfig::GLIB + PkgConfig::GIO +) +add_dependencies(flutter flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CMAKE_CURRENT_BINARY_DIR}/_phony_ + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.sh" + ${FLUTTER_TARGET_PLATFORM} ${CMAKE_BUILD_TYPE} + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..e71a16d --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..e0f0a47 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 0000000..2e1de87 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/linux/runner/CMakeLists.txt b/linux/runner/CMakeLists.txt new file mode 100644 index 0000000..e97dabc --- /dev/null +++ b/linux/runner/CMakeLists.txt @@ -0,0 +1,26 @@ +cmake_minimum_required(VERSION 3.13) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} + "main.cc" + "my_application.cc" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the application ID. +add_definitions(-DAPPLICATION_ID="${APPLICATION_ID}") + +# Add dependency libraries. Add any application-specific dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter) +target_link_libraries(${BINARY_NAME} PRIVATE PkgConfig::GTK) + +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") diff --git a/linux/runner/main.cc b/linux/runner/main.cc new file mode 100644 index 0000000..e7c5c54 --- /dev/null +++ b/linux/runner/main.cc @@ -0,0 +1,6 @@ +#include "my_application.h" + +int main(int argc, char** argv) { + g_autoptr(MyApplication) app = my_application_new(); + return g_application_run(G_APPLICATION(app), argc, argv); +} diff --git a/linux/runner/my_application.cc b/linux/runner/my_application.cc new file mode 100644 index 0000000..60c370d --- /dev/null +++ b/linux/runner/my_application.cc @@ -0,0 +1,148 @@ +#include "my_application.h" + +#include +#ifdef GDK_WINDOWING_X11 +#include +#endif + +#include "flutter/generated_plugin_registrant.h" + +struct _MyApplication { + GtkApplication parent_instance; + char** dart_entrypoint_arguments; +}; + +G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION) + +// Called when first Flutter frame received. +static void first_frame_cb(MyApplication* self, FlView* view) { + gtk_widget_show(gtk_widget_get_toplevel(GTK_WIDGET(view))); +} + +// Implements GApplication::activate. +static void my_application_activate(GApplication* application) { + MyApplication* self = MY_APPLICATION(application); + GtkWindow* window = + GTK_WINDOW(gtk_application_window_new(GTK_APPLICATION(application))); + + // Use a header bar when running in GNOME as this is the common style used + // by applications and is the setup most users will be using (e.g. Ubuntu + // desktop). + // If running on X and not using GNOME then just use a traditional title bar + // in case the window manager does more exotic layout, e.g. tiling. + // If running on Wayland assume the header bar will work (may need changing + // if future cases occur). + gboolean use_header_bar = TRUE; +#ifdef GDK_WINDOWING_X11 + GdkScreen* screen = gtk_window_get_screen(window); + if (GDK_IS_X11_SCREEN(screen)) { + const gchar* wm_name = gdk_x11_screen_get_window_manager_name(screen); + if (g_strcmp0(wm_name, "GNOME Shell") != 0) { + use_header_bar = FALSE; + } + } +#endif + if (use_header_bar) { + GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new()); + gtk_widget_show(GTK_WIDGET(header_bar)); + gtk_header_bar_set_title(header_bar, "etm_powersync_app"); + gtk_header_bar_set_show_close_button(header_bar, TRUE); + gtk_window_set_titlebar(window, GTK_WIDGET(header_bar)); + } else { + gtk_window_set_title(window, "etm_powersync_app"); + } + + gtk_window_set_default_size(window, 1280, 720); + + g_autoptr(FlDartProject) project = fl_dart_project_new(); + fl_dart_project_set_dart_entrypoint_arguments( + project, self->dart_entrypoint_arguments); + + FlView* view = fl_view_new(project); + GdkRGBA background_color; + // Background defaults to black, override it here if necessary, e.g. #00000000 + // for transparent. + gdk_rgba_parse(&background_color, "#000000"); + fl_view_set_background_color(view, &background_color); + gtk_widget_show(GTK_WIDGET(view)); + gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(view)); + + // Show the window when Flutter renders. + // Requires the view to be realized so we can start rendering. + g_signal_connect_swapped(view, "first-frame", G_CALLBACK(first_frame_cb), + self); + gtk_widget_realize(GTK_WIDGET(view)); + + fl_register_plugins(FL_PLUGIN_REGISTRY(view)); + + gtk_widget_grab_focus(GTK_WIDGET(view)); +} + +// Implements GApplication::local_command_line. +static gboolean my_application_local_command_line(GApplication* application, + gchar*** arguments, + int* exit_status) { + MyApplication* self = MY_APPLICATION(application); + // Strip out the first argument as it is the binary name. + self->dart_entrypoint_arguments = g_strdupv(*arguments + 1); + + g_autoptr(GError) error = nullptr; + if (!g_application_register(application, nullptr, &error)) { + g_warning("Failed to register: %s", error->message); + *exit_status = 1; + return TRUE; + } + + g_application_activate(application); + *exit_status = 0; + + return TRUE; +} + +// Implements GApplication::startup. +static void my_application_startup(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application startup. + + G_APPLICATION_CLASS(my_application_parent_class)->startup(application); +} + +// Implements GApplication::shutdown. +static void my_application_shutdown(GApplication* application) { + // MyApplication* self = MY_APPLICATION(object); + + // Perform any actions required at application shutdown. + + G_APPLICATION_CLASS(my_application_parent_class)->shutdown(application); +} + +// Implements GObject::dispose. +static void my_application_dispose(GObject* object) { + MyApplication* self = MY_APPLICATION(object); + g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev); + G_OBJECT_CLASS(my_application_parent_class)->dispose(object); +} + +static void my_application_class_init(MyApplicationClass* klass) { + G_APPLICATION_CLASS(klass)->activate = my_application_activate; + G_APPLICATION_CLASS(klass)->local_command_line = + my_application_local_command_line; + G_APPLICATION_CLASS(klass)->startup = my_application_startup; + G_APPLICATION_CLASS(klass)->shutdown = my_application_shutdown; + G_OBJECT_CLASS(klass)->dispose = my_application_dispose; +} + +static void my_application_init(MyApplication* self) {} + +MyApplication* my_application_new() { + // Set the program name to the application ID, which helps various systems + // like GTK and desktop environments map this running application to its + // corresponding .desktop file. This ensures better integration by allowing + // the application to be recognized beyond its binary name. + g_set_prgname(APPLICATION_ID); + + return MY_APPLICATION(g_object_new(my_application_get_type(), + "application-id", APPLICATION_ID, "flags", + G_APPLICATION_NON_UNIQUE, nullptr)); +} diff --git a/linux/runner/my_application.h b/linux/runner/my_application.h new file mode 100644 index 0000000..db16367 --- /dev/null +++ b/linux/runner/my_application.h @@ -0,0 +1,21 @@ +#ifndef FLUTTER_MY_APPLICATION_H_ +#define FLUTTER_MY_APPLICATION_H_ + +#include + +G_DECLARE_FINAL_TYPE(MyApplication, + my_application, + MY, + APPLICATION, + GtkApplication) + +/** + * my_application_new: + * + * Creates a new Flutter-based application. + * + * Returns: a new #MyApplication. + */ +MyApplication* my_application_new(); + +#endif // FLUTTER_MY_APPLICATION_H_ diff --git a/macos/.gitignore b/macos/.gitignore new file mode 100644 index 0000000..746adbb --- /dev/null +++ b/macos/.gitignore @@ -0,0 +1,7 @@ +# Flutter-related +**/Flutter/ephemeral/ +**/Pods/ + +# Xcode-related +**/dgph +**/xcuserdata/ diff --git a/macos/Flutter/Flutter-Debug.xcconfig b/macos/Flutter/Flutter-Debug.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/macos/Flutter/Flutter-Debug.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/Flutter-Release.xcconfig b/macos/Flutter/Flutter-Release.xcconfig new file mode 100644 index 0000000..c2efd0b --- /dev/null +++ b/macos/Flutter/Flutter-Release.xcconfig @@ -0,0 +1 @@ +#include "ephemeral/Flutter-Generated.xcconfig" diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift new file mode 100644 index 0000000..724bb2a --- /dev/null +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -0,0 +1,12 @@ +// +// Generated file. Do not edit. +// + +import FlutterMacOS +import Foundation + +import shared_preferences_foundation + +func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { + SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) +} diff --git a/macos/Runner.xcodeproj/project.pbxproj b/macos/Runner.xcodeproj/project.pbxproj new file mode 100644 index 0000000..e455769 --- /dev/null +++ b/macos/Runner.xcodeproj/project.pbxproj @@ -0,0 +1,705 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 54; + objects = { + +/* Begin PBXAggregateTarget section */ + 33CC111A2044C6BA0003C045 /* Flutter Assemble */ = { + isa = PBXAggregateTarget; + buildConfigurationList = 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */; + buildPhases = ( + 33CC111E2044C6BF0003C045 /* ShellScript */, + ); + dependencies = ( + ); + name = "Flutter Assemble"; + productName = FLX; + }; +/* End PBXAggregateTarget section */ + +/* Begin PBXBuildFile section */ + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C80D7294CF71000263BE5 /* RunnerTests.swift */; }; + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F42044A3C60003C045 /* MainMenu.xib */; }; + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC10EC2044A3C60003C045; + remoteInfo = Runner; + }; + 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 33CC10E52044A3C60003C045 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 33CC111A2044C6BA0003C045; + remoteInfo = FLX; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 33CC110E2044A8840003C045 /* Bundle Framework */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = ""; + dstSubfolderSpec = 10; + files = ( + ); + name = "Bundle Framework"; + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = ""; }; + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = ""; }; + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = ""; }; + 33CC10ED2044A3C60003C045 /* etm_powersync_app.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "etm_powersync_app.app"; sourceTree = BUILT_PRODUCTS_DIR; }; + 33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = ""; }; + 33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; + 33CC10F72044A3C60003C045 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Runner/Info.plist; sourceTree = ""; }; + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainFlutterWindow.swift; sourceTree = ""; }; + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Debug.xcconfig"; sourceTree = ""; }; + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = "Flutter-Release.xcconfig"; sourceTree = ""; }; + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = "Flutter-Generated.xcconfig"; path = "ephemeral/Flutter-Generated.xcconfig"; sourceTree = ""; }; + 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; + 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; + 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 331C80D2294CF70F00263BE5 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EA2044A3C60003C045 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 331C80D6294CF71000263BE5 /* RunnerTests */ = { + isa = PBXGroup; + children = ( + 331C80D7294CF71000263BE5 /* RunnerTests.swift */, + ); + path = RunnerTests; + sourceTree = ""; + }; + 33BA886A226E78AF003329D5 /* Configs */ = { + isa = PBXGroup; + children = ( + 33E5194F232828860026EE4D /* AppInfo.xcconfig */, + 9740EEB21CF90195004384FC /* Debug.xcconfig */, + 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, + 333000ED22D3DE5D00554162 /* Warnings.xcconfig */, + ); + path = Configs; + sourceTree = ""; + }; + 33CC10E42044A3C60003C045 = { + isa = PBXGroup; + children = ( + 33FAB671232836740065AC1E /* Runner */, + 33CEB47122A05771004F2AC0 /* Flutter */, + 331C80D6294CF71000263BE5 /* RunnerTests */, + 33CC10EE2044A3C60003C045 /* Products */, + D73912EC22F37F3D000D13A0 /* Frameworks */, + ); + sourceTree = ""; + }; + 33CC10EE2044A3C60003C045 /* Products */ = { + isa = PBXGroup; + children = ( + 33CC10ED2044A3C60003C045 /* etm_powersync_app.app */, + 331C80D5294CF71000263BE5 /* RunnerTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 33CC11242044D66E0003C045 /* Resources */ = { + isa = PBXGroup; + children = ( + 33CC10F22044A3C60003C045 /* Assets.xcassets */, + 33CC10F42044A3C60003C045 /* MainMenu.xib */, + 33CC10F72044A3C60003C045 /* Info.plist */, + ); + name = Resources; + path = ..; + sourceTree = ""; + }; + 33CEB47122A05771004F2AC0 /* Flutter */ = { + isa = PBXGroup; + children = ( + 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */, + 33CEB47222A05771004F2AC0 /* Flutter-Debug.xcconfig */, + 33CEB47422A05771004F2AC0 /* Flutter-Release.xcconfig */, + 33CEB47722A0578A004F2AC0 /* Flutter-Generated.xcconfig */, + ); + path = Flutter; + sourceTree = ""; + }; + 33FAB671232836740065AC1E /* Runner */ = { + isa = PBXGroup; + children = ( + 33CC10F02044A3C60003C045 /* AppDelegate.swift */, + 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */, + 33E51913231747F40026EE4D /* DebugProfile.entitlements */, + 33E51914231749380026EE4D /* Release.entitlements */, + 33CC11242044D66E0003C045 /* Resources */, + 33BA886A226E78AF003329D5 /* Configs */, + ); + path = Runner; + sourceTree = ""; + }; + D73912EC22F37F3D000D13A0 /* Frameworks */ = { + isa = PBXGroup; + children = ( + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 331C80D4294CF70F00263BE5 /* RunnerTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */; + buildPhases = ( + 331C80D1294CF70F00263BE5 /* Sources */, + 331C80D2294CF70F00263BE5 /* Frameworks */, + 331C80D3294CF70F00263BE5 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 331C80DA294CF71000263BE5 /* PBXTargetDependency */, + ); + name = RunnerTests; + productName = RunnerTests; + productReference = 331C80D5294CF71000263BE5 /* RunnerTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 33CC10EC2044A3C60003C045 /* Runner */ = { + isa = PBXNativeTarget; + buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; + buildPhases = ( + 33CC10E92044A3C60003C045 /* Sources */, + 33CC10EA2044A3C60003C045 /* Frameworks */, + 33CC10EB2044A3C60003C045 /* Resources */, + 33CC110E2044A8840003C045 /* Bundle Framework */, + 3399D490228B24CF009A79C7 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + 33CC11202044C79F0003C045 /* PBXTargetDependency */, + ); + name = Runner; + productName = Runner; + productReference = 33CC10ED2044A3C60003C045 /* etm_powersync_app.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 33CC10E52044A3C60003C045 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = YES; + LastSwiftUpdateCheck = 0920; + LastUpgradeCheck = 1510; + ORGANIZATIONNAME = ""; + TargetAttributes = { + 331C80D4294CF70F00263BE5 = { + CreatedOnToolsVersion = 14.0; + TestTargetID = 33CC10EC2044A3C60003C045; + }; + 33CC10EC2044A3C60003C045 = { + CreatedOnToolsVersion = 9.2; + LastSwiftMigration = 1100; + ProvisioningStyle = Automatic; + SystemCapabilities = { + com.apple.Sandbox = { + enabled = 1; + }; + }; + }; + 33CC111A2044C6BA0003C045 = { + CreatedOnToolsVersion = 9.2; + ProvisioningStyle = Manual; + }; + }; + }; + buildConfigurationList = 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 33CC10E42044A3C60003C045; + productRefGroup = 33CC10EE2044A3C60003C045 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 33CC10EC2044A3C60003C045 /* Runner */, + 331C80D4294CF70F00263BE5 /* RunnerTests */, + 33CC111A2044C6BA0003C045 /* Flutter Assemble */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 331C80D3294CF70F00263BE5 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10EB2044A3C60003C045 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */, + 33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 3399D490228B24CF009A79C7 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename && \"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh embed\n"; + }; + 33CC111E2044C6BF0003C045 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, + ); + outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 331C80D1294CF70F00263BE5 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 331C80D8294CF71000263BE5 /* RunnerTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 33CC10E92044A3C60003C045 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */, + 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */, + 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 331C80DA294CF71000263BE5 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC10EC2044A3C60003C045 /* Runner */; + targetProxy = 331C80D9294CF71000263BE5 /* PBXContainerItemProxy */; + }; + 33CC11202044C79F0003C045 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 33CC111A2044C6BA0003C045 /* Flutter Assemble */; + targetProxy = 33CC111F2044C79F0003C045 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 33CC10F42044A3C60003C045 /* MainMenu.xib */ = { + isa = PBXVariantGroup; + children = ( + 33CC10F52044A3C60003C045 /* Base */, + ); + name = MainMenu.xib; + path = Runner; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 331C80DB294CF71000263BE5 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/etm_powersync_app.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/etm_powersync_app"; + }; + name = Debug; + }; + 331C80DC294CF71000263BE5 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/etm_powersync_app.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/etm_powersync_app"; + }; + name = Release; + }; + 331C80DD294CF71000263BE5 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + BUNDLE_LOADER = "$(TEST_HOST)"; + CURRENT_PROJECT_VERSION = 1; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp.RunnerTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/etm_powersync_app.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/etm_powersync_app"; + }; + name = Profile; + }; + 338D0CE9231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Profile; + }; + 338D0CEA231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Profile; + }; + 338D0CEB231458BD00FA5F75 /* Profile */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Profile; + }; + 33CC10F92044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 33CC10FA2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CODE_SIGN_IDENTITY = "-"; + COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = NO; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.15; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = macosx; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + }; + name = Release; + }; + 33CC10FC2044A3C60003C045 /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 33CC10FD2044A3C60003C045 /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLANG_ENABLE_MODULES = YES; + CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + INFOPLIST_FILE = Runner/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + ); + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; + 33CC111C2044C6BA0003C045 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Manual; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 33CC111D2044C6BA0003C045 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CODE_SIGN_STYLE = Automatic; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 331C80DE294CF71000263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 331C80DB294CF71000263BE5 /* Debug */, + 331C80DC294CF71000263BE5 /* Release */, + 331C80DD294CF71000263BE5 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10E82044A3C60003C045 /* Build configuration list for PBXProject "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10F92044A3C60003C045 /* Debug */, + 33CC10FA2044A3C60003C045 /* Release */, + 338D0CE9231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC10FC2044A3C60003C045 /* Debug */, + 33CC10FD2044A3C60003C045 /* Release */, + 338D0CEA231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 33CC111B2044C6BA0003C045 /* Build configuration list for PBXAggregateTarget "Flutter Assemble" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 33CC111C2044C6BA0003C045 /* Debug */, + 33CC111D2044C6BA0003C045 /* Release */, + 338D0CEB231458BD00FA5F75 /* Profile */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 33CC10E52044A3C60003C045 /* Project object */; +} diff --git a/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme new file mode 100644 index 0000000..ecf8b87 --- /dev/null +++ b/macos/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -0,0 +1,99 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner.xcworkspace/contents.xcworkspacedata b/macos/Runner.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..1d526a1 --- /dev/null +++ b/macos/Runner.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/macos/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/macos/Runner/AppDelegate.swift b/macos/Runner/AppDelegate.swift new file mode 100644 index 0000000..b3c1761 --- /dev/null +++ b/macos/Runner/AppDelegate.swift @@ -0,0 +1,13 @@ +import Cocoa +import FlutterMacOS + +@main +class AppDelegate: FlutterAppDelegate { + override func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { + return true + } + + override func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { + return true + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..a2ec33f --- /dev/null +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,68 @@ +{ + "images" : [ + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_16.png", + "scale" : "1x" + }, + { + "size" : "16x16", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "2x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_32.png", + "scale" : "1x" + }, + { + "size" : "32x32", + "idiom" : "mac", + "filename" : "app_icon_64.png", + "scale" : "2x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_128.png", + "scale" : "1x" + }, + { + "size" : "128x128", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "2x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_256.png", + "scale" : "1x" + }, + { + "size" : "256x256", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "2x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_512.png", + "scale" : "1x" + }, + { + "size" : "512x512", + "idiom" : "mac", + "filename" : "app_icon_1024.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png new file mode 100644 index 0000000..82b6f9d Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png new file mode 100644 index 0000000..13b35eb Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png new file mode 100644 index 0000000..0a3f5fa Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png new file mode 100644 index 0000000..bdb5722 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png new file mode 100644 index 0000000..f083318 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_32.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png new file mode 100644 index 0000000..326c0e7 Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png differ diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png new file mode 100644 index 0000000..2f1632c Binary files /dev/null and b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png differ diff --git a/macos/Runner/Base.lproj/MainMenu.xib b/macos/Runner/Base.lproj/MainMenu.xib new file mode 100644 index 0000000..80e867a --- /dev/null +++ b/macos/Runner/Base.lproj/MainMenu.xib @@ -0,0 +1,343 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macos/Runner/Configs/AppInfo.xcconfig b/macos/Runner/Configs/AppInfo.xcconfig new file mode 100644 index 0000000..c158e80 --- /dev/null +++ b/macos/Runner/Configs/AppInfo.xcconfig @@ -0,0 +1,14 @@ +// Application-level settings for the Runner target. +// +// This may be replaced with something auto-generated from metadata (e.g., pubspec.yaml) in the +// future. If not, the values below would default to using the project name when this becomes a +// 'flutter create' template. + +// The application's name. By default this is also the title of the Flutter window. +PRODUCT_NAME = etm_powersync_app + +// The application's bundle identifier +PRODUCT_BUNDLE_IDENTIFIER = com.example.etmPowersyncApp + +// The copyright displayed in application information +PRODUCT_COPYRIGHT = Copyright © 2026 com.example. All rights reserved. diff --git a/macos/Runner/Configs/Debug.xcconfig b/macos/Runner/Configs/Debug.xcconfig new file mode 100644 index 0000000..36b0fd9 --- /dev/null +++ b/macos/Runner/Configs/Debug.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Debug.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Release.xcconfig b/macos/Runner/Configs/Release.xcconfig new file mode 100644 index 0000000..dff4f49 --- /dev/null +++ b/macos/Runner/Configs/Release.xcconfig @@ -0,0 +1,2 @@ +#include "../../Flutter/Flutter-Release.xcconfig" +#include "Warnings.xcconfig" diff --git a/macos/Runner/Configs/Warnings.xcconfig b/macos/Runner/Configs/Warnings.xcconfig new file mode 100644 index 0000000..42bcbf4 --- /dev/null +++ b/macos/Runner/Configs/Warnings.xcconfig @@ -0,0 +1,13 @@ +WARNING_CFLAGS = -Wall -Wconditional-uninitialized -Wnullable-to-nonnull-conversion -Wmissing-method-return-type -Woverlength-strings +GCC_WARN_UNDECLARED_SELECTOR = YES +CLANG_UNDEFINED_BEHAVIOR_SANITIZER_NULLABILITY = YES +CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE +CLANG_WARN__DUPLICATE_METHOD_MATCH = YES +CLANG_WARN_PRAGMA_PACK = YES +CLANG_WARN_STRICT_PROTOTYPES = YES +CLANG_WARN_COMMA = YES +GCC_WARN_STRICT_SELECTOR_MATCH = YES +CLANG_WARN_OBJC_REPEATED_USE_OF_WEAK = YES +CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES +GCC_WARN_SHADOW = YES +CLANG_WARN_UNREACHABLE_CODE = YES diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements new file mode 100644 index 0000000..dddb8a3 --- /dev/null +++ b/macos/Runner/DebugProfile.entitlements @@ -0,0 +1,12 @@ + + + + + com.apple.security.app-sandbox + + com.apple.security.cs.allow-jit + + com.apple.security.network.server + + + diff --git a/macos/Runner/Info.plist b/macos/Runner/Info.plist new file mode 100644 index 0000000..4789daa --- /dev/null +++ b/macos/Runner/Info.plist @@ -0,0 +1,32 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIconFile + + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $(FLUTTER_BUILD_NAME) + CFBundleVersion + $(FLUTTER_BUILD_NUMBER) + LSMinimumSystemVersion + $(MACOSX_DEPLOYMENT_TARGET) + NSHumanReadableCopyright + $(PRODUCT_COPYRIGHT) + NSMainNibFile + MainMenu + NSPrincipalClass + NSApplication + + diff --git a/macos/Runner/MainFlutterWindow.swift b/macos/Runner/MainFlutterWindow.swift new file mode 100644 index 0000000..3cc05eb --- /dev/null +++ b/macos/Runner/MainFlutterWindow.swift @@ -0,0 +1,15 @@ +import Cocoa +import FlutterMacOS + +class MainFlutterWindow: NSWindow { + override func awakeFromNib() { + let flutterViewController = FlutterViewController() + let windowFrame = self.frame + self.contentViewController = flutterViewController + self.setFrame(windowFrame, display: true) + + RegisterGeneratedPlugins(registry: flutterViewController) + + super.awakeFromNib() + } +} diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements new file mode 100644 index 0000000..852fa1a --- /dev/null +++ b/macos/Runner/Release.entitlements @@ -0,0 +1,8 @@ + + + + + com.apple.security.app-sandbox + + + diff --git a/macos/RunnerTests/RunnerTests.swift b/macos/RunnerTests/RunnerTests.swift new file mode 100644 index 0000000..61f3bd1 --- /dev/null +++ b/macos/RunnerTests/RunnerTests.swift @@ -0,0 +1,12 @@ +import Cocoa +import FlutterMacOS +import XCTest + +class RunnerTests: XCTestCase { + + func testExample() { + // If you add code to the Runner application, consider adding tests here. + // See https://developer.apple.com/documentation/xctest for more information about using XCTest. + } + +} diff --git a/pubspec.lock b/pubspec.lock new file mode 100644 index 0000000..3d1be9a --- /dev/null +++ b/pubspec.lock @@ -0,0 +1,418 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb" + url: "https://pub.dev" + source: hosted + version: "2.13.0" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + characters: + dependency: transitive + description: + name: characters + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + url: "https://pub.dev" + source: hosted + version: "1.4.1" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: ba631d1c7f7bef6b729a622b7b752645a2d076dba9976925b8f25725a30e1ee6 + url: "https://pub.dev" + source: hosted + version: "1.0.8" + equatable: + dependency: transitive + description: + name: equatable + sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" + url: "https://pub.dev" + source: hosted + version: "2.0.8" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fl_chart: + dependency: "direct main" + description: + name: fl_chart + sha256: "5276944c6ffc975ae796569a826c38a62d2abcf264e26b88fa6f482e107f4237" + url: "https://pub.dev" + source: hosted + version: "0.70.2" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "3105dc8492f6183fb076ccf1f351ac3d60564bff92e20bfc4af9cc1651f4e7e1" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + flutter_web_plugins: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + lints: + dependency: transitive + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" + url: "https://pub.dev" + source: hosted + version: "0.12.18" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + url: "https://pub.dev" + source: hosted + version: "0.13.0" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + path_provider_linux: + dependency: transitive + description: + name: path_provider_linux + sha256: f7a1fe3a634fe7734c8d3f2766ad746ae2a2884abe22e241a8b301bf5cac3279 + url: "https://pub.dev" + source: hosted + version: "2.2.1" + path_provider_platform_interface: + dependency: transitive + description: + name: path_provider_platform_interface + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_windows: + dependency: transitive + description: + name: path_provider_windows + sha256: bd6f00dbd873bfb70d0761682da2b3a2c2fccc2b9e84c495821639601d81afe7 + url: "https://pub.dev" + source: hosted + version: "2.3.0" + percent_indicator: + dependency: "direct main" + description: + name: percent_indicator + sha256: "157d29133bbc6ecb11f923d36e7960a96a3f28837549a20b65e5135729f0f9fd" + url: "https://pub.dev" + source: hosted + version: "4.2.5" + platform: + dependency: transitive + description: + name: platform + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" + url: "https://pub.dev" + source: hosted + version: "3.1.6" + plugin_platform_interface: + dependency: transitive + description: + name: plugin_platform_interface + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" + source: hosted + version: "2.1.8" + provider: + dependency: "direct main" + description: + name: provider + sha256: "4e82183fa20e5ca25703ead7e05de9e4cceed1fbd1eadc1ac3cb6f565a09f272" + url: "https://pub.dev" + source: hosted + version: "6.1.5+1" + shared_preferences: + dependency: "direct main" + description: + name: shared_preferences + sha256: "2939ae520c9024cb197fc20dee269cd8cdbf564c8b5746374ec6cacdc5169e64" + url: "https://pub.dev" + source: hosted + version: "2.5.4" + shared_preferences_android: + dependency: transitive + description: + name: shared_preferences_android + sha256: cbc40be9be1c5af4dab4d6e0de4d5d3729e6f3d65b89d21e1815d57705644a6f + url: "https://pub.dev" + source: hosted + version: "2.4.20" + shared_preferences_foundation: + dependency: transitive + description: + name: shared_preferences_foundation + sha256: "4e7eaffc2b17ba398759f1151415869a34771ba11ebbccd1b0145472a619a64f" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + shared_preferences_linux: + dependency: transitive + description: + name: shared_preferences_linux + sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_platform_interface: + dependency: transitive + description: + name: shared_preferences_platform_interface + sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + shared_preferences_web: + dependency: transitive + description: + name: shared_preferences_web + sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019 + url: "https://pub.dev" + source: hosted + version: "2.4.3" + shared_preferences_windows: + dependency: transitive + description: + name: shared_preferences_windows + sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" + url: "https://pub.dev" + source: hosted + version: "0.7.9" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60" + url: "https://pub.dev" + source: hosted + version: "15.0.2" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: "direct main" + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + xdg_directories: + dependency: transitive + description: + name: xdg_directories + sha256: "7a3f37b05d989967cdddcbb571f1ea834867ae2faa29725fd085180e0883aa15" + url: "https://pub.dev" + source: hosted + version: "1.1.0" +sdks: + dart: ">=3.11.0 <4.0.0" + flutter: ">=3.35.0" diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 0000000..06a32ed --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,94 @@ +name: etm_powersync_app +description: "A new Flutter project." +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number is used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +# In Windows, build-name is used as the major, minor, and patch parts +# of the product and file versions while build-number is used as the build suffix. +version: 1.0.0+1 + +environment: + sdk: ^3.11.0 + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.8 + provider: ^6.1.2 + web_socket_channel: ^3.0.1 + fl_chart: ^0.70.2 + percent_indicator: ^4.2.3 + shared_preferences: ^2.3.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^6.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/to/resolution-aware-images + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/to/asset-from-package + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/to/font-from-package diff --git a/test/widget_test.dart b/test/widget_test.dart new file mode 100644 index 0000000..3b87a07 --- /dev/null +++ b/test/widget_test.dart @@ -0,0 +1,16 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:provider/provider.dart'; +import 'package:etm_powersync_app/main.dart'; +import 'package:etm_powersync_app/services/nymea_service.dart'; + +void main() { + testWidgets('App smoke test', (WidgetTester tester) async { + await tester.pumpWidget( + ChangeNotifierProvider( + create: (_) => NymeaService(), + child: const NymeaEnergyApp(), + ), + ); + expect(find.byType(NymeaEnergyApp), findsOneWidget); + }); +} diff --git a/web/favicon.png b/web/favicon.png new file mode 100644 index 0000000..8aaa46a Binary files /dev/null and b/web/favicon.png differ diff --git a/web/icons/Icon-192.png b/web/icons/Icon-192.png new file mode 100644 index 0000000..b749bfe Binary files /dev/null and b/web/icons/Icon-192.png differ diff --git a/web/icons/Icon-512.png b/web/icons/Icon-512.png new file mode 100644 index 0000000..88cfd48 Binary files /dev/null and b/web/icons/Icon-512.png differ diff --git a/web/icons/Icon-maskable-192.png b/web/icons/Icon-maskable-192.png new file mode 100644 index 0000000..eb9b4d7 Binary files /dev/null and b/web/icons/Icon-maskable-192.png differ diff --git a/web/icons/Icon-maskable-512.png b/web/icons/Icon-maskable-512.png new file mode 100644 index 0000000..d69c566 Binary files /dev/null and b/web/icons/Icon-maskable-512.png differ diff --git a/web/index.html b/web/index.html new file mode 100644 index 0000000..28d3702 --- /dev/null +++ b/web/index.html @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + etm_powersync_app + + + + + + + diff --git a/web/manifest.json b/web/manifest.json new file mode 100644 index 0000000..3ed15cf --- /dev/null +++ b/web/manifest.json @@ -0,0 +1,35 @@ +{ + "name": "etm_powersync_app", + "short_name": "etm_powersync_app", + "start_url": ".", + "display": "standalone", + "background_color": "#0175C2", + "theme_color": "#0175C2", + "description": "A new Flutter project.", + "orientation": "portrait-primary", + "prefer_related_applications": false, + "icons": [ + { + "src": "icons/Icon-192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "icons/Icon-512.png", + "sizes": "512x512", + "type": "image/png" + }, + { + "src": "icons/Icon-maskable-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "maskable" + }, + { + "src": "icons/Icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/windows/.gitignore b/windows/.gitignore new file mode 100644 index 0000000..d492d0d --- /dev/null +++ b/windows/.gitignore @@ -0,0 +1,17 @@ +flutter/ephemeral/ + +# Visual Studio user-specific files. +*.suo +*.user +*.userosscache +*.sln.docstates + +# Visual Studio build-related files. +x64/ +x86/ + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ diff --git a/windows/CMakeLists.txt b/windows/CMakeLists.txt new file mode 100644 index 0000000..b36e2a6 --- /dev/null +++ b/windows/CMakeLists.txt @@ -0,0 +1,108 @@ +# Project-level configuration. +cmake_minimum_required(VERSION 3.14) +project(etm_powersync_app LANGUAGES CXX) + +# The name of the executable created for the application. Change this to change +# the on-disk name of your application. +set(BINARY_NAME "etm_powersync_app") + +# Explicitly opt in to modern CMake behaviors to avoid warnings with recent +# versions of CMake. +cmake_policy(VERSION 3.14...3.25) + +# Define build configuration option. +get_property(IS_MULTICONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) +if(IS_MULTICONFIG) + set(CMAKE_CONFIGURATION_TYPES "Debug;Profile;Release" + CACHE STRING "" FORCE) +else() + if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) + set(CMAKE_BUILD_TYPE "Debug" CACHE + STRING "Flutter build mode" FORCE) + set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + "Debug" "Profile" "Release") + endif() +endif() +# Define settings for the Profile build mode. +set(CMAKE_EXE_LINKER_FLAGS_PROFILE "${CMAKE_EXE_LINKER_FLAGS_RELEASE}") +set(CMAKE_SHARED_LINKER_FLAGS_PROFILE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILE "${CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_PROFILE "${CMAKE_CXX_FLAGS_RELEASE}") + +# Use Unicode for all projects. +add_definitions(-DUNICODE -D_UNICODE) + +# Compilation settings that should be applied to most targets. +# +# Be cautious about adding new options here, as plugins use this function by +# default. In most cases, you should add new options to specific targets instead +# of modifying this function. +function(APPLY_STANDARD_SETTINGS TARGET) + target_compile_features(${TARGET} PUBLIC cxx_std_17) + target_compile_options(${TARGET} PRIVATE /W4 /WX /wd"4100") + target_compile_options(${TARGET} PRIVATE /EHsc) + target_compile_definitions(${TARGET} PRIVATE "_HAS_EXCEPTIONS=0") + target_compile_definitions(${TARGET} PRIVATE "$<$:_DEBUG>") +endfunction() + +# Flutter library and tool build rules. +set(FLUTTER_MANAGED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/flutter") +add_subdirectory(${FLUTTER_MANAGED_DIR}) + +# Application build; see runner/CMakeLists.txt. +add_subdirectory("runner") + + +# Generated plugin build rules, which manage building the plugins and adding +# them to the application. +include(flutter/generated_plugins.cmake) + + +# === Installation === +# Support files are copied into place next to the executable, so that it can +# run in place. This is done instead of making a separate bundle (as on Linux) +# so that building and running from within Visual Studio will work. +set(BUILD_BUNDLE_DIR "$") +# Make the "install" step default, as it's required to run. +set(CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD 1) +if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) + set(CMAKE_INSTALL_PREFIX "${BUILD_BUNDLE_DIR}" CACHE PATH "..." FORCE) +endif() + +set(INSTALL_BUNDLE_DATA_DIR "${CMAKE_INSTALL_PREFIX}/data") +set(INSTALL_BUNDLE_LIB_DIR "${CMAKE_INSTALL_PREFIX}") + +install(TARGETS ${BINARY_NAME} RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_ICU_DATA_FILE}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + COMPONENT Runtime) + +install(FILES "${FLUTTER_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +if(PLUGIN_BUNDLED_LIBRARIES) + install(FILES "${PLUGIN_BUNDLED_LIBRARIES}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) +endif() + +# Copy the native assets provided by the build.dart from all packages. +set(NATIVE_ASSETS_DIR "${PROJECT_BUILD_DIR}native_assets/windows/") +install(DIRECTORY "${NATIVE_ASSETS_DIR}" + DESTINATION "${INSTALL_BUNDLE_LIB_DIR}" + COMPONENT Runtime) + +# Fully re-copy the assets directory on each build to avoid having stale files +# from a previous install. +set(FLUTTER_ASSET_DIR_NAME "flutter_assets") +install(CODE " + file(REMOVE_RECURSE \"${INSTALL_BUNDLE_DATA_DIR}/${FLUTTER_ASSET_DIR_NAME}\") + " COMPONENT Runtime) +install(DIRECTORY "${PROJECT_BUILD_DIR}/${FLUTTER_ASSET_DIR_NAME}" + DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" COMPONENT Runtime) + +# Install the AOT library on non-Debug builds only. +install(FILES "${AOT_LIBRARY}" DESTINATION "${INSTALL_BUNDLE_DATA_DIR}" + CONFIGURATIONS Profile;Release + COMPONENT Runtime) diff --git a/windows/flutter/CMakeLists.txt b/windows/flutter/CMakeLists.txt new file mode 100644 index 0000000..903f489 --- /dev/null +++ b/windows/flutter/CMakeLists.txt @@ -0,0 +1,109 @@ +# This file controls Flutter-level build steps. It should not be edited. +cmake_minimum_required(VERSION 3.14) + +set(EPHEMERAL_DIR "${CMAKE_CURRENT_SOURCE_DIR}/ephemeral") + +# Configuration provided via flutter tool. +include(${EPHEMERAL_DIR}/generated_config.cmake) + +# TODO: Move the rest of this into files in ephemeral. See +# https://github.com/flutter/flutter/issues/57146. +set(WRAPPER_ROOT "${EPHEMERAL_DIR}/cpp_client_wrapper") + +# Set fallback configurations for older versions of the flutter tool. +if (NOT DEFINED FLUTTER_TARGET_PLATFORM) + set(FLUTTER_TARGET_PLATFORM "windows-x64") +endif() + +# === Flutter Library === +set(FLUTTER_LIBRARY "${EPHEMERAL_DIR}/flutter_windows.dll") + +# Published to parent scope for install step. +set(FLUTTER_LIBRARY ${FLUTTER_LIBRARY} PARENT_SCOPE) +set(FLUTTER_ICU_DATA_FILE "${EPHEMERAL_DIR}/icudtl.dat" PARENT_SCOPE) +set(PROJECT_BUILD_DIR "${PROJECT_DIR}/build/" PARENT_SCOPE) +set(AOT_LIBRARY "${PROJECT_DIR}/build/windows/app.so" PARENT_SCOPE) + +list(APPEND FLUTTER_LIBRARY_HEADERS + "flutter_export.h" + "flutter_windows.h" + "flutter_messenger.h" + "flutter_plugin_registrar.h" + "flutter_texture_registrar.h" +) +list(TRANSFORM FLUTTER_LIBRARY_HEADERS PREPEND "${EPHEMERAL_DIR}/") +add_library(flutter INTERFACE) +target_include_directories(flutter INTERFACE + "${EPHEMERAL_DIR}" +) +target_link_libraries(flutter INTERFACE "${FLUTTER_LIBRARY}.lib") +add_dependencies(flutter flutter_assemble) + +# === Wrapper === +list(APPEND CPP_WRAPPER_SOURCES_CORE + "core_implementations.cc" + "standard_codec.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_CORE PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_PLUGIN + "plugin_registrar.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_PLUGIN PREPEND "${WRAPPER_ROOT}/") +list(APPEND CPP_WRAPPER_SOURCES_APP + "flutter_engine.cc" + "flutter_view_controller.cc" +) +list(TRANSFORM CPP_WRAPPER_SOURCES_APP PREPEND "${WRAPPER_ROOT}/") + +# Wrapper sources needed for a plugin. +add_library(flutter_wrapper_plugin STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} +) +apply_standard_settings(flutter_wrapper_plugin) +set_target_properties(flutter_wrapper_plugin PROPERTIES + POSITION_INDEPENDENT_CODE ON) +set_target_properties(flutter_wrapper_plugin PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_link_libraries(flutter_wrapper_plugin PUBLIC flutter) +target_include_directories(flutter_wrapper_plugin PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_plugin flutter_assemble) + +# Wrapper sources needed for the runner. +add_library(flutter_wrapper_app STATIC + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_APP} +) +apply_standard_settings(flutter_wrapper_app) +target_link_libraries(flutter_wrapper_app PUBLIC flutter) +target_include_directories(flutter_wrapper_app PUBLIC + "${WRAPPER_ROOT}/include" +) +add_dependencies(flutter_wrapper_app flutter_assemble) + +# === Flutter tool backend === +# _phony_ is a non-existent file to force this command to run every time, +# since currently there's no way to get a full input/output list from the +# flutter tool. +set(PHONY_OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/_phony_") +set_source_files_properties("${PHONY_OUTPUT}" PROPERTIES SYMBOLIC TRUE) +add_custom_command( + OUTPUT ${FLUTTER_LIBRARY} ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} + ${PHONY_OUTPUT} + COMMAND ${CMAKE_COMMAND} -E env + ${FLUTTER_TOOL_ENVIRONMENT} + "${FLUTTER_ROOT}/packages/flutter_tools/bin/tool_backend.bat" + ${FLUTTER_TARGET_PLATFORM} $ + VERBATIM +) +add_custom_target(flutter_assemble DEPENDS + "${FLUTTER_LIBRARY}" + ${FLUTTER_LIBRARY_HEADERS} + ${CPP_WRAPPER_SOURCES_CORE} + ${CPP_WRAPPER_SOURCES_PLUGIN} + ${CPP_WRAPPER_SOURCES_APP} +) diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc new file mode 100644 index 0000000..8b6d468 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void RegisterPlugins(flutter::PluginRegistry* registry) { +} diff --git a/windows/flutter/generated_plugin_registrant.h b/windows/flutter/generated_plugin_registrant.h new file mode 100644 index 0000000..dc139d8 --- /dev/null +++ b/windows/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void RegisterPlugins(flutter::PluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake new file mode 100644 index 0000000..b93c4c3 --- /dev/null +++ b/windows/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/windows plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/windows plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/windows/runner/CMakeLists.txt b/windows/runner/CMakeLists.txt new file mode 100644 index 0000000..394917c --- /dev/null +++ b/windows/runner/CMakeLists.txt @@ -0,0 +1,40 @@ +cmake_minimum_required(VERSION 3.14) +project(runner LANGUAGES CXX) + +# Define the application target. To change its name, change BINARY_NAME in the +# top-level CMakeLists.txt, not the value here, or `flutter run` will no longer +# work. +# +# Any new source files that you add to the application should be added here. +add_executable(${BINARY_NAME} WIN32 + "flutter_window.cpp" + "main.cpp" + "utils.cpp" + "win32_window.cpp" + "${FLUTTER_MANAGED_DIR}/generated_plugin_registrant.cc" + "Runner.rc" + "runner.exe.manifest" +) + +# Apply the standard set of build settings. This can be removed for applications +# that need different build settings. +apply_standard_settings(${BINARY_NAME}) + +# Add preprocessor definitions for the build version. +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION=\"${FLUTTER_VERSION}\"") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MAJOR=${FLUTTER_VERSION_MAJOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_MINOR=${FLUTTER_VERSION_MINOR}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_PATCH=${FLUTTER_VERSION_PATCH}") +target_compile_definitions(${BINARY_NAME} PRIVATE "FLUTTER_VERSION_BUILD=${FLUTTER_VERSION_BUILD}") + +# Disable Windows macros that collide with C++ standard library functions. +target_compile_definitions(${BINARY_NAME} PRIVATE "NOMINMAX") + +# Add dependency libraries and include directories. Add any application-specific +# dependencies here. +target_link_libraries(${BINARY_NAME} PRIVATE flutter flutter_wrapper_app) +target_link_libraries(${BINARY_NAME} PRIVATE "dwmapi.lib") +target_include_directories(${BINARY_NAME} PRIVATE "${CMAKE_SOURCE_DIR}") + +# Run the Flutter tool portions of the build. This must not be removed. +add_dependencies(${BINARY_NAME} flutter_assemble) diff --git a/windows/runner/Runner.rc b/windows/runner/Runner.rc new file mode 100644 index 0000000..2eedaaf --- /dev/null +++ b/windows/runner/Runner.rc @@ -0,0 +1,121 @@ +// Microsoft Visual C++ generated resource script. +// +#pragma code_page(65001) +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "winres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (United States) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#include ""winres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +IDI_APP_ICON ICON "resources\\app_icon.ico" + + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +#if defined(FLUTTER_VERSION_MAJOR) && defined(FLUTTER_VERSION_MINOR) && defined(FLUTTER_VERSION_PATCH) && defined(FLUTTER_VERSION_BUILD) +#define VERSION_AS_NUMBER FLUTTER_VERSION_MAJOR,FLUTTER_VERSION_MINOR,FLUTTER_VERSION_PATCH,FLUTTER_VERSION_BUILD +#else +#define VERSION_AS_NUMBER 1,0,0,0 +#endif + +#if defined(FLUTTER_VERSION) +#define VERSION_AS_STRING FLUTTER_VERSION +#else +#define VERSION_AS_STRING "1.0.0" +#endif + +VS_VERSION_INFO VERSIONINFO + FILEVERSION VERSION_AS_NUMBER + PRODUCTVERSION VERSION_AS_NUMBER + FILEFLAGSMASK VS_FFI_FILEFLAGSMASK +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_APP + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904e4" + BEGIN + VALUE "CompanyName", "com.example" "\0" + VALUE "FileDescription", "etm_powersync_app" "\0" + VALUE "FileVersion", VERSION_AS_STRING "\0" + VALUE "InternalName", "etm_powersync_app" "\0" + VALUE "LegalCopyright", "Copyright (C) 2026 com.example. All rights reserved." "\0" + VALUE "OriginalFilename", "etm_powersync_app.exe" "\0" + VALUE "ProductName", "etm_powersync_app" "\0" + VALUE "ProductVersion", VERSION_AS_STRING "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1252 + END +END + +#endif // English (United States) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED diff --git a/windows/runner/flutter_window.cpp b/windows/runner/flutter_window.cpp new file mode 100644 index 0000000..955ee30 --- /dev/null +++ b/windows/runner/flutter_window.cpp @@ -0,0 +1,71 @@ +#include "flutter_window.h" + +#include + +#include "flutter/generated_plugin_registrant.h" + +FlutterWindow::FlutterWindow(const flutter::DartProject& project) + : project_(project) {} + +FlutterWindow::~FlutterWindow() {} + +bool FlutterWindow::OnCreate() { + if (!Win32Window::OnCreate()) { + return false; + } + + RECT frame = GetClientArea(); + + // The size here must match the window dimensions to avoid unnecessary surface + // creation / destruction in the startup path. + flutter_controller_ = std::make_unique( + frame.right - frame.left, frame.bottom - frame.top, project_); + // Ensure that basic setup of the controller was successful. + if (!flutter_controller_->engine() || !flutter_controller_->view()) { + return false; + } + RegisterPlugins(flutter_controller_->engine()); + SetChildContent(flutter_controller_->view()->GetNativeWindow()); + + flutter_controller_->engine()->SetNextFrameCallback([&]() { + this->Show(); + }); + + // Flutter can complete the first frame before the "show window" callback is + // registered. The following call ensures a frame is pending to ensure the + // window is shown. It is a no-op if the first frame hasn't completed yet. + flutter_controller_->ForceRedraw(); + + return true; +} + +void FlutterWindow::OnDestroy() { + if (flutter_controller_) { + flutter_controller_ = nullptr; + } + + Win32Window::OnDestroy(); +} + +LRESULT +FlutterWindow::MessageHandler(HWND hwnd, UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + // Give Flutter, including plugins, an opportunity to handle window messages. + if (flutter_controller_) { + std::optional result = + flutter_controller_->HandleTopLevelWindowProc(hwnd, message, wparam, + lparam); + if (result) { + return *result; + } + } + + switch (message) { + case WM_FONTCHANGE: + flutter_controller_->engine()->ReloadSystemFonts(); + break; + } + + return Win32Window::MessageHandler(hwnd, message, wparam, lparam); +} diff --git a/windows/runner/flutter_window.h b/windows/runner/flutter_window.h new file mode 100644 index 0000000..6da0652 --- /dev/null +++ b/windows/runner/flutter_window.h @@ -0,0 +1,33 @@ +#ifndef RUNNER_FLUTTER_WINDOW_H_ +#define RUNNER_FLUTTER_WINDOW_H_ + +#include +#include + +#include + +#include "win32_window.h" + +// A window that does nothing but host a Flutter view. +class FlutterWindow : public Win32Window { + public: + // Creates a new FlutterWindow hosting a Flutter view running |project|. + explicit FlutterWindow(const flutter::DartProject& project); + virtual ~FlutterWindow(); + + protected: + // Win32Window: + bool OnCreate() override; + void OnDestroy() override; + LRESULT MessageHandler(HWND window, UINT const message, WPARAM const wparam, + LPARAM const lparam) noexcept override; + + private: + // The project to run. + flutter::DartProject project_; + + // The Flutter instance hosted by this window. + std::unique_ptr flutter_controller_; +}; + +#endif // RUNNER_FLUTTER_WINDOW_H_ diff --git a/windows/runner/main.cpp b/windows/runner/main.cpp new file mode 100644 index 0000000..572e5bd --- /dev/null +++ b/windows/runner/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +#include "flutter_window.h" +#include "utils.h" + +int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev, + _In_ wchar_t *command_line, _In_ int show_command) { + // Attach to console when present (e.g., 'flutter run') or create a + // new console when running with a debugger. + if (!::AttachConsole(ATTACH_PARENT_PROCESS) && ::IsDebuggerPresent()) { + CreateAndAttachConsole(); + } + + // Initialize COM, so that it is available for use in the library and/or + // plugins. + ::CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); + + flutter::DartProject project(L"data"); + + std::vector command_line_arguments = + GetCommandLineArguments(); + + project.set_dart_entrypoint_arguments(std::move(command_line_arguments)); + + FlutterWindow window(project); + Win32Window::Point origin(10, 10); + Win32Window::Size size(1280, 720); + if (!window.Create(L"etm_powersync_app", origin, size)) { + return EXIT_FAILURE; + } + window.SetQuitOnClose(true); + + ::MSG msg; + while (::GetMessage(&msg, nullptr, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + + ::CoUninitialize(); + return EXIT_SUCCESS; +} diff --git a/windows/runner/resource.h b/windows/runner/resource.h new file mode 100644 index 0000000..66a65d1 --- /dev/null +++ b/windows/runner/resource.h @@ -0,0 +1,16 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Runner.rc +// +#define IDI_APP_ICON 101 + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff --git a/windows/runner/resources/app_icon.ico b/windows/runner/resources/app_icon.ico new file mode 100644 index 0000000..c04e20c Binary files /dev/null and b/windows/runner/resources/app_icon.ico differ diff --git a/windows/runner/runner.exe.manifest b/windows/runner/runner.exe.manifest new file mode 100644 index 0000000..153653e --- /dev/null +++ b/windows/runner/runner.exe.manifest @@ -0,0 +1,14 @@ + + + + + PerMonitorV2 + + + + + + + + + diff --git a/windows/runner/utils.cpp b/windows/runner/utils.cpp new file mode 100644 index 0000000..3a0b465 --- /dev/null +++ b/windows/runner/utils.cpp @@ -0,0 +1,65 @@ +#include "utils.h" + +#include +#include +#include +#include + +#include + +void CreateAndAttachConsole() { + if (::AllocConsole()) { + FILE *unused; + if (freopen_s(&unused, "CONOUT$", "w", stdout)) { + _dup2(_fileno(stdout), 1); + } + if (freopen_s(&unused, "CONOUT$", "w", stderr)) { + _dup2(_fileno(stdout), 2); + } + std::ios::sync_with_stdio(); + FlutterDesktopResyncOutputStreams(); + } +} + +std::vector GetCommandLineArguments() { + // Convert the UTF-16 command line arguments to UTF-8 for the Engine to use. + int argc; + wchar_t** argv = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + if (argv == nullptr) { + return std::vector(); + } + + std::vector command_line_arguments; + + // Skip the first argument as it's the binary name. + for (int i = 1; i < argc; i++) { + command_line_arguments.push_back(Utf8FromUtf16(argv[i])); + } + + ::LocalFree(argv); + + return command_line_arguments; +} + +std::string Utf8FromUtf16(const wchar_t* utf16_string) { + if (utf16_string == nullptr) { + return std::string(); + } + unsigned int target_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + -1, nullptr, 0, nullptr, nullptr) + -1; // remove the trailing null character + int input_length = (int)wcslen(utf16_string); + std::string utf8_string; + if (target_length == 0 || target_length > utf8_string.max_size()) { + return utf8_string; + } + utf8_string.resize(target_length); + int converted_length = ::WideCharToMultiByte( + CP_UTF8, WC_ERR_INVALID_CHARS, utf16_string, + input_length, utf8_string.data(), target_length, nullptr, nullptr); + if (converted_length == 0) { + return std::string(); + } + return utf8_string; +} diff --git a/windows/runner/utils.h b/windows/runner/utils.h new file mode 100644 index 0000000..3879d54 --- /dev/null +++ b/windows/runner/utils.h @@ -0,0 +1,19 @@ +#ifndef RUNNER_UTILS_H_ +#define RUNNER_UTILS_H_ + +#include +#include + +// Creates a console for the process, and redirects stdout and stderr to +// it for both the runner and the Flutter library. +void CreateAndAttachConsole(); + +// Takes a null-terminated wchar_t* encoded in UTF-16 and returns a std::string +// encoded in UTF-8. Returns an empty std::string on failure. +std::string Utf8FromUtf16(const wchar_t* utf16_string); + +// Gets the command line arguments passed in as a std::vector, +// encoded in UTF-8. Returns an empty std::vector on failure. +std::vector GetCommandLineArguments(); + +#endif // RUNNER_UTILS_H_ diff --git a/windows/runner/win32_window.cpp b/windows/runner/win32_window.cpp new file mode 100644 index 0000000..60608d0 --- /dev/null +++ b/windows/runner/win32_window.cpp @@ -0,0 +1,288 @@ +#include "win32_window.h" + +#include +#include + +#include "resource.h" + +namespace { + +/// Window attribute that enables dark mode window decorations. +/// +/// Redefined in case the developer's machine has a Windows SDK older than +/// version 10.0.22000.0. +/// See: https://docs.microsoft.com/windows/win32/api/dwmapi/ne-dwmapi-dwmwindowattribute +#ifndef DWMWA_USE_IMMERSIVE_DARK_MODE +#define DWMWA_USE_IMMERSIVE_DARK_MODE 20 +#endif + +constexpr const wchar_t kWindowClassName[] = L"FLUTTER_RUNNER_WIN32_WINDOW"; + +/// Registry key for app theme preference. +/// +/// A value of 0 indicates apps should use dark mode. A non-zero or missing +/// value indicates apps should use light mode. +constexpr const wchar_t kGetPreferredBrightnessRegKey[] = + L"Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"; +constexpr const wchar_t kGetPreferredBrightnessRegValue[] = L"AppsUseLightTheme"; + +// The number of Win32Window objects that currently exist. +static int g_active_window_count = 0; + +using EnableNonClientDpiScaling = BOOL __stdcall(HWND hwnd); + +// Scale helper to convert logical scaler values to physical using passed in +// scale factor +int Scale(int source, double scale_factor) { + return static_cast(source * scale_factor); +} + +// Dynamically loads the |EnableNonClientDpiScaling| from the User32 module. +// This API is only needed for PerMonitor V1 awareness mode. +void EnableFullDpiSupportIfAvailable(HWND hwnd) { + HMODULE user32_module = LoadLibraryA("User32.dll"); + if (!user32_module) { + return; + } + auto enable_non_client_dpi_scaling = + reinterpret_cast( + GetProcAddress(user32_module, "EnableNonClientDpiScaling")); + if (enable_non_client_dpi_scaling != nullptr) { + enable_non_client_dpi_scaling(hwnd); + } + FreeLibrary(user32_module); +} + +} // namespace + +// Manages the Win32Window's window class registration. +class WindowClassRegistrar { + public: + ~WindowClassRegistrar() = default; + + // Returns the singleton registrar instance. + static WindowClassRegistrar* GetInstance() { + if (!instance_) { + instance_ = new WindowClassRegistrar(); + } + return instance_; + } + + // Returns the name of the window class, registering the class if it hasn't + // previously been registered. + const wchar_t* GetWindowClass(); + + // Unregisters the window class. Should only be called if there are no + // instances of the window. + void UnregisterWindowClass(); + + private: + WindowClassRegistrar() = default; + + static WindowClassRegistrar* instance_; + + bool class_registered_ = false; +}; + +WindowClassRegistrar* WindowClassRegistrar::instance_ = nullptr; + +const wchar_t* WindowClassRegistrar::GetWindowClass() { + if (!class_registered_) { + WNDCLASS window_class{}; + window_class.hCursor = LoadCursor(nullptr, IDC_ARROW); + window_class.lpszClassName = kWindowClassName; + window_class.style = CS_HREDRAW | CS_VREDRAW; + window_class.cbClsExtra = 0; + window_class.cbWndExtra = 0; + window_class.hInstance = GetModuleHandle(nullptr); + window_class.hIcon = + LoadIcon(window_class.hInstance, MAKEINTRESOURCE(IDI_APP_ICON)); + window_class.hbrBackground = 0; + window_class.lpszMenuName = nullptr; + window_class.lpfnWndProc = Win32Window::WndProc; + RegisterClass(&window_class); + class_registered_ = true; + } + return kWindowClassName; +} + +void WindowClassRegistrar::UnregisterWindowClass() { + UnregisterClass(kWindowClassName, nullptr); + class_registered_ = false; +} + +Win32Window::Win32Window() { + ++g_active_window_count; +} + +Win32Window::~Win32Window() { + --g_active_window_count; + Destroy(); +} + +bool Win32Window::Create(const std::wstring& title, + const Point& origin, + const Size& size) { + Destroy(); + + const wchar_t* window_class = + WindowClassRegistrar::GetInstance()->GetWindowClass(); + + const POINT target_point = {static_cast(origin.x), + static_cast(origin.y)}; + HMONITOR monitor = MonitorFromPoint(target_point, MONITOR_DEFAULTTONEAREST); + UINT dpi = FlutterDesktopGetDpiForMonitor(monitor); + double scale_factor = dpi / 96.0; + + HWND window = CreateWindow( + window_class, title.c_str(), WS_OVERLAPPEDWINDOW, + Scale(origin.x, scale_factor), Scale(origin.y, scale_factor), + Scale(size.width, scale_factor), Scale(size.height, scale_factor), + nullptr, nullptr, GetModuleHandle(nullptr), this); + + if (!window) { + return false; + } + + UpdateTheme(window); + + return OnCreate(); +} + +bool Win32Window::Show() { + return ShowWindow(window_handle_, SW_SHOWNORMAL); +} + +// static +LRESULT CALLBACK Win32Window::WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + if (message == WM_NCCREATE) { + auto window_struct = reinterpret_cast(lparam); + SetWindowLongPtr(window, GWLP_USERDATA, + reinterpret_cast(window_struct->lpCreateParams)); + + auto that = static_cast(window_struct->lpCreateParams); + EnableFullDpiSupportIfAvailable(window); + that->window_handle_ = window; + } else if (Win32Window* that = GetThisFromHandle(window)) { + return that->MessageHandler(window, message, wparam, lparam); + } + + return DefWindowProc(window, message, wparam, lparam); +} + +LRESULT +Win32Window::MessageHandler(HWND hwnd, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept { + switch (message) { + case WM_DESTROY: + window_handle_ = nullptr; + Destroy(); + if (quit_on_close_) { + PostQuitMessage(0); + } + return 0; + + case WM_DPICHANGED: { + auto newRectSize = reinterpret_cast(lparam); + LONG newWidth = newRectSize->right - newRectSize->left; + LONG newHeight = newRectSize->bottom - newRectSize->top; + + SetWindowPos(hwnd, nullptr, newRectSize->left, newRectSize->top, newWidth, + newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + return 0; + } + case WM_SIZE: { + RECT rect = GetClientArea(); + if (child_content_ != nullptr) { + // Size and position the child window. + MoveWindow(child_content_, rect.left, rect.top, rect.right - rect.left, + rect.bottom - rect.top, TRUE); + } + return 0; + } + + case WM_ACTIVATE: + if (child_content_ != nullptr) { + SetFocus(child_content_); + } + return 0; + + case WM_DWMCOLORIZATIONCOLORCHANGED: + UpdateTheme(hwnd); + return 0; + } + + return DefWindowProc(window_handle_, message, wparam, lparam); +} + +void Win32Window::Destroy() { + OnDestroy(); + + if (window_handle_) { + DestroyWindow(window_handle_); + window_handle_ = nullptr; + } + if (g_active_window_count == 0) { + WindowClassRegistrar::GetInstance()->UnregisterWindowClass(); + } +} + +Win32Window* Win32Window::GetThisFromHandle(HWND const window) noexcept { + return reinterpret_cast( + GetWindowLongPtr(window, GWLP_USERDATA)); +} + +void Win32Window::SetChildContent(HWND content) { + child_content_ = content; + SetParent(content, window_handle_); + RECT frame = GetClientArea(); + + MoveWindow(content, frame.left, frame.top, frame.right - frame.left, + frame.bottom - frame.top, true); + + SetFocus(child_content_); +} + +RECT Win32Window::GetClientArea() { + RECT frame; + GetClientRect(window_handle_, &frame); + return frame; +} + +HWND Win32Window::GetHandle() { + return window_handle_; +} + +void Win32Window::SetQuitOnClose(bool quit_on_close) { + quit_on_close_ = quit_on_close; +} + +bool Win32Window::OnCreate() { + // No-op; provided for subclasses. + return true; +} + +void Win32Window::OnDestroy() { + // No-op; provided for subclasses. +} + +void Win32Window::UpdateTheme(HWND const window) { + DWORD light_mode; + DWORD light_mode_size = sizeof(light_mode); + LSTATUS result = RegGetValue(HKEY_CURRENT_USER, kGetPreferredBrightnessRegKey, + kGetPreferredBrightnessRegValue, + RRF_RT_REG_DWORD, nullptr, &light_mode, + &light_mode_size); + + if (result == ERROR_SUCCESS) { + BOOL enable_dark_mode = light_mode == 0; + DwmSetWindowAttribute(window, DWMWA_USE_IMMERSIVE_DARK_MODE, + &enable_dark_mode, sizeof(enable_dark_mode)); + } +} diff --git a/windows/runner/win32_window.h b/windows/runner/win32_window.h new file mode 100644 index 0000000..e901dde --- /dev/null +++ b/windows/runner/win32_window.h @@ -0,0 +1,102 @@ +#ifndef RUNNER_WIN32_WINDOW_H_ +#define RUNNER_WIN32_WINDOW_H_ + +#include + +#include +#include +#include + +// A class abstraction for a high DPI-aware Win32 Window. Intended to be +// inherited from by classes that wish to specialize with custom +// rendering and input handling +class Win32Window { + public: + struct Point { + unsigned int x; + unsigned int y; + Point(unsigned int x, unsigned int y) : x(x), y(y) {} + }; + + struct Size { + unsigned int width; + unsigned int height; + Size(unsigned int width, unsigned int height) + : width(width), height(height) {} + }; + + Win32Window(); + virtual ~Win32Window(); + + // Creates a win32 window with |title| that is positioned and sized using + // |origin| and |size|. New windows are created on the default monitor. Window + // sizes are specified to the OS in physical pixels, hence to ensure a + // consistent size this function will scale the inputted width and height as + // as appropriate for the default monitor. The window is invisible until + // |Show| is called. Returns true if the window was created successfully. + bool Create(const std::wstring& title, const Point& origin, const Size& size); + + // Show the current window. Returns true if the window was successfully shown. + bool Show(); + + // Release OS resources associated with window. + void Destroy(); + + // Inserts |content| into the window tree. + void SetChildContent(HWND content); + + // Returns the backing Window handle to enable clients to set icon and other + // window properties. Returns nullptr if the window has been destroyed. + HWND GetHandle(); + + // If true, closing this window will quit the application. + void SetQuitOnClose(bool quit_on_close); + + // Return a RECT representing the bounds of the current client area. + RECT GetClientArea(); + + protected: + // Processes and route salient window messages for mouse handling, + // size change and DPI. Delegates handling of these to member overloads that + // inheriting classes can handle. + virtual LRESULT MessageHandler(HWND window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Called when CreateAndShow is called, allowing subclass window-related + // setup. Subclasses should return false if setup fails. + virtual bool OnCreate(); + + // Called when Destroy is called. + virtual void OnDestroy(); + + private: + friend class WindowClassRegistrar; + + // OS callback called by message pump. Handles the WM_NCCREATE message which + // is passed when the non-client area is being created and enables automatic + // non-client DPI scaling so that the non-client area automatically + // responds to changes in DPI. All other messages are handled by + // MessageHandler. + static LRESULT CALLBACK WndProc(HWND const window, + UINT const message, + WPARAM const wparam, + LPARAM const lparam) noexcept; + + // Retrieves a class instance pointer for |window| + static Win32Window* GetThisFromHandle(HWND const window) noexcept; + + // Update the window frame's theme to match the system theme. + static void UpdateTheme(HWND const window); + + bool quit_on_close_ = false; + + // window handle for top level window. + HWND window_handle_ = nullptr; + + // window handle for hosted content. + HWND child_content_ = nullptr; +}; + +#endif // RUNNER_WIN32_WINDOW_H_