### Python Discovery Strategy Example Source: https://apps.developer.homey.app/~/changes/1149/wireless/wi-fi/discovery This Python example shows how to fetch previously discovered devices and set up a listener for new discovery results. Ensure the 'homey' Python SDK is installed. ```python from typing import cast from homey import app from homey.discovery_result_mac import DiscoveryResultMAC class App(app.App): async def on_init(self) -> None: discovery_strategy = self.homey.discovery.get_strategy("my_strategy") initial_discovery_results = discovery_strategy.get_discovery_results() for discovery_result in initial_discovery_results.values(): self.handle_discovery_result(cast(DiscoveryResultMAC, discovery_result)) discovery_strategy.on("result", self.handle_discovery_result) def handle_discovery_result(self, discovery_result: DiscoveryResultMAC): self.log("Got result:", discovery_result) homey_export = App ``` -------------------------------- ### Dynamic Documentation Query Example Source: https://apps.developer.homey.app/~/changes/1149/cloud/webhooks This example demonstrates how to perform an HTTP GET request to dynamically query the documentation. By appending the 'ask' query parameter with a natural language question, you can retrieve specific answers and relevant excerpts from the documentation. ```http GET https://apps.developer.homey.app/~/changes/1149/cloud/webhooks.md?ask= ``` -------------------------------- ### Example GET Request with `ask` Parameter Source: https://apps.developer.homey.app/the-basics/devices/pairing/system-views/oauth2-login Perform an HTTP GET request to the current page URL with the `ask` query parameter to ask a specific question about the documentation. The response will contain a direct answer and relevant excerpts. ```http GET https://apps.developer.homey.app/the-basics/devices/pairing/system-views/oauth2-login.md?ask= ``` -------------------------------- ### JavaScript App Class Setup Source: https://apps.developer.homey.app/the-basics/app Instantiate shared resources like an API client within the `onInit` method of the App class. This ensures the client is created only once when the app starts. ```javascript const Homey = require('homey'); const ApiClient = require('your-external-api-client'); class App extends Homey.App { async onInit() { // create an ApiClient once when the app is started this.client = new ApiClient(); } } module.exports = App; ``` -------------------------------- ### JavaScript Device Store Example Source: https://apps.developer.homey.app/the-basics/devices Demonstrates how to get and set store values in JavaScript. Use `getStoreValue` to retrieve a value and `setStoreValue` to save it. Errors during saving are caught and logged. ```javascript const Homey = require("homey"); const DeviceApi = require("device-api"); class Device extends Homey.Device { async onInit() { this.currentAddress = this.getStoreValue("address"); DeviceApi.on("address-changed", (address) => { this.currentAddress = address; this.setStoreValue("address", address).catch(this.error); }); } } module.exports = Device; ``` -------------------------------- ### RTMP Camera Setup (TypeScript) Source: https://apps.developer.homey.app/advanced/videos This TypeScript example shows how to initialize an RTMP video stream for a Homey device. It includes setting up a URL listener and attaching the camera video, similar to the JavaScript version. ```typescript import Homey from "homey"; export default class Device extends Homey.Device { async onInit(): Promise { try { const video = await this.homey.videos.createVideoRTMP(); /* * The video url listener takes no arguments. It simply builds the * URL to the RTMP stream. */ video.registerVideoUrlListener(async () => { // Normally, you would get the device's IP from Discovery, or another method return { url: `rtmp://@192.168.1.100:1935`, }; }); /* * Attach the camera to the device. */ await this.setCameraVideo("main", "Main Camera", video); } catch (err) { this.error("Error creating camera:", err); } } } ``` -------------------------------- ### TypeScript Device Trigger Card Setup Source: https://apps.developer.homey.app/~/changes/1149/the-basics/flow Set up a device-specific trigger card using TypeScript. This example demonstrates obtaining the trigger card and initiating a flow from a device instance. ```typescript import Homey, { FlowCardTriggerDevice } from 'homey'; import type Device from './device.mjs'; export default class Driver extends Homey.Driver { private deviceTurnedOn?: FlowCardTriggerDevice; async onInit(): Promise { this.deviceTurnedOn = this.homey.flow.getDeviceTriggerCard('turned_on'); } triggerMyFlow(device: Device, tokens: object, state: object): void { this.deviceTurnedOn?.trigger(device, tokens, state); } } ``` ```typescript import Homey from 'homey'; import type Driver from './driver.mjs'; export default class Device extends Homey.Device { async onInit(): Promise { (this.driver as Driver).triggerMyFlow(this, {}, {}); } } ``` -------------------------------- ### Python WebRTC Camera Setup (Partial) Source: https://apps.developer.homey.app/advanced/videos This Python code snippet outlines the setup for a WebRTC camera device, including comments on data channel requirements and stream keep-alive mechanisms. It serves as a starting point for implementing WebRTC functionality in Python. ```python from homey import device from homey.video_web_rtc import WebRTCAnswer from .oauth2_client import OAuth2Client class Device(device.Device): oauth2_client: OAuth2Client """ Some cameras require a data channel in order to work, while other cameras only work when the offer does not contain a data channel. This can be customized through the options object in the createCamera method. There are also cameras that only keep their stream open for a few minutes. These can often be extended through an API call. The keep alive listener can be used to send such a request. """ ``` -------------------------------- ### Trigger Rain Start Flow (Python) Source: https://apps.developer.homey.app/the-basics/flow This Python example illustrates how to retrieve the 'rain_start' trigger card and execute it when rain is detected, using the 'rain-api' library. ```python from homey import app from rain_api import RainApi class App(app.App): async def on_init(self) -> None: rain_start_trigger_card = self.homey.flow.get_trigger_card("rain_start") async def on_raining(): await rain_start_trigger_card.trigger() RainApi.on("raining", on_raining) homey_export = App ``` -------------------------------- ### Query Documentation API Source: https://apps.developer.homey.app/wireless/zigbee/zigbee-firmware-updates Example of how to dynamically query documentation using an HTTP GET request with the `ask` query parameter. This is useful for retrieving specific information not explicitly present on the page. ```http GET https://apps.developer.homey.app/wireless/zigbee/zigbee-firmware-updates.md?ask= ``` -------------------------------- ### Z-Wave Device Initialization and Basic Commands (Python) Source: https://apps.developer.homey.app/wireless/z-wave Initializes a Z-Wave device in Python, retrieves its node, gets the BASIC status, and registers for report events. This example demonstrates Pythonic async/await patterns for Z-Wave interaction. ```python from homey import device class Device(device.Device): async def on_init(self) -> None: # get the node by our Device's instance node = await self.homey.zwave.get_node(self) # get the BASIC status try: result = await node.command_classes["COMMAND_CLASS_BASIC"].send_command( "BASIC_GET" ) if result.Value: self.log("Device is turned on") else: self.log("Device is turned off") except Exception as e: self.error(e) # battery nodes can emit an 'online' event when they're available # you can send commands within 10s of this event, before the node goes to sleep again def on_online(online: bool) -> None: if online: self.log("Device is online") else: self.log("Device is offline") node.on("online", on_online) # register for 'report' events def on_report(command, report) -> None: self.log(command.name) # e.g. BASIC_REPORT self.log(report) # e.g. { Value: true } node.command_classes["COMMAND_CLASS_BASIC"].on("report", on_report) homey_export = Device ``` -------------------------------- ### Matter Driver Manifest Example Source: https://apps.developer.homey.app/wireless/matter Example `driver.compose.json` for a Matter device, including vendor and product IDs, and pairing instructions. ```json { "name": { "en": "My Driver" }, "platforms": ["local"], "connectivity": ["matter"], "class": "socket", "capabilities": ["onoff", "dim"], "matter": { "vendorId": 1234, "productId": 4567, "learnmode": { "instruction": { "en": "Press the button on your device three times" }, "image": "/drivers//assets/learnmode.svg" } } } ``` -------------------------------- ### Python App Class Setup Source: https://apps.developer.homey.app/the-basics/app Instantiate shared resources like an API client within the `on_init` method of the Python App class. This ensures the client is created only once when the app starts. ```python from homey import app from your_external_api_client import ApiClient class App(app.App): client: ApiClient async def on_init(self) -> None: # create an ApiClient once when the app is started self.client = ApiClient() homey_export = App ``` -------------------------------- ### Install homey-rfdriver Source: https://apps.developer.homey.app/wireless/infrared Install the necessary Node.js library for Infrared device support. ```bash npm install homey-rfdriver ``` -------------------------------- ### Install homey-zwavedriver Source: https://apps.developer.homey.app/wireless/z-wave Install the `homey-zwavedriver` library using npm. This library is compatible with SDK version 3. ```bash npm install homey-zwavedriver ``` -------------------------------- ### TypeScript Discovery Strategy Example Source: https://apps.developer.homey.app/wireless/wi-fi/discovery This TypeScript example demonstrates how to retrieve existing discovery results and subscribe to new ones. The 'my_strategy' ID must correspond to your App Manifest configuration. ```typescript import Homey, { type DiscoveryResultMAC } from "homey"; export default class App extends Homey.App { async onInit(): Promise { const discoveryStrategy = this.homey.discovery.getStrategy("my_strategy"); // Use the discovery results that were already found const initialDiscoveryResults = discoveryStrategy.getDiscoveryResults() as { [id: string]: DiscoveryResultMAC }; for (const discoveryResult of Object.values(initialDiscoveryResults)) { this.handleDiscoveryResult(discoveryResult); } // And listen to new results while the app is running discoveryStrategy.on("result", (discoveryResult: DiscoveryResultMAC) => { this.handleDiscoveryResult(discoveryResult); }); } handleDiscoveryResult(discoveryResult: DiscoveryResultMAC): void { this.log("Got result:", discoveryResult); } } ``` -------------------------------- ### JavaScript Discovery Strategy Example Source: https://apps.developer.homey.app/wireless/wi-fi/discovery Use this JavaScript snippet to get initial discovery results and listen for new ones using a discovery strategy. Ensure the 'my_strategy' ID matches your App Manifest. ```javascript const Homey = require('homey'); class App extends Homey.App { async onInit() { const discoveryStrategy = this.homey.discovery.getStrategy("my_strategy"); // Use the discovery results that were already found const initialDiscoveryResults = discoveryStrategy.getDiscoveryResults(); for (const discoveryResult of Object.values(initialDiscoveryResults)) { this.handleDiscoveryResult(discoveryResult); } // And listen to new results while the app is running discoveryStrategy.on("result", discoveryResult => { this.handleDiscoveryResult(discoveryResult); }); } handleDiscoveryResult(discoveryResult) { this.log("Got result:", discoveryResult); } } module.exports = App; ``` -------------------------------- ### Install Homey App Source: https://apps.developer.homey.app/the-basics/getting-started/homey-cli Installs your Homey app on Homey without requiring a persistent command. Useful for long-term testing, but does not provide live console output. ```bash homey app install ``` -------------------------------- ### Querying Documentation via HTTP GET Source: https://apps.developer.homey.app/cloud/webhooks Demonstrates how to dynamically query Homey's documentation using an HTTP GET request with the 'ask' query parameter. This is useful for retrieving specific information not explicitly present on the page. ```http GET https://apps.developer.homey.app/cloud/webhooks.md?ask= ``` -------------------------------- ### Install TypeScript Utilities Source: https://apps.developer.homey.app/the-basics/getting-started/homey-cli Installs all necessary packages for using TypeScript within your Homey app. Refer to the TypeScript guide for more details. ```bash homey app add-types ``` -------------------------------- ### Trigger Rain Start Flow (JavaScript) Source: https://apps.developer.homey.app/the-basics/flow This snippet shows how to get a trigger card for 'rain_start' and trigger it when rain starts, using the 'rain-api' library. ```javascript const Homey = require('homey'); const RainApi = require('rain-api'); class App extends Homey.App { async onInit() { const rainStartTrigger = this.homey.flow.getTriggerCard('rain_start'); RainApi.on('raining', () => { await rainStartTrigger.trigger(); }); } } module.exports = App; ``` -------------------------------- ### Example Capabilities Displayed Source: https://apps.developer.homey.app/the-basics/devices/capabilities Illustrates how capabilities like 'meter_power', 'measure_battery', and 'alarm_motion' are displayed. Note that 'measure_battery' uses a custom icon. ```text meter_power, measure_battery, alarm_motion ``` -------------------------------- ### Initialize Driver with SDK v3 Source: https://apps.developer.homey.app/upgrade-guides/upgrading-to-sdk-v3 Example of initializing a driver in SDK v3, demonstrating the use of `this.homey` to access Flow cards and images, and utilizing `async/await`. ```javascript const Homey = require("homey"); class Driver extends Homey.Driver { async onInit() { this.rainingCondition = this.homey.flow.getConditionCard("is_raining"); this.myImage = await this.homey.images.createImage(); this.myImage.setUrl("https://www.example.com/image.png"); } } module.exports = Driver; ``` -------------------------------- ### Interact with Web API: GET Request (Python) Source: https://apps.developer.homey.app/~/changes/1149/advanced/web-api Demonstrates making a GET request to another app's API. Ensure the target app is installed and compatible before use. ```python from homey import app from homey.api_app import ApiApp class App(app.App): other_app_api: ApiApp async def on_init(self) -> None: self.other_app_api = self.homey.api.get_api_app("com.athom.otherApp") # Make a get request to "otherApp"s API get_response = await self.other_app_api.get("/") ``` -------------------------------- ### Basic ZigBeeDevice Initialization Source: https://apps.developer.homey.app/wireless/zigbee Example of extending the ZigBeeDevice class and toggling the onOff cluster on node initialization. Always catch Promises in onNodeInit. ```javascript const { ZigBeeDevice } = require("homey-zigbeedriver"); class Device extends ZigBeeDevice { async onNodeInit({ zclNode }) { await zclNode.endpoints[1].clusters.onOff.toggle() .catch(err => { this.error(err); /* Always catch Promises, especially in onNodeInit */ }); } } module.exports = Device; ``` -------------------------------- ### Get ApiApp Client and Subscribe to Events (Python) Source: https://apps.developer.homey.app/~/changes/1149/advanced/web-api Instantiates an `ApiApp` client for 'com.athom.otherApp' and subscribes to its install and uninstall events. Use this to monitor the lifecycle of another app. ```python from homey import app from homey.api_app import ApiApp class App(app.App): other_app_api: ApiApp async def on_init(self) -> None: self.other_app_api = self.homey.api.get_api_app("com.athom.otherApp") is_installed = await self.other_app_api.get_installed() version = await self.other_app_api.get_version() def on_install(): print("otherApp is installed") self.other_app_api.on_install(on_install) def on_uninstall(): print("otherApp is uninstalled") self.other_app_api.on_uninstall(on_uninstall) homey_export = App ``` -------------------------------- ### Trigger Flow with Local Tokens (JavaScript) Source: https://apps.developer.homey.app/~/changes/1149/the-basics/flow/tokens This JavaScript code snippet shows how to get a trigger card and fire it with 'mm_per_hour' and 'city' tokens. Ensure the 'rain-api' is installed and configured. ```javascript const Homey = require('homey'); const RainApi = require('rain-api'); class App extends Homey.App { async onInit() { const rainStartTrigger = this.homey.flow.getTriggerCard("rain_start"); RainApi.on('raining', (city, amount) => { const tokens = { mm_per_hour: amount, city: city }; rainStartTrigger.trigger(tokens) .then(this.log) .catch(this.error); }); } } ``` -------------------------------- ### Initialize Driver with SDK v2 Source: https://apps.developer.homey.app/upgrade-guides/upgrading-to-sdk-v3 Example of initializing a driver in SDK v2, including registering a Flow card condition and an image, using the global `Homey` object. ```javascript const Homey = require("homey"); class Driver extends Homey.Driver { onInit() { this.rainingCondition = new Homey.FlowCardCondition("is_raining"); this.rainingCondition.register(); this.myImage = new Homey.Image(); this.myImage.setUrl("https://www.example.com/image.png"); this.myImage.register().catch(this.error); } } module.exports = Driver; ``` -------------------------------- ### Make API Requests (Python) Source: https://apps.developer.homey.app/advanced/web-api Demonstrates making a GET request to another app's API. Always check app installation and version compatibility before making requests. ```python from homey import app from homey.api_app import ApiApp class App(app.App): other_app_api: ApiApp async def on_init(self) -> None: self.other_app_api = self.homey.api.get_api_app("com.athom.otherApp") # Make a get request to "otherApp"s API get_response = await self.other_app_api.get("/") ``` -------------------------------- ### Query Documentation Dynamically Source: https://apps.developer.homey.app/the-basics/devices/settings Use this GET request to ask questions about the documentation. The response will provide direct answers and relevant excerpts. ```HTTP GET https://apps.developer.homey.app/the-basics/devices/settings.md?ask= ``` -------------------------------- ### Example: Custom target_power_mode values Source: https://apps.developer.homey.app/the-basics/devices/energy Demonstrates how to define custom strategy modes for `target_power_mode` beyond the default 'device' and 'homey'. This is useful for devices with multiple operational strategies like self-consumption or price-based optimization. ```json { "target_power_mode": { "values": [ { "id": "homey", "title": { "en": "Homey" } }, { "id": "self_use", "title": { "en": "Self-use" } }, { "id": "price_based", "title": { "en": "Price-based" } } ] } } ``` -------------------------------- ### TypeScript RTSP Camera Setup Source: https://apps.developer.homey.app/~/changes/1149/advanced/videos This TypeScript snippet shows how to set up an RTSP camera. It involves creating a video stream instance, defining a listener to dynamically generate the RTSP URL with authentication, and then associating this camera feed with the device. Ensure correct settings are retrieved for authentication. ```mts import Homey from "homey"; export default class Device extends Homey.Device { /* * To play an RTSP stream, you simply need to return the URL to the stream * from the video url listener. Some streams require authentication in * different formats. This example uses query parameters for authentication. */ async onInit(): Promise { try { const video = await this.homey.videos.createVideoRTSP({ allowInvalidCertificates: true, demuxer: "h265", }); /* * The video url listener takes no arguments. It simply builds the * URL to the RTSP stream using the username and password. */ video.registerVideoUrlListener(async () => { // Get the username and password that were set during pairing const { username, password } = this.getSettings(); // Normally, you would get the device's IP from Discovery, or another method return { url: `rtsp://${username}:${password}@192.168.1.100:554/stream` }; }); /* * Attach the camera to the device. */ await this.setCameraVideo("main", "Main Camera", video); } catch (err) { this.error("Error creating camera:", err); } } } ``` -------------------------------- ### JavaScript Device Trigger Card Setup Source: https://apps.developer.homey.app/~/changes/1149/the-basics/flow Implement a device-specific trigger card in JavaScript. This snippet shows how to get the trigger card in the driver's `onInit` and trigger it from a device method. ```javascript const Homey = require('homey'); class Driver extends Homey.Driver { async onInit() { this._deviceTurnedOn = this.homey.flow.getDeviceTriggerCard("turned_on"); } triggerMyFlow(device, tokens, state) { this._deviceTurnedOn .trigger(device, tokens, state) .then(this.log) .catch(this.error); } } module.exports = Driver; ``` ```javascript const Homey = require('homey'); class Device extends Homey.Device { async onInit() { let device = this; // We're in a Device instance let tokens = {}; let state = {}; this.driver.ready().then(() => { this.driver.triggerMyFlow(device, tokens, state); }); } } module.exports = Device; ``` -------------------------------- ### Upgrade onPairListDevices from Callback to Promise Source: https://apps.developer.homey.app/upgrade-guides/upgrading-to-sdk-v3 This example demonstrates upgrading the `onPairListDevices` method from SDK v2's callback pattern to SDK v3's async/Promise-based approach, returning the device list directly. ```javascript const Homey = require('homey'); class Driver extends Homey.Driver { onPairListDevices(data, callback) { const discoveryStrategy = this.getDiscoveryStrategy(); const discoveryResults = Object.values( discoveryStrategy.getDiscoveryResults() ); const devices = discoveryResults.map((discoveryResult) => { return { name: discoveryResult.txt.name, data: { id: discoveryResult.id, }, }; }); callback(null, devices); } } ``` ```javascript const Homey = require('homey'); class Driver extends Homey.Driver { async onPairListDevices() { const discoveryStrategy = this.getDiscoveryStrategy(); const discoveryResults = Object.values( discoveryStrategy.getDiscoveryResults() ); const devices = discoveryResults.map((discoveryResult) => { return { name: discoveryResult.txt.name, data: { id: discoveryResult.id, }, }; }); return devices; } } ``` -------------------------------- ### List Devices for Pairing (SDK v3) Source: https://apps.developer.homey.app/~/changes/1149/upgrade-guides/upgrading-to-sdk-v3 Example of onPairListDevices in SDK v3, using async/await to return the device list directly. ```javascript const Homey = require('homey'); class Driver extends Homey.Driver { async onPairListDevices() { const discoveryStrategy = this.getDiscoveryStrategy(); const discoveryResults = Object.values( discoveryStrategy.getDiscoveryResults() ); const devices = discoveryResults.map((discoveryResult) => { return { name: discoveryResult.txt.name, data: { id: discoveryResult.id, }, }; }); return devices; } } module.exports = Driver; ``` -------------------------------- ### DASH Camera Integration (TypeScript) Source: https://apps.developer.homey.app/advanced/videos This TypeScript example demonstrates how to set up a DASH camera stream. It's similar to the JavaScript version, requiring video object creation and URL listener registration. ```mts import Homey from "homey"; export default class Device extends Homey.Device { async onInit(): Promise { try { const video = await this.homey.videos.createVideoDASH(); /* * The video url listener takes no arguments. It simply builds the * URL to the DASH stream. */ video.registerVideoUrlListener(async () => { // Normally, you would get the device's IP from Discovery, or another method return { url: `http://@192.168.1.100/stream.mpd`, }; }); /* * Attach the camera to the device. */ await this.setCameraVideo("main", "Main Camera", video); } catch (err) { this.error("Error creating camera:", err); } } } ``` -------------------------------- ### Define API Routes in App Manifest Source: https://apps.developer.homey.app/advanced/web-api Configure the available API endpoints, including their HTTP methods and paths, within the app.json file. This example shows configurations for GET, POST, PUT, and DELETE operations. ```json "api": { "getSomething": { "method": "GET", "path": "/" }, "addSomething": { "method": "POST", "path": "/" }, "updateSomething": { "method": "PUT", "path": "/:id" }, "deleteSomething": { "method": "DELETE", "path": "/:id" } } ``` -------------------------------- ### Homey.openURL() Source: https://apps.developer.homey.app/advanced/custom-views/app-settings Show a new window. ```APIDOC ## Homey.openURL( String url ) ### Description Show a new window. ### Method `Homey.openURL(url)` ### Parameters #### Path Parameters - **url** (String) - Required - The URL to open in a new window. ``` -------------------------------- ### Homey.__ Source: https://apps.developer.homey.app/~/changes/1149/the-basics/widgets Translate a string programmatically. The first argument `input` is the name in your `/locales/__language__.json`. Use dots to get a sub-property, e.g. `settings.title`. The optional second argument `tokens` is an object with replacers. Read more about translations in the [internationalization guide](/~/changes/1149/the-basics/app/internationalization.md). ```APIDOC ## Homey.__ ### Description Translate a string programmatically. The first argument `input` is the name in your `/locales/__language__.json`. Use dots to get a sub-property, e.g. `settings.title`. The optional second argument `tokens` is an object with replacers. Read more about translations in the [internationalization guide](/~/changes/1149/the-basics/app/internationalization.md). ### Method Signature ```javascript Homey.__(input: string, tokens?: object): string ``` ``` -------------------------------- ### Make API Requests and Listen to Realtime Events (TypeScript) Source: https://apps.developer.homey.app/advanced/web-api Demonstrates making GET and POST requests to another app's API and listening for realtime events. Always check app installation and version compatibility before making requests. ```typescript import Homey, { ApiApp } from "homey"; export default class App extends Homey.App { otherAppApi!: ApiApp; async onInit(): Promise { this.otherAppApi = this.homey.api.getApiApp("com.athom.otherApp"); // Make a get request to "otherApp"s API const getResponse = await this.otherAppApi.get("/"); // Post some data to "otherApp", the second argument is the request body const postResponse = await this.otherAppApi.post("/play", { sound: "bell" }); // Listen to app realtime events this.otherAppApi.on("realtime", event => { console.log("otherApp.onRealtime", event); }); } } ``` -------------------------------- ### Make API Requests and Listen to Realtime Events (JavaScript) Source: https://apps.developer.homey.app/advanced/web-api Demonstrates making GET and POST requests to another app's API and listening for realtime events. Always check app installation and version compatibility before making requests. ```javascript const Homey = require('homey'); class App extends Homey.App { async onInit() { this.otherAppApi = this.homey.api.getApiApp("com.athom.otherApp"); // Make a get request to "otherApp"s API const getResponse = await this.otherAppApi.get('/'); // Post some data to "otherApp", the second argument is the request body const postResponse = await this.otherAppApi.post('/play', { sound: 'bell' }); // Listen to app realtime events this.otherAppApi.on('realtime', (event) => { console.log('otherApp.onRealtime', event); }); } } module.exports = App; ``` -------------------------------- ### Query Cloud Documentation Source: https://apps.developer.homey.app/~/changes/1149/cloud Use this GET request to dynamically query the documentation. Include your question as the `ask` query parameter. The response will contain a direct answer and relevant excerpts. ```http GET https://apps.developer.homey.app/~/changes/1149/cloud.md?ask= ``` -------------------------------- ### Create and Use Image Token (Python) Source: https://apps.developer.homey.app/~/changes/1149/the-basics/flow/tokens This Python example illustrates how to create an image token, associate an image with it, and then use it within Flow actions and triggers. It also demonstrates how to process image streams received from Flow actions. ```python import os from typing import TypedDict from homey import app from homey.image import Image class ImageActionArgs(TypedDict): droptoken: Image class App(app.App): async def on_init(self) -> None: my_image = await self.homey.images.create_image() my_image.set_path( os.path.join(os.path.dirname(__file__), "assets", "images", "kitten.jpg") ) my_image_token = await self.homey.flow.create_token( "my_token", "image", "My Image Token", my_image ) my_action_card = self.homey.flow.get_action_card("image_action") async def run_listener(card_arguments: ImageActionArgs, **trigger_kwargs): image_stream = await card_arguments.get("droptoken").get_stream() self.log( f"saving {image_stream['meta']['contentType']} to {image_stream['meta']['filename']}" ) # save the image with open( os.path.join("/userdata", image_stream["meta"]["filename"]), "wb", ) as target_file: target_file.write(image_stream["data"].buffer.read()) my_action_card.register_run_listener(run_listener) my_trigger_card = self.homey.flow.get_trigger_card("image_trigger") # pass the image to the trigger call await my_trigger_card.trigger({"my_image": my_image}) homey_export = App ``` -------------------------------- ### GET / Source: https://apps.developer.homey.app/~/changes/1149/advanced/web-api Defines a GET endpoint at the root path. Used for retrieving data. ```APIDOC ## GET / ### Description Defines a GET endpoint at the root path. Used for retrieving data. ### Method GET ### Endpoint / ### Parameters #### Query Parameters - **query** (object) - Optional - Access query parameters like "/?foo=bar" through `query.foo`. #### Request Body None ### Response #### Success Response (200) - **result** (any) - The result of the operation. ### Request Example None ### Response Example { "example": "response body" } ``` -------------------------------- ### CommonJS App Initialization Source: https://apps.developer.homey.app/guides/using-esm-in-homey-apps Example of a basic Homey app using CommonJS module system. ```javascript 'use strict'; const Homey = require('homey'); class MyApp extends Homey.App { async onInit() { this.log('MyApp has been initialized'); } } module.exports = MyApp; ``` -------------------------------- ### Query Documentation via HTTP GET Source: https://apps.developer.homey.app/app-store/publishing To get additional information not directly present on the page, make an HTTP GET request with the 'ask' query parameter. The question should be specific and in natural language. ```http GET https://apps.developer.homey.app/app-store/publishing.md?ask= ``` -------------------------------- ### Install Zigbee Dependencies Source: https://apps.developer.homey.app/upgrade-guides/upgrading-to-sdk-v3/upgrading-zigbee Install the necessary homey-zigbeedriver and zigbee-clusters packages using npm. ```bash npm install --save homey-zigbeedriver zigbee-clusters ``` -------------------------------- ### Querying Documentation via HTTP GET Source: https://apps.developer.homey.app/the-basics/app/permissions To get specific information not readily available, make an HTTP GET request to the current page URL with an 'ask' query parameter. The question should be clear and in natural language. ```http GET https://apps.developer.homey.app/the-basics/app/permissions.md?ask= ``` -------------------------------- ### TypeScript App Class Setup Source: https://apps.developer.homey.app/the-basics/app Initialize shared resources like an API client in the `onInit` method of the TypeScript App class. This ensures the client is created only once upon app startup. ```typescript import Homey from 'homey'; import ApiClient from 'your-external-api-client'; export default class App extends Homey.App { client?: ApiClient; async onInit(): Promise { // create an ApiClient once when the app is started this.client = new ApiClient(); } } ``` -------------------------------- ### RTMP Camera Setup (Python) Source: https://apps.developer.homey.app/advanced/videos This Python code demonstrates setting up an RTMP camera stream within the Homey environment. It defines a URL listener and attaches the video stream to the device, mirroring the functionality in other languages. ```python from homey import device class Device(device.Device): async def on_init(self) -> None: try: video = await self.homey.videos.create_video_rtmp() # The video url listener takes no arguments. It simply builds the # URL to the RTMP stream. async def url_listener() -> str: # Normally, you would get the device's IP from Discovery, or another method return f"rtmp://@192.168.1.100:1935" video.register_video_url_listener(url_listener) # Attach the camera to the device. await self.set_camera_video("main", "Main Camera", video) except Exception as err: self.error("Error creating camera:", err) homey_export = Device ``` -------------------------------- ### Initialize API Client and Subscribe to Events (Python) Source: https://apps.developer.homey.app/advanced/web-api Initializes an API client for another app and subscribes to its install and uninstall events. Ensure the target app ID is correct. ```python from homey import app from homey.api_app import ApiApp class App(app.App): other_app_api: ApiApp async def on_init(self) -> None: self.other_app_api = self.homey.api.get_api_app("com.athom.otherApp") is_installed = await self.other_app_api.get_installed() version = await self.other_app_api.get_version() def on_install(): print("otherApp is installed") self.other_app_api.on_install(on_install) def on_uninstall(): print("otherApp is uninstalled") self.other_app_api.on_uninstall(on_uninstall) homey_export = App ``` -------------------------------- ### GET / Source: https://apps.developer.homey.app/advanced/web-api Defines a GET endpoint at the root path. This function can access query parameters and the Homey app instance. ```APIDOC ## GET / ### Description Defines a GET endpoint at the root path. This function can access query parameters and the Homey app instance. ### Method GET ### Endpoint / ### Parameters #### Query Parameters - **foo** (string) - Optional - Example: `?foo=bar` ### Request Example ```json { "example": "request body" } ``` ### Response #### Success Response (200) - **result** (any) - Description of the result returned by the app. ### Response Example ```json { "example": "response body" } ``` ``` -------------------------------- ### Python WebRTC Camera Setup Source: https://apps.developer.homey.app/advanced/videos Implement WebRTC camera stream in Python. This code creates a video stream, registers an offer listener for SDP exchange, and attaches the camera to the device. ```python from homey import device from homey.video_web_rtc import WebRTCAnswer from .oauth2_client import OAuth2Client class Device(device.Device): oauth2_client: OAuth2Client # WebRTC works by creating an offer SDP in the frontend, exchanging it for # an answer SDP through the cameras API, and using that answer SDP in the # frontend to set up the connection. async def on_init(self) -> None: try: video = await self.homey.videos.create_video_web_rtc() # This listener is called when the user opens the camera stream in the # mobile app. The argument is an SDP offer generated by the mobile app. async def offer_listener(offer: str) -> WebRTCAnswer: # Normally, you would call an API to exchange an SDP offer for an SDP answer result = await self.oauth2_client.create_stream(offer) return { "answerSdp": result.get("answerSdp"), } video.register_offer_listener(offer_listener) # Attach the camera to the device. await self.set_camera_video("main", "Main Camera", video) except Exception as err: self.error("Error creating camera:", err) homey_export = Device ``` -------------------------------- ### Install Homey CLI Source: https://apps.developer.homey.app/the-basics/getting-started Installs the Homey CLI globally using npm. You may need superuser rights for this command. ```bash npm install --global homey ``` -------------------------------- ### Safe Device Initialization with Zigbee Source: https://apps.developer.homey.app/wireless/zigbee Demonstrates how to safely read Zigbee attributes in the onNodeInit phase by properly handling promises to prevent errors when Zigbee is not ready. ```javascript const { ZigBeeDevice } = require("homey-zigbeedriver"); class Device extends ZigBeeDevice { async onNodeInit({ zclNode }) { // Read the "onOff" attribute from the "onOff" cluster const currentOnOffValue = await zclNode.endpoints[1].clusters.onOff.readAttributes( ["onOff"] ).catch(err => { this.error(err); /* Always catch Promises, especially in onNodeInit */ }); } } module.exports = Device; ``` -------------------------------- ### Homey.ready() Source: https://apps.developer.homey.app/advanced/custom-views/app-settings The settings view will be hidden until this method has been called. Use the extra time to make required API calls to prevent flickering on screen. ```APIDOC ## Homey.ready() ### Description The settings view will be hidden until this method has been called. Use the extra time to make required API calls to prevent flickering on screen. ### Method `Homey.ready()` ``` -------------------------------- ### Install Homey App Dependencies Source: https://apps.developer.homey.app/the-basics/getting-started/homey-cli Installs the necessary libraries that your Homey app depends on. For Python apps, this includes pre-compiling dependencies for distribution. ```bash homey app dependencies install ``` -------------------------------- ### Webhook HTTP Request Example (Headers) Source: https://apps.developer.homey.app/~/changes/1149/cloud/webhooks Example of an HTTP POST request to a Homey webhook, demonstrating how headers are used for device identification. ```http POST /webhook/56db7fb12dcf75604ea7977d HTTP/1.1 X-Device-Id: aaa Host: webhooks.athom.com Content-Type: application/json; charset=utf-8 { "turned_on": true } ``` -------------------------------- ### Implement Pairing with onPairListDevices (JavaScript) Source: https://apps.developer.homey.app/the-basics/devices/pairing Use the `Driver#onPairListDevices()` method to quickly implement pairing when using only 'list_devices' and 'add_devices' templates. This method returns a list of devices to be presented to the user. ```javascript const Homey = require("homey"); const DeviceApi = require("device-api"); class Driver extends Homey.Driver { async onPairListDevices() { const devices = await DeviceApi.discoverDevices(); return devices; } } module.exports = Driver; ``` -------------------------------- ### Webhook HTTP Request Example (Body) Source: https://apps.developer.homey.app/~/changes/1149/cloud/webhooks Example of an HTTP POST request to a Homey webhook, demonstrating how the device key can be specified within the request body. ```http POST /webhook/56db7fb12dcf75604ea7977d HTTP/1.1 X-Device-Id: aaa Host: webhooks.athom.com Content-Type: application/json; charset=utf-8 { "X-Device-Id": "bbb", "turned_on": true } ```