immersive-home/README.md

156 lines
6.8 KiB
Markdown
Raw Normal View History

2023-11-04 15:24:50 +02:00
![logo](assets/banner.png)
2023-10-16 20:10:02 +03:00
2023-11-04 16:34:46 +02:00
# 🏠 Introduction
Immersive Home is project to bring Smart Home and Mixed Reality technologies together for an intuitive and immersive experience.
## Features
- **Fast and Intuitive control over IoT devices**
- **Live overview over your smart home**
- **Simple way for creating automations**
- **Comfortable way of consuming virtual media unobstructed**
- **Advanced automations based on position in room**
## Supported Devices
**Smart Home Platforms**
- [Home Assistant](https://www.home-assistant.io/)
**Mixed Reality Headsets**
- Meta Quest 2 / Pro / 3
2023-11-21 12:48:35 +02:00
## Connecting to your Home Assistant Instance
Right now, as a temporary solution, the app will use whatever is saved into your clipboard to connect to your Home Assistant instance.
Format: `ws://<ip/url>:<port>/api/websocket <token>`
Example `ws://192.168.0.31:8123/api/websocket eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiIzZjQ0ZGM2N2Y3YzY0MDc1OGZlMWI2ZjJlNmIxZjRkNSIsImlhdCI6MTY5ODAxMDcyOCwiZXhwIjoyMDEzMzcwNzI4fQ.K6ydLUC-4Q7BNIRCU1nWlI2s6sg9UCiOu-Lpedw2zJc`
To generate a HASS token, login into your dashboard, click on your name (bottom left), scroll down and create a long-lived access token.
You can check if you are properly connected by opening the settings tab in the app and looking at the bottom right corner.
2023-11-04 16:35:48 +02:00
# 🛠 Development
2023-11-04 16:34:46 +02:00
In order to contribute to this project, you need the following to be setup before you can start working:
- Godot 4.1.3 installed
## Fundamentals
Communication with the Smart Home Environment is done using the `HomeAdapters` global. Each environment is made up of devices and entities.
A device is a collection of different entities and entities can represent many different things in a smart home.
For example, the entity of name `lights.smart_lamp_1` would control the kitchen lamps while `state.smart_lamp_1_temp` would show the current temperature of the lamp.
2023-11-05 16:27:57 +02:00
### File Structure
```
.
├── addons (All installed Godot Addons are saved here)
├── assets (Files like logos or assets that are shared across scenes)
2023-11-05 16:28:41 +02:00
├── content/ (Main files of the project)
2023-11-05 16:27:57 +02:00
│ ├── entities (Entities that can be placed into the room)
2023-11-11 19:26:58 +02:00
│ ├── functions (Generic functions that can be used in scenes)
2023-11-05 16:27:57 +02:00
│ └── ui (User Interface Scenes and related files)
2023-11-05 16:28:41 +02:00
└── lib/ (Code that is global or shared across scenes)
2023-11-05 16:27:57 +02:00
├── globals (Globally running scripts)
└── home_adapters (Code allowing control smart home entities)
```
2023-11-04 16:34:46 +02:00
### Home Adapters
The `HomeAdapters` global allows to communicate with different backends and offers a set of fundamental functions allowing communication with the Smart Home.
```python
Device {
"id": String,
"name": String,
"entities": Array[Entity]
}
Entity {
"state": String
"attributes": Dictionary
}
# Get a list of all devices
func get_devices() -> Signal[Array[Device]]
# Get a single device by id
func get_device(id: String) -> Signal[Device]
# Returns the current state of an entity.
func get_state(entity: String) -> Signal[Entity]
# Updates the state of the entity and returns the resulting state
func set_state(entity: String, state: String, attributes: Dictionary) -> Signal[Entity]
# Watches the state and each time it changes, calls the callback with the changed state, returns a function to stop watching the state
func watch_state(entity: String, callback: Callable[entity: Entity]) -> Callable
```
### Interaction Events
2023-11-05 14:59:33 +02:00
Each time a button is pressed on the primary controller, a ray-cast is done to be able to interact with devices or the UI.
2023-11-11 19:25:59 +02:00
Additionally, each event will bubble up until the root node is reached, allowing to handle events on parents.
In case that an event of a specific node has to be reacted on, use the `Clickable` function node.
2023-11-04 16:34:46 +02:00
2023-11-16 20:23:17 +02:00
It is also possible to bubble up information by returning a dictionary from a function like `_on_click`.
2023-11-05 14:59:33 +02:00
```python
InteractionEvent {
"controller": XRController3D, # The controller that triggered the event
"ray": RayCast3D, # The ray-cast that triggered the event
2023-11-11 19:25:59 +02:00
"target": Node3D, # The node that was hit by the ray-cast
2023-11-04 16:34:46 +02:00
}
```
| Function called | Args | Description |
| -- | -- | -- |
2023-11-05 14:59:33 +02:00
| `_on_click` | `[event: InteractionEvent]` | The back trigger button has been pressed and released |
| `_on_press_down` | `[event: InteractionEvent]` | The back trigger button has been pressed down |
| `_on_press_move` | `[event: InteractionEvent]` | The back trigger button has been moved while pressed down |
| `_on_press_up` | `[event: InteractionEvent]` | The back trigger button has been released |
| `_on_grab_down` | `[event: InteractionEvent]` | The side grab button been pressed down |
| `_on_grab_move` | `[event: InteractionEvent]` | The side grab button been pressed down |
| `_on_grab_up` | `[event: InteractionEvent]` | The side grab button been released |
| `_on_ray_enter` | `[event: InteractionEvent]` | The ray-cast enters the the collision body |
| `_on_ray_leave` | `[event: InteractionEvent]` | The ray-cast leaves the the collision body |
2023-11-04 16:34:46 +02:00
2023-11-11 19:25:59 +02:00
### Functions
In order to implement generic features, a set of functions is available to be used in the project.
#### Movable
The `Movable` node allows to move a node around in the room. It uses the grab events in order to transform the parent node.
#### Clickable
The `Clickable` allows to access events of the parent using signals this node emits.
2023-11-21 12:48:35 +02:00
## Installing Locally
1. Make sure Git LFS is installed
2. Run `git clone https://github.com/Nitwel/Immersive-Home.git` in your terminal
3. Import the created `Immersive-Home` folder in Godot
4. Open the project in Godot 4.1.3
2023-11-04 16:34:46 +02:00
### Testing without a VR Headset
In order to test without a headset, press the run project (F5) button in Godot and ignore the prompt that OpenXR failed to start.
To simulate the headset and controller movement, we're using the [XR Input Simulator](https://godotengine.org/asset-library/asset/1775) asset.
2023-11-05 14:59:33 +02:00
Click at the link to get a list of the supported controls.
## Building
2023-11-21 12:48:35 +02:00
1. Possibly fix importing scenes error
2. Follow the following guide to setup exporting for android. [link](https://docs.godotengine.org/en/stable/tutorials/export/exporting_for_android.html)
3. Make sure to reuse any existing `debug.keystore` when updating an app
4. Don't forget to set the JAVA_HOME variable and restart Godot to take effect
5. Install the `Godot XR Android OpenXR Loaders` plugin in Godot
6. Configure the following in the android build template:
2023-11-13 15:12:46 +02:00
- XRMode set to OpenXR
- Check `Use Grandle Build`
- Check `Godot OpenXR Meta`
- In XRFeatures, select at least optional for passthrough
- Ckeck Internet under the permissions
- Under Resources > Filters to export, add `*.j2`
2023-11-21 12:48:35 +02:00
7. `<uses-feature android:name="com.oculus.feature.CONTEXTUAL_BOUNDARYLESS_APP" android:required="true" />` can be added to the `AndroidManifest.xml` to disable the boundary system.